Skip to content

Latest commit

 

History

History
135 lines (119 loc) · 7.02 KB

File metadata and controls

135 lines (119 loc) · 7.02 KB

Changelog

Format: Keep a Changelog. This project follows Semantic Versioning.

The JSON output contract has its own SCHEMA_VERSION, tracked independently of the package version below.

0.2.0 - 2026-06-21

First release published to PyPI. (0.1.0 was prepared and tagged in the changelog below but never uploaded; this is the first public artifact.) Builds on the 0.1.0 baseline with the cache wired in, a CPU-runnable full pipeline, and opt-in Schaefer-400 detail.

SCHEMA_VERSION moves 1.01.1 (additive, backward-compatible).

Added

  • Two-tier cache wired into the scoring path. score() now reuses a cached TRIBE forward pass for the same video (prediction cache) and a cached ScoreResult for identical scoring inputs (score cache); score_from_predictions / score_from_prediction_bundle use the score cache. cache info reports real, non-zero counts after a run. Toggle with ScoreConfig(use_cache=..., refresh=...) / the CLI --no-cache and --refresh flags (the --no-cache flag removed in 0.1.0 returns, as promised).
  • ReplayRunner (cortex_score.runners.ReplayRunner): a torch-free PredictionRunner that replays a saved (T, 20484) tensor through the full score(video, runner=...) path. Re-score predictions offline on CPU and get byte-identical JSON to a GPU run; also gives the headline path deterministic CI coverage.
  • Opt-in Schaefer-400 per-parcel detail (SCHEMA_VERSION = "1.1"). ScoreConfig(include_schaefer_parcels=True) adds a ScoreResult.schaefer object with mean_energy / peak_energy / temporal_volatility for all 400 Schaefer-2018 parcels, each tagged with its parent Yeo-17 network. The default 5-network output is numerically unchanged; the only deltas in a default result are the bumped version string and a nullable schaefer field. This is the first runtime consumer of the bundled Schaefer-400 vertex map, the Schaefer-400 → Yeo-17 mapping, and processing.metrics.
  • python -m cortex_score entry point (mirrors the cortex-score CLI).
  • torchaudio added to the [gpu-deps] extra and whisperx pinned in requirements/tribev2-gpu.txt, so pip install "cortex-score[gpu-deps]" plus the requirements file is genuinely sufficient to run the full path.
  • benchmarks/bench_aggregate.py: reproducible aggregation micro-benchmark.

Changed

  • aggregate_to_rois reimplemented with a stable-argsort grouping instead of an O(n_rois × V) per-ROI boolean scan - bit-identical output (proven by a property test against the previous loop; the default network scores are unchanged) and ~2.5× faster at Schaefer-400 scale.
  • _parse_segments extracted from the GPU-only runner into a testable, pandas-free runners.segments.parse_segments seam (duck-types the DataFrame path via .columns/.iterrows).
  • api._load_default_runner simplified: the dead MissingOptionalDependencyError / ImportError handlers were removed (importing the TRIBE runner is torch-free; the optional-dependency error correctly surfaces from predict_video).
  • Documentation reconciled with the code: "aggregate to Yeo-17" (not Schaefer-400); examples use the full 40-char TRIBE commit SHA; the modal_smoke per-clip cost comment matches its own arithmetic (≈ $0.11); honest "Not a brain scan" framing added to the hero/spotlight SVGs.

Removed

  • processing.aggregate.remap_atlas - it was a one-line alias of aggregate_to_rois used only by its own test; the Schaefer detail needs the parcel → network label map, not numeric Schaefer → Yeo aggregation.
  • The unused [viz] extra (nibabel): the MZ3 overlay writer is pure stdlib + numpy and there is no NIfTI export. The dependency advertised a capability that did not exist.

[0.1.0] - 2026-06-10

Initial release preparation. Note: 0.1.0 was never published to PyPI - it is recorded here as the development baseline that 0.2.0 builds on. The CPU-only postprocessing tier (score_from_predictions / score_from_prediction_bundle) and the ScoreResult JSON contract (SCHEMA_VERSION = "1.0") were stabilized here.

Added

  • Initial package scaffold (Epics 0-8):
    • Bundled atlas data (Schaefer-400 + Yeo-17 + 5-network rollup) with SHA-256 manifest.
    • Pure-NumPy processing core: aggregate, normalize, metrics, networks, validate.
    • Pydantic v2 schema layer with full provenance: PredictionBundle, ScoreResult, NetworkScore, AtlasMeta, ProvenanceMeta, NormalizationMeta, LicenseRestriction, ScoreWarning.
    • Three-tier public API:
      • score_from_prediction_bundle(bundle) - type-safe.
      • score_from_predictions(preds, mesh=..., tr_seconds=..., ...) - ergonomic, requires explicit scientific assumptions.
      • score(video_path, runner=None) - full pipeline.
    • CortexScorer class for batch reuse.
    • TRIBE v2 adapter under the [gpu-deps] extra (TRIBE itself installed from requirements/tribev2-gpu.txt, pinned to commit 34f52344e5ba96660fac877393e1954e399d3ef3).
    • Two-tier cache infrastructure (prediction cache + score cache, atomic writes, cache_manifest.json, invalidation matrix). NOTE: shipped as plumbing only in 0.1.0 - the scoring path did not read or write it yet (wired in 0.2.0).
    • Typer CLI under [cli] extra: doctor, score, from-predictions, schema, cache info, cache clear.
    • Test suite with property tests, schema snapshot, cache invalidation matrix, packaging smoke, MZ3 format round-trip, result_id verifiability, and import-without-GPU gate.

Fixed (pre-release hardening)

  • result_id is now the SHA-256 of the result's own canonical JSON (with result_id blanked), so it is reproducible from the serialized artifact. The previous hand-built hash payload disagreed with the serialized form (+00:00 vs Z datetimes), making the documented audit hash unverifiable.
  • MZ3 scalar-overlay export now emits the real NiiVue format (uint16 magic 0x5A4D, attr=8/isSCALAR, 16-byte header, gzip). The earlier port wrote a header NiiVue rejected at the magic check.
  • score_from_predictions rejects 1-D/non-finite inputs and unsupported meshes with clear errors at the boundary (UnsupportedMeshError) instead of an opaque IndexError / a raw traceback through the CLI.
  • Version is read from installed distribution metadata (importlib.metadata); the build no longer ships a generated _version.py.

Removed

  • The no-op score --no-cache flag (it silently did nothing). It returns in 0.2.0 now that the cache is wired into the scoring path.

Notes

  • The package source is MIT-licensed. The bundled atlases ship under their original licenses (Schaefer MIT, Yeo BSD-like). The full score() path uses TRIBE v2 which is CC-BY-NC-4.0: outputs from that path inherit the non-commercial restriction. See LICENSE-THIRD-PARTY.md.