lbm_suite2p_python 2.2.0__tar.gz → 2.3.1__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.
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/LICENSE.md +17 -17
- lbm_suite2p_python-2.3.1/PKG-INFO +181 -0
- lbm_suite2p_python-2.3.1/README.md +153 -0
- lbm_suite2p_python-2.3.1/lbm_suite2p_python/__init__.py +67 -0
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/__main__.py +101 -101
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/_benchmarking.py +29 -29
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/default_ops.py +213 -214
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/merging.py +363 -363
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/postprocessing.py +840 -489
- lbm_suite2p_python-2.3.1/lbm_suite2p_python/run_lsp.py +2002 -0
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/utils.py +173 -173
- lbm_suite2p_python-2.3.1/lbm_suite2p_python/volume.py +1512 -0
- lbm_suite2p_python-2.3.1/lbm_suite2p_python/zplane.py +3565 -0
- lbm_suite2p_python-2.3.1/lbm_suite2p_python.egg-info/PKG-INFO +181 -0
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python.egg-info/SOURCES.txt +1 -0
- lbm_suite2p_python-2.3.1/lbm_suite2p_python.egg-info/requires.txt +18 -0
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/pyproject.toml +125 -106
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/setup.cfg +4 -4
- lbm_suite2p_python-2.3.1/tests/test_pipeline_parameters.py +619 -0
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/tests/test_run_volume.py +79 -79
- lbm_suite2p_python-2.2.0/PKG-INFO +0 -98
- lbm_suite2p_python-2.2.0/README.md +0 -82
- lbm_suite2p_python-2.2.0/lbm_suite2p_python/__init__.py +0 -34
- lbm_suite2p_python-2.2.0/lbm_suite2p_python/run_lsp.py +0 -1057
- lbm_suite2p_python-2.2.0/lbm_suite2p_python/volume.py +0 -526
- lbm_suite2p_python-2.2.0/lbm_suite2p_python/zplane.py +0 -1516
- lbm_suite2p_python-2.2.0/lbm_suite2p_python.egg-info/PKG-INFO +0 -98
- lbm_suite2p_python-2.2.0/lbm_suite2p_python.egg-info/requires.txt +0 -1
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/MANIFEST.in +0 -0
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python.egg-info/dependency_links.txt +0 -0
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python.egg-info/entry_points.txt +0 -0
- {lbm_suite2p_python-2.2.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python.egg-info/top_level.txt +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
This software license is the 3-clause BSD license plus a fourth clause that prohibits redistribution for commercial purposes without further permission.
|
|
2
|
-
|
|
3
|
-
BSD 3-Clause License
|
|
4
|
-
|
|
5
|
-
Copyright (c) 2024, Miller Brain Observatory.
|
|
6
|
-
|
|
7
|
-
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
8
|
-
|
|
9
|
-
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
10
|
-
|
|
11
|
-
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
12
|
-
|
|
13
|
-
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
14
|
-
|
|
15
|
-
Redistributions for commercial purposes are not permitted without the written permission of all code authors. For purposes of this license, commercial purposes is the incorporation of LBM-Suite2p-Python into anything for which you will charge fees or other compensation. Contact mbo@rockefeller.edu for more information.
|
|
16
|
-
|
|
17
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1
|
+
This software license is the 3-clause BSD license plus a fourth clause that prohibits redistribution for commercial purposes without further permission.
|
|
2
|
+
|
|
3
|
+
BSD 3-Clause License
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2024, Miller Brain Observatory.
|
|
6
|
+
|
|
7
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
12
|
+
|
|
13
|
+
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
14
|
+
|
|
15
|
+
Redistributions for commercial purposes are not permitted without the written permission of all code authors. For purposes of this license, commercial purposes is the incorporation of LBM-Suite2p-Python into anything for which you will charge fees or other compensation. Contact mbo@rockefeller.edu for more information.
|
|
16
|
+
|
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lbm_suite2p_python
|
|
3
|
+
Version: 2.3.1
|
|
4
|
+
Summary: Light Beads Microscopy Pipeline using Suite2p
|
|
5
|
+
License-Expression: BSD-3-Clause
|
|
6
|
+
Project-URL: homepage, https://github.com/MillerBrainObservatory/LBM-Suite2p-Python
|
|
7
|
+
Keywords: Pipeline,Numpy,Microscopy,ScanImage,Suite2p,tiff
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Requires-Python: <3.12.10,>=3.12.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE.md
|
|
14
|
+
Requires-Dist: mbo_utilities>=2.3.0
|
|
15
|
+
Requires-Dist: fastplotlib
|
|
16
|
+
Provides-Extra: suite2p
|
|
17
|
+
Requires-Dist: suite2p_mbo>=2.0.0; extra == "suite2p"
|
|
18
|
+
Provides-Extra: rastermap
|
|
19
|
+
Requires-Dist: rastermap; extra == "rastermap"
|
|
20
|
+
Provides-Extra: cellpose
|
|
21
|
+
Requires-Dist: cellpose>=4.0.6; extra == "cellpose"
|
|
22
|
+
Provides-Extra: torch
|
|
23
|
+
Requires-Dist: torch>=2.7.0; extra == "torch"
|
|
24
|
+
Requires-Dist: torchvision>=0.22.0; extra == "torch"
|
|
25
|
+
Provides-Extra: all
|
|
26
|
+
Requires-Dist: lbm_suite2p_python[cellpose,rastermap,suite2p,torch]; extra == "all"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# LBM-Suite2p-Python
|
|
30
|
+
|
|
31
|
+
> **Status:** Late-beta stage of development
|
|
32
|
+
|
|
33
|
+
[](https://millerbrainobservatory.github.io/LBM-Suite2p-Python/index.html)
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/lbm-suite2p-python/)
|
|
36
|
+
[](https://doi.org/10.1038/s41592-021-01239-8)
|
|
37
|
+
|
|
38
|
+
A volumetric 2-photon calcium imaging processing pipeline for Light Beads Microscopy (LBM) datasets, built on Suite2p.
|
|
39
|
+
|
|
40
|
+
A GUI is available via [mbo_utilities](https://millerbrainobservatory.github.io/mbo_utilities/index.html#gui) (GUI functionality will lag behind this pipeline).
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
LBM-Suite2p-Python is a pure `pip` install. You can use `venv`, `uv` (recommended), or `conda`. Just remove the `uv` prefix.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# create a new project folder
|
|
48
|
+
mkdir my_project
|
|
49
|
+
cd my_project
|
|
50
|
+
|
|
51
|
+
# (uv only) create environment and install
|
|
52
|
+
uv venv --python 3.12.9
|
|
53
|
+
uv pip install lbm_suite2p_python
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Optional Dependencies
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# With rastermap for activity clustering visualization
|
|
60
|
+
uv pip install "lbm_suite2p_python[rastermap]"
|
|
61
|
+
|
|
62
|
+
# With cellpose for anatomical cell detection (includes PyTorch)
|
|
63
|
+
uv pip install "lbm_suite2p_python[cellpose]"
|
|
64
|
+
|
|
65
|
+
# All optional dependencies
|
|
66
|
+
uv pip install "lbm_suite2p_python[all]"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Development Installation
|
|
70
|
+
|
|
71
|
+
While this pipeline is in active development, you can keep a local copy to quickly pull changes:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
git clone https://github.com/MillerBrainObservatory/LBM-Suite2p-Python.git
|
|
75
|
+
cd LBM-Suite2p-Python
|
|
76
|
+
uv pip install .
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### GUI Dependencies
|
|
80
|
+
|
|
81
|
+
**Linux / macOS:**
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
sudo apt install libxcursor-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Windows:**
|
|
88
|
+
Install [Microsoft Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist)
|
|
89
|
+
|
|
90
|
+
### Troubleshooting
|
|
91
|
+
|
|
92
|
+
When installing from github, you may get:
|
|
93
|
+
|
|
94
|
+
**Git LFS Error:** If you see `smudge filter lfs failed`:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
GIT_LFS_SKIP_SMUDGE=1 uv sync --all-extras --active
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Quick Start
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
import lbm_suite2p_python as lsp
|
|
104
|
+
|
|
105
|
+
results = lsp.pipeline(
|
|
106
|
+
input_data="D:/data/raw", # path to file, directory, or list of files
|
|
107
|
+
save_path=None, # default: save next to input
|
|
108
|
+
ops=None, # default: use MBO-optimized parameters
|
|
109
|
+
planes=None, # default: process all planes
|
|
110
|
+
roi=None, # default: stitch multi-ROI data
|
|
111
|
+
keep_reg=True, # default: keep data.bin (registered binary)
|
|
112
|
+
keep_raw=False, # default: delete data_raw.bin after processing
|
|
113
|
+
force_reg=False, # default: skip if already registered
|
|
114
|
+
force_detect=False, # default: skip if stat.npy exists
|
|
115
|
+
dff_window_size=None, # default: auto-calculate from tau and framerate
|
|
116
|
+
dff_percentile=20, # default: 20th percentile for baseline
|
|
117
|
+
dff_smooth_window=None, # default: auto-calculate from tau and framerate
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Planar Results
|
|
122
|
+
|
|
123
|
+
Each z-plane produces diagnostic images automatically saved during processing.
|
|
124
|
+
|
|
125
|
+
<p align="center">
|
|
126
|
+
<img src="docs/_images/segmentation_summary.gif" alt="Segmentation Summary" width="500"/>
|
|
127
|
+
<br><em>Segmentation overlays on reference images</em>
|
|
128
|
+
</p>
|
|
129
|
+
|
|
130
|
+
<p align="center">
|
|
131
|
+
<img src="docs/_images/05_quality_diagnostics.png" alt="Quality Diagnostics" width="550"/>
|
|
132
|
+
<br><em>ROI quality metrics: size, SNR, compactness</em>
|
|
133
|
+
</p>
|
|
134
|
+
|
|
135
|
+
<p align="center">
|
|
136
|
+
<img src="docs/_images/08_traces_dff.png" alt="ΔF/F Traces" width="500"/>
|
|
137
|
+
<br><em>ΔF/F traces sorted by quality</em>
|
|
138
|
+
</p>
|
|
139
|
+
|
|
140
|
+
## Volumetric Results
|
|
141
|
+
|
|
142
|
+
Volume-level visualizations combine data across all z-planes.
|
|
143
|
+
|
|
144
|
+
<p align="center">
|
|
145
|
+
<img src="docs/_images/all_planes_masks.png" alt="All Planes Masks" width="550"/>
|
|
146
|
+
<br><em>ROI masks across all z-planes</em>
|
|
147
|
+
</p>
|
|
148
|
+
|
|
149
|
+
<p align="center">
|
|
150
|
+
<img src="docs/_images/roi_map_3d_snr.png" alt="3D ROI Map" width="450"/>
|
|
151
|
+
<br><em>3D ROI centroids colored by SNR</em>
|
|
152
|
+
</p>
|
|
153
|
+
|
|
154
|
+
<p align="center">
|
|
155
|
+
<img src="docs/_images/rastermap.png" alt="Rastermap" width="550"/>
|
|
156
|
+
<br><em>Activity sorted by similarity (Rastermap)</em>
|
|
157
|
+
</p>
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
## Built With
|
|
161
|
+
|
|
162
|
+
This pipeline integrates several open-source tools:
|
|
163
|
+
|
|
164
|
+
- **[Suite2p](https://github.com/MouseLand/suite2p)** - Core registration and segmentation
|
|
165
|
+
- **[Cellpose](https://github.com/MouseLand/cellpose)** - Anatomical segmentation (optional)
|
|
166
|
+
- **[Rastermap](https://github.com/MouseLand/rastermap)** - Activity clustering (optional)
|
|
167
|
+
- **[mbo_utilities](https://github.com/MillerBrainObservatory/mbo_utilities)** - ScanImage I/O and metadata
|
|
168
|
+
- **[scanreader](https://github.com/atlab/scanreader)** - ScanImage metadata parsing
|
|
169
|
+
|
|
170
|
+
## Issues & Support
|
|
171
|
+
|
|
172
|
+
- **Bug reports:** [GitHub Issues](https://github.com/MillerBrainObservatory/LBM-Suite2p-Python/issues)
|
|
173
|
+
- **Questions:** See [Suite2p documentation](https://suite2p.readthedocs.io/) for Suite2p-specific questions
|
|
174
|
+
- **Known issues:** Widgets may throw "Invalid Rect" errors ([upstream issue](https://github.com/pygfx/wgpu-py/issues/716#issuecomment-2880853089))
|
|
175
|
+
|
|
176
|
+
## Contributing
|
|
177
|
+
|
|
178
|
+
Contributions are welcome! This project follows Suite2p's conventions and uses:
|
|
179
|
+
- **Ruff** for linting and formatting (line length: 88, numpy docstring style)
|
|
180
|
+
- **pytest** for testing
|
|
181
|
+
- **Sphinx** for documentation
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# LBM-Suite2p-Python
|
|
2
|
+
|
|
3
|
+
> **Status:** Late-beta stage of development
|
|
4
|
+
|
|
5
|
+
[](https://millerbrainobservatory.github.io/LBM-Suite2p-Python/index.html)
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/lbm-suite2p-python/)
|
|
8
|
+
[](https://doi.org/10.1038/s41592-021-01239-8)
|
|
9
|
+
|
|
10
|
+
A volumetric 2-photon calcium imaging processing pipeline for Light Beads Microscopy (LBM) datasets, built on Suite2p.
|
|
11
|
+
|
|
12
|
+
A GUI is available via [mbo_utilities](https://millerbrainobservatory.github.io/mbo_utilities/index.html#gui) (GUI functionality will lag behind this pipeline).
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
LBM-Suite2p-Python is a pure `pip` install. You can use `venv`, `uv` (recommended), or `conda`. Just remove the `uv` prefix.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# create a new project folder
|
|
20
|
+
mkdir my_project
|
|
21
|
+
cd my_project
|
|
22
|
+
|
|
23
|
+
# (uv only) create environment and install
|
|
24
|
+
uv venv --python 3.12.9
|
|
25
|
+
uv pip install lbm_suite2p_python
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Optional Dependencies
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# With rastermap for activity clustering visualization
|
|
32
|
+
uv pip install "lbm_suite2p_python[rastermap]"
|
|
33
|
+
|
|
34
|
+
# With cellpose for anatomical cell detection (includes PyTorch)
|
|
35
|
+
uv pip install "lbm_suite2p_python[cellpose]"
|
|
36
|
+
|
|
37
|
+
# All optional dependencies
|
|
38
|
+
uv pip install "lbm_suite2p_python[all]"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Development Installation
|
|
42
|
+
|
|
43
|
+
While this pipeline is in active development, you can keep a local copy to quickly pull changes:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/MillerBrainObservatory/LBM-Suite2p-Python.git
|
|
47
|
+
cd LBM-Suite2p-Python
|
|
48
|
+
uv pip install .
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### GUI Dependencies
|
|
52
|
+
|
|
53
|
+
**Linux / macOS:**
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
sudo apt install libxcursor-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Windows:**
|
|
60
|
+
Install [Microsoft Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist)
|
|
61
|
+
|
|
62
|
+
### Troubleshooting
|
|
63
|
+
|
|
64
|
+
When installing from github, you may get:
|
|
65
|
+
|
|
66
|
+
**Git LFS Error:** If you see `smudge filter lfs failed`:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
GIT_LFS_SKIP_SMUDGE=1 uv sync --all-extras --active
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Quick Start
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import lbm_suite2p_python as lsp
|
|
76
|
+
|
|
77
|
+
results = lsp.pipeline(
|
|
78
|
+
input_data="D:/data/raw", # path to file, directory, or list of files
|
|
79
|
+
save_path=None, # default: save next to input
|
|
80
|
+
ops=None, # default: use MBO-optimized parameters
|
|
81
|
+
planes=None, # default: process all planes
|
|
82
|
+
roi=None, # default: stitch multi-ROI data
|
|
83
|
+
keep_reg=True, # default: keep data.bin (registered binary)
|
|
84
|
+
keep_raw=False, # default: delete data_raw.bin after processing
|
|
85
|
+
force_reg=False, # default: skip if already registered
|
|
86
|
+
force_detect=False, # default: skip if stat.npy exists
|
|
87
|
+
dff_window_size=None, # default: auto-calculate from tau and framerate
|
|
88
|
+
dff_percentile=20, # default: 20th percentile for baseline
|
|
89
|
+
dff_smooth_window=None, # default: auto-calculate from tau and framerate
|
|
90
|
+
)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Planar Results
|
|
94
|
+
|
|
95
|
+
Each z-plane produces diagnostic images automatically saved during processing.
|
|
96
|
+
|
|
97
|
+
<p align="center">
|
|
98
|
+
<img src="docs/_images/segmentation_summary.gif" alt="Segmentation Summary" width="500"/>
|
|
99
|
+
<br><em>Segmentation overlays on reference images</em>
|
|
100
|
+
</p>
|
|
101
|
+
|
|
102
|
+
<p align="center">
|
|
103
|
+
<img src="docs/_images/05_quality_diagnostics.png" alt="Quality Diagnostics" width="550"/>
|
|
104
|
+
<br><em>ROI quality metrics: size, SNR, compactness</em>
|
|
105
|
+
</p>
|
|
106
|
+
|
|
107
|
+
<p align="center">
|
|
108
|
+
<img src="docs/_images/08_traces_dff.png" alt="ΔF/F Traces" width="500"/>
|
|
109
|
+
<br><em>ΔF/F traces sorted by quality</em>
|
|
110
|
+
</p>
|
|
111
|
+
|
|
112
|
+
## Volumetric Results
|
|
113
|
+
|
|
114
|
+
Volume-level visualizations combine data across all z-planes.
|
|
115
|
+
|
|
116
|
+
<p align="center">
|
|
117
|
+
<img src="docs/_images/all_planes_masks.png" alt="All Planes Masks" width="550"/>
|
|
118
|
+
<br><em>ROI masks across all z-planes</em>
|
|
119
|
+
</p>
|
|
120
|
+
|
|
121
|
+
<p align="center">
|
|
122
|
+
<img src="docs/_images/roi_map_3d_snr.png" alt="3D ROI Map" width="450"/>
|
|
123
|
+
<br><em>3D ROI centroids colored by SNR</em>
|
|
124
|
+
</p>
|
|
125
|
+
|
|
126
|
+
<p align="center">
|
|
127
|
+
<img src="docs/_images/rastermap.png" alt="Rastermap" width="550"/>
|
|
128
|
+
<br><em>Activity sorted by similarity (Rastermap)</em>
|
|
129
|
+
</p>
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
## Built With
|
|
133
|
+
|
|
134
|
+
This pipeline integrates several open-source tools:
|
|
135
|
+
|
|
136
|
+
- **[Suite2p](https://github.com/MouseLand/suite2p)** - Core registration and segmentation
|
|
137
|
+
- **[Cellpose](https://github.com/MouseLand/cellpose)** - Anatomical segmentation (optional)
|
|
138
|
+
- **[Rastermap](https://github.com/MouseLand/rastermap)** - Activity clustering (optional)
|
|
139
|
+
- **[mbo_utilities](https://github.com/MillerBrainObservatory/mbo_utilities)** - ScanImage I/O and metadata
|
|
140
|
+
- **[scanreader](https://github.com/atlab/scanreader)** - ScanImage metadata parsing
|
|
141
|
+
|
|
142
|
+
## Issues & Support
|
|
143
|
+
|
|
144
|
+
- **Bug reports:** [GitHub Issues](https://github.com/MillerBrainObservatory/LBM-Suite2p-Python/issues)
|
|
145
|
+
- **Questions:** See [Suite2p documentation](https://suite2p.readthedocs.io/) for Suite2p-specific questions
|
|
146
|
+
- **Known issues:** Widgets may throw "Invalid Rect" errors ([upstream issue](https://github.com/pygfx/wgpu-py/issues/716#issuecomment-2880853089))
|
|
147
|
+
|
|
148
|
+
## Contributing
|
|
149
|
+
|
|
150
|
+
Contributions are welcome! This project follows Suite2p's conventions and uses:
|
|
151
|
+
- **Ruff** for linting and formatting (line length: 88, numpy docstring style)
|
|
152
|
+
- **pytest** for testing
|
|
153
|
+
- **Sphinx** for documentation
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
2
|
+
|
|
3
|
+
from lbm_suite2p_python.default_ops import default_ops
|
|
4
|
+
from lbm_suite2p_python.run_lsp import *
|
|
5
|
+
from lbm_suite2p_python.utils import *
|
|
6
|
+
from lbm_suite2p_python.volume import *
|
|
7
|
+
from lbm_suite2p_python.zplane import *
|
|
8
|
+
from lbm_suite2p_python.postprocessing import *
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
__version__ = version("lbm_suite2p_python")
|
|
12
|
+
except PackageNotFoundError:
|
|
13
|
+
# fallback for editable installs
|
|
14
|
+
__version__ = "0.0.0"
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"pipeline",
|
|
18
|
+
"run_volume",
|
|
19
|
+
"run_plane",
|
|
20
|
+
"grid_search",
|
|
21
|
+
"consolidate_volume",
|
|
22
|
+
"add_processing_step",
|
|
23
|
+
"plot_traces",
|
|
24
|
+
"plot_masks",
|
|
25
|
+
"plot_rastermap",
|
|
26
|
+
"plot_traces_noise",
|
|
27
|
+
"plot_volume_signal",
|
|
28
|
+
"plot_volume_neuron_counts",
|
|
29
|
+
"plot_volume_diagnostics",
|
|
30
|
+
"plot_orthoslices",
|
|
31
|
+
"plot_3d_roi_map",
|
|
32
|
+
"plot_projection",
|
|
33
|
+
"plot_execution_time",
|
|
34
|
+
"plot_noise_distribution",
|
|
35
|
+
"plot_multiplane_masks",
|
|
36
|
+
"plot_plane_quality_metrics",
|
|
37
|
+
"plot_plane_diagnostics",
|
|
38
|
+
"plot_trace_analysis",
|
|
39
|
+
"plot_zplane_figures",
|
|
40
|
+
"plot_mask_comparison",
|
|
41
|
+
"create_volume_summary_table",
|
|
42
|
+
"dff_rolling_percentile",
|
|
43
|
+
"dff_median_filter",
|
|
44
|
+
"dff_shot_noise",
|
|
45
|
+
"compute_trace_quality_score",
|
|
46
|
+
"sort_traces_by_quality",
|
|
47
|
+
"load_ops",
|
|
48
|
+
"load_planar_results",
|
|
49
|
+
"default_ops",
|
|
50
|
+
# Image processing utilities
|
|
51
|
+
"normalize99",
|
|
52
|
+
"apply_hp_filter",
|
|
53
|
+
"random_colors_for_mask",
|
|
54
|
+
"mask_overlay",
|
|
55
|
+
"stat_to_mask",
|
|
56
|
+
# Filtering utilities
|
|
57
|
+
"filter_by_max_diameter",
|
|
58
|
+
"filter_by_diameter",
|
|
59
|
+
"filter_by_area",
|
|
60
|
+
"filter_by_eccentricity",
|
|
61
|
+
"plot_regional_zoom",
|
|
62
|
+
"plot_filtered_cells",
|
|
63
|
+
"plot_diameter_histogram",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
# Re-export with public name
|
|
67
|
+
from lbm_suite2p_python.run_lsp import _add_processing_step as add_processing_step
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import argparse
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from functools import partial
|
|
5
|
-
import lbm_suite2p_python as lsp
|
|
6
|
-
import mbo_utilities as mbo
|
|
7
|
-
|
|
8
|
-
print = partial(print, flush=True)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def add_args(parser: argparse.ArgumentParser):
|
|
12
|
-
"""
|
|
13
|
-
Add command-line arguments to the parser, dynamically adding arguments
|
|
14
|
-
for each key in the `ops` dictionary.
|
|
15
|
-
|
|
16
|
-
Parameters
|
|
17
|
-
----------
|
|
18
|
-
parser : argparse.ArgumentParser
|
|
19
|
-
The argument parser to which arguments are added.
|
|
20
|
-
|
|
21
|
-
Returns
|
|
22
|
-
-------
|
|
23
|
-
argparse.ArgumentParser
|
|
24
|
-
The parser with added arguments.
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
parser.add_argument("--version", type=str, help="Print the version of the package.")
|
|
28
|
-
parser.add_argument("--ops", type=str, help="Path to the ops .npy file.")
|
|
29
|
-
parser.add_argument("--data", type=str, help="Path to the data.")
|
|
30
|
-
parser.add_argument("--save", type=str, help="Path to save the results.")
|
|
31
|
-
parser.add_argument(
|
|
32
|
-
"--subdir", type=str, help="Additional subdirectory add to save-path."
|
|
33
|
-
)
|
|
34
|
-
parser.add_argument(
|
|
35
|
-
"--max-depth",
|
|
36
|
-
type=int,
|
|
37
|
-
help="Number of subdirectories to check for files to process.",
|
|
38
|
-
)
|
|
39
|
-
parser.add_argument(
|
|
40
|
-
"--overwrite", action="store_true", help="Overwrite existing files."
|
|
41
|
-
)
|
|
42
|
-
parser.add_argument(
|
|
43
|
-
"--skip-existing", action="store_true", help="Skip existing files."
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
return parser
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def main():
|
|
50
|
-
"""
|
|
51
|
-
The main function that orchestrates the CLI operations.
|
|
52
|
-
"""
|
|
53
|
-
print("\n----------- LBM-Suite2p-Pipeline -----------\n")
|
|
54
|
-
from suite2p.default_ops import default_ops
|
|
55
|
-
|
|
56
|
-
parser = argparse.ArgumentParser(description="LBM-Suite2p-pipeline parameters")
|
|
57
|
-
parser = add_args(parser)
|
|
58
|
-
args = parser.parse_args()
|
|
59
|
-
|
|
60
|
-
if args.version:
|
|
61
|
-
print(f"lbm_suite2p_python v{lsp.__version__}")
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
ops = (
|
|
65
|
-
np.load(args.ops, allow_pickle=True).item()
|
|
66
|
-
if args.ops
|
|
67
|
-
else default_ops()
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
if not args.data:
|
|
71
|
-
raise ValueError("No input file or directory specified. Use --data")
|
|
72
|
-
|
|
73
|
-
input_path = Path(args.data)
|
|
74
|
-
|
|
75
|
-
# default to data-path / 'results'
|
|
76
|
-
save_path = Path(args.save) if args.save else input_path.parent / "results"
|
|
77
|
-
save_path.mkdir(parents=True, exist_ok=True)
|
|
78
|
-
|
|
79
|
-
# Optional user-defined save folder (e.g., plane_01_runA)
|
|
80
|
-
subdir = Path(args.subdir) if args.subdir else None
|
|
81
|
-
|
|
82
|
-
if input_path.is_file():
|
|
83
|
-
output_ops = lsp.run_plane(
|
|
84
|
-
input_path=input_path,
|
|
85
|
-
save_path=save_path,
|
|
86
|
-
ops=ops,
|
|
87
|
-
)
|
|
88
|
-
elif input_path.is_dir():
|
|
89
|
-
files = mbo.get_files(input_path, "tiff", max_depth=args.max_depth)
|
|
90
|
-
output_ops = lsp.run_volume(
|
|
91
|
-
ops=ops, input_files=files, save_path=save_path, save_folder=subdir
|
|
92
|
-
)
|
|
93
|
-
else:
|
|
94
|
-
raise FileNotFoundError(f"Input path does not exist: {input_path}")
|
|
95
|
-
|
|
96
|
-
print("Processing complete -----------")
|
|
97
|
-
return output_ops
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if __name__ == "__main__":
|
|
101
|
-
main()
|
|
1
|
+
import numpy as np
|
|
2
|
+
import argparse
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from functools import partial
|
|
5
|
+
import lbm_suite2p_python as lsp
|
|
6
|
+
import mbo_utilities as mbo
|
|
7
|
+
|
|
8
|
+
print = partial(print, flush=True)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def add_args(parser: argparse.ArgumentParser):
|
|
12
|
+
"""
|
|
13
|
+
Add command-line arguments to the parser, dynamically adding arguments
|
|
14
|
+
for each key in the `ops` dictionary.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
parser : argparse.ArgumentParser
|
|
19
|
+
The argument parser to which arguments are added.
|
|
20
|
+
|
|
21
|
+
Returns
|
|
22
|
+
-------
|
|
23
|
+
argparse.ArgumentParser
|
|
24
|
+
The parser with added arguments.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
parser.add_argument("--version", type=str, help="Print the version of the package.")
|
|
28
|
+
parser.add_argument("--ops", type=str, help="Path to the ops .npy file.")
|
|
29
|
+
parser.add_argument("--data", type=str, help="Path to the data.")
|
|
30
|
+
parser.add_argument("--save", type=str, help="Path to save the results.")
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"--subdir", type=str, help="Additional subdirectory add to save-path."
|
|
33
|
+
)
|
|
34
|
+
parser.add_argument(
|
|
35
|
+
"--max-depth",
|
|
36
|
+
type=int,
|
|
37
|
+
help="Number of subdirectories to check for files to process.",
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--overwrite", action="store_true", help="Overwrite existing files."
|
|
41
|
+
)
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
"--skip-existing", action="store_true", help="Skip existing files."
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return parser
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def main():
|
|
50
|
+
"""
|
|
51
|
+
The main function that orchestrates the CLI operations.
|
|
52
|
+
"""
|
|
53
|
+
print("\n----------- LBM-Suite2p-Pipeline -----------\n")
|
|
54
|
+
from suite2p.default_ops import default_ops
|
|
55
|
+
|
|
56
|
+
parser = argparse.ArgumentParser(description="LBM-Suite2p-pipeline parameters")
|
|
57
|
+
parser = add_args(parser)
|
|
58
|
+
args = parser.parse_args()
|
|
59
|
+
|
|
60
|
+
if args.version:
|
|
61
|
+
print(f"lbm_suite2p_python v{lsp.__version__}")
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
ops = (
|
|
65
|
+
np.load(args.ops, allow_pickle=True).item()
|
|
66
|
+
if args.ops
|
|
67
|
+
else default_ops()
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
if not args.data:
|
|
71
|
+
raise ValueError("No input file or directory specified. Use --data")
|
|
72
|
+
|
|
73
|
+
input_path = Path(args.data)
|
|
74
|
+
|
|
75
|
+
# default to data-path / 'results'
|
|
76
|
+
save_path = Path(args.save) if args.save else input_path.parent / "results"
|
|
77
|
+
save_path.mkdir(parents=True, exist_ok=True)
|
|
78
|
+
|
|
79
|
+
# Optional user-defined save folder (e.g., plane_01_runA)
|
|
80
|
+
subdir = Path(args.subdir) if args.subdir else None
|
|
81
|
+
|
|
82
|
+
if input_path.is_file():
|
|
83
|
+
output_ops = lsp.run_plane(
|
|
84
|
+
input_path=input_path,
|
|
85
|
+
save_path=save_path,
|
|
86
|
+
ops=ops,
|
|
87
|
+
)
|
|
88
|
+
elif input_path.is_dir():
|
|
89
|
+
files = mbo.get_files(input_path, "tiff", max_depth=args.max_depth)
|
|
90
|
+
output_ops = lsp.run_volume(
|
|
91
|
+
ops=ops, input_files=files, save_path=save_path, save_folder=subdir
|
|
92
|
+
)
|
|
93
|
+
else:
|
|
94
|
+
raise FileNotFoundError(f"Input path does not exist: {input_path}")
|
|
95
|
+
|
|
96
|
+
print("Processing complete -----------")
|
|
97
|
+
return output_ops
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == "__main__":
|
|
101
|
+
main()
|