{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://stac-extensions.github.io/mlm/v1.5.2/schema.json",
  "title": "Machine Learning Model STAC Extension Schema",
  "description": "This object represents the metadata for a Machine Learning Model (MLM) used in STAC documents.",
  "$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'.",
  "allOf": [
    {
      "description": "This is the schema for STAC extension MLM in Items.",
      "if": {
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "const": "Feature"
          }
        }
      },
      "then": {
        "allOf": [
          {
            "description": "Schema to validate the MLM fields permitted under Item properties or Assets properties.",
            "type": "object",
            "required": [
              "properties",
              "assets"
            ],
            "properties": {
              "properties": {
                "$comment": "Schema to validate the MLM fields permitted under Item properties.",
                "$ref": "#/$defs/mlmItemFields"
              },
              "assets": {
                "additionalProperties": {
                  "$comment": "Schema to validate the MLM fields permitted under Asset properties.",
                  "$ref": "#/$defs/mlmAssetFields"
                }
              }
            }
          },
          {
            "$ref": "#/$defs/stac_extensions_mlm"
          },
          {
            "$comment": "Schema to validate cross-references of bands between MLM inputs and any compliant section describing them using another STAC definition.",
            "$ref": "#/$defs/AnyBandsRef"
          },
          {
            "$comment": "Schema to validate cross-references of variables between MLM inputs and any compliant section describing them using another STAC definition.",
            "$ref": "#/$defs/AnyVariablesRef"
          },
          {
            "$comment": "Schema to validate that at least one Asset defines a model role.",
            "$ref": "#/$defs/AssetModelRoleMinimumOneDefinition"
          },
          {
            "$comment": "Schema to validate any Asset containing an entrypoint is associated with code role.",
            "$ref": "#/$defs/AssetCodeRoleWithEntrypoint"
          },
          {
            "$comment": "Schema to validate that the Asset model properties are mutually exclusive to the model role.",
            "$ref": "#/$defs/AssetModelRequiredProperties"
          }
        ]
      }
    },
    {
      "description": "This is the schema for STAC extension MLM in Collections.",
      "if": {
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "const": "Collection"
          }
        }
      },
      "then": {
        "allOf": [
          {
            "type": "object",
            "properties": {
              "summaries": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/$defs/mlmCollectionFields"
                }
              },
              "assets": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/$defs/mlmAssetFields"
                }
              },
              "item_assets": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/$defs/mlmAssetFields"
                }
              }
            }
          },
          {
            "$ref": "#/$defs/stac_extensions_mlm"
          }
        ]
      }
    }
  ],
  "$defs": {
    "stac_extensions_mlm": {
      "type": "object",
      "required": [
        "stac_extensions"
      ],
      "properties": {
        "stac_extensions": {
          "type": "array",
          "contains": {
            "const": "https://stac-extensions.github.io/mlm/v1.5.2/schema.json"
          }
        }
      }
    },
    "stac_extensions_datacube_variables": {
      "$comment": "STAC extension reference to [https://github.com/stac-extensions/datacube]. V2 and above is required to reference 'cube:variables'.",
      "type": "object",
      "required": [
        "stac_extensions"
      ],
      "properties": {
        "stac_extensions": {
          "type": "array",
          "contains": {
            "type": "string",
            "pattern": "https://stac-extensions\\.github\\.io/datacube/v2(\\.[0-9]+){2}/schema\\.json"
          }
        }
      }
    },
    "stac_extensions_datacube_variables_field": {
      "type": "object",
      "required": [
        "cube:variables"
      ],
      "properties": {
        "cube:variables": {
          "type": "object",
          "minProperties": 1,
          "additionalProperties": true
        }
      }
    },
    "stac_extensions_datacube_variables_item": {
      "$comment": "This is the JSON-object 'properties' definition, which describes the STAC-Item field named 'properties' containing 'cube:variables' as described in [https://github.com/stac-extensions/datacube#fields].",
      "properties": {
        "properties": {
          "$ref": "#/$defs/stac_extensions_datacube_variables_field"
        }
      }
    },
    "stac_extensions_datacube_variables_asset": {
      "required": [
        "assets"
      ],
      "$comment": "This is the JSON-object 'properties' definition, which describes the STAC-Asset containing 'cube:variables' as described in [https://github.com/stac-extensions/datacube#fields].",
      "properties": {
        "assets": {
          "additionalProperties": {
            "if": {
              "$ref": "#/$defs/AssetModelRole"
            },
            "then": {
              "$ref": "#/$defs/stac_extensions_datacube_variables_field"
            }
          }
        }
      }
    },
    "stac_extensions_eo": {
      "type": "object",
      "required": [
        "stac_extensions"
      ],
      "properties": {
        "stac_extensions": {
          "type": "array",
          "contains": {
            "type": "string",
            "pattern": "https://stac-extensions\\.github\\.io/eo/v1(\\.[0-9]+){2}/schema\\.json"
          }
        }
      }
    },
    "stac_extensions_eo_bands_item": {
      "$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].",
      "properties": {
        "properties": {
          "required": [
            "eo:bands"
          ],
          "properties": {
            "eo:bands": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    },
    "stac_extensions_eo_bands_asset": {
      "required": [
        "assets"
      ],
      "$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].",
      "properties": {
        "assets": {
          "additionalProperties": {
            "if": {
              "$ref": "#/$defs/AssetModelRole"
            },
            "then": {
              "required": [
                "eo:bands"
              ],
              "properties": {
                "eo:bands": {
                  "type": "array",
                  "minItems": 1,
                  "items": {
                    "type": "object"
                  }
                }
              }
            }
          }
        }
      }
    },
    "stac_extensions_raster": {
      "type": "object",
      "required": [
        "stac_extensions"
      ],
      "properties": {
        "stac_extensions": {
          "type": "array",
          "contains": {
            "type": "string",
            "pattern": "https://stac-extensions\\.github\\.io/raster/v1(\\.[0-9]+){2}/schema\\.json"
          }
        }
      }
    },
    "stac_extensions_raster_bands_asset": {
      "required": [
        "assets"
      ],
      "$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].",
      "properties": {
        "assets": {
          "additionalProperties": {
            "if": {
              "$ref": "#/$defs/AssetModelRole"
            },
            "then": {
              "required": [
                "raster:bands"
              ],
              "properties": {
                "raster:bands": {
                  "type": "array",
                  "minItems": 1,
                  "items": {
                    "$comment": "Raster extension does not explicitly indicate a 'name', but one is needed for MLM.",
                    "type": "object",
                    "required": [
                      "name"
                    ],
                    "properties": {
                      "name": {
                        "type": "string",
                        "minLength": 1
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "stac_version_1.1": {
      "$comment": "Requirement for STAC 1.1 or above.",
      "type": "object",
      "required": [
        "stac_version"
      ],
      "properties": {
        "stac_version": {
          "pattern": "1\\.[1-9][0-9]*\\.[0-9]+(-.*)?"
        }
      }
    },
    "fields": {
      "description": "All possible MLM fields regardless of the level they apply (Collection, Item, Asset, Link).",
      "type": "object",
      "properties": {
        "mlm:name": {
          "$ref": "#/$defs/mlm:name"
        },
        "mlm:architecture": {
          "$ref": "#/$defs/mlm:architecture"
        },
        "mlm:tasks": {
          "$ref": "#/$defs/mlm:tasks"
        },
        "mlm:framework": {
          "$ref": "#/$defs/mlm:framework"
        },
        "mlm:framework_version": {
          "$ref": "#/$defs/mlm:framework_version"
        },
        "mlm:memory_size": {
          "$ref": "#/$defs/mlm:memory_size"
        },
        "mlm:total_parameters": {
          "$ref": "#/$defs/mlm:total_parameters"
        },
        "mlm:pretrained": {
          "$ref": "#/$defs/mlm:pretrained"
        },
        "mlm:pretrained_source": {
          "$ref": "#/$defs/mlm:pretrained_source"
        },
        "mlm:batch_size_suggestion": {
          "$ref": "#/$defs/mlm:batch_size_suggestion"
        },
        "mlm:accelerator": {
          "$ref": "#/$defs/mlm:accelerator"
        },
        "mlm:accelerator_constrained": {
          "$ref": "#/$defs/mlm:accelerator_constrained"
        },
        "mlm:accelerator_summary": {
          "$ref": "#/$defs/mlm:accelerator_summary"
        },
        "mlm:accelerator_count": {
          "$ref": "#/$defs/mlm:accelerator_count"
        },
        "mlm:input": {
          "$ref": "#/$defs/mlm:input"
        },
        "mlm:output": {
          "$ref": "#/$defs/mlm:output"
        },
        "mlm:hyperparameters": {
          "$ref": "#/$defs/mlm:hyperparameters"
        },
        "mlm:artifact_type": {
          "$ref": "#/$defs/mlm:artifact_type"
        },
        "mlm:compile_method": {
          "$ref": "#/$defs/mlm:compile_method"
        },
        "mlm:entrypoint": {
          "$ref": "#/$defs/mlm:entrypoint"
        }
      },
      "$comment": "Allow properties not defined by MLM prefix to work with other extensions and attributes, but disallow undefined MLM fields.",
      "patternProperties": {
        "^(?!mlm:)": {}
      },
      "additionalProperties": false
    },
    "mlmCollectionFields": {
      "description": "Schema to validate the MLM fields permitted under Collection summaries.",
      "allOf": [
        {
          "description": "Fields that are mandatory under the Collection summaries.",
          "type": "object",
          "required": []
        },
        {
          "description": "Fields that are disallowed under the Collection summaries.",
          "not": {
            "required": [
              "mlm:input",
              "mlm:output",
              "mlm:artifact_type",
              "mlm:compile_method"
            ]
          }
        },
        {
          "description": "Field with known definitions that must be validated.",
          "$ref": "#/$defs/fields"
        }
      ]
    },
    "mlmItemFields": {
      "description": "Schema to validate the MLM fields permitted under Item properties.",
      "allOf": [
        {
          "description": "Fields that are mandatory under the Item properties.",
          "required": [
            "mlm:name",
            "mlm:architecture",
            "mlm:tasks",
            "mlm:input",
            "mlm:output"
          ]
        },
        {
          "description": "Fields that are disallowed under the Item properties.",
          "$comment": "Particularity of the 'not/required' approach: they must be tested one by one. Otherwise, it validates that they are all (simultaneously) not present.",
          "not": {
            "anyOf": [
              {"required": ["mlm:artifact_type"]},
              {"required": ["mlm:compile_method"]},
              {"required": ["mlm:entrypoint"]}
            ]
          }
        },
        {
          "description": "Field with known definitions that must be validated.",
          "$ref": "#/$defs/fields"
        }
      ]
    },
    "mlmAssetFields": {
      "description": "Schema to validate the MLM fields permitted under Assets properties.",
      "allOf": [
        {
          "description": "Fields that are disallowed under the Asset properties.",
          "$comment": "Particularity of the 'not/required' approach: they must be tested one by one. Otherwise, it validates that they are all (simultaneously) not present.",
          "not": {
            "anyOf": [
              {
                "required": [
                  "mlm:name"
                ]
              },
              {
                "required": [
                  "mlm:input"
                ]
              },
              {
                "required": [
                  "mlm:output"
                ]
              },
              {
                "required": [
                  "mlm:hyperparameters"
                ]
              }
            ]
          }
        },
        {
          "description": "Field with known definitions that must be validated.",
          "$ref": "#/$defs/fields"
        }
      ]
    },
    "mlm:name": {
      "type": "string",
      "pattern": "^[a-zA-Z][a-zA-Z0-9_.\\-\\s]+[a-zA-Z0-9]$"
    },
    "mlm:architecture": {
      "type": "string",
      "title": "Model Architecture",
      "description": "A descriptive name of the model architecture, typically a common name from the literature.",
      "examples": [
        "ResNet",
        "VGG",
        "GAN",
        "Vision Transformer"
      ]
    },
    "mlm:framework": {
      "title": "Name of the machine learning framework used.",
      "anyOf": [
        {
          "$comment": "Add more entries here as needed, and repeat them in the README.",
          "description": "Notable predefined framework names.",
          "type": "string",
          "enum": [
            "PyTorch",
            "TensorFlow",
            "scikit-learn",
            "Hugging Face",
            "Keras",
            "ONNX",
            "rgee",
            "spatialRF",
            "JAX",
            "Flax",
            "MXNet",
            "Caffe",
            "PyMC",
            "Weka",
            "Paddle"
          ]
        },
        {
          "type": "string",
          "minLength": 1,
          "pattern": "^(?=[^\\s._\\-]).*[^\\s._\\-]$",
          "description": "Any other framework name to allow extension. Enum names should be preferred when possible to allow better portability."
        }
      ]
    },
    "mlm:framework_version": {
      "title": "Framework version",
      "type": "string",
      "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-]+)*))?$"
    },
    "mlm:artifact_type": {
      "type": "string",
      "minLength": 1,
      "examples": [
        "torch.save",
        "torch.jit.save",
        "torch.export.save",
        "tf.keras.Model.save",
        "tf.keras.Model.save_weights",
        "tf.keras.Model.export",
        "safetensors.torch.save_file",
        "safetensors.tensorflow.save_file",
        "safetensors.flax.save_file",
        "safetensors.paddle.save_file"
      ]
    },
    "mlm:compile_method": {
      "type": "string",
      "minLength": 1,
      "examples": [
        "aot",
        "jit"
      ]
    },
    "mlm:entrypoint": {
      "type": "string",
      "minLength": 1,
      "description": "Entrypoint script or function where the model can be invoked for inference on input data.",
      "examples": [
        "my_package.my_module:inference_function",
        "inference.py"
      ]
    },
    "mlm:tasks": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "string",
        "enum": [
          "regression",
          "classification",
          "scene-classification",
          "detection",
          "object-detection",
          "segmentation",
          "semantic-segmentation",
          "instance-segmentation",
          "panoptic-segmentation",
          "similarity-search",
          "generative",
          "image-captioning",
          "super-resolution",
          "downscaling"
        ]
      }
    },
    "mlm:memory_size": {
      "description": "Memory size (in bytes) required to load the model with the specified accelerator.",
      "type": "integer",
      "minimum": 0
    },
    "mlm:total_parameters": {
      "description": "Total number of model parameters (weights).",
      "type": "integer",
      "minimum": 0
    },
    "mlm:pretrained": {
      "type": "boolean",
      "$comment": "If trained from scratch, the source should be explicitly 'null'. However, omitting the source if pretrained is allowed.",
      "if": {
        "$comment": "This is the JSON-object 'properties' definition, which describes the STAC-Item field named 'properties'.",
        "properties": {
          "properties": {
            "$comment": "This is the JSON-object 'properties' definition for the STAC MLM pretraining reference.",
            "properties": {
              "mlm:pretrained": {
                "const": false
              }
            }
          }
        }
      },
      "then": {
        "$comment": "This is the JSON-object 'properties' definition, which describes the STAC-Item field named 'properties'.",
        "properties": {
          "properties": {
            "$comment": "This is the JSON-object 'properties' definition for the STAC MLM pretraining reference.",
            "required": [
              "mlm:pretrained_source"
            ],
            "properties": {
              "mlm:pretrained_source": {
                "const": null
              }
            }
          }
        }
      }
    },
    "mlm:pretrained_source": {
      "description": "Pre-training dataset reference or training from scratch definition.",
      "oneOf": [
        {
          "type": "string",
          "description": "The name or URI of the dataset used for pretraining the model.",
          "examples": [
            "ImageNet",
            "EuroSAT"
          ]
        },
        {
          "type": "null",
          "description": "Explicit mention that the model is trained from scratch."
        }
      ]
    },
    "mlm:batch_size_suggestion": {
      "description": "Recommended batch size to employ the model with the accelerator.",
      "type": "integer",
      "minimum": 0
    },
    "mlm:accelerator": {
      "oneOf": [
        {
          "type": "string",
          "enum": [
            "amd64",
            "cuda",
            "xla",
            "amd-rocm",
            "intel-ipex-cpu",
            "intel-ipex-gpu",
            "macos-arm"
          ]
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "mlm:accelerator_constrained": {
      "type": "boolean",
      "default": false
    },
    "mlm:accelerator_summary": {
      "type": "string"
    },
    "mlm:accelerator_count": {
      "type": "integer",
      "minimum": 1
    },
    "mlm:input": {
      "type": "array",
      "items": {
        "allOf": [
          {"$ref": "#/$defs/ModelInput"},
          {"$ref": "#/$defs/ModelInputBandsDimensionRef"},
          {"$ref": "#/$defs/ModelInputVariablesDimensionRef"}
        ]
      }
    },
    "ModelInput": {
      "title": "Model Input Object",
      "type": "object",
      "required": [
        "name",
        "input"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "bands": {
          "$ref": "#/$defs/ModelBandsVariables"
        },
        "variables": {
          "$ref": "#/$defs/ModelBandsVariables"
        },
        "input": {
          "$ref": "#/$defs/InputStructure"
        },
        "description": {
          "type": "string",
          "minLength": 1
        },
        "value_scaling": {
          "$ref": "#/$defs/ValueScaling"
        },
        "resize_type": {
          "$ref": "#/$defs/ResizeType"
        },
        "pre_processing_function": {
          "oneOf": [
            {"$ref": "#/$defs/ProcessingExpression"},
            {
              "type": "array",
              "items": {
                "$ref": "#/$defs/ProcessingExpression"
              },
              "minItems": 1
            }
          ]
        }
      }
    },
    "mlm:output": {
      "type": "array",
      "items": {
        "allOf": [
          {"$ref": "#/$defs/ModelOutput"},
          {"$ref": "#/$defs/ModelOutputBandsDimensionRef"},
          {"$ref": "#/$defs/ModelOutputVariablesDimensionRef"}
        ]
      }
    },
    "ModelOutput": {
      "title": "Model Output Object",
      "type": "object",
      "required": [
        "name",
        "tasks",
        "result"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1
        },
        "description": {
          "type": "string",
          "minLength": 1
        },
        "tasks": {
          "$ref": "#/$defs/mlm:tasks"
        },
        "result": {
          "$ref": "#/$defs/ResultStructure"
        },
        "bands": {
          "$ref": "#/$defs/ModelBandsVariables"
        },
        "variables": {
          "$ref": "#/$defs/ModelBandsVariables"
        },
        "classification:classes": {
          "$ref": "#/$defs/ClassificationClasses"
        },
        "post_processing_function": {
          "oneOf": [
            {"$ref": "#/$defs/ProcessingExpression"},
            {
              "type": "array",
              "items": {
                "$ref": "#/$defs/ProcessingExpression"
              },
              "minItems": 1
            }
          ]
        }
      }
    },
    "mlm:hyperparameters": {
      "type": "object",
      "minProperties": 1,
      "patternProperties": {
        "^[0-9a-zA-Z_.-]+$": true
      },
      "additionalProperties": false
    },
    "InputStructure": {
      "title": "Input Structure Object",
      "type": "object",
      "required": [
        "shape",
        "dim_order",
        "data_type"
      ],
      "properties": {
        "shape": {
          "$ref": "#/$defs/DimensionShape"
        },
        "dim_order": {
          "$ref": "#/$defs/DimensionOrder"
        },
        "data_type": {
          "$ref": "#/$defs/DataType"
        }
      }
    },
    "ResultStructure": {
      "title": "Result Structure Object",
      "type": "object",
      "required": [
        "shape",
        "dim_order",
        "data_type"
      ],
      "properties": {
        "shape": {
          "$ref": "#/$defs/DimensionShape"
        },
        "dim_order": {
          "$ref": "#/$defs/DimensionOrder"
        },
        "data_type": {
          "$ref": "#/$defs/DataType"
        }
      }
    },
    "DimensionShape": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "integer",
        "minimum": -1
      }
    },
    "DimensionOrder": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "string",
        "minLength": 1,
        "pattern": "^[a-z-_]+$",
        "examples": [
          "batch",
          "channel",
          "bands",
          "variables",
          "temperature",
          "pressure",
          "time",
          "height",
          "width",
          "depth",
          "token",
          "class",
          "score",
          "confidence",
          "embedding"
        ]
      }
    },
    "ValueScaling": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/$defs/ValueScalingObject"
          }
        }
      ]
    },
    "ValueScalingObject": {
      "oneOf": [
        {
          "type": "object",
          "required": [
            "type",
            "minimum",
            "maximum"
          ],
          "properties": {
            "type": {
              "const": "min-max"
            },
            "minimum": {
              "type": "number"
            },
            "maximum": {
              "type": "number"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "type",
            "mean",
            "stddev"
          ],
          "properties": {
            "type": {
              "const": "z-score"
            },
            "mean": {
              "type": "number"
            },
            "stddev": {
              "type": "number"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "type",
            "minimum",
            "maximum"
          ],
          "properties": {
            "type": {
              "const": "clip"
            },
            "minimum": {
              "type": "number"
            },
            "maximum": {
              "type": "number"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "type",
            "minimum"
          ],
          "properties": {
            "type": {
              "const": "clip-min"
            },
            "minimum": {
              "type": "number"
            },
            "maximum": {
              "type": "number"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "type",
            "maximum"
          ],
          "properties": {
            "type": {
              "const": "clip-max"
            },
            "maximum": {
              "type": "number"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "type",
            "value"
          ],
          "properties": {
            "type": {
              "const": "offset"
            },
            "value": {
              "type": "number"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "type",
            "value"
          ],
          "properties": {
            "type": {
              "const": "scale"
            },
            "value": {
              "type": "number"
            }
          }
        },
        {
          "$ref": "#/$defs/ValueScalingProcessingExpression"
        }
      ]
    },
    "ValueScalingProcessingExpression": {
      "allOf": [
        {
          "type": "object",
          "required": [
            "type"
          ],
          "properties": {
            "type": {
              "const": "processing"
            }
          }
        },
        {
          "$ref": "#/$defs/ProcessingExpression"
        }
      ]
    },
    "ResizeType": {
      "oneOf": [
        {
          "type": "string",
          "enum": [
            "crop",
            "pad",
            "interpolation-nearest",
            "interpolation-linear",
            "interpolation-cubic",
            "interpolation-area",
            "interpolation-lanczos4",
            "interpolation-max",
            "wrap-fill-outliers",
            "wrap-inverse-map"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "ClassificationClasses": {
      "$comment": "Must allow empty array for outputs that provide other predictions than classes.",
      "oneOf": [
        {
          "$ref": "https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes"
        },
        {
          "type": "array",
          "maxItems": 0
        }
      ]
    },
    "ProcessingExpression": {
      "oneOf": [
        {
          "allOf": [
            {
              "$ref": "https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression"
            },
            {
              "properties": {
                "description": {
                  "type": "string",
                  "description": "Optional information about the processing function."
                }
              }
            }
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "DataType": {
      "$ref": "https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type"
    },
    "HasArtifactType": {
      "$comment": "Used to check the artifact type property that is required by a Model Asset annotated by 'mlm:model' role.",
      "type": "object",
      "required": [
        "mlm:artifact_type"
      ],
      "properties": {
        "mlm:artifact_type": {
          "$ref": "#/$defs/mlm:artifact_type"
        }
      }
    },
    "AssetModelRole": {
      "$comment": "Used to check the presence of 'mlm:model' role required by a Model Asset.",
      "type": "object",
      "required": [
        "roles"
      ],
      "properties": {
        "roles": {
          "type": "array",
          "contains": {
            "const": "mlm:model"
          },
          "minItems": 1
        }
      }
    },
    "AssetModelRequiredProperties": {
      "$comment": "Asset containing the model definition must indicate both the 'mlm:model' role and an artifact type.",
      "required": [
        "assets"
      ],
      "properties": {
        "assets": {
          "additionalProperties": {
            "if": {
              "$ref": "#/$defs/AssetModelRole"
            },
            "then": {
              "$ref": "#/$defs/HasArtifactType"
            },
            "else": {
              "not": {
                "$ref": "#/$defs/HasArtifactType"
              }
            }
          }
        }
      }
    },
    "AssetModelRoleMinimumOneDefinition": {
      "$comment": "At least one Asset must provide the model definition indicated by the 'mlm:model' role.",
      "required": [
        "assets"
      ],
      "anyOf": [
        {
          "properties": {
            "assets": {
              "additionalProperties": {
                "$ref": "#/$defs/AssetModelRole"
              }
            }
          }
        },
        {
          "not": {
            "properties": {
              "assets": {
                "additionalProperties": {
                  "properties": {
                    "roles": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "not": {
                          "const": "mlm:model"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      ]
    },
    "AssetCodeRoleWithEntrypoint": {
      "$comment": "Used to check the presence of 'code' role if an entrypoint is provided in an Asset.",
      "properties": {
        "assets": {
          "additionalProperties": {
            "oneOf": [
              {
                "required": [
                  "mlm:entrypoint",
                  "roles"
                ],
                "properties": {
                  "mlm:entrypoint": {
                    "$ref": "#/$defs/mlm:entrypoint"
                  },
                  "roles": {
                    "type": "array",
                    "contains": {
                      "const": "code"
                    },
                    "minItems": 1
                  }
                }
              },
              {
                "not": {
                  "required": [
                    "mlm:entrypoint"
                  ]
                }
              }
            ]
          }
        }
      }
    },
    "ModelBandsVariables": {
      "description": "List of bands or variables (if any) that compose the input. Band and/or variable order represents the index position within the input. If both bands and variables are provided, their order should be distinguished using corresponding names in 'dim_order'.",
      "$comment": "No 'minItems' here to support model inputs not using any band (other data source).",
      "type": "array",
      "items": {
        "oneOf": [
          {
            "description": "Implied name of the band or variable with the name directly provided with no further properties.",
            "type": "string",
            "minLength": 1
          },
          {
            "description": "Explicitly named band or variable with optional derived expression to obtain it.",
            "type": "object",
            "required": [
              "name"
            ],
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1
              },
              "format": {
                "description": "Format to interpret the specified expression used to obtain the band.",
                "type": "string",
                "minLength": 1
              },
              "expression": {
                "description": "Any representation relevant for the specified 'format'."
              }
            },
            "dependencies": {
              "format": [
                "expression"
              ],
              "expression": [
                "format"
              ]
            },
            "additionalProperties": false
          }
        ]
      }
    },
    "ModelInputBandsDimensionRef": {
      "$comment": "This definition ensures that, if an MLM input 'bands' is provided with at least one entry, the corresponding 'bands' dimension is defined in 'dim_order'. Otherwise, 'bands' must be omitted or empty.",
      "if": {
        "required": [
          "bands"
        ],
        "properties": {
          "bands": {
            "type": "array",
            "minItems": 1
          }
        }
      },
      "then": {
        "$comment": "The 'bands' dimension is required if bands were indicated.",
        "properties": {
          "input": {
            "properties": {
              "dim_order": {
                "type": "array",
                "contains": {
                  "const": "bands"
                }
              }
            }
          }
        }
      },
      "else": {
        "$comment": "The 'bands' dimension is forbidden since none are indicated.",
        "properties": {
          "input": {
            "properties": {
              "dim_order": {
                "not": {
                  "contains": {
                    "const": "bands"
                  }
                }
              }
            }
          }
        }
      }
    },
    "ModelOutputBandsDimensionRef": {
      "$comment": "This definition ensures that, if an MLM output 'bands' is provided with at least one entry, the corresponding 'bands' dimension is defined in 'dim_order'. Otherwise, 'bands' must be omitted or empty.",
      "if": {
        "required": [
          "bands"
        ],
        "properties": {
          "bands": {
            "type": "array",
            "minItems": 1
          }
        }
      },
      "then": {
        "$comment": "The 'bands' dimension is required if bands were indicated.",
        "properties": {
          "result": {
            "properties": {
              "dim_order": {
                "type": "array",
                "contains": {
                  "const": "bands"
                }
              }
            }
          }
        }
      },
      "else": {
        "$comment": "The 'bands' dimension is forbidden since none are indicated.",
        "properties": {
          "result": {
            "properties": {
              "dim_order": {
                "not": {
                  "contains": {
                    "const": "bands"
                  }
                }
              }
            }
          }
        }
      }
    },
    "ModelInputVariablesDimensionRef": {
      "$comment": "This definition ensures that, if an MLM input 'variables' is provided with at least one entry, the corresponding 'variables' dimension is defined in 'dim_order'. Otherwise, 'variables' must be omitted or empty.",
      "if": {
        "required": [
          "variables"
        ],
        "properties": {
          "variables": {
            "type": "array",
            "minItems": 1
          }
        }
      },
      "then": {
        "$comment": "The 'variables' dimension is required if bands were indicated.",
        "properties": {
          "input": {
            "properties": {
              "dim_order": {
                "type": "array",
                "contains": {
                  "const": "variables"
                }
              }
            }
          }
        }
      },
      "else": {
        "$comment": "The 'variables' dimension is forbidden since none are indicated.",
        "properties": {
          "input": {
            "properties": {
              "dim_order": {
                "not": {
                  "contains": {
                    "const": "variables"
                  }
                }
              }
            }
          }
        }
      }
    },
    "ModelOutputVariablesDimensionRef": {
      "$comment": "This definition ensures that, if an MLM output 'variables' is provided with at least one entry, the corresponding 'variables' dimension is defined in 'dim_order'. Otherwise, 'variables' must be omitted or empty.",
      "if": {
        "required": [
          "variables"
        ],
        "properties": {
          "variables": {
            "type": "array",
            "minItems": 1
          }
        }
      },
      "then": {
        "$comment": "The 'variables' dimension is required if bands were indicated.",
        "properties": {
          "result": {
            "properties": {
              "dim_order": {
                "type": "array",
                "contains": {
                  "const": "variables"
                }
              }
            }
          }
        }
      },
      "else": {
        "$comment": "The 'variables' dimension is forbidden since none are indicated.",
        "properties": {
          "result": {
            "properties": {
              "dim_order": {
                "not": {
                  "contains": {
                    "const": "variables"
                  }
                }
              }
            }
          }
        }
      }
    },
    "AnyBandInputRef": {
      "type": "object",
      "$comment": "This is the JSON-object 'properties' definition, which describes the STAC-Item field named 'properties'.",
      "properties": {
        "properties": {
          "type": "object",
          "required": [
            "mlm:input"
          ],
          "$comment": "This is the JSON-object 'properties' definition for the MLM input with bands listing referring to at least one band name.",
          "properties": {
            "mlm:input": {
              "type": "array",
              "$comment": "Below 'minItems' ensures that band check does not fail for explicitly empty 'mlm:input'.",
              "minItems": 1,
              "items": {
                "type": "object",
                "required": [
                  "bands"
                ],
                "$comment": "This is the 'Model Input Object' properties.",
                "properties": {
                  "bands": {
                    "type": "array",
                    "minItems": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "AnyBandOutputRef": {
      "type": "object",
      "$comment": "This is the JSON-object 'properties' definition, which describes the STAC-Item field named 'properties'.",
      "properties": {
        "properties": {
          "type": "object",
          "required": [
            "mlm:output"
          ],
          "$comment": "This is the JSON-object 'properties' definition for the MLM output with bands listing referring to at least one band name.",
          "properties": {
            "mlm:output": {
              "type": "array",
              "$comment": "Below 'minItems' ensures that band check does not fail for explicitly empty 'mlm:output'.",
              "minItems": 1,
              "items": {
                "type": "object",
                "required": [
                  "bands"
                ],
                "$comment": "This is the 'Model Output Object' properties.",
                "properties": {
                  "bands": {
                    "type": "array",
                    "minItems": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "AnyBandsRef": {
      "$comment": "This definition ensures that, if at least 1 named MLM input or output '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.",
      "if": {
        "anyOf": [
          {"$ref": "#/$defs/AnyBandInputRef"},
          {"$ref": "#/$defs/AnyBandOutputRef"}
        ]
      },
      "then": {
        "$comment": "Need at least one 'bands' definition, but multiple are allowed.",
        "anyOf": [
          {
            "$comment": "Bands described by raster extension.",
            "allOf": [
              {
                "$ref": "#/$defs/stac_extensions_raster"
              },
              {
                "$ref": "#/$defs/stac_extensions_raster_bands_asset"
              }
            ]
          },
          {
            "$comment": "Bands described by eo extension.",
            "allOf": [
              {
                "$ref": "#/$defs/stac_extensions_eo"
              },
              {
                "anyOf": [
                  {
                    "$ref": "#/$defs/stac_extensions_eo_bands_item"
                  },
                  {
                    "$ref": "#/$defs/stac_extensions_eo_bands_asset"
                  }
                ]
              }
            ]
          },
          {
            "$comment": "Bands described by STAC Core 1.1.",
            "allOf": [
              {
                "$ref": "#/$defs/stac_version_1.1"
              },
              {
                "$comment": "This is the JSON-object 'properties' definition, which describes the STAC-Item field named 'properties'.",
                "properties": {
                  "properties": {
                    "required": [
                      "bands"
                    ],
                    "$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].",
                    "properties": {
                      "bands": {
                        "type": "array",
                        "minItems": 1,
                        "items": {
                          "type": "object"
                        }
                      }
                    }
                  }
                }
              }
            ]
          }
        ]
      },
      "else": {
        "$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."
      }
    },
    "AnyVariablesInputRef": {
      "type": "object",
      "$comment": "This is the JSON-object 'properties' definition, which describes the STAC-Item field named 'properties'.",
      "properties": {
        "properties": {
          "type": "object",
          "required": [
            "mlm:input"
          ],
          "$comment": "This is the JSON-object 'properties' definition for the MLM input with variables listing referring to at least one variable name.",
          "properties": {
            "mlm:input": {
              "type": "array",
              "$comment": "Below 'minItems' ensures that band check does not fail for explicitly empty 'mlm:input'.",
              "minItems": 1,
              "items": {
                "type": "object",
                "required": [
                  "variables"
                ],
                "$comment": "This is the 'Model Input Object' properties.",
                "properties": {
                  "variables": {
                    "type": "array",
                    "minItems": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "AnyVariablesOutputRef": {
      "type": "object",
      "$comment": "This is the JSON-object 'properties' definition, which describes the STAC-Item field named 'properties'.",
      "properties": {
        "properties": {
          "type": "object",
          "required": [
            "mlm:output"
          ],
          "$comment": "This is the JSON-object 'properties' definition for the MLM output with variables listing referring to at least one variable name.",
          "properties": {
            "mlm:output": {
              "type": "array",
              "$comment": "Below 'minItems' ensures that band check does not fail for explicitly empty 'mlm:output'.",
              "minItems": 1,
              "items": {
                "type": "object",
                "required": [
                  "variables"
                ],
                "$comment": "This is the 'Model Output Object' properties.",
                "properties": {
                  "variables": {
                    "type": "array",
                    "minItems": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "AnyVariablesRef": {
      "$comment": "This definition ensures that, if at least 1 named MLM input or output 'variables' is provided, at least 1 of the supported references from STAC datacube is provided as well. Otherwise, 'variables' must be explicitly empty.",
      "if": {
        "anyOf": [
          {"$ref": "#/$defs/AnyVariablesInputRef"},
          {"$ref": "#/$defs/AnyVariablesOutputRef"}
        ]
      },
      "then": {
        "$comment": "Need at least one 'variables' definition, but multiple are allowed (although for now, only 'datacube' is defined).",
        "anyOf": [
          {
            "$comment": "Variables described by datacube extension.",
            "allOf": [
              {
                "$ref": "#/$defs/stac_extensions_datacube_variables"
              },
              {
                "anyOf": [
                  {
                    "$ref": "#/$defs/stac_extensions_datacube_variables_item"
                  },
                  {
                    "$ref": "#/$defs/stac_extensions_datacube_variables_asset"
                  }
                ]
              }
            ]
          }
        ]
      },
      "else": {
        "$comment": "Case where no 'variables' (empty list) are referenced in the MLM input. Because models can use a mixture of inputs with/without variables, we cannot enforce their references to be omitted. If variables are provided in the 'mlm:model', it will simply be an odd case if none are used in any 'mlm:input' variables."
      }
    }
  }
}
