lfpack 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. lfpack-0.1.0/.githooks/pre-commit +4 -0
  2. lfpack-0.1.0/.github/workflows/docs.yml +57 -0
  3. lfpack-0.1.0/.github/workflows/publish_to_pypi.yaml +26 -0
  4. lfpack-0.1.0/.github/workflows/tests.yml +51 -0
  5. lfpack-0.1.0/.gitignore +134 -0
  6. lfpack-0.1.0/CHANGELOG.md +6 -0
  7. lfpack-0.1.0/CLAUDE.md +77 -0
  8. lfpack-0.1.0/CONTRIBUTING.md +77 -0
  9. lfpack-0.1.0/PKG-INFO +46 -0
  10. lfpack-0.1.0/README.md +27 -0
  11. lfpack-0.1.0/docs/.gitignore +2 -0
  12. lfpack-0.1.0/docs/README.txt +25 -0
  13. lfpack-0.1.0/docs/_quarto.yml +64 -0
  14. lfpack-0.1.0/docs/explanation/gallery.qmd +51 -0
  15. lfpack-0.1.0/docs/explanation/pipeline.qmd +149 -0
  16. lfpack-0.1.0/docs/figures/density_lfp_dab512bd.png +0 -0
  17. lfpack-0.1.0/docs/figures/favicon.png +0 -0
  18. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_1a276285-8b0e-4cc9-9f0a-a3a002978724.png +0 -0
  19. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_1e104bf4-7a24-4624-a5b2-c2c8289c0de7.png +0 -0
  20. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_6638cfb3-3831-4fc2-9327-194b76cf22e1.png +0 -0
  21. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_749cb2b7-e57e-4453-a794-f6230e4d0226.png +0 -0
  22. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_d7ec0892-0a6c-4f4f-9d8f-72083692af5c.png +0 -0
  23. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_da8dfec1-d265-44e8-84ce-6ae9c109b8bd.png +0 -0
  24. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_dab512bd-a02d-4c1f-8dbc-9155a163efc0.png +0 -0
  25. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_dc7e9403-19f7-409f-9240-05ee57cb7aea.png +0 -0
  26. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_e8f9fba4-d151-4b00-bee7-447f0f3e752c.png +0 -0
  27. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_eebcaf65-7fa4-4118-869d-a084e84530e2.png +0 -0
  28. lfpack-0.1.0/docs/figures/gallery/2026-06-02_lfp_density_voltage_fe380793-8035-414e-b000-09bfe5ece92a.png +0 -0
  29. lfpack-0.1.0/docs/figures/gallery/2026-06-15_lfp_compression_aggregate.png +0 -0
  30. lfpack-0.1.0/docs/figures/logo.png +0 -0
  31. lfpack-0.1.0/docs/how-to/binned-reads.qmd +59 -0
  32. lfpack-0.1.0/docs/how-to/multi-recording.qmd +58 -0
  33. lfpack-0.1.0/docs/index.qmd +47 -0
  34. lfpack-0.1.0/docs/objects.json +1 -0
  35. lfpack-0.1.0/docs/reference/LFPCompressed.qmd +33 -0
  36. lfpack-0.1.0/docs/reference/LFPackReader.qmd +152 -0
  37. lfpack-0.1.0/docs/reference/_sidebar.yml +20 -0
  38. lfpack-0.1.0/docs/reference/compress.qmd +21 -0
  39. lfpack-0.1.0/docs/reference/compress_bin_to_h5.qmd +63 -0
  40. lfpack-0.1.0/docs/reference/compress_pipeline.qmd +36 -0
  41. lfpack-0.1.0/docs/reference/compress_to_h5.qmd +56 -0
  42. lfpack-0.1.0/docs/reference/decompress.qmd +20 -0
  43. lfpack-0.1.0/docs/reference/hdf5-layout.qmd +93 -0
  44. lfpack-0.1.0/docs/reference/index.qmd +30 -0
  45. lfpack-0.1.0/docs/reference/run_cadzow_checkpoint.qmd +49 -0
  46. lfpack-0.1.0/docs/references.bib +18 -0
  47. lfpack-0.1.0/docs/tutorials/first-compression.qmd +79 -0
  48. lfpack-0.1.0/pyproject.toml +55 -0
  49. lfpack-0.1.0/src/lfpack/__init__.py +17 -0
  50. lfpack-0.1.0/src/lfpack/_core.py +1228 -0
  51. lfpack-0.1.0/tests/__init__.py +0 -0
  52. lfpack-0.1.0/tests/test_lfpack.py +578 -0
  53. lfpack-0.1.0/uv.lock +2561 -0
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+ uv run ruff check src/ tests/
4
+ uv run ruff format --check src/ tests/
@@ -0,0 +1,57 @@
1
+ name: docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+
7
+ permissions:
8
+ contents: read
9
+ pages: write
10
+ id-token: write
11
+
12
+ concurrency:
13
+ group: pages
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ build:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Install Quarto
23
+ uses: quarto-dev/quarto-actions/setup@v2
24
+
25
+ - name: Install uv
26
+ uses: astral-sh/setup-uv@v4
27
+ with:
28
+ enable-cache: true
29
+ cache-dependency-glob: "uv.lock"
30
+
31
+ - name: Set up Python
32
+ run: uv python install 3.14
33
+
34
+ - name: Install dependencies
35
+ run: uv sync --group dev
36
+
37
+ - name: Build API reference
38
+ run: uv run quartodoc build --config docs/_quarto.yml
39
+
40
+ - name: Render site
41
+ run: quarto render docs/
42
+
43
+ - name: Upload pages artifact
44
+ uses: actions/upload-pages-artifact@v3
45
+ with:
46
+ path: docs/_site
47
+
48
+ deploy:
49
+ needs: build
50
+ runs-on: ubuntu-latest
51
+ environment:
52
+ name: github-pages
53
+ url: ${{ steps.deployment.outputs.page_url }}
54
+ steps:
55
+ - name: Deploy to GitHub Pages
56
+ id: deployment
57
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,26 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ deploy:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Install uv
17
+ uses: astral-sh/setup-uv@v4
18
+
19
+ - name: Build package
20
+ run: uv build
21
+
22
+ - name: Publish package
23
+ uses: pypa/gh-action-pypi-publish@release/v1
24
+ with:
25
+ user: __token__
26
+ password: ${{ secrets.PYPI_API_TOKEN }}
@@ -0,0 +1,51 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Install uv
15
+ uses: astral-sh/setup-uv@v4
16
+ with:
17
+ enable-cache: true
18
+ cache-dependency-glob: "uv.lock"
19
+
20
+ - name: Set up Python
21
+ run: uv python install 3.14
22
+
23
+ - name: Install dependencies
24
+ run: uv sync --extra dev
25
+
26
+ - name: Run tests with coverage
27
+ run: uv run pytest tests/ -v --cov=lfpack --cov-report=term-missing --cov-report=json
28
+
29
+ - name: Post coverage to step summary
30
+ if: always()
31
+ run: |
32
+ python -c "
33
+ import json, pathlib, os
34
+ data = json.loads(pathlib.Path('coverage.json').read_text())
35
+ t = data['totals']
36
+ lines = [
37
+ '## Coverage report',
38
+ f\"| Statements | Covered | Missed | % |\",
39
+ f\"|---|---|---|---|\",
40
+ f\"| {t['num_statements']} | {t['covered_lines']} | {t['missing_lines']} | **{t['percent_covered']:.1f}%** |\",
41
+ '',
42
+ '| File | Stmts | Miss | Cover |',
43
+ '|---|---|---|---|',
44
+ ]
45
+ for path, info in data['files'].items():
46
+ s = info['summary']
47
+ lines.append(f\"| \`{path}\` | {s['num_statements']} | {s['missing_lines']} | {s['percent_covered']:.1f}% |\")
48
+ summary = os.environ.get('GITHUB_STEP_SUMMARY', '/dev/null')
49
+ with open(summary, 'a') as f:
50
+ f.write('\n'.join(lines) + '\n')
51
+ "
@@ -0,0 +1,134 @@
1
+ TODO.md
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ pip-wheel-metadata/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ .python-version
88
+
89
+ # pipenv
90
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
91
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
92
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
93
+ # install all needed dependencies.
94
+ #Pipfile.lock
95
+
96
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
97
+ __pypackages__/
98
+
99
+ # Celery stuff
100
+ celerybeat-schedule
101
+ celerybeat.pid
102
+
103
+ # SageMath parsed files
104
+ *.sage.py
105
+
106
+ # Environments
107
+ .env
108
+ .venv
109
+ env/
110
+ venv/
111
+ ENV/
112
+ env.bak/
113
+ venv.bak/
114
+
115
+ # Spyder project settings
116
+ .spyderproject
117
+ .spyproject
118
+
119
+ # Rope project settings
120
+ .ropeproject
121
+
122
+ # mkdocs documentation
123
+ /site
124
+
125
+ # Quarto rendered output
126
+ docs/_site/
127
+
128
+ # mypy
129
+ .mypy_cache/
130
+ .dmypy.json
131
+ dmypy.json
132
+
133
+ # Pyre type checker
134
+ .pyre/
@@ -0,0 +1,6 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
lfpack-0.1.0/CLAUDE.md ADDED
@@ -0,0 +1,77 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What this project is
6
+
7
+ **lfpack** is a lossy LFP (local-field-potential) codec for Neuropixels recordings. It compresses raw `.cbin` LFP binaries into HDF5 files at >100× compression with RMSE < 25 µV, using an 8-stage pipeline followed by adaptive SVD + wavelet-packet thresholding.
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ # Dev setup
13
+ uv sync --group dev
14
+ git config core.hooksPath .githooks # installs ruff pre-commit hook
15
+
16
+ # Tests
17
+ uv run pytest # all tests
18
+ uv run pytest tests/test_lfpack.py::TestLfpack::test_compress_output_shapes # single test
19
+
20
+ # Lint / format
21
+ uv run ruff check src/ tests/
22
+ uv run ruff format src/ tests/
23
+
24
+ # Docs — regenerate API reference from docstrings, then preview
25
+ uv run quartodoc build --config docs/_quarto.yml
26
+ quarto preview docs/
27
+ ```
28
+
29
+ ## Architecture
30
+
31
+ Nearly all code lives in `src/lfpack/_core.py` (~1000 lines). The public API is re-exported from `src/lfpack/__init__.py`.
32
+
33
+ ### Compression pipeline (`compress_bin_to_h5`)
34
+
35
+ 1. Bad-channel detection (`ibldsp.voltage.detect_bad_channels_cbin`)
36
+ 2. Dephasing — sample-shift correction (NP1 only, via `ibldsp.fourier.fshift`)
37
+ 3. Highpass filter — 2 Hz zero-phase 3rd-order Butterworth
38
+ 4. Bad-channel interpolation — distance-weighted neighbors
39
+ 5. CAR — median subtraction across channels
40
+ 6. Decimation — 2500 → 250 Hz (Q=10)
41
+ 7. Cadzow denoising — spatial rank reduction (`ibldsp.cadzow`)
42
+ 8. **Adaptive SVD + wavelet-packet thresholding** — the actual codec
43
+
44
+ Steps 6–7 are checkpointed to a `.npy` file so the expensive decimation can be skipped on resume. Steps 7–8 are parallelised with `joblib`.
45
+
46
+ ### Codec (`compress` / `decompress`)
47
+
48
+ `compress(data, epsilon=150, alpha=28)` → `LFPCompressed` dataclass:
49
+ - **SVD rank selection**: keep singular values > `epsilon × sigma_noise`
50
+ - **Wavelet-packet thresholding**: db4, level 5; per-component threshold `alpha × sigma_noise / sv[k]`
51
+ - Sparse Vh stored as `(vh_indices, vh_values)` in HDF5; `U_scaled` with shuffle+gzip
52
+
53
+ Guard bands: 64-sample Cadzow halos, 128-sample SVD/WP overlap to prevent edge transients.
54
+
55
+ ### HDF5 layout (multi-recording, pyramidal)
56
+
57
+ ```
58
+ <file>.h5
59
+ └─ <recording>/
60
+ └─ <scale_2digit>/
61
+ ├─ meta # nc, ns_total, fs, fs_sync, t0_sync, epsilon, alpha, geometry, …
62
+ └─ chunks/
63
+ └─ <i>/ # U_scaled, vh_indices, vh_values + attrs
64
+ ```
65
+
66
+ Legacy flat layout (meta at root) is still readable for backwards compatibility.
67
+
68
+ ### `LFPackReader`
69
+
70
+ Drop-in replacement for `spikeglx.Reader`. Wraps an HDF5 file and decompresses chunks on demand. Supports multi-recording files via `recording=` kwarg and pyramidal scales via `scale=` kwarg.
71
+
72
+ ## Ecosystem interconnections
73
+
74
+ lfpack sits in a tight three-way dependency with two sibling IBL packages:
75
+
76
+ - **ibl-neuropixel** (`/Users/olivier/PycharmProjects/ephys-atlas/ibl-neuropixel`) — provides the low-level Neuropixels binary I/O (`spikeglx.Reader`), destriping, dephasing (`ibldsp.fourier.fshift`), decimation (`ibldsp.voltage.resample_denoise_lfp_cbin`), bad-channel detection (`ibldsp.voltage.detect_bad_channels_cbin`), and Cadzow denoising (`ibldsp.cadzow`). lfpack wraps these directly; changes to ibldsp can break the pipeline.
77
+ - **viewephys** (`/Users/olivier/PycharmProjects/ephys-atlas/viewephys`) — Qt-based interactive viewer for raw Neuropixels traces. `LFPackReader` is a drop-in for `spikeglx.Reader`, so any file readable by viewephys can be replaced with an `LFPackReader` instance. `viewephys(traces.T, fs=sr.fs)` is the canonical way to visualise decompressed LFP data; note the transpose (`LFPackReader` returns time-first, viewephys expects channel-first).
@@ -0,0 +1,77 @@
1
+ # Contributing to lfpack
2
+
3
+ ## Development setup
4
+
5
+ ```bash
6
+ git clone https://github.com/int-brain-lab/lfpack
7
+ cd lfpack
8
+ uv sync --group dev
9
+ git config core.hooksPath .githooks
10
+ ```
11
+
12
+ The last command installs the pre-commit hook from the tracked `.githooks/` directory.
13
+
14
+ ## Code style
15
+
16
+ All code is formatted and linted with [ruff](https://docs.astral.sh/ruff/).
17
+ Configuration lives in `pyproject.toml` (`line-length = 120`, rules `E F W I`).
18
+
19
+ Before committing, run:
20
+
21
+ ```bash
22
+ uv run ruff format src/ tests/ # format
23
+ uv run ruff check src/ tests/ # lint
24
+ ```
25
+
26
+ The pre-commit hook installed above runs both checks automatically and blocks commits that fail.
27
+
28
+ ## Docstrings
29
+
30
+ All public functions, classes, and methods use [NumPy/SciPy docstring format](https://numpydoc.readthedocs.io/en/latest/format.html).
31
+ These docstrings are rendered into the API reference by [quartodoc](https://machow.github.io/quartodoc/).
32
+
33
+ ## Documentation
34
+
35
+ The docs site lives in `docs/` and follows the [Diátaxis](https://diataxis.fr) framework:
36
+
37
+ | Directory | Type | Purpose |
38
+ |---|---|---|
39
+ | `docs/tutorials/` | Tutorial | Guided learning paths |
40
+ | `docs/how-to/` | How-To | Step-by-step task guides |
41
+ | `docs/reference/` | Reference | API docs (quartodoc) + HDF5 spec |
42
+ | `docs/explanation/` | Explanation | Concepts, design choices, benchmarks |
43
+
44
+ Build the docs:
45
+
46
+ ```bash
47
+ # Generate API reference pages from docstrings
48
+ uv run quartodoc build --config docs/_quarto.yml
49
+
50
+ # Render HTML (output → docs/_site/)
51
+ quarto render docs/
52
+
53
+ # Live preview with hot-reload
54
+ quarto preview docs/
55
+ ```
56
+
57
+ ## Tests
58
+
59
+ ```bash
60
+ uv run pytest # run all tests
61
+ uv run pytest --cov --cov-report=term-missing # with coverage report
62
+ ```
63
+
64
+ All existing tests must pass and coverage must not regress before opening a pull request.
65
+
66
+ ## Versioning
67
+
68
+ This project uses [Semantic Versioning](https://semver.org):
69
+
70
+ - **PATCH** (`0.1.x`) — bug fixes, no API changes.
71
+ - **MINOR** (`0.x.0`) — new backwards-compatible features or API additions.
72
+ - **MAJOR** (`x.0.0`) — breaking changes (e.g. new HDF5 layout, removed parameters).
73
+
74
+ Changes are recorded in `CHANGELOG.md` following the
75
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) convention.
76
+ The `[Unreleased]` section accumulates work until a release, at which point it is
77
+ renamed to `[x.y.z] - YYYY-MM-DD` and a matching git tag `vx.y.z` is pushed.
lfpack-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,46 @@
1
+ Metadata-Version: 2.4
2
+ Name: lfpack
3
+ Version: 0.1.0
4
+ Summary: LFP codec — lossy compression of local-field-potential recordings via adaptive SVD and wavelet-packet thresholding
5
+ Project-URL: Homepage, https://github.com/int-brain-lab/lfpack
6
+ Project-URL: Bug Tracker, https://github.com/int-brain-lab/lfpack/issues
7
+ Author: The International Brain Laboratory
8
+ License: MIT
9
+ Requires-Python: >=3.10
10
+ Requires-Dist: h5py>=3.0
11
+ Requires-Dist: ibl-neuropixel
12
+ Requires-Dist: numpy
13
+ Requires-Dist: pywavelets
14
+ Requires-Dist: scipy
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest; extra == 'dev'
17
+ Requires-Dist: pytest-cov; extra == 'dev'
18
+ Description-Content-Type: text/markdown
19
+
20
+ # lfpack — LFP codec for Neuropixels recordings
21
+
22
+ <p align="center">
23
+ <img src="docs/figures/logo.png" alt="lfpack logo" width="300"/>
24
+ </p>
25
+
26
+ Lossy codec for local-field-potential (LFP) recordings from Neuropixels probes.
27
+ Achieves **>100× compression** with median RMSE < 25 µV via an 8-stage pipeline
28
+ (bad-channel detection → dephasing → highpass → interpolation → CAR → decimation → Cadzow → adaptive SVD + wavelet-packet thresholding).
29
+
30
+ ```bash
31
+ pip install lfpack
32
+ ```
33
+
34
+ ## Documentation
35
+
36
+ Full documentation is at **https://int-brain-lab.github.io/lfpack/**.
37
+
38
+ | Section | Contents |
39
+ | --- | --- |
40
+ | [Tutorial](https://int-brain-lab.github.io/lfpack/tutorials/first-compression.html) | End-to-end compression and decompression of a recording |
41
+ | [How-To: binned reads](https://int-brain-lab.github.io/lfpack/how-to/binned-reads.html) | Memory-efficient channel-binned access |
42
+ | [How-To: multi-recording files](https://int-brain-lab.github.io/lfpack/how-to/multi-recording.html) | Combining multiple recordings in one HDF5 file |
43
+ | [API reference](https://int-brain-lab.github.io/lfpack/reference/) | Full public API (`compress_bin_to_h5`, `LFPackReader`, …) |
44
+ | [HDF5 format](https://int-brain-lab.github.io/lfpack/reference/hdf5-layout.html) | On-disk layout specification |
45
+ | [Pipeline explanation](https://int-brain-lab.github.io/lfpack/explanation/pipeline.html) | Stage-by-stage description of the compression pipeline |
46
+ | [SVD+WP benchmark](https://int-brain-lab.github.io/lfpack/explanation/benchmark.html) | RMSE, SNR, and compression-ratio results across 11 insertions |
lfpack-0.1.0/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # lfpack — LFP codec for Neuropixels recordings
2
+
3
+ <p align="center">
4
+ <img src="docs/figures/logo.png" alt="lfpack logo" width="300"/>
5
+ </p>
6
+
7
+ Lossy codec for local-field-potential (LFP) recordings from Neuropixels probes.
8
+ Achieves **>100× compression** with median RMSE < 25 µV via an 8-stage pipeline
9
+ (bad-channel detection → dephasing → highpass → interpolation → CAR → decimation → Cadzow → adaptive SVD + wavelet-packet thresholding).
10
+
11
+ ```bash
12
+ pip install lfpack
13
+ ```
14
+
15
+ ## Documentation
16
+
17
+ Full documentation is at **https://int-brain-lab.github.io/lfpack/**.
18
+
19
+ | Section | Contents |
20
+ | --- | --- |
21
+ | [Tutorial](https://int-brain-lab.github.io/lfpack/tutorials/first-compression.html) | End-to-end compression and decompression of a recording |
22
+ | [How-To: binned reads](https://int-brain-lab.github.io/lfpack/how-to/binned-reads.html) | Memory-efficient channel-binned access |
23
+ | [How-To: multi-recording files](https://int-brain-lab.github.io/lfpack/how-to/multi-recording.html) | Combining multiple recordings in one HDF5 file |
24
+ | [API reference](https://int-brain-lab.github.io/lfpack/reference/) | Full public API (`compress_bin_to_h5`, `LFPackReader`, …) |
25
+ | [HDF5 format](https://int-brain-lab.github.io/lfpack/reference/hdf5-layout.html) | On-disk layout specification |
26
+ | [Pipeline explanation](https://int-brain-lab.github.io/lfpack/explanation/pipeline.html) | Stage-by-stage description of the compression pipeline |
27
+ | [SVD+WP benchmark](https://int-brain-lab.github.io/lfpack/explanation/benchmark.html) | RMSE, SNR, and compression-ratio results across 11 insertions |
@@ -0,0 +1,2 @@
1
+ /.quarto/
2
+ **/*.quarto_ipynb
@@ -0,0 +1,25 @@
1
+ Local development
2
+ -----------------
3
+
4
+ 1. Install dependencies (once):
5
+ uv sync --group dev
6
+
7
+ 2. Regenerate API reference from docstrings (run after editing _core.py):
8
+ uv run quartodoc build --config docs/_quarto.yml
9
+
10
+ 3. Live-preview the site:
11
+ quarto preview docs/
12
+
13
+ The preview server reloads automatically when .qmd files change.
14
+ Re-run step 2 manually whenever docstrings change — quartodoc output
15
+ is not watched by the preview server.
16
+
17
+
18
+ Production build
19
+ ----------------
20
+
21
+ The site is built and deployed automatically by GitHub Actions on every
22
+ push to main (.github/workflows/docs.yml). The workflow runs the same
23
+ three steps above (quartodoc build → quarto render → deploy to GitHub Pages).
24
+
25
+ Do not commit the generated _site/ directory; it is built in CI.
@@ -0,0 +1,64 @@
1
+ project:
2
+ type: website
3
+ output-dir: _site
4
+
5
+ website:
6
+ title: "lfpack"
7
+ favicon: figures/favicon.png
8
+ repo-url: https://github.com/int-brain-lab/lfpack
9
+ navbar:
10
+ left:
11
+ - text: "Tutorial"
12
+ file: tutorials/first-compression.qmd
13
+ - text: "How-To"
14
+ menu:
15
+ - text: "Binned-channel reads"
16
+ file: how-to/binned-reads.qmd
17
+ - text: "Multi-recording files"
18
+ file: how-to/multi-recording.qmd
19
+ - text: "Reference"
20
+ menu:
21
+ - text: "API"
22
+ file: reference/index.qmd
23
+ - text: "HDF5 format"
24
+ file: reference/hdf5-layout.qmd
25
+ - text: "Explanation"
26
+ menu:
27
+ - text: "Compression pipeline"
28
+ file: explanation/pipeline.qmd
29
+ - text: "Benchmark gallery"
30
+ file: explanation/gallery.qmd
31
+ right:
32
+ - icon: github
33
+ href: https://github.com/int-brain-lab/lfpack
34
+
35
+ format:
36
+ html:
37
+ theme: minty
38
+ toc: true
39
+ code-copy: true
40
+ code-overflow: wrap
41
+ lightbox: true
42
+
43
+ quartodoc:
44
+ package: lfpack
45
+ dir: reference
46
+ sidebar: reference/_sidebar.yml
47
+ sections:
48
+ - title: "Compression"
49
+ desc: "Compress LFP recordings to HDF5."
50
+ contents:
51
+ - compress_bin_to_h5
52
+ - compress_to_h5
53
+ - compress_pipeline
54
+ - compress
55
+ - decompress
56
+ - run_cadzow_checkpoint
57
+ - title: "Data types"
58
+ desc: "Core data structures."
59
+ contents:
60
+ - LFPCompressed
61
+ - title: "Reader"
62
+ desc: "Random-access decompression."
63
+ contents:
64
+ - LFPackReader
@@ -0,0 +1,51 @@
1
+ ---
2
+ title: "Benchmark gallery"
3
+ ---
4
+
5
+ Compression results across 11 IBL Neuropixels (NP1) recordings spanning a range of brain
6
+ regions and recording quality. Each recording was compressed with two parameter sets:
7
+
8
+ | Label | ε | α | Typical CR |
9
+ |---|---|---|---|
10
+ | **default** | 150 | 28 | ~350× |
11
+ | **aggressive** | 450 | 96 | ~750× |
12
+
13
+ Click any figure to open it full-size with keyboard navigation.
14
+
15
+ ---
16
+
17
+ ## Aggregate metrics
18
+
19
+ RMSE distribution (bar = median, ▽ = p95) and compression ratio across all recordings.
20
+
21
+ ![Aggregate RMSE and compression ratio across all 11 PIDs](../figures/gallery/2026-06-15_lfp_compression_aggregate.png){.lightbox}
22
+
23
+ ---
24
+
25
+ ## Voltage density
26
+
27
+ Columns within each panel: original → Cadzow → default → aggressive (top row), with
28
+ residuals vs the previous stage (bottom row).
29
+
30
+ ![`1a276285`](../figures/gallery/2026-06-02_lfp_density_voltage_1a276285-8b0e-4cc9-9f0a-a3a002978724.png){group="density" .lightbox}
31
+
32
+ ![`1e104bf4`](../figures/gallery/2026-06-02_lfp_density_voltage_1e104bf4-7a24-4624-a5b2-c2c8289c0de7.png){group="density" .lightbox}
33
+
34
+ ![`6638cfb3`](../figures/gallery/2026-06-02_lfp_density_voltage_6638cfb3-3831-4fc2-9327-194b76cf22e1.png){group="density" .lightbox}
35
+
36
+ ![`749cb2b7`](../figures/gallery/2026-06-02_lfp_density_voltage_749cb2b7-e57e-4453-a794-f6230e4d0226.png){group="density" .lightbox}
37
+
38
+ ![`d7ec0892`](../figures/gallery/2026-06-02_lfp_density_voltage_d7ec0892-0a6c-4f4f-9d8f-72083692af5c.png){group="density" .lightbox}
39
+
40
+ ![`da8dfec1`](../figures/gallery/2026-06-02_lfp_density_voltage_da8dfec1-d265-44e8-84ce-6ae9c109b8bd.png){group="density" .lightbox}
41
+
42
+ ![`dab512bd`](../figures/gallery/2026-06-02_lfp_density_voltage_dab512bd-a02d-4c1f-8dbc-9155a163efc0.png){group="density" .lightbox}
43
+
44
+ ![`dc7e9403`](../figures/gallery/2026-06-02_lfp_density_voltage_dc7e9403-19f7-409f-9240-05ee57cb7aea.png){group="density" .lightbox}
45
+
46
+ ![`e8f9fba4`](../figures/gallery/2026-06-02_lfp_density_voltage_e8f9fba4-d151-4b00-bee7-447f0f3e752c.png){group="density" .lightbox}
47
+
48
+ ![`eebcaf65`](../figures/gallery/2026-06-02_lfp_density_voltage_eebcaf65-7fa4-4118-869d-a084e84530e2.png){group="density" .lightbox}
49
+
50
+ ![`fe380793`](../figures/gallery/2026-06-02_lfp_density_voltage_fe380793-8035-414e-b000-09bfe5ece92a.png){group="density" .lightbox}
51
+