{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://nooscope.org/schema/reading.schema.json",
  "title": "Nooscope reading",
  "description": "A single reading. See METHOD.md section 4. A reading is a record with a number in it, not a number.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "id",
    "subject",
    "type",
    "status",
    "value",
    "interval",
    "state",
    "n",
    "method_version",
    "computation",
    "source",
    "commissioned_by",
    "fee",
    "caveats",
    "issued"
  ],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^NS-[0-9]{4}$",
      "description": "Permanent identifier. Never reused, never reissued with different content."
    },
    "subject": {
      "type": "string",
      "minLength": 3,
      "description": "What was measured, in plain language, at the specificity actually achieved."
    },
    "type": {
      "enum": [
        "A",
        "B",
        "C",
        "D",
        "E",
        "F"
      ],
      "description": "Reading type per METHOD.md section 3. Governs scale comparability."
    },
    "status": {
      "enum": [
        "planned",
        "in_progress",
        "issued",
        "superseded",
        "withdrawn_source"
      ]
    },
    "scale": {
      "enum": [
        "perturbational",
        "spontaneous_proxy",
        "cited",
        "indicator_profile",
        "separation"
      ],
      "description": "Derived from type. Only 'perturbational' readings share one axis."
    },
    "value": {
      "type": [
        "number",
        "null"
      ],
      "description": "The scalar. Null for type E and for any reading not yet issued."
    },
    "interval": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "required": [
        "low",
        "high",
        "basis"
      ],
      "properties": {
        "low": {
          "type": "number"
        },
        "high": {
          "type": "number"
        },
        "basis": {
          "type": "string",
          "minLength": 10,
          "description": "How the interval was derived and which wideners of section 5 applied."
        },
        "wideners": {
          "type": "array",
          "items": {
            "enum": [
              "small_n",
              "instrumentation_mismatch",
              "species_extrapolation",
              "preparation_extrapolation",
              "proxy_substitution",
              "parameter_departure"
            ]
          }
        },
        "spans_cutoff": {
          "type": "boolean",
          "description": "True if the interval spans the empirical cutoff. If true, summary must say the reading does not resolve the question."
        },
        "factors": {
          "type": "array",
          "description": "INSTRUCTION.md Domain 5. One entry per applied widener. A factor whose basis is `provisional` has no measurement behind it and is listed for review each cycle.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "widener",
              "factor",
              "basis"
            ],
            "properties": {
              "widener": {
                "enum": [
                  "small_n",
                  "instrumentation_mismatch",
                  "species_extrapolation",
                  "preparation_extrapolation",
                  "proxy_substitution",
                  "parameter_departure"
                ]
              },
              "factor": {
                "type": "number",
                "exclusiveMinimum": 1.0
              },
              "basis": {
                "enum": [
                  "measured",
                  "provisional"
                ]
              },
              "basis_note": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        },
        "base": {
          "enum": [
            "between_unit_sd"
          ],
          "description": "INSTRUCTION.md 5.1. The base is the between-unit standard deviation. The standard error of the mean is not admissible: it narrows as cells accumulate, while the section 5 wideners are systematic and do not."
        },
        "widener_product": {
          "type": [
            "number",
            "null"
          ],
          "exclusiveMinimum": 0,
          "description": "INSTRUCTION.md 5, 1.7.0. The combined multiplier actually applied. Required where a dependent widener pair is declared, so the combination rule is machine-checkable rather than implied."
        }
      }
    },
    "state": {
      "type": "string",
      "description": "Condition of the subject at the time of measurement."
    },
    "n": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "subjects"
      ],
      "properties": {
        "subjects": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "sessions": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "trials": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        }
      }
    },
    "method_version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
    },
    "computation": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "required": [
        "library",
        "version",
        "parameters"
      ],
      "properties": {
        "library": {
          "type": "string"
        },
        "version": {
          "type": "string"
        },
        "commit": {
          "type": "string",
          "description": "Exact commit hash of the computation library used."
        },
        "parameter_set": {
          "type": "string",
          "description": "Name of the documented set, or 'custom'."
        },
        "parameters": {
          "type": "object"
        },
        "departure_reason": {
          "type": [
            "string",
            "null"
          ],
          "description": "Required and non-null whenever parameter_set is 'custom'."
        },
        "seed": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Required when a computation involves randomness (METHOD.md s2.1)."
        },
        "spec_version": {
          "type": [
            "string",
            "null"
          ],
          "description": "METHOD.md 2.1, 0.4.1. The version of spec/PCIST-1.0.md the computation was executed under. Required from 0.4.1: METHOD has required this field since 0.4.1 while the schema rejected it until 0.4.4, so no reading could carry it and validate."
        }
      }
    },
    "source": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "dataset",
        "license",
        "commercial_use"
      ],
      "properties": {
        "dataset": {
          "type": "string"
        },
        "identifier": {
          "type": [
            "string",
            "null"
          ]
        },
        "access": {
          "type": [
            "string",
            "null"
          ]
        },
        "license": {
          "type": "string"
        },
        "commercial_use": {
          "enum": [
            "permitted",
            "restricted",
            "unconfirmed"
          ],
          "description": "Travels with the reading so the restriction is never separated from the number."
        },
        "retrieved": {
          "type": [
            "string",
            "null"
          ],
          "format": "date"
        },
        "verified": {
          "type": "boolean",
          "description": "False where the citation has not yet been confirmed against the source."
        }
      }
    },
    "commissioned_by": {
      "type": [
        "string",
        "null"
      ],
      "description": "The party who paid for this reading, or null. REQUIRED FIELD WITH NO DEFAULT. See METHOD.md section 10."
    },
    "fee": {
      "type": [
        "number",
        "null"
      ],
      "description": "Fee received in USD, or null. REQUIRED FIELD WITH NO DEFAULT."
    },
    "caveats": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "What went wrong, what is weak, what a critic should attack first."
    },
    "summary": {
      "type": [
        "string",
        "null"
      ],
      "description": "One plain-language sentence. Must not contain a claim barred by METHOD.md section 7."
    },
    "issued": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "required": [
        "date",
        "by"
      ],
      "properties": {
        "date": {
          "type": "string",
          "format": "date"
        },
        "by": {
          "type": "string"
        }
      }
    },
    "supersedes": {
      "type": [
        "string",
        "null"
      ]
    },
    "superseded_by": {
      "type": [
        "string",
        "null"
      ]
    },
    "indicator_profile": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "required": [
        "access_level",
        "assessable",
        "results"
      ],
      "properties": {
        "access_level": {
          "enum": [
            "L0",
            "L1",
            "L2"
          ]
        },
        "assessable": {
          "type": "integer",
          "minimum": 0,
          "maximum": 14
        },
        "results": {
          "type": "object"
        },
        "controls_applied": {
          "type": "array",
          "items": {
            "enum": [
              "vocabulary_free",
              "paraphrase_invariance",
              "negative_controls",
              "rotating_holdout"
            ]
          }
        }
      }
    },
    "stimulation": {
      "type": [
        "object",
        "null"
      ],
      "description": "Required for Type A and Type B readings (METHOD.md 2.1). Perturbational readings are not comparable across stimulation intensities.",
      "additionalProperties": false,
      "required": [
        "modality",
        "intensity",
        "intensity_units",
        "site"
      ],
      "properties": {
        "modality": {
          "type": "string",
          "description": "e.g. TMS, SPES, intracortical microstimulation"
        },
        "intensity": {
          "type": [
            "number",
            "array"
          ],
          "description": "Single value, or [low, high] when an aggregate pools a range."
        },
        "intensity_units": {
          "type": "string",
          "description": "e.g. uA, mA, %MSO, V/m"
        },
        "site": {
          "type": "string"
        },
        "depth": {
          "type": [
            "string",
            "null"
          ],
          "description": "e.g. deep, superficial, or a stated coordinate."
        },
        "pooled_across_intensity": {
          "type": "boolean",
          "description": "True when the reading aggregates more than one intensity; requires intensity to be a range."
        },
        "waveform": {
          "type": [
            "string",
            "null"
          ],
          "description": "METHOD.md s2.1 (0.3.4). monophasic or biphasic, as delivered."
        },
        "pulse_width_ms": {
          "type": [
            "number",
            "null"
          ],
          "description": "METHOD.md s2.1 (0.3.4). Pulse width in milliseconds. null only where the source does not state it."
        },
        "repetition_rate_hz": {
          "type": [
            "number",
            "null"
          ],
          "description": "METHOD.md s2.1 (0.3.4). Repetition rate in hertz. null only where the source does not state it."
        },
        "protocol_name": {
          "type": [
            "string",
            "null"
          ],
          "description": "METHOD.md s2.1 (0.3.4). The deposit's own label for the protocol, where it has one."
        }
      }
    },
    "rejection": {
      "type": [
        "object",
        "null"
      ],
      "description": "Channels and trials excluded, and the rule applied (METHOD.md 2.1). Excluding nothing must be stated explicitly, not left absent.",
      "additionalProperties": false,
      "required": [
        "channel_rule",
        "trial_rule",
        "channels_excluded",
        "trials_excluded"
      ],
      "properties": {
        "channel_rule": {
          "type": "string",
          "enum": [
            "source_flags",
            "manual",
            "none"
          ]
        },
        "trial_rule": {
          "type": "string",
          "enum": [
            "amplitude",
            "manual",
            "none"
          ]
        },
        "trial_threshold_uv": {
          "type": [
            "number",
            "array",
            "null"
          ],
          "items": {
            "type": "number"
          },
          "minItems": 2,
          "maxItems": 2,
          "description": "The threshold in uV, or [low, high] across sessions when the rule derives one per session."
        },
        "channels_excluded": {
          "type": "integer",
          "minimum": 0
        },
        "channels_retained": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "trials_excluded": {
          "type": "integer",
          "minimum": 0
        },
        "trials_retained": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "trial_threshold_rule": {
          "type": [
            "string",
            "null"
          ],
          "description": "How the threshold was derived, when it is not a fixed constant."
        }
      }
    },
    "matching": {
      "type": [
        "object",
        "null"
      ],
      "description": "How a between-state comparison was held constant across the states it compares (METHOD.md 2.1). Required when a reading's comparison_state is set.",
      "additionalProperties": false,
      "required": [
        "channel_rule",
        "trial_rule"
      ],
      "properties": {
        "channel_rule": {
          "type": "string",
          "enum": [
            "intersect_across_states",
            "per_recording",
            "none"
          ],
          "description": "per_recording compares two states on two different arrays and must be justified."
        },
        "trial_rule": {
          "type": "string",
          "enum": [
            "match_per_site",
            "match_per_session",
            "none"
          ]
        },
        "trial_selection": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "evenly_spaced",
            "random_seeded",
            "first_n",
            "last_n",
            null
          ],
          "description": "Deterministic selection is preferred; random_seeded must state the seed in computation."
        },
        "channels_dropped_for_disagreement": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0,
          "description": "Channels good in one state but not the other, and therefore excluded from both."
        },
        "trials_excluded_matching": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "unmatched_reported": {
          "type": "boolean",
          "description": "True when the uncorrected computation is published alongside the matched one."
        }
      }
    },
    "comparison_state": {
      "type": [
        "string",
        "null"
      ],
      "description": "The other state this reading is to be compared against, when the reading is one arm of a within-subject contrast. Its presence makes the matching record required."
    },
    "derived_from": {
      "type": [
        "array",
        "null"
      ],
      "minItems": 2,
      "maxItems": 2,
      "items": {
        "type": "string",
        "pattern": "^NS-[0-9]{4}$"
      },
      "description": "Type F only (METHOD.md 3.2). The two issued readings the contrast is computed between, high state first."
    },
    "separation": {
      "type": [
        "object",
        "null"
      ],
      "description": "Type F only (METHOD.md 3.2). How the contrast was paired and what it showed.",
      "additionalProperties": false,
      "required": [
        "pairing_unit",
        "pairs",
        "higher_fraction",
        "test",
        "p_value"
      ],
      "properties": {
        "pairing_unit": {
          "type": "string",
          "description": "The unit both readings share: session, stimulation site, subject."
        },
        "pairs": {
          "type": "integer",
          "minimum": 2
        },
        "higher": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "higher_fraction": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "test": {
          "type": "string"
        },
        "p_value": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "pairs_dropped": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0,
          "description": "Pairs excluded from the ratio, and why, e.g. a zero denominator."
        },
        "subjects_agreeing": {
          "type": [
            "string",
            "null"
          ],
          "description": "How many subjects separate in the same direction, as 'k/n'."
        }
      }
    },
    "geometry": {
      "enum": [
        "ecog_grid",
        "seeg_depth",
        "scalp_eeg",
        "mea",
        "probe_linear",
        "epidural_array",
        null
      ],
      "description": "METHOD.md s3.3. The recording arrangement that produced this value. The set is CLOSED and extended only by amendment. Until 0.4.4 this field was free text whose description still read 'or another named arrangement' \u2014 the phrase METHOD removed in 0.3.7 \u2014 so the closure existed in the document and not in the schema. Required on type A and B readings issued under method 0.3.3 or later; null only on readings issued before the field existed. Absolute values are not compared across geometries."
    },
    "modality_tier": {
      "enum": [
        "M1",
        "M2",
        "M3",
        "M4"
      ],
      "description": "METHOD 3.4. M1 instrumented perturbational; M2 instrumented spontaneous; M3 instrumented indirect; M4 report-dependent. Displayed on the face of the reading, never in a footnote. Determines the strongest comparison the reading may support. Not a restatement of `type`: type records provenance, tier records what kind of measurement it is."
    },
    "instruction_version": {
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
      "description": "Version of INSTRUCTION.md in force when the reading was produced. Cited with the reading per METHOD 12 condition 10."
    },
    "rating": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "mode",
        "rater_a"
      ],
      "description": "METHOD 9.3. Two independent raters who did not confer. Pre-adjudication ratings are retained permanently: discarding them would make every published reliability statistic unverifiable.",
      "properties": {
        "rater_a": {
          "$ref": "#/$defs/rater"
        },
        "rater_b": {
          "anyOf": [
            {
              "$ref": "#/$defs/rater"
            },
            {
              "type": "null"
            }
          ]
        },
        "agreed_pre_adjudication": {
          "type": "boolean"
        },
        "adjudicator": {
          "type": [
            "string",
            "null"
          ],
          "description": "Named third party. Required where agreed_pre_adjudication is false."
        },
        "adjudication_note": {
          "type": [
            "string",
            "null"
          ],
          "description": "The adjudicator's decision and reasoning."
        },
        "mode": {
          "enum": [
            "dual_independent_human",
            "dual_independent_implementation",
            "dual_implementation_same_author",
            "single"
          ],
          "description": "METHOD 9.3.1. How the reading was rated. `dual_independent_human` is the full condition. `dual_independent_implementation` is two independent executions of INSTRUCTION.md, at least one written from the instruction text alone without sight of the other's code: it tests whether the method is specified tightly enough to execute the same way twice, which is weaker than whether two minds agree, and is labeled as the weaker thing. `single` is one rater and is NOT conformant under METHOD 12 condition 9; the reading is a valid record and says so on its face."
        }
      }
    },
    "grain": {
      "type": "object",
      "description": "Recording resolution (METHOD 3.5). Required for readings issued under 0.3.9 or later; enforcement is versioned in the profile, not here.",
      "properties": {
        "pitch_mm": {
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "Nominal centre-to-centre spacing the array was manufactured at, in millimetres, from a specification. A catalog figure, not a measurement (METHOD 3.5)."
        },
        "channels": {
          "type": "integer",
          "minimum": 1,
          "description": "Admitted channel count the value was computed from, after METHOD 3.3 exclusions."
        },
        "basis": {
          "enum": [
            "deposit_electrode_description",
            "manufacturer_specification",
            "computed_from_coordinates"
          ],
          "description": "Where the pitch came from. A closed set: a pitch is never estimated from array dimensions or a comparable implant (INSTRUCTION 3.6)."
        },
        "pitch_measured_mm": {
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "Median nearest-neighbour distance over adjacent admitted contacts of the majority group, from stated coordinates. Must sit within 15% of pitch_mm (INSTRUCTION 3.7). Omitted where the deposit states no coordinates."
        },
        "layout": {
          "enum": [
            "uniform",
            "non_uniform"
          ],
          "description": "uniform = a lattice with one manufactured spacing; non_uniform = individually specified site positions, which have no single pitch (METHOD 3.5)."
        },
        "basis_source": {
          "type": "string",
          "minLength": 4,
          "description": "The specification, catalog page or paper the pitch came from. Required for a non_uniform layout, where the figure is derived from a published coordinate table."
        }
      },
      "required": [
        "pitch_mm",
        "channels",
        "basis",
        "layout"
      ],
      "additionalProperties": false
    },
    "matched_null": {
      "type": "object",
      "description": "METHOD 2.3. The per-recording sham floor: the same channels, trial count, parameter set and averaging, with epoch onsets drawn away from any stimulation. Required for perturbational readings from 0.4.4.",
      "properties": {
        "sham_median": {
          "type": "number",
          "minimum": 0
        },
        "sham_p95": {
          "type": "number",
          "minimum": 0
        },
        "n_draws": {
          "type": "integer",
          "minimum": 1
        },
        "clearance": {
          "type": "number",
          "minimum": 0,
          "description": "value / sham_median, per recording. A reading whose clearance is near or below 1 is not distinguishable from its own instrument."
        },
        "rule": {
          "type": "string",
          "minLength": 4
        }
      },
      "required": [
        "sham_median",
        "n_draws",
        "clearance",
        "rule"
      ],
      "additionalProperties": true
    },
    "temporal_grain": {
      "type": "object",
      "description": "METHOD 3.6. The temporal resolution of the recording as computed. Required for readings issued under 0.4.9 or later.",
      "properties": {
        "fs_hz": {
          "type": [
            "number",
            "null"
          ],
          "description": "Acquisition sampling rate of the admitted signal, before any resampling.",
          "exclusiveMinimum": 0
        },
        "resample_hz": {
          "type": [
            "number",
            "null"
          ],
          "description": "Rate the computation resampled to, or null where none was applied.",
          "exclusiveMinimum": 0
        },
        "response_samples": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Realized samples in the response window. The figure METHOD 3.6's sensitivity curve is indexed on.",
          "minimum": 1
        },
        "trials": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Trials entering the average.",
          "minimum": 1
        },
        "sites": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Distinct perturbation sites those trials are drawn from. One trial per site is a different paradigm, not a trial count of one.",
          "minimum": 1
        }
      },
      "required": [
        "fs_hz",
        "resample_hz",
        "response_samples",
        "trials"
      ],
      "additionalProperties": false
    }
  },
  "$defs": {
    "rater": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "rater_id",
        "value",
        "type",
        "modality_tier"
      ],
      "properties": {
        "rater_id": {
          "type": "string",
          "minLength": 1
        },
        "value": {
          "type": [
            "number",
            "null"
          ]
        },
        "type": {
          "enum": [
            "A",
            "B",
            "C",
            "D",
            "E",
            "F"
          ]
        },
        "modality_tier": {
          "enum": [
            "M1",
            "M2",
            "M3",
            "M4"
          ]
        },
        "geometry": {
          "type": [
            "string",
            "null"
          ]
        },
        "wideners": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "assessment_minutes": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0
        }
      }
    }
  }
}