Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Project Contents & User Guide

A map of everything in this repository: the tools, datasets, and extracted derivatives, what is included so far, and how to load, view, and inspect them. For a hands-on tour run docs/walkthrough.m in MATLAB.

What this project is. Infrastructure that turns a movie or audio story into second-by-second, hierarchical, computational annotations (visual, audio, language, social, situational, affective), stored in a constant-shape format that loads into MATLAB, plus tools to analyze the annotation structure across a corpus and to design high-variance / low-redundancy stimulus sets.

Status at a glance

PhaseWhatState
1 Scoping reviewbest-in-class tools per feature classdocs/scoping_review/
2 Pipeline23 extractors → constant-shape annotations + MATLAB readersrc/nfe/, matlab/
3 Corpusmanifest + batch runner; 83 stimuli annotated (53 audiovisual + 29 audio stories + 1 text)annotations/corpus/
4 Analysiscorpus reader, viewer, correlation/PCA/network, design tool, web search, draft papermatlab/, analysis/web/, REVIEW_PAPER.md

Folder map

README.md                  project overview + quickstart
requirements.txt           Python deps (pipeline)
data/
  manifest.csv / .json     stimulus catalog (83 stimuli) — tools/build_manifest.py
  movies/spacetop/         lab fMRI stimulus clips (49)        [internal]
  movies/open/             CC-BY Blender films (3) + SOURCES.md
  lexicons/                optional psycholinguistic norm CSVs (README.md)
  stories/narratives/      29 Narratives spoken-story audio clips (+ SOURCES.md)
  stories/samples/         pure-text sample story (.txt)
  movies/hcp/, movies/camcan/  placeholders for credentialed stimuli (see EXTERNAL_STIMULI.md)
schema/
  channel_template.json    the 95-channel constant-shape template
  annotation_schema.json   v0.1 pure-JSON profile schema
  example_annotation.json  tiny worked example
src/nfe/                   the Python annotation pipeline (see "Tools")
matlab/                    the MATLAB readers + analysis (see "Tools")
annotations/
  corpus/<id>/<id>.h5      DERIVATIVES: one annotation per stimulus (+ .manifest.json)
  corpus/corpus_index.csv  batch status/index
analysis/figures/          generated analysis figures (PNG)
analysis/corpus_stats.json corpus summary numbers the docs cite (refreshAnalysis)
analysis/web/              interactive segment search (index.html + segments.json + README)
docs/
  CONTENTS.md              ← this file
  walkthrough.m            runnable MATLAB tour
  scoping_review/          Phase 1 review (hierarchy, recommendations, ...)
  design/                  format spec, plans, per-phase status
tools/                     helper scripts (manifest, template, review assembly)

Datasets

  • Corpus manifest: 83 stimuli (data/manifest.csv) — 49 spacetop audiovisual clips + 4 short films (3 CC-BY Blender open films + Kung Fury) + 29 Narratives spoken-story audio clips (data/stories/narratives/, ~5.3 h; OpenNeuro ds002345, Nastase et al.) + 1 pure-text sample story. 53 audiovisual, 29 audio-only, 1 text-only. Add media under data/movies/<source>/ (movies/audio) or data/stories/<source>/ (audio/text stories) and re-run tools/build_manifest.py. See ADDING_MOVIES.md; credentialed sets (HCP, CamCAN) in EXTERNAL_STIMULI.md. All 83 are annotated; corpus-wide analysis focuses on the audio/language channels shared across modalities, with visual/social/ affective structure on the 53-stimulus audiovisual subset (see REVIEW_PAPER.md §5–6).
  • Lexicons (optional): drop data/lexicons/<field>.csv (valence, arousal, dominance, concreteness, aoa) to light up those per-word channels; absent → NaN.

Extracted derivatives

One annotation per stimulus at annotations/corpus/<id>/:

  • <id>.h5 — canonical HDF5. Hierarchical groups mirror the feature taxonomy:
    /time/        common 1 Hz grid (rate_hz, t_start_sec, n_samples, time_sec)
    /stimulus/    id, title, modality, duration, source, sha256
    /features/    visual/ audio/ language/ social/ situation/ affect/
                    → each leaf = one channel dataset [n_samples (× dim)] + attrs
                      (dtype, applicable, units, model, version, native_rate_hz, resample)
    /human/       reserved, empty — slots for later human annotation
    /provenance/  per-channel model registry
    
  • <id>.manifest.json — readable sidecar: same hierarchy + metadata, no bulk arrays.

