Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
55c0849
add report generation dependencies, use UV venv
celefthe Jan 27, 2026
53cac2b
add click
celefthe Jan 27, 2026
bed98ea
add cli skeleton
celefthe Jan 27, 2026
14dcdf4
add summarise command, session_cmd wrapper
celefthe Jan 28, 2026
d3bbb0d
add html templates, add metadata getter function
celefthe Jan 28, 2026
92f7dc5
add sdt type determinant for old sessions
celefthe Feb 2, 2026
a7770b1
add metadata fields
celefthe Feb 2, 2026
48f1355
refine metadata extraction, stimulus info extraction and sdt extracti…
celefthe Feb 6, 2026
e5f9725
session analysis api explorer
celefthe Feb 6, 2026
8365a36
interaction is now environemnt
celefthe Feb 6, 2026
3c358ec
unpack items properly
celefthe Feb 6, 2026
0bc4dee
rename summary function
celefthe Feb 6, 2026
e3ad2c9
refactor metadata calls, summary call
celefthe Feb 10, 2026
e3acef2
refactor metrics
celefthe Feb 10, 2026
a4e0795
add summary wip
celefthe Feb 10, 2026
f86c907
more api exploration
celefthe Feb 10, 2026
bdc4796
remove noddy pc calculation from metrics
celefthe Feb 11, 2026
46c7ecc
add summary function
celefthe Feb 11, 2026
940ebd6
type casting
celefthe Feb 11, 2026
2bcb5ef
add metadata to summary
celefthe Feb 11, 2026
20c4df9
add starter plots
celefthe Feb 17, 2026
7a41bca
rename bias to criterion
celefthe Feb 17, 2026
96f2e94
add RT plots
celefthe Feb 17, 2026
909cb69
add correction trial metrics
celefthe Feb 18, 2026
a62f6b7
formatting
celefthe Feb 18, 2026
549c79f
add sdt plots
celefthe Feb 18, 2026
a50373b
add timeseries
celefthe Feb 18, 2026
af5b557
formatting
celefthe Feb 19, 2026
e20fd95
comment out summary dump
celefthe Feb 19, 2026
432709b
test session api changes
celefthe Apr 6, 2026
37a0794
ignore csv and html outputs
celefthe Apr 6, 2026
ec4f2d3
summarise function parses both csv and json files
celefthe Apr 6, 2026
9e7c0ad
add collate session function
celefthe Apr 6, 2026
6a821b3
test different file inputs to summarise
celefthe Apr 6, 2026
3411992
test collate_session function
celefthe Apr 6, 2026
d23a7bb
add cli call
celefthe Apr 6, 2026
9edb58b
ignore warnings in cli calls
celefthe Apr 6, 2026
695be97
wip
celefthe Apr 6, 2026
82cc88a
ignore scratch symlinks
celefthe Aug 3, 2026
86afae6
wip regressor generator
celefthe Aug 3, 2026
509b174
formatting chagnes
celefthe Aug 3, 2026
cc407d0
add function to generate regressors from go/nogo trial data
celefthe Aug 3, 2026
09d4b6e
vectorise regressor generation
celefthe Aug 3, 2026
bc082f9
add option to session command to generate regressors file
celefthe Aug 3, 2026
9132298
add separate command for generating regressors only
celefthe Aug 3, 2026
837ad14
add separate command for generating regressors only
celefthe Aug 3, 2026
69f1512
replace dataframe indexing from attribute to label based
celefthe Aug 3, 2026
6209088
replace dataframe indexing from attribute to label based, some missed…
celefthe Aug 3, 2026
da64d15
handle timestamps file in either txt or csv format
celefthe Aug 4, 2026
b8e4fea
fix regressor length to match input timestamps
celefthe Aug 4, 2026
a8ecd92
remove unnecessary string decoding
celefthe Aug 4, 2026
5cb8741
minor regressor adjustments
celefthe Aug 5, 2026
3a0fad4
add option to return trial epoch indeceS
celefthe Aug 5, 2026
93884d9
test regressor generation
celefthe Aug 5, 2026
d14a459
test regressor generation
celefthe Aug 5, 2026
f79195d
fix bug where hit or fa rate of 0 is treated as not provided
celefthe Aug 6, 2026
457657d
add initial test suite
celefthe Aug 6, 2026
29aa1be
add ci runner for tests
celefthe Aug 6, 2026
196e08b
remove support for 3.10
celefthe Aug 7, 2026
bf047ec
change python requirement to >=3.11
celefthe Aug 7, 2026
670acb6
ignore ai guff
celefthe Aug 11, 2026
3b2ac62
update readme
celefthe Aug 11, 2026
9a59cdc
add release checklist
celefthe Aug 6, 2026
c6f8577
update lock
celefthe Aug 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Tests

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Cache uv
uses: actions/cache@v4
with:
path: ~/.cache/uv
key: uv-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}
restore-keys: |
uv-${{ runner.os }}-py${{ matrix.python-version }}-

