diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 392ed45..d9af372 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -30,10 +30,30 @@ jobs: - name: Build release distributions run: | - # NOTE: put your own distribution build steps here. python -m pip install build python -m build + - name: Check distributions + run: | + python -m pip install twine + python -m twine check dist/* + + # Install the built wheel in a clean venv and exercise it end to end. This + # catches packaging faults that the test suite cannot see, because the + # tests run against the source tree rather than the built distribution + # (e.g. package data missing from the wheel). + - name: Smoke test built wheel + run: | + python -m venv /tmp/smoke + /tmp/smoke/bin/pip install dist/*.whl + /tmp/smoke/bin/visiomode-analysis --version + mkdir -p /tmp/smoke-out + /tmp/smoke/bin/visiomode-analysis session \ + exploratory/test_data/example-gonogo-leverpush.json \ + -o /tmp/smoke-out + test -n "$(find /tmp/smoke-out -name '*report-session.html' -print -quit)" + test -n "$(find /tmp/smoke-out -name '*trials.csv' -print -quit)" + - name: Upload distributions uses: actions/upload-artifact@v4 with: @@ -51,7 +71,7 @@ jobs: - name: Download build artifacts uses: actions/download-artifact@v4 with: - name: dist + name: release-dists path: dist/ - name: Create release @@ -78,12 +98,7 @@ jobs: # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules environment: name: pypi - # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status: - # url: https://pypi.org/p/YOURPROJECT - # - # ALTERNATIVE: if your GitHub Release name is the PyPI project version string - # ALTERNATIVE: exactly, uncomment the following line instead: - # url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }} + url: https://pypi.org/p/visiomode-analysis steps: - name: Retrieve release distributions diff --git a/.gitignore b/.gitignore index ceb4223..5374379 100644 --- a/.gitignore +++ b/.gitignore @@ -163,10 +163,14 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ -# Ignore outputs +# Ignore outputs *.csv *.html +# ...but the report templates are package data, not outputs. Without this the +# build backend honours the *.html rule above and silently ships a broken wheel. +!src/visiomode_analysis/reports/templates/*.html + scratch/ scratch diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c7e64fd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,52 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.0] - 2026-08-11 + +First public release. + +### Added + +- **Session processing** (`visiomode_analysis.session`) — reads a raw Visiomode + session JSON and flattens its nested trial list into a per-trial + `pandas.DataFrame`, reconciling several historical Visiomode JSON schema + versions along the way. +- **Session metadata** — `get_metadata()` derives animal ID, experiment, date, + protocol and stimulus spec, preferring BIDS-like tokens encoded in the + filename (`sub-_exp-_ses-_behaviour-.json`) over + the JSON body. +- **Session summaries** — `summary()` aggregates trials into signal-detection-theory + metrics (hit and false alarm rates, d', criterion), trial counts and reaction + time statistics, with `_wc` ("with corrections") variants computed alongside + the corrections-excluded defaults. +- **Signal detection theory metrics** (`session.metrics`) — `d_prime`, + `criterion` and `perseveration`, including a 2AFC correction for d'. +- **HTML session reports** — `generate_report()` renders a standalone, + self-contained report from a Jinja2 template with embedded Plotly figures. +- **Plotly figure builders** (`session.plots`) — reusable figures for session + reports, each able to return an embeddable HTML `
` via `as_html=True`. +- **GLM regressors** (`session.regressor`) — `generate_regressors()` builds + stimulus, response and reward event regressors aligned to an external + timestamp series such as imaging frame times or an electrophysiology + acquisition clock. Go/No-Go is implemented; other protocols raise + `NotImplementedError`. +- **Subject-level collation** (`visiomode_analysis.subject`) — + `collate_sessions()` globs the `*trials.csv` files produced by the `session` + command for one subject, aggregates them into a single per-subject summary CSV + and assigns per-protocol `task_session` ranks. +- **Command line interface** — a `visiomode-analysis` entry point with `session`, + `regressors`, `subject` and `group` subcommands. Output files follow the same + BIDS-like naming convention as the inputs so downstream steps can find them + automatically. +- **Group-level analysis** — `group` subcommand scaffolded; not yet implemented. +- Test suite covering trial flattening, metrics, plots, regressors, session + summaries, subject collation and the CLI, run against Python 3.11–3.13 in CI. + +[Unreleased]: https://github.com/DuguidLab/visiomode_analysis/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/DuguidLab/visiomode_analysis/releases/tag/v0.1.0 diff --git a/README.md b/README.md index 01ce2f2..51ef351 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,12 @@ Analysis library and CLI for behavioural session data recorded with [Visiomode]( Requires Python 3.11+. +```bash +pip install visiomode-analysis +``` + +Or, to install the latest unreleased code from `main`: + ```bash pip install git+https://github.com/DuguidLab/visiomode_analysis.git ``` @@ -115,7 +121,7 @@ hatch test --cover hatch run types:check ``` -See [CONTRIBUTING.md](CONTRIBUTING.md). +See [CONTRIBUTING.md](CONTRIBUTING.md) for the issue workflow, and [CHANGELOG.md](CHANGELOG.md) for release notes. ## License diff --git a/pyproject.toml b/pyproject.toml index 7b7e3a2..8484f82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,9 +46,13 @@ path = ".venv" # Use uv environment path [tool.hatch.build.targets.wheel] packages = ["src/visiomode_analysis"] +# The report templates match the *.html rule in .gitignore, which the build +# backend honours. Listing them as artifacts forces them into the wheel. +artifacts = ["src/visiomode_analysis/reports/templates/*.html"] [tool.hatch.build.targets.sdist] -exclude = ["/.github", "/docs"] +exclude = ["/.github", "/.claude", "/docs"] +artifacts = ["src/visiomode_analysis/reports/templates/*.html"] [tool.hatch.version] path = "src/visiomode_analysis/__about__.py"