{
 "$schema": "http://json-schema.org/draft-07/schema#",
 "$id": "https://ausmt.auscope.org.au/data/schemas/mtcat/2.0/mtcat.schema.json",
 "title": "MTCAT v2.0: Magnetotelluric Catalogue interchange document",
 "description": "Discovery interchange document for magnetotelluric survey and station holdings. Semantics are defined by the MTCAT specification; this schema enforces the machine-checkable layer. Record objects keep additionalProperties true so later minor versions and local extensions never break validation; described fields are strictly typed and vocabulary fields are enum-pinned.",
 "type": "object",
 "required": [
  "portal",
  "surveys",
  "stations"
 ],
 "additionalProperties": true,
 "properties": {
  "portal": {
   "type": "object",
   "description": "identity of the portal that produced this document",
   "required": [
    "portal_id",
    "portal_name",
    "schema",
    "version",
    "generated_at"
   ],
   "additionalProperties": true,
   "properties": {
    "portal_id": {
     "type": "string",
     "minLength": 1,
     "description": "stable opaque identity token of the producing catalogue; never changes across rebuilds or host migrations, and global keys pair it with survey_id or station_id"
    },
    "portal_name": {
     "type": "string",
     "description": "human-readable catalogue name; presentational"
    },
    "schema": {
     "type": "string",
     "const": "mtcat",
     "description": "document self-identification"
    },
    "version": {
     "type": "string",
     "pattern": "^[0-9]+\\.[0-9]+$",
     "description": "schema version this document conforms to, as major.minor"
    },
    "schema_url": {
     "type": "string",
     "description": "location of this schema served beside the document, relative or absolute, so a harvester can validate without resolving the canonical $id"
    },
    "metadata_license": {
     "type": "string",
     "description": "licence of the catalogue metadata itself, distinct from per-survey data licences, e.g. an SPDX identifier"
    },
    "generated_at": {
     "type": "string",
     "description": "UTC build timestamp of this document, ISO 8601",
     "format": "date-time"
    }
   }
  },
  "surveys": {
   "type": "array",
   "items": {
    "type": "object",
    "required": [
     "survey_id",
     "title",
     "organisation",
     "country"
    ],
    "additionalProperties": true,
    "properties": {
     "survey_id": {
      "type": "string",
      "minLength": 1,
      "description": "stable discovery identifier of this survey record within the producing catalogue"
     },
     "title": {
      "type": "string",
      "description": "human-readable survey dataset title"
     },
     "organisation": {
      "type": "string",
      "description": "organisation with primary custodial responsibility for the represented dataset"
     },
     "country": {
      "type": "string",
      "description": "country of the holdings"
     },
     "doi": {
      "type": "string",
      "description": "persistent DOI of the exact dataset or release this record represents, bare form; never a containing collection, report, or activity identifier"
     },
     "license": {
      "type": "string",
      "description": "licence of the survey's data"
     },
     "access": {
      "type": "string",
      "description": "normalised access level; open, metadata_only and embargoed are the well-known values. Deliberately not enum-pinned: an unrecognised value means a withheld survey, not a broken document"
     },
     "embargo_until": {
      "type": "string",
      "description": "date a declared embargo lapses; absent means no declared end date, not open access",
      "format": "date"
     },
     "bbox": {
      "type": "object",
      "description": "geographic footprint derived from published station coordinates; omitted when no station is located",
      "required": [
       "west",
       "south",
       "east",
       "north"
      ],
      "additionalProperties": true,
      "properties": {
       "west": {
        "type": "number"
       },
       "south": {
        "type": "number"
       },
       "east": {
        "type": "number"
       },
       "north": {
        "type": "number"
       }
      }
     },
     "centroid": {
      "type": "object",
      "description": "centre of the bbox; omitted when no station is located",
      "required": [
       "latitude",
       "longitude"
      ],
      "additionalProperties": true,
      "properties": {
       "latitude": {
        "type": "number"
       },
       "longitude": {
        "type": "number"
       }
      }
     },
     "n_stations": {
      "type": "integer",
      "minimum": 0,
      "description": "count of this survey's station records in stations[]"
     },
     "data_types": {
      "type": "object",
      "description": "band mix as counts per data_type, using the stations[].data_type vocabulary; omitted when the survey has no stations",
      "propertyNames": {
       "type": "string",
       "enum": [
        "AMT",
        "BBMT",
        "LPMT",
        "GDS",
        "unknown"
       ]
      },
      "additionalProperties": {
       "type": "integer",
       "minimum": 0
      },
      "minProperties": 1
     },
     "period_min_s": {
      "type": "number",
      "description": "shortest period in seconds across the represented transfer functions; omitted when none reports a range",
      "exclusiveMinimum": 0
     },
     "period_max_s": {
      "type": "number",
      "description": "longest period in seconds across the represented transfer functions; omitted when none reports a range",
      "exclusiveMinimum": 0
     },
     "n_stations_tipper": {
      "type": "integer",
      "minimum": 0,
      "description": "how many of this survey's stations carry a tipper; at most n_stations"
     },
     "formats": {
      "type": "array",
      "description": "distribution formats this catalogue currently serves for the survey; emitted only when at least one format is distributed, omitted otherwise (no empty-array state)",
      "uniqueItems": true,
      "items": {
       "type": "string",
       "enum": [
        "edi",
        "edi-zip",
        "emtfxml",
        "mth5",
        "xml-zip"
       ]
      },
      "minItems": 1
     },
     "year_start": {
      "type": "integer",
      "description": "first declared year of acquisition; omitted when undeclared, never inferred from file timestamps"
     },
     "year_end": {
      "type": "integer",
      "description": "last declared year of acquisition; equal to year_start for a single season"
     },
     "version": {
      "type": "string",
      "description": "semantic version of the represented dataset release"
     },
     "collection_id": {
      "type": "string",
      "description": "collection this survey belongs to, matching a collections[].collection_id"
     },
     "organisation_ror": {
      "type": "string",
      "description": "ROR identifier of the custodian organisation"
     },
     "raid": {
      "type": "string",
      "description": "identifier of the related research activity, emitted only when exactly one activity is asserted; surveys with several related activities omit it and express them in richer linked metadata"
     },
     "creators": {
      "type": "array",
      "description": "citation authors of the release, in citation order; the order is preserved verbatim by consumers",
      "items": {
       "type": "object",
       "required": [
        "name"
       ],
       "additionalProperties": true,
       "properties": {
        "name": {
         "type": "string",
         "minLength": 1,
         "description": "the creator as cited"
        },
        "name_type": {
         "type": "string",
         "enum": [
          "person",
          "organisation"
         ],
         "description": "person or organisation"
        },
        "orcid": {
         "type": "string",
         "description": "ORCID iD of a person creator, bare or as a full URL; omitted when none"
        },
        "ror": {
         "type": "string",
         "description": "ROR identifier of an organisation creator; omitted when none"
        }
       }
      },
      "minItems": 1
     },
     "contributors": {
      "type": "array",
      "description": "who did what on the release, as DataCite contributors, in declared order; a hosting-portal row with role HostingInstitution may be appended by the producer",
      "items": {
       "type": "object",
       "required": [
        "name"
       ],
       "additionalProperties": true,
       "properties": {
        "name": {
         "type": "string",
         "minLength": 1
        },
        "name_type": {
         "type": "string",
         "enum": [
          "person",
          "organisation"
         ],
         "description": "person or organisation"
        },
        "role": {
         "type": "string",
         "enum": [
          "ProjectLeader",
          "ProjectMember",
          "DataCollector",
          "ContactPerson",
          "DataCurator",
          "Sponsor",
          "RightsHolder",
          "Distributor",
          "HostingInstitution"
         ],
         "description": "DataCite contributorType; HostingInstitution is reserved for the appended portal row and is not declared by a survey"
        },
        "orcid": {
         "type": "string",
         "description": "ORCID iD of a person contributor, bare or as a full URL; omitted when none"
        },
        "ror": {
         "type": "string",
         "description": "ROR identifier of an organisation contributor; omitted when none"
        }
       }
      },
      "minItems": 1
     },
     "related_identifiers": {
      "type": "array",
      "description": "typed links to related records; present only when the survey declares at least one",
      "items": {
       "type": "object",
       "additionalProperties": true,
       "properties": {
        "identifier": {
         "type": "string",
         "description": "the identifier itself, bare form for DOIs",
         "minLength": 1
        },
        "identifier_type": {
         "type": "string",
         "enum": [
          "DOI",
          "Handle",
          "URL",
          "RAiD"
         ],
         "description": "kind of identifier; omitted when undeclared"
        },
        "relation": {
         "type": "string",
         "enum": [
          "IsDerivedFrom",
          "IsVariantFormOf",
          "IsSupplementTo",
          "Cites",
          "IsPartOf",
          "IsSourceOf",
          "References",
          "IsIdenticalTo",
          "HasMetadata",
          "IsDocumentedBy"
         ],
         "description": "DataCite relationType, read as 'this survey, relation, that record', chosen case by case for the true relation; a HasMetadata target must genuinely provide metadata about the dataset, never an inventory or manifest; an IsDocumentedBy target documents the ACTIVITY behind the dataset (e.g. an ANSIR project record), not the data bytes; omitted when undeclared"
        },
        "custodian": {
         "type": "string",
         "description": "who holds the identified record"
        },
        "identifies": {
         "type": "string",
         "enum": [
          "collection",
          "raw_packed",
          "level0",
          "level1",
          "level2",
          "level3",
          "entire"
         ],
         "description": "what the identifier points at, in data-level terms: collection is the parent record, raw_packed is raw or packed time series, level0 edited time series, level1 transformed time series, level2 processed frequency-domain data, level3 models, entire one record covering all levels; absent on legacy rows means level not stated"
        },
        "resolution": {
         "type": "string",
         "enum": [
          "ok",
          "reserved"
         ],
         "description": "whether the identifier currently resolves: ok, or reserved (registered but not yet active); absent means unknown, never broken"
        },
        "scheme": {
         "type": "string",
         "description": "for HasMetadata rows, the metadata family at the target, e.g. mt_metadata, ISO19115, DataCite"
        }
       },
       "required": [
        "identifier"
       ]
      },
      "minItems": 1
     },
     "attribution": {
      "type": "object",
      "description": "rights declaration of this release; present only when declared",
      "additionalProperties": true,
      "properties": {
       "custodian": {
        "type": "string",
        "description": "rights holder of record, which may differ from the acquiring organisation"
       },
       "custodian_ror": {
        "type": "string",
        "description": "ROR identifier of the custodian"
       },
       "statement": {
        "type": "string",
        "description": "attribution wording to reproduce verbatim, never reformatted or abbreviated"
       },
       "changes_made": {
        "type": "boolean",
        "description": "whether this release changed the upstream material"
       },
       "changes_summary": {
        "type": "string",
        "description": "plain-language summary of the changes, when changes_made is true"
       },
       "declared_by": {
        "type": "string",
        "description": "who recorded the declaration"
       },
       "declared_date": {
        "type": "string",
        "description": "date of the declaration, not of the data",
        "format": "date"
       }
      }
     },
     "description": {
      "type": "string",
      "description": "concise discovery blurb for the dataset this record represents; complements, never replaces, the source's own documentation"
     },
     "subjects": {
      "type": "array",
      "items": {
       "type": "object",
       "additionalProperties": true,
       "required": [
        "code",
        "scheme"
       ],
       "properties": {
        "code": {
         "type": "string",
         "minLength": 1,
         "description": "the classification code within the named scheme, e.g. 370602"
        },
        "scheme": {
         "type": "string",
         "minLength": 1,
         "description": "explicit scheme token; registered tokens bind the token to a scheme URI so code and scheme pairs compare across producers"
        },
        "label": {
         "type": "string",
         "description": "human-readable label of the concept, for consumers that cannot resolve the scheme"
        },
        "uri": {
         "type": "string",
         "description": "stable concept URI governed by the scheme's authority, where one exists"
        }
       },
       "description": "one thematic subject as a controlled, optionally labelled, optionally resolvable concept"
      },
      "description": "thematic classification of the represented dataset for discovery and cross-catalogue mapping; absent means no assertion",
      "minItems": 1
     },
     "sample_rates_hz": {
      "type": "array",
      "uniqueItems": true,
      "items": {
       "type": "number",
       "exclusiveMinimum": 0
      },
      "description": "distinct acquisition sample rates known to be represented in the survey, in Hz; discrete modes, never an extent, taken only from explicit acquisition metadata and never inferred from instrument capability or period coverage; canonicalised and sorted ascending",
      "minItems": 1
     },
     "n_stations_time_series_verified": {
      "type": "integer",
      "minimum": 0,
      "description": "count of this survey's station records carrying has_time_series true; a count of verified existence, stable across access transitions, never subtracted from n_stations to infer absence"
     },
     "coordinates_state": {
      "type": "string",
      "enum": [
       "exact",
       "generalised",
       "withheld"
      ],
      "description": "how published coordinates relate to acquisition positions; over mixed per-station states: all exact means exact, all withheld means withheld, any other mixture means generalised. The state is public, the reason need not be; absence makes no assertion. A withheld state forbids bbox and centroid (they would republish the withheld footprint)"
     }
    },
    "if": {
     "properties": {
      "coordinates_state": {
       "const": "withheld"
      }
     },
     "required": [
      "coordinates_state"
     ]
    },
    "then": {
     "properties": {
      "bbox": false,
      "centroid": false
     }
    }
   }
  },
  "stations": {
   "type": "array",
   "items": {
    "type": "object",
    "required": [
     "station_id",
     "survey_id",
     "latitude",
     "longitude",
     "data_type"
    ],
    "additionalProperties": true,
    "properties": {
     "station_id": {
      "type": "string",
      "minLength": 1,
      "description": "identifier of this published station record, unique within the document"
     },
     "survey_id": {
      "type": "string",
      "minLength": 1,
      "description": "the surveys[].survey_id this station belongs to"
     },
     "latitude": {
      "type": [
       "number",
       "null"
      ],
      "minimum": -90,
      "maximum": 90,
      "description": "WGS84 latitude in decimal degrees; may be deliberately generalised per the survey's coordinates_state. Null is defined: the position is not published (withheld under policy, or unlocated)"
     },
     "longitude": {
      "type": [
       "number",
       "null"
      ],
      "minimum": -180,
      "maximum": 180,
      "description": "WGS84 longitude in decimal degrees; see the latitude note; null means the position is not published"
     },
     "data_type": {
      "type": "string",
      "enum": [
       "AMT",
       "BBMT",
       "LPMT",
       "GDS",
       "unknown"
      ],
      "description": "band class derived from the shortest period and the transfer functions present: AMT under 1e-3 s, BBMT under 1 s, LPMT long period, GDS tipper-only with no impedance, unknown when no period range could be read"
     },
     "has_time_series": {
      "const": true,
      "description": "present with value true when the producing catalogue has positively verified that a time-series resource for this station exists; existence semantics, with access a separate question; absence makes no assertion and false is never emitted"
     }
    },
    "oneOf": [
     {
      "properties": {
       "latitude": {
        "type": "number"
       },
       "longitude": {
        "type": "number"
       }
      }
     },
     {
      "properties": {
       "latitude": {
        "type": "null"
       },
       "longitude": {
        "type": "null"
       }
      }
     }
    ],
    "description": "one published station record; latitude and longitude are either both numeric or both null (a half-null position is invalid) - both null means the position is not published"
   }
  },
  "collections": {
   "type": "array",
   "description": "optional groupings of related surveys, e.g. a programme; discovery rollup only, with all scientific provenance staying on member surveys",
   "items": {
    "type": "object",
    "additionalProperties": true,
    "required": [
     "collection_id",
     "title"
    ],
    "properties": {
     "collection_id": {
      "type": "string",
      "description": "id member surveys reference via surveys[].collection_id, by exact string match"
     },
     "title": {
      "type": "string"
     },
     "type": {
      "type": "string",
      "description": "e.g. programme"
     },
     "status": {
      "type": "string",
      "description": "lifecycle state; active, completed and archived are the well-known values; deliberately not enum-pinned"
     },
     "start_year": {
      "type": "integer",
      "description": "year the programme began, as declared by member surveys; omitted when none declares one"
     },
     "last_updated": {
      "type": "string",
      "description": "curation date of the programme description, not an acquisition date and not this document's generated_at",
      "format": "date"
     },
     "description": {
      "type": "string",
      "description": "prose description of the programme"
     },
     "n_surveys": {
      "type": "integer",
      "minimum": 0,
      "description": "how many surveys belong to this collection"
     },
     "n_stations": {
      "type": "integer",
      "minimum": 0,
      "description": "total stations across the member surveys"
     },
     "bbox": {
      "type": "object",
      "description": "footprint across every member survey's stations; omitted when none is located",
      "required": [
       "west",
       "south",
       "east",
       "north"
      ],
      "additionalProperties": true,
      "properties": {
       "west": {
        "type": "number"
       },
       "south": {
        "type": "number"
       },
       "east": {
        "type": "number"
       },
       "north": {
        "type": "number"
       }
      }
     },
     "centroid": {
      "type": "object",
      "description": "mean of member station positions, unlike a survey centroid which is the centre of its bbox; omitted when none is located",
      "required": [
       "latitude",
       "longitude"
      ],
      "additionalProperties": true,
      "properties": {
       "latitude": {
        "type": "number"
       },
       "longitude": {
        "type": "number"
       }
      }
     }
    }
   },
   "minItems": 1
  }
 }
}