- name: Install Hatch
run: pip install hatch

- name: Run tests with coverage
run: hatch test --python ${{ matrix.python-version }} --cover
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,17 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Ignore outputs
*.csv
*.html

scratch/
scratch

# AI agent instruction files (not tracked for now)
CLAUDE.md
AGENTS.md
GEMINI.md
.claude/CLAUDE.md

130 changes: 128 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,128 @@
# visiomode_analysis
Analysis library for behaviour data generated with visiomode
# visiomode-analysis

Analysis library and CLI for behavioural session data recorded with [Visiomode](https://github.com/DuguidLab/visiomode), a visuomotor behaviour platform for rodents.

## Features

- **Session summaries** — quickly summarise session stats, including signal detection theory metrics.
- **HTML reports** — standalone, self-contained session reports with embedded Plotly figures.
- **GLM regressors** — event regressors (stimulus/response/reward windows) aligned to an external timestamp series, such as imaging frame timestamps or electrophysiology acquisition rates.
- **Subject-level and cohort-level analysis** — combine per-session trial summaries into a single per-subject summary CSV, as well as group-level analysis across subjects.

## Installation

Requires Python 3.11+.

```bash
pip install git+https://github.com/DuguidLab/visiomode_analysis.git
```

For local development, this project uses [uv](https://docs.astral.sh/uv/) to manage the virtual environment:

```bash
git clone https://github.com/DuguidLab/visiomode_analysis.git
cd visiomode_analysis
uv sync
```

This creates a `.venv` with the package and its dependencies installed in editable mode.

## Usage

### CLI

The package installs a `visiomode-analysis` command with four subcommands: `session`, `regressors`, `subject`, and `group`.

**Process a single session** — generates an HTML report and a trials CSV:

```bash
visiomode-analysis session path/to/sub-01_exp-myexperiment_ses-20260101_behaviour-gonogo.json -o output/
```

Skip the HTML report, or generate GLM regressors alongside it, with:

```bash
visiomode-analysis session path/to/session.json -o output/ --no-report
visiomode-analysis session path/to/session.json -o output/ --with-regressors --regressor-timestamps frame_times.csv
```

**Generate regressors** for an already-processed session, aligned to an external timestamp series:

```bash
visiomode-analysis regressors path/to/session.json -o output/ --regressor-timestamps frame_times.csv
```

**Collate a subject's sessions** — combines every `*trials.csv` file in a directory (as produced by `session`) into one subject-level summary CSV:

```bash
visiomode-analysis subject path/to/subject_dir/ -o output/
```

Run `visiomode-analysis --help` or `visiomode-analysis <command> --help` for full option details.

### Python API

The CLI is a thin wrapper around the `visiomode_analysis.session` module, which can also be used directly:

```python
from visiomode_analysis import session

trials = session.get_trials("path/to/session.json")
metadata = session.get_metadata("path/to/session.json")
summary = session.summary(trials)

session.generate_report(trials, metadata, output_dir="output/")
```

### Input files and naming convention

Session JSON filenames are expected to follow a BIDS-like pattern:

```
sub-<animal_id>_exp-<experiment>_ses-<YYYYMMDD>_behaviour-<protocol>.json
```

Metadata encoded in the filename takes precedence over the same fields in the JSON body. Output files (trials CSV, report HTML, regressors `.npz`, subject summary CSV) are named following the same convention, so downstream steps — e.g. `subject` globbing for `*trials.csv` — can find their inputs automatically.

## Project structure

```sh
src/visiomode_analysis/
├── __init__.py # top-level Click CLI group, wires up subcommands
├── session/ # Session-level statistics
│ ├── __init__.py # JSON → trials DataFrame, metadata, summaries, report/regressor generation
│ ├── metrics.py # signal-detection-theory statistics
│ ├── plots.py # Plotly figure builders
│ └── regressor.py # per-protocol GLM regressor construction
├── subject/ # collates per-session trials.csv files into a subject summary
│ └── __init__.py
├── group/ # cohort-level aggregation across subjects (stub, unimplemented)
│ └── __init__.py
└── reports/ # Jinja2 templates for HTML session reports
├── __init__.py
└── templates/
├── base.html
└── session.html
```

## Development

```bash
# Run the full test suite with coverage (matches CI)
hatch test --cover

# Run tests directly with pytest (faster iteration)
.venv/bin/pytest

# Run a single test file / test
.venv/bin/pytest tests/test_metrics.py::test_d_prime_afc_correction -v

# Type checking
hatch run types:check
```

See [CONTRIBUTING.md](CONTRIBUTING.md).

## License

MIT — see [LICENSE](LICENSE).
Loading
Loading