Skip to main content

Aind.Behavior.VrForaging.Packaging

CI License ruff uv

Parses raw AIND VR-foraging behavioral sessions into analysis-ready parquet tables and an NWB file.

Architecture

A session is loaded once (via contraqctor), then a set of independent processors fan out over it. Each processor owns one output and knows how to express it in two targets:

raw session dir
      │
      ▼
  Dataset  ◄── aind_behavior_vr_foraging.data_contract.dataset(path)
      │
      ▼
  create_processors(dataset)          # picks processor variants by dataset version
      │   [SiteTable, PositionAndVelocity, Licks, Sniffing, SoftwareEvents, Events]
      │
      ├─► proc.compute()  ──► pandas DataFrame  ──► one <name>.parquet   (run_session)
      │                        (provenance stamped into df.attrs / parquet schema)
      │
      └─► proc.nwbize(nwb) ──► populates an NWBFile ──► .nwb.zarr (NwbSession)
  • Processor — every processor subclasses AbstractProcessor, implementing _compute() and (optionally) nwbize(). compute() wraps _compute() and stamps provenance (packaging_version, data_contract_version, dataset_version, processor) into the DataFrame's attrs.
  • DataFrame — the common in-memory representation. One row per unit of the output (e.g. one site-table row = one site).
  • Parquetsession_pipeline.run_session() calls compute() on each processor and writes a parquet per processor, promoting df.attrs to first-class parquet metadata (readable from DuckDB, Polars, R arrow, Spark, …).
  • NWBNwbSession builds a single NWBFile from AIND metadata, then calls each processor's nwbize() to fill it, and writes NWB-Zarr.

Version dispatch is automatic: datasets with schema version < 0.6.0 receive legacy processor variants.

Examples

Get a sites table

Install straight from GitHub with uv:

# into a uv project
uv add "git+https://github.com/AllenNeuralDynamics/Aind.Behavior.VrForaging.Packaging.git"

# or into the current environment
uv pip install "git+https://github.com/AllenNeuralDynamics/Aind.Behavior.VrForaging.Packaging.git"

Then load a session and compute the sites table (one row per site):

from aind_behavior_vr_foraging.data_contract import dataset
from aind_behavior_vr_foraging_packaging.session_pipeline import get_site_table_processor

ds = dataset("path/to/session")  # load the raw session
sites_df = get_site_table_processor(ds).compute()

sites_df.to_parquet("sites.parquet")  # optional: persist to disk
print(f"{len(sites_df)} sites, {sites_df['has_reward'].sum()} rewarded")

get_site_table_processor automatically picks the current or legacy variant based on the dataset's schema version. To produce every table at once, use run_session(ds, "output_dir") instead — it writes sites.parquet, position_velocity.parquet, and the rest, and returns them keyed by name.

Exporting a dataset collection

Install the CLI with uvx:

uvx install "git+https://github.com/AllenNeuralDynamics/Aind.Behavior.VrForaging.Packaging.git"

Then run the export pipeline across a folder of raw session directories (--input-dir must contain one subdirectory per session):

uvx run aind-vr-export --input-dir /data/raw --output-dir /data/export

--output-dir receives the results:

/data/export/
├── session.parquet          # session catalogue (one row per session)
├── sites.parquet            # aggregated sites table (all sessions)
└── sessions/
    └── <session_id>/
        ├── sites.parquet
        ├── position_velocity.parquet
        └── ...

Common flags

Flag Default Description
--workers N 1 Parallel threads for Phase 1 (per-session processing)
--exclude-processors a b (none) Skip named processors, e.g. sniffing software_events
--include-processors a b (all) Run only the listed processors
--dataset-tables a b sites Tables to flatten across sessions in Phase 2
--skip-processing false Jump straight to Phase 2 (sessions/ already written)
--skip-aggregation false Write only per-session parquets
--log-file path (none) Append a structured log to this path
--raise-on-error false Abort on the first failure instead of logging and continuing

Example: fast parallel run, skip sniffing

uvx run aind-vr-export \
    --input-dir /data/raw \
    --output-dir /data/export \
    --workers 8 \
    --exclude-processors sniffing software_events \
    --log-file /data/export/run.log

Example: re-aggregate only

Per-session parquets already written in sessions/:

