{
  "$defs": {
    "AdamW": {
      "properties": {
        "name": {
          "const": "adamw",
          "title": "Name",
          "type": "string"
        },
        "lr": {
          "description": "The learning rate to use for the optimizer.",
          "minimum": 0,
          "title": "Lr",
          "type": "number"
        }
      },
      "required": [
        "name",
        "lr"
      ],
      "title": "AdamW",
      "type": "object"
    },
    "AdditionalPostprocessor": {
      "discriminator": {
        "mapping": {
          "value_transform": "#/$defs/ValueTransformPostprocessor",
          "vectorize": "#/$defs/VectorizePostprocessor"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/VectorizePostprocessor"
        },
        {
          "$ref": "#/$defs/ValueTransformPostprocessor"
        }
      ]
    },
    "AnnotationSampler": {
      "discriminator": {
        "mapping": {
          "choose_n": "#/$defs/ChooseNSampler",
          "manual": "#/$defs/EscapeHatchComponent",
          "noop": "#/$defs/NoopSampler"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/NoopSampler"
        },
        {
          "$ref": "#/$defs/ChooseNSampler"
        },
        {
          "$ref": "#/$defs/EscapeHatchComponent"
        }
      ]
    },
    "AnnotationType": {
      "description": "Declares the expected type of training annotations. Currently represents only vector labels, but may grow to include raster.",
      "enum": [
        "point",
        "polygon"
      ],
      "title": "AnnotationType",
      "type": "string"
    },
    "Buffered": {
      "description": "Window is produced by expanding the annotation geometry bounds by a fixed buffer on each side.\n\nPoint geometries: (2*buffer + 1) \u00d7 (2*buffer + 1) window.\nPolygon geometries: (bbox_width + 2*buffer) \u00d7 (bbox_height + 2*buffer) window.\n\nLabel layer is filled with `nodata_value` in the raster label case.\n\nExample: buffer = 3, point annotation at \u00d7\n\n    \u2190\u2500 3 \u2500\u2192      \u2190\u2500 3 \u2500\u2192\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 \u2191\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 3\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 \u2193\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u00d7\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 \u2191\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 3\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 \u2193\n    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n    Window = 7 \u00d7 7  (2*3 + 1)\n\nExample: buffer = 3, polygon annotation (20 \u00d7 10 bbox)\n\n    \u2190\u2500 3 \u2500\u2192               \u2190\u2500 3 \u2500\u2192\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 \u2191\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 3\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 \u2193\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2502  polygon    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2502    bbox     \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 \u2191\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 3\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 \u2193\n    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n    Window = 26 \u00d7 16  (20+2*3) \u00d7 (10+2*3)\n    \u2591\u2591\u2591\u2591\u2591 = buffer region (nodata in raster labels)",
      "properties": {
        "name": {
          "const": "buffered",
          "title": "Name",
          "type": "string"
        },
        "buffer": {
          "description": "Buffer in pixels to add on each side of the annotation bounds.",
          "exclusiveMinimum": 0,
          "title": "Buffer",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "buffer"
      ],
      "title": "Buffered",
      "type": "object"
    },
    "CRSProjection": {
      "properties": {
        "method": {
          "const": "crs",
          "title": "Method",
          "type": "string"
        },
        "crs": {
          "description": "The CRS code of the output projection.",
          "title": "Crs",
          "type": "string"
        },
        "x_resolution": {
          "description": "The x resolution of the output projection, in projection units.",
          "exclusiveMinimum": 0,
          "title": "X Resolution",
          "type": "number"
        },
        "y_resolution": {
          "description": "The y resolution of the output projection, in projection units.",
          "exclusiveMaximum": 0,
          "title": "Y Resolution",
          "type": "number"
        }
      },
      "required": [
        "method",
        "crs",
        "x_resolution",
        "y_resolution"
      ],
      "title": "CRSProjection",
      "type": "object"
    },
    "CenterCropStrategy": {
      "description": "Crop to the largest centered rectangle that fits whole cells.\n\nExample: 120\u00d7120 pixel region with 50\u00d750 pixel cells\n\n120 \u00f7 50 = 2 whole cells + 20px remainder\nRemainder split equally: 10px margin on each side\n\n        10px    50px      50px    10px\n        \u250c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2510\n   10px \u2502\u2591\u2591\u2591\u2591\u2591\u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\u2591\u2591\u2591\u2591\u2591\u2502\n        \u251c\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2524\n        \u2502\u2591\u2591\u2591\u2591\u2591\u2502          \u2502          \u2502\u2591\u2591\u2591\u2591\u2591\u2502\n   50px \u2502\u2591\u2591\u2591\u2591\u2591\u2502  Cell 1  \u2502  Cell 2  \u2502\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502\u2591\u2591\u2591\u2591\u2591\u2502          \u2502          \u2502\u2591\u2591\u2591\u2591\u2591\u2502\n        \u251c\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2524\n        \u2502\u2591\u2591\u2591\u2591\u2591\u2502          \u2502          \u2502\u2591\u2591\u2591\u2591\u2591\u2502\n   50px \u2502\u2591\u2591\u2591\u2591\u2591\u2502  Cell 3  \u2502  Cell 4  \u2502\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502\u2591\u2591\u2591\u2591\u2591\u2502          \u2502          \u2502\u2591\u2591\u2591\u2591\u2591\u2502\n        \u251c\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2524\n   10px \u2502\u2591\u2591\u2591\u2591\u2591\u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2518\n\n        \u2591\u2591\u2591\u2591\u2591 = NODATA (not included in any cell)\n\nResult: 4 cells (2\u00d72), each with complete valid data\n        Outer 10px border becomes nodata\n\nWhen the region is smaller than one cell, a single cell is produced\ncentered on the region, with padding on all sides (nodata fills\nnaturally). This avoids dropping small tasks entirely.",
      "properties": {
        "name": {
          "const": "center_crop",
          "title": "Name",
          "type": "string"
        },
        "grid_size": {
          "description": "Side length of each square grid cell in pixels.",
          "exclusiveMinimum": 0,
          "title": "Grid Size",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "grid_size"
      ],
      "title": "CenterCropStrategy",
      "type": "object"
    },
    "ChooseNSampler": {
      "description": "Sampler that chooses a random subset of annotation tasks.",
      "properties": {
        "name": {
          "const": "choose_n",
          "title": "Name",
          "type": "string"
        },
        "n": {
          "description": "The number of samples to take",
          "minimum": 0,
          "title": "N",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "n"
      ],
      "title": "ChooseNSampler",
      "type": "object"
    },
    "ClassValue": {
      "description": "A class value for vector classification, with an integer class index.",
      "properties": {
        "value": {
          "description": "The integer class index (used as the value in GeoJSON label properties)",
          "minimum": 0,
          "title": "Value",
          "type": "integer"
        },
        "label": {
          "description": "The human-readable class name",
          "title": "Label",
          "type": "string"
        },
        "color": {
          "anyOf": [
            {
              "maxItems": 3,
              "minItems": 3,
              "prefixItems": [
                {
                  "maximum": 255,
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "maximum": 255,
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "maximum": 255,
                  "minimum": 0,
                  "type": "integer"
                }
              ],
              "type": "array"
            },
            {
              "maxItems": 4,
              "minItems": 4,
              "prefixItems": [
                {
                  "maximum": 255,
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "maximum": 255,
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "maximum": 255,
                  "minimum": 0,
                  "type": "integer"
                },
                {
                  "maximum": 255,
                  "minimum": 0,
                  "type": "integer"
                }
              ],
              "type": "array"
            }
          ],
          "description": "The RGB(A) color for this value",
          "title": "Color"
        }
      },
      "required": [
        "value",
        "label",
        "color"
      ],
      "title": "ClassValue",
      "type": "object"
    },
    "ClassificationDecoder": {
      "discriminator": {
        "mapping": {
          "pooling": "#/$defs/PoolingClassificationDecoder"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/PoolingClassificationDecoder"
        }
      ]
    },
    "ClassificationField": {
      "description": "A field that represents vector-level classification",
      "properties": {
        "field_type": {
          "const": "classification",
          "title": "Field Type",
          "type": "string"
        },
        "allowed_values": {
          "items": {
            "$ref": "#/$defs/ClassValue"
          },
          "minItems": 2,
          "title": "Allowed Values",
          "type": "array"
        }
      },
      "required": [
        "field_type",
        "allowed_values"
      ],
      "title": "ClassificationField",
      "type": "object"
    },
    "ClassificationTask": {
      "properties": {
        "name": {
          "const": "classification",
          "title": "Name",
          "type": "string"
        },
        "decoder": {
          "$ref": "#/$defs/ClassificationDecoder"
        }
      },
      "required": [
        "name",
        "decoder"
      ],
      "title": "ClassificationTask",
      "type": "object"
    },
    "ComponentConfig": {
      "description": "A reference to an arbitrary class to be initialized: class_path + optional init_args.",
      "properties": {
        "class_path": {
          "title": "Class Path",
          "type": "string"
        },
        "init_args": {
          "anyOf": [
            {
              "additionalProperties": true,
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Init Args"
        }
      },
      "required": [
        "class_path"
      ],
      "title": "ComponentConfig",
      "type": "object"
    },
    "Data": {
      "description": "Input/output data specification for an OlmoEarth model.\n\nDescribes the temporal strategy, remote-sensing modalities, and output\nschema that a model expects.  Corresponds to the top-level ``data`` key\nin an olmoearth_config YAML file.",
      "properties": {
        "temporality": {
          "$ref": "#/$defs/Temporality"
        },
        "modalities": {
          "$ref": "#/$defs/Modalities"
        },
        "output": {
          "anyOf": [
            {
              "$ref": "#/$defs/Output"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "required": [
        "temporality",
        "modalities",
        "output"
      ],
      "title": "Data",
      "type": "object"
    },
    "DataSplitter": {
      "discriminator": {
        "mapping": {
          "field": "#/$defs/FieldDataSplitter",
          "manual": "#/$defs/EscapeHatchComponent",
          "random": "#/$defs/RandomDataSplitter",
          "spatial": "#/$defs/SpatialDataSplitter"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/RandomDataSplitter"
        },
        {
          "$ref": "#/$defs/SpatialDataSplitter"
        },
        {
          "$ref": "#/$defs/FieldDataSplitter"
        },
        {
          "$ref": "#/$defs/EscapeHatchComponent"
        }
      ]
    },
    "DefaultInputPreprocessing": {
      "description": "Controls how windows are processed before being provided to the model.\n\nThis class applies default rules to all training-time splits (train/val/test),\nas well as the `predict` preprocessor at inference time. Most values can be\noverriden by the non-default preprocessors.\n\n\nCONCEPTUAL OVERVIEW:\n\nRaw windows are not passed directly into the model during forward passes.\nThey are first cropped or tiled into \"inputs\", which may subsequently be\ntransformed by one or more transformation functions, serially. Each \"input\"\nis treated as an independent item in a batch to the model.\n\nA config author can define `input_size` to specify the edge length of each square crop,\nas well as `input_mode`, which determines whether the model will see a single random\ncrop or the full grid of cropped inputs. Desired behavior here is variable based on\nthe model, the data split, and whether we are performing fine-tuning or inference.\n\nThe size of the windows being provided to preprocessors is determined as follows:\n\n* training time: `labeled_data_prep.window_preparer`\n* inference time: `prediction_requests.partitioners`\n\nSCENARIOS:\n\n    Window size == input_size\n    \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n        input_mode has no practical effect \u2014 one input either way.\n\n        window\n        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n        \u2502          \u2502\n        \u2502  input   \u2502  input_size \u00d7 input_size\n        \u2502 (=window)\u2502\n        \u2502          \u2502\n        \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n\n    Window size > input_size\n    \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n        input_mode: all_tiles             input_mode: single_random_crop\n        \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500             \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n        Tile the full window with         Take ONE random input from\n        a grid of inputs (complete        the window (used during\n        spatial coverage).                training for augmentation\n                                          via random positioning).\n\n        window                            window\n        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510     \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n        \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510   \u2502     \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502 \u2502          \u2502          \u2502   \u2502     \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502 \u2502 input 1  \u2502 input 2  \u2502   \u2502     \u2502\u2591\u2591\u2591\u2591\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502 \u2502          \u2502          \u2502   \u2502     \u2502\u2591\u2591\u2591\u2591\u2502          \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524   \u2502     \u2502\u2591\u2591\u2591\u2591\u2502  random  \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502 \u2502          \u2502          \u2502   \u2502     \u2502\u2591\u2591\u2591\u2591\u2502  input   \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502 \u2502 input 3  \u2502 input 4  \u2502   \u2502     \u2502\u2591\u2591\u2591\u2591\u2502          \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502 \u2502          \u2502          \u2502   \u2502     \u2502\u2591\u2591\u2591\u2591\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518   \u2502     \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n        \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518     \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n        Each input is input_size          Input is input_size \u00d7 input_size\n        \u00d7 input_size. Edge inputs         at a random position.\n        may overlap at predict time       \u2591 = window pixels not seen\n        (see PredictInputPreprocessing    by the model in this pass.\n        .overlap_pixels).\n\n\n    Window size < input_size\n    \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n        INVALID \u2014 raises an error at runtime. The window must be at\n        least as large as input_size.\n\n\nNOTE:\n\n`input_mode` is inherited by the val and test splits (unless overridden per-split), however:\n* `train` always uses `single_random_crop`\n* `predict` always tiles",
      "properties": {
        "input_size": {
          "description": "Side length of the square input fed to the model.",
          "minimum": 1,
          "title": "Input Size",
          "type": "integer"
        },
        "input_mode": {
          "$ref": "#/$defs/InputMode",
          "description": "How windows are converted to model inputs. all_tiles: tile the full window with a grid of inputs (complete spatial coverage). single_random_crop: take one random input from the window (training augmentation via random positioning). Inherited by val/test splits unless overridden per-split. Train always uses single_random_crop regardless of this setting. Predict always tiles regardless of this setting."
        },
        "transforms": {
          "description": "The transforms to apply to the input tensors before they are provided to the model.",
          "items": {
            "$ref": "#/$defs/Transform"
          },
          "title": "Transforms",
          "type": "array"
        }
      },
      "required": [
        "input_size",
        "input_mode"
      ],
      "title": "DefaultInputPreprocessing",
      "type": "object"
    },
    "DetectionDecoder": {
      "discriminator": {
        "mapping": {
          "faster_rcnn": "#/$defs/FasterRCNNDetectionDecoder"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/FasterRCNNDetectionDecoder"
        }
      ]
    },
    "DetectionField": {
      "description": "A field that represents the classes for detected objects.",
      "properties": {
        "field_type": {
          "const": "detection",
          "title": "Field Type",
          "type": "string"
        },
        "detectable_object_classes": {
          "items": {
            "$ref": "#/$defs/ClassValue"
          },
          "title": "Detectable Object Classes",
          "type": "array"
        }
      },
      "required": [
        "field_type",
        "detectable_object_classes"
      ],
      "title": "DetectionField",
      "type": "object"
    },
    "DetectionTask": {
      "properties": {
        "name": {
          "const": "detection",
          "title": "Name",
          "type": "string"
        },
        "decoder": {
          "$ref": "#/$defs/DetectionDecoder"
        },
        "box_side_length": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When set, each annotation's geometry is replaced by a fixed box of this side length (in pixels) centered on the geometry's centroid, and that box becomes the training label. When unset, the geometry's native bounding box is used. Required for point annotations (which have degenerate bounding boxes); optional for polygons. Must be less than input_size.",
          "title": "Box Side Length"
        }
      },
      "required": [
        "name",
        "decoder"
      ],
      "title": "DetectionTask",
      "type": "object"
    },
    "EarlyStopping": {
      "description": "Controls early-stopping behavior during supervised fine tuning.\n\nMonitors a validation metric and stops training after `patience` epochs\nwithout improvement. When monitoring begins depends on the encoder strategy:\nimmediately for layer-wise LR decay, or after the encoder unfreeze epoch\nfor freeze/unfreeze.",
      "properties": {
        "patience": {
          "description": "Epochs without improvement before stopping.",
          "minimum": 1,
          "title": "Patience",
          "type": "integer"
        }
      },
      "required": [
        "patience"
      ],
      "title": "EarlyStopping",
      "type": "object"
    },
    "EmbeddingOutput": {
      "description": "Embedding output.\n\nEmbeddings are always power-quantized to int8 (4x compression); the runner\nadds that value transform automatically. There is nothing to configure.",
      "properties": {
        "data_type": {
          "const": "embeddings",
          "title": "Data Type",
          "type": "string"
        },
        "max_pixels_per_dimension": {
          "default": 10000,
          "description": "Maximum pixels per dimension when combining embedding tiles into the output GeoTIFF. Caps output resolution.",
          "exclusiveMinimum": 0,
          "title": "Max Pixels Per Dimension",
          "type": "integer"
        }
      },
      "required": [
        "data_type"
      ],
      "title": "EmbeddingOutput",
      "type": "object"
    },
    "EmbeddingTask": {
      "description": "Prediction-only task that produces encoder embeddings directly.\n\nNo decoder or training configuration -- the encoder's feature map\nis saved as the output via EmbeddingHead.",
      "properties": {
        "name": {
          "const": "embedding",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "EmbeddingTask",
      "type": "object"
    },
    "Encoder": {
      "discriminator": {
        "mapping": {
          "olmoearth": "#/$defs/OlmoEarthEncoder"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/OlmoEarthEncoder"
        }
      ]
    },
    "EncoderFreezing": {
      "description": "Freeze encoder weights for a number of epochs, then unfreeze at a reduced learning rate.",
      "properties": {
        "name": {
          "const": "freeze_unfreeze",
          "default": "freeze_unfreeze",
          "title": "Name",
          "type": "string"
        },
        "unfreeze_at_epoch": {
          "description": "The epoch at which weights in the encoder can be updated by the optimizer.",
          "minimum": 0,
          "title": "Unfreeze At Epoch",
          "type": "integer"
        },
        "unfreeze_lr_factor": {
          "description": "The factor by which the learning rate is multiplied when the encoder is unfrozen.",
          "minimum": 0,
          "title": "Unfreeze Lr Factor",
          "type": "number"
        }
      },
      "required": [
        "unfreeze_at_epoch",
        "unfreeze_lr_factor"
      ],
      "title": "EncoderFreezing",
      "type": "object"
    },
    "EncoderTrainingStrategy": {
      "discriminator": {
        "mapping": {
          "freeze_unfreeze": "#/$defs/EncoderFreezing",
          "layer_wise_lr_decay": "#/$defs/LayerWiseLRDecay"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/EncoderFreezing"
        },
        {
          "$ref": "#/$defs/LayerWiseLRDecay"
        }
      ]
    },
    "EscapeHatchComponent": {
      "description": "ComponentConfig with a 'manual' discriminator for use in typed unions.",
      "properties": {
        "class_path": {
          "title": "Class Path",
          "type": "string"
        },
        "init_args": {
          "anyOf": [
            {
              "additionalProperties": true,
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Init Args"
        },
        "name": {
          "const": "manual",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "class_path",
        "name"
      ],
      "title": "EscapeHatchComponent",
      "type": "object"
    },
    "FasterRCNNDetectionDecoder": {
      "description": "A decoder that uses a Faster R-CNN architecture to perform detection + classification.",
      "properties": {
        "name": {
          "const": "faster_rcnn",
          "title": "Name",
          "type": "string"
        },
        "anchor_sizes": {
          "description": "Anchor box sizes in input image pixels for the Region Proposal Network. Each inner list corresponds to one encoder feature map level. OlmoEarth produces a single feature map, so use one inner list, e.g. [[32]]. Set values to roughly match the expected pixel size of detectable objects.",
          "items": {
            "items": {
              "type": "integer"
            },
            "type": "array"
          },
          "title": "Anchor Sizes",
          "type": "array"
        }
      },
      "required": [
        "name",
        "anchor_sizes"
      ],
      "title": "FasterRCNNDetectionDecoder",
      "type": "object"
    },
    "FieldDataSplitter": {
      "description": "Data splitter that reads pre-assigned splits from each annotation's oe_split field.",
      "properties": {
        "name": {
          "const": "field",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "FieldDataSplitter",
      "type": "object"
    },
    "FixedSize": {
      "description": "User-specified explicit window size in pixels.\n\nSupplied geometries will be centered within a square window of this size.\nNo checking for geometry clipping is performed.\n\nExample: size = 128, point annotation at \u00d7\n\n    \u2190\u2500\u2500\u2500\u2500\u2500 128 px \u2500\u2500\u2500\u2500\u2500\u2192\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u2191\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u00d7\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 128 px\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2193\n\nExample: size = 128, polygon annotation\n\n    \u2190\u2500\u2500\u2500\u2500\u2500 128 px \u2500\u2500\u2500\u2500\u2500\u2192\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u2191\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u250c\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2510\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2506  polygon   \u2506\u2591\u2591\u2591\u2502 128 px\n    \u2502\u2591\u2591\u2591\u2506 (centered) \u2506\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2514\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2518\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2193",
      "properties": {
        "name": {
          "const": "fixed_size",
          "title": "Name",
          "type": "string"
        },
        "size": {
          "description": "Side length of each square window in pixels.",
          "exclusiveMinimum": 0,
          "title": "Size",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "size"
      ],
      "title": "FixedSize",
      "type": "object"
    },
    "FixedWindowPartitioner": {
      "description": "Partitioner that creates fixed-size square windows.\n\nWindow size is determined by the window_sizing strategy. Defaults to\nMatchInputSize, which uses input_preprocessing.default.input_size.",
      "properties": {
        "name": {
          "const": "fixed_window",
          "title": "Name",
          "type": "string"
        },
        "window_sizing": {
          "$ref": "#/$defs/PartitionWindowSizing",
          "default": {
            "name": "match_input_size"
          },
          "description": "Strategy for determining the window size."
        }
      },
      "required": [
        "name"
      ],
      "title": "FixedWindowPartitioner",
      "type": "object"
    },
    "FramedPointInTimeTemporality": {
      "description": "Represents a specific instant we're making a prediction for, with context from before and/or after.\nOptional offsets allow gaps between the prediction point and observation windows.",
      "properties": {
        "name": {
          "const": "framed_point_in_time",
          "title": "Name",
          "type": "string"
        },
        "lookbehind_observation": {
          "anyOf": [
            {
              "$ref": "#/$defs/ObservationStrategy"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Observation window preceding the prediction point."
        },
        "lookbehind_offset_days": {
          "anyOf": [
            {
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Gap between end of lookbehind window and prediction point.",
          "title": "Lookbehind Offset Days"
        },
        "lookahead_observation": {
          "anyOf": [
            {
              "$ref": "#/$defs/ObservationStrategy"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Observation window following the prediction point."
        },
        "lookahead_offset_days": {
          "anyOf": [
            {
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Gap between prediction point and start of lookahead window.",
          "title": "Lookahead Offset Days"
        }
      },
      "required": [
        "name"
      ],
      "title": "FramedPointInTimeTemporality",
      "type": "object"
    },
    "GridPartitioner": {
      "description": "Partitioner that uses a grid to partition the input data.",
      "properties": {
        "name": {
          "const": "grid",
          "title": "Name",
          "type": "string"
        },
        "grid_size": {
          "description": "The size of the grid cells in units of the output projection.",
          "exclusiveMinimum": 0,
          "title": "Grid Size",
          "type": "number"
        },
        "overlap_size": {
          "default": 0,
          "description": "The size of the overlap between adjacent grid cells in units of the output projection.",
          "minimum": 0,
          "title": "Overlap Size",
          "type": "number"
        },
        "projection": {
          "anyOf": [
            {
              "$ref": "#/$defs/Projection"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Projection strategy to use for output geometries. If not provided, no re-projection will take place."
        }
      },
      "required": [
        "name",
        "grid_size"
      ],
      "title": "GridPartitioner",
      "type": "object"
    },
    "GriddingStrategy": {
      "discriminator": {
        "mapping": {
          "center_crop": "#/$defs/CenterCropStrategy",
          "pad_to_fill": "#/$defs/PadToFillStrategy"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/CenterCropStrategy"
        },
        {
          "$ref": "#/$defs/PadToFillStrategy"
        }
      ]
    },
    "InputMode": {
      "enum": [
        "single_random_crop",
        "all_tiles"
      ],
      "title": "InputMode",
      "type": "string"
    },
    "InputPreprocessing": {
      "description": "Defines how input tensors are prepared before being provided to the model.\nEach training dataset split (train, val, test) can have its own preprocessing configuration,\nas can input data at inference (\"predict\") time.\nAll take their base configuration from \"default\", which can be overridden for each group.",
      "properties": {
        "default": {
          "$ref": "#/$defs/DefaultInputPreprocessing",
          "description": "Default input preprocessing configuration"
        },
        "train": {
          "anyOf": [
            {
              "$ref": "#/$defs/TrainInputPreprocessing"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "val": {
          "anyOf": [
            {
              "$ref": "#/$defs/ValTestSplitInputPreprocessing"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "test": {
          "anyOf": [
            {
              "$ref": "#/$defs/ValTestSplitInputPreprocessing"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "predict": {
          "anyOf": [
            {
              "$ref": "#/$defs/PredictInputPreprocessing"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        }
      },
      "required": [
        "default"
      ],
      "title": "InputPreprocessing",
      "type": "object"
    },
    "LabeledDataPrep": {
      "description": "Controls the preparation of labeled data for training.",
      "properties": {
        "annotation_type": {
          "$ref": "#/$defs/AnnotationType"
        },
        "sampler": {
          "$ref": "#/$defs/AnnotationSampler",
          "description": "Controls the sampling of annotated data for training."
        },
        "window_preparer": {
          "$ref": "#/$defs/WindowPreparer",
          "description": "Controls the preparation of annotated spatiotemporal geometries into labeled rslearn windows."
        },
        "data_splitter": {
          "$ref": "#/$defs/DataSplitter",
          "description": "Controls the splitting of labeled data into training, validation, and test sets."
        }
      },
      "required": [
        "annotation_type",
        "sampler",
        "window_preparer",
        "data_splitter"
      ],
      "title": "LabeledDataPrep",
      "type": "object"
    },
    "Landsat89C2L1": {
      "description": "Landsat 8/9 Collection 2 Level-1 imagery modality.",
      "properties": {
        "sort_by": {
          "$ref": "#/$defs/Landsat89C2L1SortBy",
          "default": "cloud_cover",
          "description": "The field to sort the data by."
        },
        "space_mode": {
          "$ref": "#/$defs/SpaceMode"
        }
      },
      "required": [
        "space_mode"
      ],
      "title": "Landsat89C2L1",
      "type": "object"
    },
    "Landsat89C2L1SortBy": {
      "enum": [
        "cloud_cover"
      ],
      "title": "Landsat89C2L1SortBy",
      "type": "string"
    },
    "LayerWiseLRDecay": {
      "description": "Apply per-layer learning rate decay to the encoder from the start of training.\n\nEach encoder layer receives a learning rate scaled by decay_factor relative to\nthe next layer. The configured optimizer learning rate applies to the decoder\n(last layer). Layer i gets: lr * decay_factor^(num_layers - i).",
      "properties": {
        "name": {
          "const": "layer_wise_lr_decay",
          "title": "Name",
          "type": "string"
        },
        "decay_factor": {
          "description": "Multiplicative factor applied per layer. Layer i LR = base_lr * decay_factor^(num_layers - i).",
          "exclusiveMinimum": 0,
          "maximum": 1,
          "title": "Decay Factor",
          "type": "number"
        },
        "num_layers": {
          "description": "Number of encoder layers. Must match the foundation model metadata (e.g. 4 for Nano, 12 for Tiny/Base).",
          "minimum": 1,
          "title": "Num Layers",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "decay_factor",
        "num_layers"
      ],
      "title": "LayerWiseLRDecay",
      "type": "object"
    },
    "LinearValueTransformConfig": {
      "description": "Linear transform: output = scale * input + offset.",
      "properties": {
        "type": {
          "const": "linear",
          "default": "linear",
          "title": "Type",
          "type": "string"
        },
        "scale": {
          "default": 1.0,
          "title": "Scale",
          "type": "number"
        },
        "offset": {
          "default": 0.0,
          "title": "Offset",
          "type": "number"
        },
        "output_dtype": {
          "anyOf": [
            {
              "enum": [
                "uint8",
                "int16",
                "int32",
                "float32"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The output dtype to transform to. If not specified, the output dtype will be the same as the input dtype.",
          "title": "Output Dtype"
        }
      },
      "title": "LinearValueTransformConfig",
      "type": "object"
    },
    "ManualTask": {
      "description": "Escape hatch task providing raw rslearn decoder_layers and task config.",
      "properties": {
        "name": {
          "const": "manual",
          "title": "Name",
          "type": "string"
        },
        "decoder_layers": {
          "items": {
            "$ref": "#/$defs/ComponentConfig"
          },
          "title": "Decoder Layers",
          "type": "array"
        },
        "task": {
          "$ref": "#/$defs/ComponentConfig"
        }
      },
      "required": [
        "name",
        "decoder_layers",
        "task"
      ],
      "title": "ManualTask",
      "type": "object"
    },
    "MatchInputSize": {
      "description": "Window size equals `input_preprocessing.default.input_size` (or split override).\n\nNatural choice for vector classification/regression where the window IS the model input.\n\nExample: input_size = 64, point annotation at \u00d7\n\n    \u2190\u2500\u2500\u2500\u2500 64 px \u2500\u2500\u2500\u2500\u2192\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u2191\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u00d7\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502 64 px\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2193\n\nExample: input_size = 64, polygon annotation\n\n    \u2190\u2500\u2500\u2500\u2500 64 px \u2500\u2500\u2500\u2500\u2192\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u2191\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2502\u2591\u2591\u250c\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2510\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2506 polygon  \u2506\u2591\u2591\u2502 64 px\n    \u2502\u2591\u2591\u2506(centered)\u2506\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2514\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2504\u2518\u2591\u2591\u2502\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\n    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2193\n\nNo checking for geometry clipping is performed.",
      "properties": {
        "name": {
          "const": "match_input_size",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "MatchInputSize",
      "type": "object"
    },
    "Modalities": {
      "properties": {
        "sentinel2_l2a": {
          "anyOf": [
            {
              "$ref": "#/$defs/Sentinel2L2A"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "sentinel1_rtc": {
          "anyOf": [
            {
              "$ref": "#/$defs/Sentinel1RTC"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "landsat_8_9_c2_l1": {
          "anyOf": [
            {
              "$ref": "#/$defs/Landsat89C2L1"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        }
      },
      "title": "Modalities",
      "type": "object"
    },
    "Model": {
      "properties": {
        "encoder": {
          "$ref": "#/$defs/Encoder",
          "description": "The encoder to use for the model. This produces embeddings from preprocessed modality data for use as input to task heads."
        },
        "tasks": {
          "additionalProperties": {
            "$ref": "#/$defs/ModelTask"
          },
          "description": "The tasks to perform with the embeddings produced by the encoder layer. Each task will produce predictions for the original inputs.",
          "title": "Tasks",
          "type": "object"
        }
      },
      "required": [
        "encoder",
        "tasks"
      ],
      "title": "Model",
      "type": "object"
    },
    "ModelTask": {
      "discriminator": {
        "mapping": {
          "classification": "#/$defs/ClassificationTask",
          "detection": "#/$defs/DetectionTask",
          "embedding": "#/$defs/EmbeddingTask",
          "manual": "#/$defs/ManualTask",
          "per_pixel_regression": "#/$defs/PerPixelRegressionTask",
          "regression": "#/$defs/RegressionTask",
          "segmentation": "#/$defs/SegmentationTask"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/SegmentationTask"
        },
        {
          "$ref": "#/$defs/PerPixelRegressionTask"
        },
        {
          "$ref": "#/$defs/ClassificationTask"
        },
        {
          "$ref": "#/$defs/RegressionTask"
        },
        {
          "$ref": "#/$defs/DetectionTask"
        },
        {
          "$ref": "#/$defs/EmbeddingTask"
        },
        {
          "$ref": "#/$defs/ManualTask"
        }
      ]
    },
    "Month": {
      "enum": [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December"
      ],
      "title": "Month",
      "type": "string"
    },
    "NoopPartitioner": {
      "description": "Partitioner that does nothing.",
      "properties": {
        "name": {
          "const": "noop",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "NoopPartitioner",
      "type": "object"
    },
    "NoopSampler": {
      "description": "No-op sampler that returns the full dataset.",
      "properties": {
        "name": {
          "const": "noop",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "NoopSampler",
      "type": "object"
    },
    "ObservationStrategy": {
      "discriminator": {
        "mapping": {
          "repeating_interval": "#/$defs/RepeatingIntervalObservation",
          "sampled": "#/$defs/SampledObservation"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/SampledObservation"
        },
        {
          "$ref": "#/$defs/RepeatingIntervalObservation"
        }
      ]
    },
    "OlmoEarthEncoder": {
      "description": "OlmoEarth encoder configuration.",
      "properties": {
        "name": {
          "const": "olmoearth",
          "title": "Name",
          "type": "string"
        },
        "patch_size": {
          "description": "The size of the patch to use for the model",
          "maximum": 8,
          "minimum": 1,
          "title": "Patch Size",
          "type": "integer"
        },
        "source": {
          "$ref": "#/$defs/OlmoEarthSource",
          "description": "Where to load the OlmoEarth encoder from"
        }
      },
      "required": [
        "name",
        "patch_size",
        "source"
      ],
      "title": "OlmoEarthEncoder",
      "type": "object"
    },
    "OlmoEarthFromDistributedCheckpoint": {
      "description": "OlmoEarth encoder loaded from distributed checkpoint files + config. For in-flight pretraining checkpoints.\nNote: the embedding size must be explicitly provided, as we have no catalog or metadata to consult.",
      "properties": {
        "name": {
          "const": "distributed_checkpoint",
          "title": "Name",
          "type": "string"
        },
        "checkpoint_path": {
          "description": "The path to the distributed checkpoint files + config to use",
          "title": "Checkpoint Path",
          "type": "string"
        },
        "embedding_size": {
          "description": "The number of dimensions in the embeddings the encoder produces.",
          "title": "Embedding Size",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "checkpoint_path",
        "embedding_size"
      ],
      "title": "OlmoEarthFromDistributedCheckpoint",
      "type": "object"
    },
    "OlmoEarthFromHuggingFace": {
      "description": "OlmoEarth encoder loaded from HuggingFace model ID.",
      "properties": {
        "name": {
          "const": "huggingface",
          "title": "Name",
          "type": "string"
        },
        "model_id": {
          "description": "The ID of the model to use (sourced from HF)",
          "title": "Model Id",
          "type": "string"
        }
      },
      "required": [
        "name",
        "model_id"
      ],
      "title": "OlmoEarthFromHuggingFace",
      "type": "object"
    },
    "OlmoEarthFromModelPath": {
      "description": "OlmoEarth encoder loaded from a model checkpoint + config path. For unpublished models.\nNote: the embedding size must be explicitly provided, as we have no catalog or metadata to consult.",
      "properties": {
        "name": {
          "const": "model_path",
          "title": "Name",
          "type": "string"
        },
        "model_path": {
          "description": "The path to the model checkpoint + config to use",
          "title": "Model Path",
          "type": "string"
        },
        "embedding_size": {
          "description": "The number of dimensions in the embeddings the encoder produces.",
          "title": "Embedding Size",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "model_path",
        "embedding_size"
      ],
      "title": "OlmoEarthFromModelPath",
      "type": "object"
    },
    "OlmoEarthFromRegistry": {
      "description": "OlmoEarth encoder loaded from OlmoEarth's foundation model registry.",
      "properties": {
        "name": {
          "const": "registry",
          "title": "Name",
          "type": "string"
        },
        "model_name": {
          "description": "The name of the foundation model to use from OlmoEarth's registry",
          "title": "Model Name",
          "type": "string"
        },
        "embedding_size": {
          "description": "The number of dimensions in the embeddings the encoder produces.",
          "title": "Embedding Size",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "model_name",
        "embedding_size"
      ],
      "title": "OlmoEarthFromRegistry",
      "type": "object"
    },
    "OlmoEarthNormalize": {
      "properties": {
        "name": {
          "const": "olmoearth_normalize",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "OlmoEarthNormalize",
      "type": "object"
    },
    "OlmoEarthSource": {
      "discriminator": {
        "mapping": {
          "distributed_checkpoint": "#/$defs/OlmoEarthFromDistributedCheckpoint",
          "huggingface": "#/$defs/OlmoEarthFromHuggingFace",
          "model_path": "#/$defs/OlmoEarthFromModelPath",
          "registry": "#/$defs/OlmoEarthFromRegistry"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/OlmoEarthFromHuggingFace"
        },
        {
          "$ref": "#/$defs/OlmoEarthFromRegistry"
        },
        {
          "$ref": "#/$defs/OlmoEarthFromModelPath"
        },
        {
          "$ref": "#/$defs/OlmoEarthFromDistributedCheckpoint"
        }
      ]
    },
    "Optimizer": {
      "discriminator": {
        "mapping": {
          "adamw": "#/$defs/AdamW",
          "manual": "#/$defs/EscapeHatchComponent"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/AdamW"
        },
        {
          "$ref": "#/$defs/EscapeHatchComponent"
        }
      ]
    },
    "Output": {
      "discriminator": {
        "mapping": {
          "embeddings": "#/$defs/EmbeddingOutput",
          "raster": "#/$defs/RasterOutput",
          "vector": "#/$defs/VectorOutput"
        },
        "propertyName": "data_type"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/RasterOutput"
        },
        {
          "$ref": "#/$defs/VectorOutput"
        },
        {
          "$ref": "#/$defs/EmbeddingOutput"
        }
      ]
    },
    "PadToFillStrategy": {
      "description": "Extend edge cells beyond task bounds (nodata fills naturally).\n\nExample: 120\u00d7120 pixel region with 50\u00d750 pixel cells\n\nceil(120 \u00f7 50) = 3 cells needed per dimension\nGrid extends 30px beyond raster on right and bottom\n\n     \u2190\u2500 50px \u2500\u2192\u2190\u2500 50px \u2500\u2192\u2190\u2500 50px \u2500\u2192\n                         \u219020\u2192\u2190\u250030\u2500\u2192\n                        valid nodata\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2510  \u2191\n    \u2502          \u2502          \u2502    \u2502\u2591\u2591\u2591\u2591\u2591\u2502  \u2502\n    \u2502  Cell 1  \u2502  Cell 2  \u2502    \u2502\u2591\u25913\u2591\u2591\u2502 50px\n    \u2502          \u2502          \u2502    \u2502\u2591\u2591\u2591\u2591\u2591\u2502  \u2502\n    \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2524  \u2193\n    \u2502          \u2502          \u2502    \u2502\u2591\u2591\u2591\u2591\u2591\u2502  \u2191\n    \u2502  Cell 4  \u2502  Cell 5  \u2502    \u2502\u2591\u25916\u2591\u2591\u2502 50px\n    \u2502          \u2502          \u2502    \u2502\u2591\u2591\u2591\u2591\u2591\u2502  \u2502\n    \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2524  \u2193  \u2191 20px valid\n    \u2502  Cell 7  \u2502  Cell 8  \u2502    \u2502\u2591\u25919\u2591\u2591\u2502     \u2193\n    \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2524     \u2191 30px nodata\n    \u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2502\u2591\u2591\u2591\u2591\u2502\u2591\u2591\u2591\u2591\u2591\u2502     \u2193\n    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2518\n\n    \u2591\u2591\u2591\u2591\u2591 = NODATA\n\nCells 1, 2, 4, 5:  100% valid data\nCells 3, 6:        rightmost 30px = nodata\nCells 7, 8:        bottom 30px = nodata\nCell 9:            right 30px AND bottom 30px = nodata",
      "properties": {
        "name": {
          "const": "pad_to_fill",
          "title": "Name",
          "type": "string"
        },
        "grid_size": {
          "description": "Side length of each square grid cell in pixels.",
          "exclusiveMinimum": 0,
          "title": "Grid Size",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "grid_size"
      ],
      "title": "PadToFillStrategy",
      "type": "object"
    },
    "PartitionWindowSizing": {
      "discriminator": {
        "mapping": {
          "fixed_size": "#/$defs/FixedSize",
          "match_input_size": "#/$defs/MatchInputSize"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/MatchInputSize"
        },
        {
          "$ref": "#/$defs/FixedSize"
        }
      ]
    },
    "Partitioner": {
      "discriminator": {
        "mapping": {
          "fixed_window": "#/$defs/FixedWindowPartitioner",
          "grid": "#/$defs/GridPartitioner",
          "manual": "#/$defs/EscapeHatchComponent",
          "noop": "#/$defs/NoopPartitioner"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/NoopPartitioner"
        },
        {
          "$ref": "#/$defs/GridPartitioner"
        },
        {
          "$ref": "#/$defs/FixedWindowPartitioner"
        },
        {
          "$ref": "#/$defs/EscapeHatchComponent"
        }
      ]
    },
    "Partitioners": {
      "properties": {
        "request_to_partitions": {
          "$ref": "#/$defs/Partitioner",
          "description": "Controls the partitioning of the initial request into smaller units for machine-level parallelism."
        },
        "partition_to_windows": {
          "$ref": "#/$defs/Partitioner",
          "description": "Controls the subdivision of a request partition into smaller units for process-level parallelism."
        }
      },
      "required": [
        "request_to_partitions",
        "partition_to_windows"
      ],
      "title": "Partitioners",
      "type": "object"
    },
    "PerAnnotationMode": {
      "description": "One window per annotation, centered on a point interior to the annotation geometry.\n\nUses the geometry's centroid when it falls inside the geometry. For concave\npolygons whose centroid lies outside the shape, falls back to a guaranteed\ninterior point.\n\nThe window size is determined by the window_sizing strategy. Defaults to\nMatchInputSize, which uses input_preprocessing.default.input_size.",
      "properties": {
        "name": {
          "const": "per_annotation",
          "title": "Name",
          "type": "string"
        },
        "window_sizing": {
          "$ref": "#/$defs/WindowSizing",
          "default": {
            "name": "match_input_size"
          },
          "description": "Strategy for determining the window size."
        }
      },
      "required": [
        "name"
      ],
      "title": "PerAnnotationMode",
      "type": "object"
    },
    "PerGroupMode": {
      "description": "Windows covering the enclosing geometry of all annotations in a group.\n\nWithout gridding_strategy, produces a single window for the entire group.\nWith gridding_strategy, divides the enclosing region into grid cells of the configured size.",
      "properties": {
        "name": {
          "const": "per_group",
          "title": "Name",
          "type": "string"
        },
        "gridding_strategy": {
          "anyOf": [
            {
              "$ref": "#/$defs/GriddingStrategy"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "If set, divides the enclosing region into grid cells using this strategy."
        },
        "drop_inconsistent_utm": {
          "default": false,
          "description": "If True, skip groups where corners span different UTM zones.",
          "title": "Drop Inconsistent Utm",
          "type": "boolean"
        }
      },
      "required": [
        "name"
      ],
      "title": "PerGroupMode",
      "type": "object"
    },
    "PerPixelRegressionDecoder": {
      "discriminator": {
        "mapping": {
          "unet": "#/$defs/UnetPerPixelRegressionDecoder"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/UnetPerPixelRegressionDecoder"
        }
      ]
    },
    "PerPixelRegressionField": {
      "properties": {
        "min_value": {
          "description": "Minimum possible value for this field",
          "title": "Min Value",
          "type": "number"
        },
        "max_value": {
          "description": "Maximum possible value for this field",
          "title": "Max Value",
          "type": "number"
        },
        "colormap_name": {
          "default": "viridis",
          "description": "Name of the rio_tiler colormap to use, see https://cogeotiff.github.io/rio-tiler/colormap/#default-rio-tilers-colormaps",
          "title": "Colormap Name",
          "type": "string"
        },
        "field_type": {
          "const": "per_pixel_regression",
          "title": "Field Type",
          "type": "string"
        },
        "nodata_value": {
          "description": "The value to use for nodata pixels. Respected for labeled training data and in inference outputs.",
          "title": "Nodata Value",
          "type": "number"
        }
      },
      "required": [
        "min_value",
        "max_value",
        "field_type",
        "nodata_value"
      ],
      "title": "PerPixelRegressionField",
      "type": "object"
    },
    "PerPixelRegressionTask": {
      "properties": {
        "name": {
          "const": "per_pixel_regression",
          "title": "Name",
          "type": "string"
        },
        "decoder": {
          "$ref": "#/$defs/PerPixelRegressionDecoder"
        }
      },
      "required": [
        "name",
        "decoder"
      ],
      "title": "PerPixelRegressionTask",
      "type": "object"
    },
    "PeriodTemporality": {
      "description": "Represents the duration of time we're making a prediction for.\nThe observation window equals the prediction period.\nrequest.time_of_interest marks the start of the prediction and observation periods.",
      "properties": {
        "name": {
          "const": "period",
          "title": "Name",
          "type": "string"
        },
        "observation": {
          "$ref": "#/$defs/ObservationStrategy"
        },
        "allowed_start_month_constraints": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Month"
              },
              "type": "array",
              "uniqueItems": true
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Months valid for starting this period.",
          "title": "Allowed Start Month Constraints"
        }
      },
      "required": [
        "name",
        "observation"
      ],
      "title": "PeriodTemporality",
      "type": "object"
    },
    "Plateau": {
      "description": "Lowers learning rate via an exponential decay strategy when model performance plateaus. ",
      "properties": {
        "name": {
          "const": "plateau",
          "title": "Name",
          "type": "string"
        },
        "factor": {
          "description": "Multiplicative factor of learning rate decay. LR = LR * factor.",
          "maximum": 1,
          "minimum": 0,
          "title": "Factor",
          "type": "number"
        },
        "patience": {
          "description": "Number of epochs with no improvement after which learning rate will be reduced.",
          "minimum": 0,
          "title": "Patience",
          "type": "integer"
        },
        "min_lr": {
          "description": "A lower bound on the learning rate.",
          "minimum": 0,
          "title": "Min Lr",
          "type": "number"
        },
        "cooldown": {
          "description": "Number of epochs to wait before resuming normal operation after lr has been reduced.",
          "minimum": 0,
          "title": "Cooldown",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "factor",
        "patience",
        "min_lr",
        "cooldown"
      ],
      "title": "Plateau",
      "type": "object"
    },
    "PointInTimeTemporality": {
      "description": "Represents a specific instant we're making a prediction for.\nUses a narrow symmetric window centered on request.time_of_interest to find imagery.",
      "properties": {
        "name": {
          "const": "point_in_time",
          "title": "Name",
          "type": "string"
        },
        "observation_window_seconds": {
          "description": "Total time covered by the symmetric observation window centered on the prediction point.",
          "minimum": 1,
          "title": "Observation Window Seconds",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "observation_window_seconds"
      ],
      "title": "PointInTimeTemporality",
      "type": "object"
    },
    "PoolingClassificationDecoder": {
      "description": "A decoder that uses global spatial pooling over encoder features followed by\nfully-connected layers and a classification head. Used for window-level\n(vector) classification tasks.",
      "properties": {
        "name": {
          "const": "pooling",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "PoolingClassificationDecoder",
      "type": "object"
    },
    "PoolingRegressionDecoder": {
      "description": "A decoder that uses global spatial pooling over encoder features followed by\nfully-connected layers and a regression head. Used for window-level\n(vector) regression tasks.",
      "properties": {
        "name": {
          "const": "pooling",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "PoolingRegressionDecoder",
      "type": "object"
    },
    "Postprocessors": {
      "description": "Post-processing configuration.\n    ",
      "properties": {
        "additional_steps": {
          "items": {
            "$ref": "#/$defs/AdditionalPostprocessor"
          },
          "title": "Additional Steps",
          "type": "array"
        }
      },
      "title": "Postprocessors",
      "type": "object"
    },
    "PredictInputPreprocessing": {
      "description": "Preprocessing overrides for the predict (inference) split.\n\n``overlap_pixels`` controls how much adjacent inputs overlap when\ntiling a window. Used to reduce boundary artifacts in dense\nprediction (i.e. segmentation, per-pixel regression, embeddings)::\n\n    overlap_pixels = 0                         overlap_pixels > 0\n    \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500      \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n    window                                    window\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510       \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n    \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502       \u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n    \u2502 \u2502              \u2502              \u2502 \u2502       \u2502 \u2502              \u2502\u00b7\u00b7\u00b7\u00b7\u2502              \u2502 \u2502\n    \u2502 \u2502              \u2502              \u2502 \u2502       \u2502 \u2502              \u2502\u00b7\u00b7\u00b7\u00b7\u2502              \u2502 \u2502\n    \u2502 \u2502   input 1    \u2502   input 2    \u2502 \u2502       \u2502 \u2502   input 1    \u2502\u00b7\u00b7\u00b7\u00b7\u2502   input 2    \u2502 \u2502\n    \u2502 \u2502              \u2502              \u2502 \u2502       \u2502 \u2502              \u2502\u00b7\u00b7\u00b7\u00b7\u2502              \u2502 \u2502\n    \u2502 \u2502              \u2502              \u2502 \u2502       \u2502 \u2502              \u2502\u00b7\u00b7\u00b7\u00b7\u2502              \u2502 \u2502\n    \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502       \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502\n    \u2502 \u2502              \u2502              \u2502 \u2502       \u2502 \u2502\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u2502\u00b7\u00b7\u00b7\u00b7\u2502\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u2502 \u2502\n    \u2502 \u2502              \u2502              \u2502 \u2502       \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502\n    \u2502 \u2502   input 3    \u2502   input 4    \u2502 \u2502       \u2502 \u2502              \u2502\u00b7\u00b7\u00b7\u00b7\u2502              \u2502 \u2502\n    \u2502 \u2502              \u2502              \u2502 \u2502       \u2502 \u2502              \u2502\u00b7\u00b7\u00b7\u00b7\u2502              \u2502 \u2502\n    \u2502 \u2502              \u2502              \u2502 \u2502       \u2502 \u2502   input 3    \u2502\u00b7\u00b7\u00b7\u00b7\u2502   input 4    \u2502 \u2502\n    \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502       \u2502 \u2502              \u2502\u00b7\u00b7\u00b7\u00b7\u2502              \u2502 \u2502\n    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518       \u2502 \u2502              \u2502\u00b7\u00b7\u00b7\u00b7\u2502              \u2502 \u2502\n                                              \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n    No shared pixels between                  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n    adjacent inputs.\n                                              \u00b7\u00b7\u00b7\u00b7 = overlap region seen by\n                                              adjacent inputs; predictions\n                                              merged by the postprocessor.",
      "properties": {
        "overlap_pixels": {
          "default": 0,
          "description": "Overlap between adjacent inputs when tiling; also used when merging inference outputs. Not relevant for vector-based tasks.",
          "minimum": 0,
          "title": "Overlap Pixels",
          "type": "integer"
        },
        "transforms": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Transform"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Transforms to apply to inputs. Replaces default transforms; takes precedence over additional_transforms.",
          "title": "Transforms"
        },
        "additional_transforms": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Transform"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Additional transforms to apply beyond the default transforms.",
          "title": "Additional Transforms"
        }
      },
      "title": "PredictInputPreprocessing",
      "type": "object"
    },
    "PredictionRequests": {
      "description": "Controls the prediction requests for the model.",
      "properties": {
        "partitioners": {
          "$ref": "#/$defs/Partitioners",
          "description": "Controls the partitioning of the input data into smaller units."
        },
        "postprocessors": {
          "$ref": "#/$defs/Postprocessors",
          "description": "Controls the postprocessing of the prediction results and their assembly into final outputs."
        }
      },
      "required": [
        "partitioners"
      ],
      "title": "PredictionRequests",
      "type": "object"
    },
    "Projection": {
      "discriminator": {
        "mapping": {
          "crs": "#/$defs/CRSProjection",
          "use_utm": "#/$defs/UseUTMProjection"
        },
        "propertyName": "method"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/UseUTMProjection"
        },
        {
          "$ref": "#/$defs/CRSProjection"
        }
      ]
    },
    "RandomDataSplitter": {
      "description": "Data splitter that assigns splits based on random sampling.",
      "properties": {
        "train_prop": {
          "description": "The proportion of data to assign to the training split.",
          "exclusiveMinimum": 0,
          "maximum": 1,
          "title": "Train Prop",
          "type": "number"
        },
        "val_prop": {
          "description": "The proportion of data to assign to the validation split.",
          "exclusiveMinimum": 0,
          "maximum": 1,
          "title": "Val Prop",
          "type": "number"
        },
        "test_prop": {
          "description": "The proportion of data to assign to the test split.",
          "maximum": 1,
          "minimum": 0,
          "title": "Test Prop",
          "type": "number"
        },
        "name": {
          "const": "random",
          "title": "Name",
          "type": "string"
        },
        "seed": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 42,
          "description": "The seed for the random number generator.",
          "title": "Seed"
        }
      },
      "required": [
        "train_prop",
        "val_prop",
        "test_prop",
        "name"
      ],
      "title": "RandomDataSplitter",
      "type": "object"
    },
    "RandomFlip": {
      "properties": {
        "name": {
          "const": "random_flip",
          "title": "Name",
          "type": "string"
        },
        "x": {
          "default": true,
          "description": "Flip the image horizontally",
          "title": "X",
          "type": "boolean"
        },
        "y": {
          "default": true,
          "description": "Flip the image vertically",
          "title": "Y",
          "type": "boolean"
        }
      },
      "required": [
        "name"
      ],
      "title": "RandomFlip",
      "type": "object"
    },
    "RandomSampler": {
      "properties": {
        "name": {
          "const": "random",
          "title": "Name",
          "type": "string"
        },
        "num_samples": {
          "description": "The number of samples to take",
          "minimum": 0,
          "title": "Num Samples",
          "type": "integer"
        },
        "replace": {
          "default": false,
          "description": "Whether sampled items can be sampled again",
          "title": "Replace",
          "type": "boolean"
        }
      },
      "required": [
        "name",
        "num_samples"
      ],
      "title": "RandomSampler",
      "type": "object"
    },
    "RasterField": {
      "discriminator": {
        "mapping": {
          "per_pixel_regression": "#/$defs/PerPixelRegressionField",
          "segmentation": "#/$defs/SegmentationField"
        },
        "propertyName": "field_type"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/SegmentationField"
        },
        {
          "$ref": "#/$defs/PerPixelRegressionField"
        }
      ]
    },
    "RasterOutput": {
      "properties": {
        "data_type": {
          "const": "raster",
          "title": "Data Type",
          "type": "string"
        },
        "fields": {
          "additionalProperties": {
            "$ref": "#/$defs/RasterField"
          },
          "title": "Fields",
          "type": "object"
        },
        "max_pixels_per_dimension": {
          "default": 10000,
          "description": "Maximum pixels per dimension when combining prediction tiles into the output GeoTIFF. Caps output resolution.",
          "exclusiveMinimum": 0,
          "title": "Max Pixels Per Dimension",
          "type": "integer"
        }
      },
      "required": [
        "data_type",
        "fields"
      ],
      "title": "RasterOutput",
      "type": "object"
    },
    "RegressionDecoder": {
      "discriminator": {
        "mapping": {
          "pooling": "#/$defs/PoolingRegressionDecoder"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/PoolingRegressionDecoder"
        }
      ]
    },
    "RegressionField": {
      "properties": {
        "min_value": {
          "description": "Minimum possible value for this field",
          "title": "Min Value",
          "type": "number"
        },
        "max_value": {
          "description": "Maximum possible value for this field",
          "title": "Max Value",
          "type": "number"
        },
        "colormap_name": {
          "default": "viridis",
          "description": "Name of the rio_tiler colormap to use, see https://cogeotiff.github.io/rio-tiler/colormap/#default-rio-tilers-colormaps",
          "title": "Colormap Name",
          "type": "string"
        },
        "field_type": {
          "const": "regression",
          "title": "Field Type",
          "type": "string"
        }
      },
      "required": [
        "min_value",
        "max_value",
        "field_type"
      ],
      "title": "RegressionField",
      "type": "object"
    },
    "RegressionTask": {
      "properties": {
        "name": {
          "const": "regression",
          "title": "Name",
          "type": "string"
        },
        "decoder": {
          "$ref": "#/$defs/RegressionDecoder"
        }
      },
      "required": [
        "name",
        "decoder"
      ],
      "title": "RegressionTask",
      "type": "object"
    },
    "RepeatingIntervalObservation": {
      "description": "Divide window into fixed sub-periods, one observation (mosaic or snapshot) per period.",
      "properties": {
        "name": {
          "const": "repeating_interval",
          "title": "Name",
          "type": "string"
        },
        "num_periods": {
          "description": "Number of intervals.",
          "maximum": 12,
          "minimum": 1,
          "title": "Num Periods",
          "type": "integer"
        },
        "period_duration_days": {
          "description": "Duration of each interval.",
          "minimum": 1,
          "title": "Period Duration Days",
          "type": "integer"
        },
        "recovery_periods": {
          "default": 0,
          "description": "Extra periods to search beyond num_periods as fallback for periods lacking satellite coverage. Extends the search window by recovery_periods * period_duration_days. For PeriodTemporality and lookbehind observations, recovery extends backward from the primary window (rslearn prefers primary periods, uses recovery as last resort). Not currently supported on lookahead observations due to rslearn's backward search strategy which would incorrectly prefer recovery periods over primary ones.",
          "minimum": 0,
          "title": "Recovery Periods",
          "type": "integer"
        },
        "reverse_chronological": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated. Use only if you need to preserve old rslearn behavior of loading periods in reverse chronological order to the model.",
          "title": "Reverse Chronological"
        }
      },
      "required": [
        "name",
        "num_periods",
        "period_duration_days"
      ],
      "title": "RepeatingIntervalObservation",
      "type": "object"
    },
    "SampledObservation": {
      "description": "Collect discrete snapshots within a window.",
      "properties": {
        "name": {
          "const": "sampled",
          "title": "Name",
          "type": "string"
        },
        "duration_days": {
          "description": "The observation window duration.",
          "minimum": 1,
          "title": "Duration Days",
          "type": "integer"
        },
        "num_samples": {
          "description": "Number of samples to collect.",
          "maximum": 12,
          "minimum": 1,
          "title": "Num Samples",
          "type": "integer"
        }
      },
      "required": [
        "name",
        "duration_days",
        "num_samples"
      ],
      "title": "SampledObservation",
      "type": "object"
    },
    "Scheduler": {
      "discriminator": {
        "mapping": {
          "manual": "#/$defs/EscapeHatchComponent",
          "plateau": "#/$defs/Plateau"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/Plateau"
        },
        {
          "$ref": "#/$defs/EscapeHatchComponent"
        }
      ]
    },
    "SegmentationDecoder": {
      "discriminator": {
        "mapping": {
          "unet": "#/$defs/UnetSegmentationDecoder",
          "upsample_conv": "#/$defs/UpsampleConvSegmentationDecoder"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/UpsampleConvSegmentationDecoder"
        },
        {
          "$ref": "#/$defs/UnetSegmentationDecoder"
        }
      ]
    },
    "SegmentationField": {
      "description": "A field that represents per-pixel classification",
      "properties": {
        "field_type": {
          "const": "segmentation",
          "title": "Field Type",
          "type": "string"
        },
        "allowed_values": {
          "items": {
            "$ref": "#/$defs/ClassValue"
          },
          "minItems": 2,
          "title": "Allowed Values",
          "type": "array"
        },
        "nodata_value": {
          "description": "The value to use for nodata pixels.",
          "title": "Nodata Value",
          "type": "integer"
        }
      },
      "required": [
        "field_type",
        "allowed_values",
        "nodata_value"
      ],
      "title": "SegmentationField",
      "type": "object"
    },
    "SegmentationTask": {
      "properties": {
        "name": {
          "const": "segmentation",
          "title": "Name",
          "type": "string"
        },
        "decoder": {
          "$ref": "#/$defs/SegmentationDecoder"
        }
      },
      "required": [
        "name",
        "decoder"
      ],
      "title": "SegmentationTask",
      "type": "object"
    },
    "Sentinel1RTC": {
      "description": "Sentinel-1 radiometrically terrain-corrected (RTC) imagery modality.",
      "properties": {
        "orbit_direction": {
          "anyOf": [
            {
              "$ref": "#/$defs/Sentinel1RTCOrbitDirection"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The direction of the orbit."
        },
        "space_mode": {
          "$ref": "#/$defs/SpaceMode"
        }
      },
      "required": [
        "space_mode"
      ],
      "title": "Sentinel1RTC",
      "type": "object"
    },
    "Sentinel1RTCOrbitDirection": {
      "enum": [
        "ascending_orbit",
        "descending_orbit"
      ],
      "title": "Sentinel1RTCOrbitDirection",
      "type": "string"
    },
    "Sentinel1ToDecibels": {
      "description": "Convert Sentinel-1 RTC data from linear to decibel scale.",
      "properties": {
        "name": {
          "const": "sentinel1_to_decibels",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "Sentinel1ToDecibels",
      "type": "object"
    },
    "Sentinel2L2A": {
      "description": "Sentinel-2 Level-2A surface reflectance imagery modality.",
      "properties": {
        "sort_by": {
          "$ref": "#/$defs/Sentinel2L2ASortBy",
          "default": "cloud_cover",
          "description": "The field to sort the data by."
        },
        "space_mode": {
          "$ref": "#/$defs/SpaceMode"
        }
      },
      "required": [
        "space_mode"
      ],
      "title": "Sentinel2L2A",
      "type": "object"
    },
    "Sentinel2L2ASortBy": {
      "enum": [
        "cloud_cover"
      ],
      "title": "Sentinel2L2ASortBy",
      "type": "string"
    },
    "SpaceMode": {
      "description": "How to build up or sample imagery.",
      "enum": [
        "mosaic",
        "contains"
      ],
      "title": "SpaceMode",
      "type": "string"
    },
    "SpatialDataSplitter": {
      "description": "Data splitter that assigns splits based on spatial grid cell location.",
      "properties": {
        "train_prop": {
          "description": "The proportion of data to assign to the training split.",
          "exclusiveMinimum": 0,
          "maximum": 1,
          "title": "Train Prop",
          "type": "number"
        },
        "val_prop": {
          "description": "The proportion of data to assign to the validation split.",
          "exclusiveMinimum": 0,
          "maximum": 1,
          "title": "Val Prop",
          "type": "number"
        },
        "test_prop": {
          "description": "The proportion of data to assign to the test split.",
          "maximum": 1,
          "minimum": 0,
          "title": "Test Prop",
          "type": "number"
        },
        "name": {
          "const": "spatial",
          "title": "Name",
          "type": "string"
        },
        "grid_size": {
          "description": "The size of the grid cells in pixels.",
          "minimum": 1,
          "title": "Grid Size",
          "type": "integer"
        }
      },
      "required": [
        "train_prop",
        "val_prop",
        "test_prop",
        "name",
        "grid_size"
      ],
      "title": "SpatialDataSplitter",
      "type": "object"
    },
    "StandardRasterWindowPreparer": {
      "description": "Standard preparer that produces raster-labeled windows.\n\nCombines any annotation geometry type with any windowing strategy.",
      "properties": {
        "name": {
          "const": "standard_raster",
          "title": "Name",
          "type": "string"
        },
        "windowing_mode": {
          "$ref": "#/$defs/WindowingMode"
        }
      },
      "required": [
        "name",
        "windowing_mode"
      ],
      "title": "StandardRasterWindowPreparer",
      "type": "object"
    },
    "StandardVectorWindowPreparer": {
      "description": "Standard preparer that produces vector-labeled windows.\n\nCombines any annotation geometry type with any windowing strategy.",
      "properties": {
        "name": {
          "const": "standard_vector",
          "title": "Name",
          "type": "string"
        },
        "windowing_mode": {
          "$ref": "#/$defs/WindowingMode"
        }
      },
      "required": [
        "name",
        "windowing_mode"
      ],
      "title": "StandardVectorWindowPreparer",
      "type": "object"
    },
    "Temporality": {
      "discriminator": {
        "mapping": {
          "framed_point_in_time": "#/$defs/FramedPointInTimeTemporality",
          "period": "#/$defs/PeriodTemporality",
          "point_in_time": "#/$defs/PointInTimeTemporality"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/PeriodTemporality"
        },
        {
          "$ref": "#/$defs/PointInTimeTemporality"
        },
        {
          "$ref": "#/$defs/FramedPointInTimeTemporality"
        }
      ]
    },
    "TrainInputPreprocessing": {
      "description": "Training split must always use single random crop.",
      "properties": {
        "transforms": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Transform"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Transforms to apply to inputs. Replaces default transforms; takes precedence over additional_transforms.",
          "title": "Transforms"
        },
        "additional_transforms": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Transform"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Additional transforms to apply beyond the default transforms.",
          "title": "Additional Transforms"
        },
        "sampler": {
          "anyOf": [
            {
              "$ref": "#/$defs/TrainingSampler"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Samples down the data to a smaller set based on the given strategy."
        },
        "input_mode": {
          "const": "single_random_crop",
          "default": "single_random_crop",
          "title": "Input Mode",
          "type": "string"
        }
      },
      "title": "TrainInputPreprocessing",
      "type": "object"
    },
    "Training": {
      "description": "Controls the model training process.",
      "properties": {
        "max_epochs": {
          "description": "The maximum number of epochs to train for.",
          "minimum": 1,
          "title": "Max Epochs",
          "type": "integer"
        },
        "batch_size": {
          "description": "The number of inputs to process in each training batch (see: `input_preprocessing`).",
          "minimum": 1,
          "title": "Batch Size",
          "type": "integer"
        },
        "optimizer": {
          "$ref": "#/$defs/Optimizer",
          "description": "Controls the optimization algorithm used to update the model's weights."
        },
        "scheduler": {
          "$ref": "#/$defs/Scheduler",
          "description": "Controls how the learning rate is modified over the course of training."
        },
        "encoder_training_strategy": {
          "$ref": "#/$defs/EncoderTrainingStrategy",
          "description": "Controls how encoder weights are managed during training."
        },
        "early_stopping": {
          "anyOf": [
            {
              "$ref": "#/$defs/EarlyStopping"
            },
            {
              "type": "null"
            }
          ],
          "description": "End fine tuning early if model performance is no longer improving."
        }
      },
      "required": [
        "max_epochs",
        "batch_size",
        "optimizer",
        "scheduler",
        "encoder_training_strategy"
      ],
      "title": "Training",
      "type": "object"
    },
    "TrainingSampler": {
      "discriminator": {
        "mapping": {
          "random": "#/$defs/RandomSampler"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/RandomSampler"
        }
      ]
    },
    "Transform": {
      "discriminator": {
        "mapping": {
          "manual": "#/$defs/EscapeHatchComponent",
          "olmoearth_normalize": "#/$defs/OlmoEarthNormalize",
          "random_flip": "#/$defs/RandomFlip",
          "sentinel1_to_decibels": "#/$defs/Sentinel1ToDecibels"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/OlmoEarthNormalize"
        },
        {
          "$ref": "#/$defs/RandomFlip"
        },
        {
          "$ref": "#/$defs/Sentinel1ToDecibels"
        },
        {
          "$ref": "#/$defs/EscapeHatchComponent"
        }
      ]
    },
    "TranspilerContext": {
      "description": "Values the transpiler cannot derive automatically from opaque components.\n\nWhen escape hatch or manual-task components are used, the transpiler cannot\nintrospect them to determine architectural properties it normally derives\nfrom sanctioned components. This model supplies those values explicitly.\n\nAll fields are nullable.\nBoth the transpiler and OlmoEarthConfig's validator raise errors when\nconditionally-required values are missing.",
      "properties": {
        "downsample_factor": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The factor by which the output resolution is lower than the input resolution. Consequence of encoder-decoder interaction, and impacts merging logic for raster data.",
          "title": "Downsample Factor"
        },
        "checkpoint_monitor": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The metric to monitor for checkpointing. Task-dependent.",
          "title": "Checkpoint Monitor"
        },
        "checkpoint_mode": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The mode to monitor for checkpointing, e.g. 'max', 'min'. Task-dependent.",
          "title": "Checkpoint Mode"
        }
      },
      "title": "TranspilerContext",
      "type": "object"
    },
    "UnetPerPixelRegressionDecoder": {
      "description": "A decoder that uses a U-Net architecture with a per-pixel regression head (single channel output).",
      "properties": {
        "name": {
          "const": "unet",
          "title": "Name",
          "type": "string"
        },
        "conv_layers_per_resolution": {
          "default": 1,
          "description": "Number of convolutional layers at each resolution level.",
          "minimum": 1,
          "title": "Conv Layers Per Resolution",
          "type": "integer"
        },
        "num_channels": {
          "anyOf": [
            {
              "additionalProperties": {
                "type": "integer"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Explicit channel counts per resolution level. When None, rslearn auto-calculates.",
          "title": "Num Channels"
        }
      },
      "required": [
        "name"
      ],
      "title": "UnetPerPixelRegressionDecoder",
      "type": "object"
    },
    "UnetSegmentationDecoder": {
      "description": "A decoder that uses a U-Net architecture to perform segmentation.",
      "properties": {
        "name": {
          "const": "unet",
          "title": "Name",
          "type": "string"
        },
        "conv_layers_per_resolution": {
          "default": 1,
          "description": "Number of convolutional layers at each resolution level.",
          "minimum": 1,
          "title": "Conv Layers Per Resolution",
          "type": "integer"
        },
        "num_channels": {
          "anyOf": [
            {
              "additionalProperties": {
                "type": "integer"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Explicit channel counts per resolution level (e.g. {8: 512, 4: 512, 2: 256, 1: 128}). When None, rslearn auto-calculates.",
          "title": "Num Channels"
        }
      },
      "required": [
        "name"
      ],
      "title": "UnetSegmentationDecoder",
      "type": "object"
    },
    "UpsampleConvSegmentationDecoder": {
      "description": "A decoder that upsamples the embeddings using a convolutional layer before passing to a segmentation decoder head.",
      "properties": {
        "name": {
          "const": "upsample_conv",
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "UpsampleConvSegmentationDecoder",
      "type": "object"
    },
    "UseUTMProjection": {
      "properties": {
        "method": {
          "const": "use_utm",
          "title": "Method",
          "type": "string"
        }
      },
      "required": [
        "method"
      ],
      "title": "UseUTMProjection",
      "type": "object"
    },
    "ValTestSplitInputPreprocessing": {
      "properties": {
        "transforms": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Transform"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Transforms to apply to inputs. Replaces default transforms; takes precedence over additional_transforms.",
          "title": "Transforms"
        },
        "additional_transforms": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Transform"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Additional transforms to apply beyond the default transforms.",
          "title": "Additional Transforms"
        },
        "sampler": {
          "anyOf": [
            {
              "$ref": "#/$defs/TrainingSampler"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Samples down the data to a smaller set based on the given strategy."
        },
        "input_mode": {
          "anyOf": [
            {
              "$ref": "#/$defs/InputMode"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "How windows are converted to model inputs. Overrides the default value for this split."
        }
      },
      "title": "ValTestSplitInputPreprocessing",
      "type": "object"
    },
    "ValueTransformPostprocessor": {
      "description": "Transform pixel values of raster prediction outputs.\n\nThe transform is applied exactly once: either to each window's raster before\ncombining (``window``, the default) or to the final combined raster\n(``request``). Window level casts to smaller dtypes early, so combining\nmoves less data.\n\nEmbedding quantization is not configured here -- the runner power-quantizes\nembeddings to int8 automatically.",
      "properties": {
        "name": {
          "const": "value_transform",
          "title": "Name",
          "type": "string"
        },
        "level": {
          "default": "window",
          "enum": [
            "window",
            "request"
          ],
          "title": "Level",
          "type": "string"
        },
        "transform": {
          "$ref": "#/$defs/LinearValueTransformConfig",
          "description": "The value transform to apply."
        }
      },
      "required": [
        "name",
        "transform"
      ],
      "title": "ValueTransformPostprocessor",
      "type": "object"
    },
    "VectorField": {
      "discriminator": {
        "mapping": {
          "classification": "#/$defs/ClassificationField",
          "detection": "#/$defs/DetectionField",
          "regression": "#/$defs/RegressionField"
        },
        "propertyName": "field_type"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/ClassificationField"
        },
        {
          "$ref": "#/$defs/RegressionField"
        },
        {
          "$ref": "#/$defs/DetectionField"
        }
      ]
    },
    "VectorOutput": {
      "properties": {
        "data_type": {
          "const": "vector",
          "title": "Data Type",
          "type": "string"
        },
        "fields": {
          "additionalProperties": {
            "$ref": "#/$defs/VectorField"
          },
          "title": "Fields",
          "type": "object"
        }
      },
      "required": [
        "data_type",
        "fields"
      ],
      "title": "VectorOutput",
      "type": "object"
    },
    "VectorizePostprocessor": {
      "description": "Polygonize a raster prediction into GeoJSON vector features.",
      "properties": {
        "name": {
          "const": "vectorize",
          "title": "Name",
          "type": "string"
        },
        "skip_label_ids": {
          "anyOf": [
            {
              "items": {
                "type": "integer"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Label IDs to exclude from vector output.",
          "title": "Skip Label Ids"
        },
        "sieve_size": {
          "default": 5,
          "description": "Minimum connected-pixel group size; smaller groups are removed before polygonizing. Higher values drop more small features, reducing noise but also dropping small real detections.",
          "minimum": 0,
          "title": "Sieve Size",
          "type": "integer"
        },
        "simplify_tolerance_px": {
          "default": 1.0,
          "description": "Douglas-Peucker tolerance in pixels of the output resolution, applied in the native CRS before reprojection. 0 disables; sub-pixel values do approximately nothing (vertices sit on the pixel grid).",
          "minimum": 0.0,
          "title": "Simplify Tolerance Px",
          "type": "number"
        },
        "coordinate_precision": {
          "default": 5,
          "description": "Decimal places to round output coordinates (5 \u2248 1 m precision).",
          "minimum": 0,
          "title": "Coordinate Precision",
          "type": "integer"
        },
        "max_features": {
          "anyOf": [
            {
              "exclusiveMinimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Hard cap on output feature count; keeps N largest by area when hit.",
          "title": "Max Features"
        }
      },
      "required": [
        "name"
      ],
      "title": "VectorizePostprocessor",
      "type": "object"
    },
    "WindowPreparer": {
      "discriminator": {
        "mapping": {
          "manual": "#/$defs/EscapeHatchComponent",
          "standard_raster": "#/$defs/StandardRasterWindowPreparer",
          "standard_vector": "#/$defs/StandardVectorWindowPreparer"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/StandardRasterWindowPreparer"
        },
        {
          "$ref": "#/$defs/StandardVectorWindowPreparer"
        },
        {
          "$ref": "#/$defs/EscapeHatchComponent"
        }
      ]
    },
    "WindowSizing": {
      "discriminator": {
        "mapping": {
          "buffered": "#/$defs/Buffered",
          "fixed_size": "#/$defs/FixedSize",
          "match_input_size": "#/$defs/MatchInputSize"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/MatchInputSize"
        },
        {
          "$ref": "#/$defs/FixedSize"
        },
        {
          "$ref": "#/$defs/Buffered"
        }
      ]
    },
    "WindowingMode": {
      "discriminator": {
        "mapping": {
          "per_annotation": "#/$defs/PerAnnotationMode",
          "per_group": "#/$defs/PerGroupMode"
        },
        "propertyName": "name"
      },
      "oneOf": [
        {
          "$ref": "#/$defs/PerGroupMode"
        },
        {
          "$ref": "#/$defs/PerAnnotationMode"
        }
      ]
    }
  },
  "description": "Unified configuration for OlmoEarth: data requirements, model, dataset prep, training, prediction.",
  "properties": {
    "config_version": {
      "description": "The version of the configuration",
      "title": "Config Version",
      "type": "string"
    },
    "data": {
      "$ref": "#/$defs/Data",
      "description": "Specifies the required data modalities, temporality of the data to retrieve, and the output schema (when a `model` is defined)."
    },
    "model": {
      "anyOf": [
        {
          "$ref": "#/$defs/Model"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Defines the model architecture and the tasks to perform during inference."
    },
    "input_preprocessing": {
      "anyOf": [
        {
          "$ref": "#/$defs/InputPreprocessing"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Defines how input tensors are prepared or transformed before being provided to the model."
    },
    "labeled_data_prep": {
      "anyOf": [
        {
          "$ref": "#/$defs/LabeledDataPrep"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Controls the preparation of labeled data for training."
    },
    "training": {
      "anyOf": [
        {
          "$ref": "#/$defs/Training"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Configuration for the training"
    },
    "prediction_requests": {
      "anyOf": [
        {
          "$ref": "#/$defs/PredictionRequests"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Controls the prediction requests for the model."
    },
    "transpiler_context": {
      "anyOf": [
        {
          "$ref": "#/$defs/TranspilerContext"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Values the transpiler cannot derive automatically when using escape hatches or rslearn pass-through mode."
    }
  },
  "required": [
    "config_version",
    "data"
  ],
  "title": "OlmoEarthConfig",
  "type": "object"
}
