Metadata-Version: 2.4
Name: plasma-app
Version: 2.1.3
Summary: PLASMA — Platform for LSL-based Acquisition of Sensor Metrics and Analytics
License: MIT
Project-URL: Homepage, https://github.com/YuyiChang/PLASMA
Project-URL: Repository, https://github.com/YuyiChang/PLASMA
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: gradio
Requires-Dist: plotly
Requires-Dist: pylsl
Requires-Dist: numpy
Provides-Extra: msense
Requires-Dist: simplepyble; extra == "msense"
Requires-Dist: bleak; extra == "msense"
Requires-Dist: scipy; extra == "msense"
Requires-Dist: matplotlib; extra == "msense"
Requires-Dist: psutil; extra == "msense"
Requires-Dist: Pillow; extra == "msense"
Requires-Dist: pandas; extra == "msense"
Requires-Dist: pyarrow; extra == "msense"
Requires-Dist: tqdm; extra == "msense"
Provides-Extra: qb2
Requires-Dist: blickfeld-qb2; extra == "qb2"
Provides-Extra: pupil
Requires-Dist: pupil-labs-realtime-api; extra == "pupil"
Provides-Extra: shimmer
Requires-Dist: pyshimmer; extra == "shimmer"
Requires-Dist: pyserial; extra == "shimmer"
Provides-Extra: obs
Requires-Dist: obsws-python; extra == "obs"
Provides-Extra: all
Requires-Dist: plasma-app[msense,obs,pupil,qb2,shimmer]; extra == "all"
Provides-Extra: desktop
Requires-Dist: pyshortcuts; extra == "desktop"
Provides-Extra: build
Requires-Dist: pyinstaller; extra == "build"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pyxdf; extra == "test"
Provides-Extra: docs
Requires-Dist: mkdocs-material; extra == "docs"
Requires-Dist: mkdocs-glightbox; extra == "docs"
Requires-Dist: playwright; extra == "docs"
Dynamic: license-file

# PLASMA

PLASMA: Platform for LSL-based Acquisition of Sensor Metrics and Analytics

**📖 Operator handbook: <https://yuyichang.github.io/PLASMA/>** — install,
configure, pair MSense wristbands, run a session, read the memo panel, recover
from faults.

## quickstart

- `conda create -n plasma python=3.12`
- `conda activate plasma`
- `pip install -e ".[all]"` — or a lean subset, e.g. `".[msense]"` / `".[qb2,pupil]"`
- `python -m plasma` (or the `plasma` console script)

`pip install -r requirements.txt` still works — it's a shim for `-e .[all,build,test]`.

Want a double-clickable icon instead of running `plasma` from a terminal?
`pip install -e ".[desktop]"` then `plasma-install-shortcut` — see
[Install & first launch](https://yuyichang.github.io/PLASMA/playbook/install/).

Writable state (device config, gyro-bias calibration, `data/` recordings, session
log) location, in order: `$PLASMA_HOME` if set → a per-user app-data dir when
running as a packaged app (`~/Library/Application Support/PLASMA` on macOS,
`%LOCALAPPDATA%\PLASMA` on Windows, `~/.local/share/plasma` on Linux) → the
working directory when running from source. Resolved once at import — set
`PLASMA_HOME` before launching to override.

### use PLASMA from another project

```
pip install "plasma-app[msense] @ git+https://github.com/YuyiChang/PLASMA@v2.0.0"
```

The distribution is `plasma-app`; the import package is `plasma`. Extras map to
plugins: `msense`, `qb2`, `pupil`, `shimmer`, `obs` (and `all`).

## Known issue / future works

- [ ] need manually set lidar ip addr
- [ ] the built-in LSL→XDF recorder captures **every** stream on the default
      liblsl session, so a concurrent `pytest` run or another lab tool leaks
      into the recording; re-Initialize doesn't fully tear down old outlets.
      Direction (SessionID scoping, outlet lifecycle): [`docs/reference/lsl-lifecycle-and-scoping.md`](docs/reference/lsl-lifecycle-and-scoping.md)
- [ ] interactive=false on ses/sub when collection started
- [x] linux aarch64 build — `PLASMA_Linux_arm64` for Jetson Orin (JetPack 6); CI job `build-linux-arm64`
- [ ] infrequent stream (e.g., PLASMA journaler) shows green after recording stop
- [ ] doc for msense workflow with better screenshots
- [ ] memo `stage` transition logic optimization (e.g., timing of "ready to start" msg wrt sensor init status)

## developing a sensor plugin

Every sensor is a plugin: a `PlasmaDevice` subclass plus a registration entry in
`plasma/plugins.py`. Core code never imports a concrete device.

> full guide: [`plasma/devices/README.md`](plasma/devices/README.md)
> base class: `PlasmaDevice` in `plasma/devices/template.py`
> reference package (config section + tabs + multi-unit): `plasma/devices/msense/`

## documentation

The playbook is a MkDocs Material site under `docs/`, deployed to GitHub Pages
by `.github/workflows/docs.yml` on every push to `main`.

```
pip install -e ".[docs]"        # mkdocs-material + mkdocs-glightbox + playwright
mkdocs serve                     # preview at http://127.0.0.1:8000
```

Screenshots (`docs/assets/screenshots/*.png`, Git LFS) are regenerated by a
Playwright script that drives PLASMA with the simulated MSense device:

```
brew install git-lfs && git lfs install     # one-time
python scripts/capture_screenshots.py        # ~4 min; needs Google Chrome
```

It uses `PLASMA_HOME=~/Library/Application Support/PLASMA` by default so the
paths shown in the memo panel match a packaged install; pass `--home /tmp/x` for
a disposable run.

## references

- qb2: https://docs.blickfeld.com/qb2/Qb2/v1.10/guides/api.html
- pupil-labs: https://pupil-labs.github.io/pl-realtime-api/dev/