Constant shape. Every file has the same 95 channels (the template). Channels not produced for a stimulus (a class that doesn’t apply to the modality, or a pass not run) are present with applicable=false and all-NaN, so the corpus stacks into rectangular matrices. Full spec: design/ANNOTATION_FORMAT.md.

The 95 channels span: visual (37 — low-level, semantic SigLIP2/DINOv2, motion, depth, action, faces, pose, saliency), audio (21 — low-level, AudioSet/CLAP, speech), language (14 — lexical, syntax, surprisal), affect (14 — text emotion/ sentiment, vocal, EmoNet image emotion, facial affect, VLM depicted), situation (5 — incl. GSBS event boundaries), social (4). What each pass computes: design/PHASE2_STATUS.md.


Tools

Python pipeline — src/nfe/ (annotate media)

python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
# annotate ONE movie (CPU passes always on; add MPS/VLM passes as flags):
PYTHONPATH=src .venv/bin/python -m nfe.run data/movies/open/BigBuckBunny.mp4 \
    --vision --audio-hl --events --template schema/channel_template.json
# annotate the WHOLE corpus (resumable, crash-safe):
PYTHONPATH=src .venv/bin/python -m nfe.batch --manifest data/manifest.csv \
    --out annotations/corpus --template schema/channel_template.json \
    --vision --audio-hl --events

Pass flags: --vision (SigLIP2/DINOv2/RAFT/depth/VideoMAE/faces/pose/saliency), --audio-hl (AST/CLAP/vocal-affect/text-emotion/surprisal), --reason (Qwen2.5-VL — slow), --events (GSBS). Modules: ingest (PyAV decode), extractors/ (the 20 passes), emit (HDF5+JSON), pipeline/run/batch, schema_registry (skeleton fill). Helpers in tools/: build_manifest.py, build_channel_template.py, build_search_index.py (segment index for the web search interface).

Browser tool to rank segments by any combination of features and play the matching moment. Serve from the project root, then open the page:

python3 tools/serve.py           # from the project root (Range-enabled, so video seeking works)
# open http://localhost:8000/analysis/web/index.html

Rebuild the index after annotating more stimuli: PYTHONPATH=src .venv/bin/python tools/build_search_index.py --seglen 5. Details: ../analysis/web/app_readme.md.

MATLAB — matlab/ (load, view, analyze)

FunctionPurpose
readAnnotations(path)load one .h5/folder/JSON → struct (stimulus, time_sec, features)
getFeature(ann, "audio/low_level/mfcc")one channel + metadata by hierarchical path
featuresToTimetable(ann)scalar channels → timetable on the common grid
readAnnotationCorpus(folder)stack the whole corpus → C.X [timepoints × channels]
annotationMovieViewer(movie, ann)play movie with synced annotation time series + marker
analyzeCorpus(C)correlation heatmap, PCA, channel + class network graphs
selectStimulusSet(C)D-optimal high-variance / low-redundancy segment selection

How to load, view, inspect (MATLAB quick recipes)

addpath matlab

% 1) Inspect ONE stimulus
ann = readAnnotations("annotations/corpus/ses-01_run-01_order-04_content-parkour");
tt  = featuresToTimetable(ann);          % scalars as a timetable
stackedplot(tt(:, ["visual__low_level_static__luminance","audio__low_level__rms"]))
mf  = getFeature(ann, "audio/low_level/mfcc");   % a vector channel [n × 13]

% 2) WATCH a movie with its annotations scrolling underneath
m = "data/movies/spacetop/videos/ses-01/ses-01_run-01_order-04_content-parkour.mp4";
annotationMovieViewer(m, "annotations/corpus/ses-01_run-01_order-04_content-parkour")

% 3) Analyze the whole CORPUS
C   = readAnnotationCorpus("annotations/corpus");
res = analyzeCorpus(C);                   % figures → analysis/figures/
sel = selectStimulusSet(C, "K", 20);      % design a stimulus set; sel.table

% Python inspection (alternative): h5py / pandas on <id>.h5 and corpus_index.csv
# 4) SEARCH segments by feature in the browser (serve from project root)
python3 tools/serve.py           # then open http://localhost:8000/analysis/web/index.html

See walkthrough.m for the same steps, runnable section by section.


Documentation index