{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://conspecta.bio/schemas/image-analysis-pipeline/v1.json",
  "title": "Image analysis pipeline file",
  "description": "One image analysis pipeline: its steps, each step's settings, the AI model each detection step uses, and the guided settings that rebuild the steps. Major version 1; within it, a new field is optional and safe to ignore.",
  "type": "object",
  "required": [
    "format",
    "formatVersion",
    "name",
    "steps"
  ],
  "properties": {
    "$schema": {
      "type": "string"
    },
    "format": {
      "const": "image-analysis-pipeline"
    },
    "formatVersion": {
      "type": "string",
      "pattern": "^1\\.(0|[1-9][0-9]*)$"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "description": {
      "type": "string",
      "maxLength": 500
    },
    "steps": {
      "type": "array",
      "minItems": 1,
      "maxItems": 20,
      "items": {
        "oneOf": [
          {
            "title": "preprocess: crop",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "preprocess"
              },
              "method": {
                "const": "crop"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "top": {
                    "type": "number",
                    "minimum": 0
                  },
                  "bottom": {
                    "type": "number",
                    "minimum": 0
                  },
                  "left": {
                    "type": "number",
                    "minimum": 0
                  },
                  "right": {
                    "type": "number",
                    "minimum": 0
                  },
                  "referenceWidth": {
                    "type": "number",
                    "minimum": 0
                  },
                  "referenceHeight": {
                    "type": "number",
                    "minimum": 0
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "preprocess: background-subtract",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "preprocess"
              },
              "method": {
                "const": "background-subtract"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "offset": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "autoPercentile": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "expectBetween": {
                    "anyOf": [
                      {
                        "type": "array",
                        "prefixItems": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "number"
                          }
                        ],
                        "minItems": 2,
                        "maxItems": 2,
                        "description": "[low, high], low at most high"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "preprocess: median-denoise",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "preprocess"
              },
              "method": {
                "const": "median-denoise"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "radius": {
                    "type": "number",
                    "minimum": 0
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "preprocess: gaussian-blur",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "preprocess"
              },
              "method": {
                "const": "gaussian-blur"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "radius": {
                    "type": "number",
                    "minimum": 0
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "preprocess: z-projection",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "preprocess"
              },
              "method": {
                "const": "z-projection"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "mode": {
                    "enum": [
                      "mip",
                      "average",
                      "sum"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "segment: threshold",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "segment"
              },
              "method": {
                "const": "threshold"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "polarity": {
                    "enum": [
                      "bright",
                      "dark"
                    ]
                  },
                  "threshold": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "strategy": {
                    "type": "object",
                    "required": [
                      "kind"
                    ],
                    "properties": {
                      "kind": {
                        "enum": [
                          "otsu",
                          "percentile",
                          "mean-sigma",
                          "triangle",
                          "adaptive"
                        ]
                      },
                      "percentile": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100
                      },
                      "k": {
                        "type": "number"
                      },
                      "window": {
                        "type": "number",
                        "minimum": 1
                      },
                      "offset": {
                        "type": "number"
                      }
                    },
                    "additionalProperties": false
                  },
                  "expectBetween": {
                    "anyOf": [
                      {
                        "type": "array",
                        "prefixItems": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "number"
                          }
                        ],
                        "minItems": 2,
                        "maxItems": 2,
                        "description": "[low, high], low at most high"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "minArea": {
                    "type": "number",
                    "minimum": 0
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "segment: watershed",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "segment"
              },
              "method": {
                "const": "watershed"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "hMinima": {
                    "type": "number",
                    "minimum": 0
                  },
                  "minDistance": {
                    "type": "number",
                    "minimum": 0
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "segment: morphology",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs",
              "params"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "segment"
              },
              "method": {
                "const": "morphology"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "op": {
                    "enum": [
                      "erode",
                      "dilate",
                      "open",
                      "close",
                      "fill-holes",
                      "clear-border"
                    ]
                  },
                  "radius": {
                    "type": "number",
                    "minimum": 0
                  },
                  "iterations": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "required": [
                  "op"
                ],
                "additionalProperties": false
              }
            }
          },
          {
            "title": "segment: sam-auto",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "segment"
              },
              "method": {
                "const": "sam-auto"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "sensitivity": {
                    "enum": [
                      "fewer",
                      "standard",
                      "more"
                    ]
                  },
                  "overlap": {
                    "enum": [
                      "merge-more",
                      "standard",
                      "merge-less"
                    ]
                  }
                },
                "additionalProperties": false
              },
              "model": {
                "type": "object",
                "required": [
                  "name",
                  "weights"
                ],
                "properties": {
                  "name": {
                    "const": "sam_auto"
                  },
                  "weights": {
                    "type": "string",
                    "description": "The published weights this step detects with"
                  },
                  "sha256": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$"
                  }
                }
              }
            }
          },
          {
            "title": "segment: stardist-fluorescence",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "segment"
              },
              "method": {
                "const": "stardist-fluorescence"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "sensitivity": {
                    "enum": [
                      "fewer",
                      "standard",
                      "more"
                    ]
                  },
                  "overlap": {
                    "enum": [
                      "merge-more",
                      "standard",
                      "merge-less"
                    ]
                  }
                },
                "additionalProperties": false
              },
              "model": {
                "type": "object",
                "required": [
                  "name",
                  "weights"
                ],
                "properties": {
                  "name": {
                    "const": "stardist"
                  },
                  "weights": {
                    "type": "string",
                    "description": "The published weights this step detects with"
                  },
                  "sha256": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$"
                  }
                }
              }
            }
          },
          {
            "title": "segment: stardist-colonies",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "segment"
              },
              "method": {
                "const": "stardist-colonies"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "sensitivity": {
                    "enum": [
                      "fewer",
                      "standard",
                      "more"
                    ]
                  },
                  "overlap": {
                    "enum": [
                      "merge-more",
                      "standard",
                      "merge-less"
                    ]
                  }
                },
                "additionalProperties": false
              },
              "model": {
                "type": "object",
                "required": [
                  "name",
                  "weights"
                ],
                "properties": {
                  "name": {
                    "const": "stardist"
                  },
                  "weights": {
                    "type": "string",
                    "description": "The published weights this step detects with"
                  },
                  "sha256": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$"
                  }
                }
              }
            }
          },
          {
            "title": "measure: colocalization-pearson",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "measure"
              },
              "method": {
                "const": "colocalization-pearson"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "componentA": {
                    "enum": [
                      0,
                      1,
                      2
                    ]
                  },
                  "componentB": {
                    "enum": [
                      0,
                      1,
                      2
                    ]
                  },
                  "thresholdMode": {
                    "enum": [
                      "costes",
                      "fixed"
                    ]
                  },
                  "thresholdA": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 255
                  },
                  "thresholdB": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 255
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "measure: area-coverage-otsu",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "measure"
              },
              "method": {
                "const": "area-coverage-otsu"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "polarity": {
                    "enum": [
                      "bright",
                      "dark"
                    ]
                  },
                  "threshold": {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "strategy": {
                    "type": "object",
                    "required": [
                      "kind"
                    ],
                    "properties": {
                      "kind": {
                        "enum": [
                          "otsu",
                          "percentile",
                          "mean-sigma",
                          "triangle"
                        ]
                      },
                      "percentile": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100
                      },
                      "k": {
                        "type": "number"
                      },
                      "window": {
                        "type": "number",
                        "minimum": 1
                      },
                      "offset": {
                        "type": "number"
                      }
                    },
                    "additionalProperties": false
                  },
                  "expectBetween": {
                    "anyOf": [
                      {
                        "type": "array",
                        "prefixItems": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "number"
                          }
                        ],
                        "minItems": 2,
                        "maxItems": 2,
                        "description": "[low, high], low at most high"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "measure: marker-intensity",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "measure"
              },
              "method": {
                "const": "marker-intensity"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          },
          {
            "title": "measure: marker-positive-pct",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "measure"
              },
              "method": {
                "const": "marker-positive-pct"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "threshold": {
                    "type": "number"
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "measure: object-color",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "measure"
              },
              "method": {
                "const": "object-color"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          },
          {
            "title": "measure: object-shape",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "measure"
              },
              "method": {
                "const": "object-shape"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "image": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          },
          {
            "title": "relate: contains",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "relate"
              },
              "method": {
                "const": "contains"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "parents": {
                    "$ref": "#/$defs/binding"
                  },
                  "children": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "rule": {
                    "enum": [
                      "center",
                      "overlap"
                    ]
                  },
                  "minOverlap": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                  }
                },
                "additionalProperties": false
              }
            }
          },
          {
            "title": "gate: threshold",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs",
              "params"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "gate"
              },
              "method": {
                "const": "threshold"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "measurements": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "metric": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "op": {
                    "enum": [
                      ">=",
                      "<=",
                      ">",
                      "<",
                      "==",
                      "between",
                      "in"
                    ]
                  },
                  "value": {
                    "type": "number"
                  },
                  "min": {
                    "type": "number"
                  },
                  "max": {
                    "type": "number"
                  },
                  "values": {
                    "type": "array",
                    "items": {
                      "type": "number"
                    },
                    "maxItems": 256
                  }
                },
                "required": [
                  "metric",
                  "op"
                ],
                "additionalProperties": false
              }
            }
          },
          {
            "title": "aggregate: count-per-parent",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "aggregate"
              },
              "method": {
                "const": "count-per-parent"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "assignments": {
                    "$ref": "#/$defs/binding"
                  },
                  "measurements": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          },
          {
            "title": "aggregate: region-count",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "aggregate"
              },
              "method": {
                "const": "region-count"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "assignments": {
                    "$ref": "#/$defs/binding"
                  },
                  "measurements": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          },
          {
            "title": "aggregate: summary",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "aggregate"
              },
              "method": {
                "const": "summary"
              },
              "scope": {
                "const": "image"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {
                  "assignments": {
                    "$ref": "#/$defs/binding"
                  },
                  "measurements": {
                    "$ref": "#/$defs/binding"
                  },
                  "regions": {
                    "$ref": "#/$defs/binding"
                  }
                },
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          },
          {
            "title": "aggregate: control-check",
            "type": "object",
            "required": [
              "id",
              "kind",
              "method",
              "inputs"
            ],
            "properties": {
              "id": {
                "$ref": "#/$defs/stepId"
              },
              "kind": {
                "const": "aggregate"
              },
              "method": {
                "const": "control-check"
              },
              "scope": {
                "const": "set"
              },
              "objectSet": {
                "$ref": "#/$defs/objectSet"
              },
              "inputs": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              },
              "params": {
                "type": "object",
                "properties": {
                  "controls": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "type": "object",
                      "required": [
                        "condition"
                      ],
                      "properties": {
                        "condition": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 120
                        },
                        "min": {
                          "type": "number"
                        },
                        "minExclusive": {
                          "type": "boolean"
                        },
                        "max": {
                          "type": "number"
                        },
                        "maxExclusive": {
                          "type": "boolean"
                        },
                        "severity": {
                          "enum": [
                            "info",
                            "warning",
                            "error"
                          ]
                        }
                      },
                      "additionalProperties": false
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        ]
      }
    },
    "settings": {
      "type": "object",
      "properties": {
        "goalId": {
          "enum": [
            "count",
            "area",
            "intensity",
            "classification",
            "spatial"
          ]
        },
        "presetId": {
          "enum": [
            "colocalization",
            "area-coverage",
            "marker-intensity",
            "marker-classification",
            "count-inside-region",
            "count-objects",
            "count-positive-objects",
            "measure-inside-region",
            "count-objects-uneven-illumination",
            "count-touching-objects",
            "count-clean-objects",
            "measure-objects"
          ]
        },
        "paramOverrides": {
          "type": "object",
          "properties": {
            "width": {
              "type": "number",
              "minimum": 0
            },
            "height": {
              "type": "number",
              "minimum": 0
            },
            "polarity": {
              "enum": [
                "bright",
                "dark"
              ]
            },
            "threshold": {
              "anyOf": [
                {
                  "type": "number"
                },
                {
                  "type": "null"
                }
              ]
            },
            "parentMinArea": {
              "type": "number",
              "minimum": 0
            },
            "componentA": {
              "enum": [
                0,
                1,
                2
              ]
            },
            "componentB": {
              "enum": [
                0,
                1,
                2
              ]
            },
            "positiveThreshold": {
              "type": "number"
            },
            "positiveObjectCutoff": {
              "type": "number"
            },
            "backgroundSubtraction": {
              "enum": [
                "off",
                "auto"
              ]
            },
            "splitTouching": {
              "enum": [
                "off",
                "on"
              ]
            },
            "fillHoles": {
              "enum": [
                "off",
                "on"
              ]
            },
            "denoise": {
              "enum": [
                "off",
                "on"
              ]
            }
          },
          "additionalProperties": false
        },
        "segmentMethods": {
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/stepId"
          },
          "additionalProperties": {
            "enum": [
              "sam-auto",
              "stardist-fluorescence",
              "stardist-colonies"
            ]
          }
        },
        "segmentFilters": {
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/stepId"
          },
          "additionalProperties": {
            "type": "object",
            "properties": {
              "size": {
                "type": "array",
                "prefixItems": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "number"
                  }
                ],
                "minItems": 2,
                "maxItems": 2,
                "description": "[low, high], low at most high"
              },
              "confidence": {
                "type": "array",
                "prefixItems": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "number"
                  }
                ],
                "minItems": 2,
                "maxItems": 2,
                "description": "[low, high], low at most high"
              },
              "brightness": {
                "type": "array",
                "prefixItems": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "number"
                  }
                ],
                "minItems": 2,
                "maxItems": 2,
                "description": "[low, high], low at most high"
              },
              "channels": {
                "type": "object",
                "additionalProperties": {
                  "type": "array",
                  "prefixItems": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "number"
                    }
                  ],
                  "minItems": 2,
                  "maxItems": 2,
                  "description": "[low, high], low at most high"
                }
              },
              "colors": {
                "type": "array",
                "items": {
                  "enum": [
                    "red",
                    "yellow",
                    "green",
                    "cyan",
                    "blue",
                    "magenta",
                    "dim"
                  ]
                }
              },
              "units": {
                "type": "object",
                "properties": {
                  "size": {
                    "enum": [
                      "pixelCount",
                      "areaUm2"
                    ]
                  },
                  "confidence": {
                    "enum": [
                      "confidence"
                    ]
                  },
                  "brightness": {
                    "enum": [
                      "mean",
                      "meanAboveBackground"
                    ]
                  }
                },
                "additionalProperties": false
              }
            },
            "additionalProperties": false
          }
        },
        "channels": {
          "description": "Read from files written before a step named its own channel.",
          "type": "object",
          "properties": {
            "parents": {
              "type": "integer",
              "minimum": 0
            },
            "children": {
              "type": "integer",
              "minimum": 0
            }
          },
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    },
    "source": {
      "type": "object",
      "properties": {
        "generator": {
          "type": "string"
        },
        "templateVersion": {
          "type": "integer",
          "minimum": 1
        }
      }
    }
  },
  "$defs": {
    "stepId": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_][A-Za-z0-9_:|-]{0,127}$",
      "not": {
        "enum": [
          "__proto__",
          "constructor",
          "prototype"
        ]
      }
    },
    "objectSet": {
      "type": "string",
      "pattern": "^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$"
    },
    "binding": {
      "oneOf": [
        {
          "type": "object",
          "required": [
            "image"
          ],
          "properties": {
            "image": {
              "type": "string",
              "pattern": "^(main|ch:(0|[1-9][0-9]{0,2}))$"
            }
          },
          "additionalProperties": false
        },
        {
          "type": "object",
          "required": [
            "from"
          ],
          "properties": {
            "from": {
              "$ref": "#/$defs/stepId"
            }
          },
          "additionalProperties": false
        },
        {
          "description": "The whole image as one region, whatever its size",
          "type": "object",
          "required": [
            "wholeImage"
          ],
          "properties": {
            "wholeImage": {
              "const": true
            }
          },
          "additionalProperties": false
        }
      ]
    }
  }
}