uvx run aind-vr-export \
    --input-dir /data/raw \
    --output-dir /data/export \
    --skip-processing

See uvx run aind-vr-export --help for the full flag reference.

Documentation

The full documentation site is built with Zensical.

Preview locally:

uv sync --group docs
uv run zensical serve

Build a static copy:

uv run zensical build --clean
# output → site/

The site deploys automatically to GitHub Pages on every push to main as part of the main CI workflow.

Contributors

Contributions to this repository are welcome! However, please ensure that your code adheres to the recommended DevOps practices below:

Linting

We use ruff as our primary linting tool.

Testing

Attempt to add tests when new features are added. To run the currently available tests, run uv run pytest from the root of the repository.

Integration tests

Integration tests run the parser end-to-end against real datasets stored in a public S3 bucket. They are gated by a pytest marker so they don't run by default.

Run locally:

uv run pytest -m integration

The first run downloads datasets (~100 MB per dataset) to tests/integration/.cache/. Subsequent runs reuse the cache when the S3 ETag matches. The cache directory is gitignored.

[!IMPORTANT] On Windows, enable long paths first. test_full_pipeline writes an NWB-Zarr file whose chunk paths exceed the legacy 260-character MAX_PATH limit, and it fails with FileNotFoundError: ... .zarray.<hash>.partial — which looks like a parsing bug but is not. Enable long paths once, in an elevated PowerShell, then restart your shell:

New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" `
  -Name LongPathsEnabled -Value 1 -PropertyType DWORD -Force

If you cannot elevate, uv run pytest -m integration --basetemp=C:\t works around it by shortening the temp path. Linux and macOS are unaffected, as is CI (the integration job runs on ubuntu-latest).

Trigger on a PR:

Integration tests do not run on every PR. To run them for a specific PR, add the run-integration label via the GitHub UI (open the PR, click Labels in the right-hand sidebar, and select run-integration) or with:

gh pr edit <PR_NUMBER> --add-label run-integration

The integration job runs automatically on push to main and on release: published. A release cannot ship without the integration suite passing.

Adding a dataset:

Add an entry to tests/integration/datasets.yml. The manifest schema and full field documentation are in tests/integration/model.py (Pydantic model). The rationale field is required and is printed alongside any test failure to make triage fast.

Lock files

We use uv to manage our lock files and therefore encourage everyone to use uv as a package manager as well.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aind_behavior_vr_foraging_packaging-0.0.10.tar.gz (299.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file aind_behavior_vr_foraging_packaging-0.0.10.tar.gz.

File metadata

  • Download URL: aind_behavior_vr_foraging_packaging-0.0.10.tar.gz
  • Upload date:
  • Size: 299.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for aind_behavior_vr_foraging_packaging-0.0.10.tar.gz
Algorithm Hash digest
SHA256 40a991ba4c39609a5fc364001354f93821f5b9b187ceec64f87d06468c3165aa
MD5 d50af9e3041d0f70e7c56daaeb723200
BLAKE2b-256 253378bb4ee6bc8f1840d3554fd7b91f91b0e2dff3f8b088a602e11dda3713d2

See more details on using hashes here.

File details

Details for the file aind_behavior_vr_foraging_packaging-0.0.10-py3-none-any.whl.

File metadata

  • Download URL: aind_behavior_vr_foraging_packaging-0.0.10-py3-none-any.whl
  • Upload date:
  • Size: 48.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for aind_behavior_vr_foraging_packaging-0.0.10-py3-none-any.whl
Algorithm Hash digest
SHA256 1fc50f1d50c11acc1f2ec6771503e974ae9dd439faccf2c174206b69bd8bc9bc
MD5 24a9be826592b3d89cd871ab141aa4e8
BLAKE2b-256 929d2a3280c6c8de554c995e45d575b0eac76862959f6081a48d676293c01bf1

See more details on using hashes here.

Release history Release notifications | RSS feed

0.0.19

2 files

0.0.18

2 files

0.0.17

2 files

0.0.16

2 files

0.0.15

2 files

0.0.14

2 files

0.0.13

2 files

0.0.12

2 files

0.0.11

2 files

This release

0.0.10 This release

2 files

0.0.9

2 files

0.0.8

2 files

0.0.7

2 files

0.0.6

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page