lbm_suite2p_python 2.5.7__tar.gz → 3.0.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.5.7/lbm_suite2p_python.egg-info → lbm_suite2p_python-3.0.1}/PKG-INFO +4 -7
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/__init__.py +4 -0
- lbm_suite2p_python-3.0.1/lbm_suite2p_python/_padding_shim.py +140 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/cli.py +529 -529
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/conversion.py +4 -2
- lbm_suite2p_python-3.0.1/lbm_suite2p_python/db_settings.py +482 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/default_ops.py +12 -4
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/gui.py +1 -1
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/postprocessing.py +22 -6
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/run_lsp.py +735 -188
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/volume.py +22 -12
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/zplane.py +599 -87
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1/lbm_suite2p_python.egg-info}/PKG-INFO +4 -7
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python.egg-info/SOURCES.txt +2 -0
- lbm_suite2p_python-3.0.1/lbm_suite2p_python.egg-info/requires.txt +12 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/pyproject.toml +5 -10
- lbm_suite2p_python-2.5.7/lbm_suite2p_python.egg-info/requires.txt +0 -16
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/LICENSE.md +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/MANIFEST.in +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/README.md +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/__main__.py +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/_benchmarking.py +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/cellpose.py +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/grid_search.py +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/merging.py +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python/utils.py +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python.egg-info/dependency_links.txt +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python.egg-info/entry_points.txt +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/lbm_suite2p_python.egg-info/top_level.txt +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/setup.cfg +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/tests/test_frame_count_aliases.py +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/tests/test_pipeline_parameters.py +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/tests/test_refactored_pipeline.py +0 -0
- {lbm_suite2p_python-2.5.7 → lbm_suite2p_python-3.0.1}/tests/test_run_volume.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lbm_suite2p_python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.1
|
|
4
4
|
Summary: Light Beads Microscopy Pipeline using Suite2p
|
|
5
5
|
License-Expression: BSD-3-Clause
|
|
6
6
|
Project-URL: homepage, https://github.com/MillerBrainObservatory/LBM-Suite2p-Python
|
|
@@ -11,18 +11,15 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
11
11
|
Requires-Python: <3.14,>=3.12.7
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE.md
|
|
14
|
-
Requires-Dist: mbo_utilities>=
|
|
15
|
-
Requires-Dist:
|
|
14
|
+
Requires-Dist: mbo_utilities>=3.0.0
|
|
15
|
+
Requires-Dist: suite2p>=1.0.0.1
|
|
16
16
|
Requires-Dist: setuptools<81
|
|
17
17
|
Provides-Extra: rastermap
|
|
18
18
|
Requires-Dist: rastermap; extra == "rastermap"
|
|
19
19
|
Provides-Extra: cellpose
|
|
20
20
|
Requires-Dist: cellpose>=4.0.6; extra == "cellpose"
|
|
21
|
-
Provides-Extra: torch
|
|
22
|
-
Requires-Dist: torch>=2.7.0; extra == "torch"
|
|
23
|
-
Requires-Dist: torchvision>=0.22.0; extra == "torch"
|
|
24
21
|
Provides-Extra: all
|
|
25
|
-
Requires-Dist: lbm_suite2p_python[cellpose,rastermap
|
|
22
|
+
Requires-Dist: lbm_suite2p_python[cellpose,rastermap]; extra == "all"
|
|
26
23
|
Dynamic: license-file
|
|
27
24
|
|
|
28
25
|
<p align="center">
|
|
@@ -39,6 +39,8 @@ from lbm_suite2p_python.zplane import (
|
|
|
39
39
|
plot_filtered_cells,
|
|
40
40
|
plot_diameter_histogram,
|
|
41
41
|
plot_projection,
|
|
42
|
+
plot_accepted_rejected_overlay,
|
|
43
|
+
plot_volume_accepted_rejected_overlay,
|
|
42
44
|
)
|
|
43
45
|
|
|
44
46
|
from lbm_suite2p_python.volume import (
|
|
@@ -151,4 +153,6 @@ __all__ = [
|
|
|
151
153
|
"plot_volume_signal",
|
|
152
154
|
"plot_volume_neuron_counts",
|
|
153
155
|
"consolidate_volume",
|
|
156
|
+
"plot_accepted_rejected_overlay",
|
|
157
|
+
"plot_volume_accepted_rejected_overlay",
|
|
154
158
|
]
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Padding-aware extraction shim for upstream suite2p.
|
|
3
|
+
|
|
4
|
+
Problem
|
|
5
|
+
-------
|
|
6
|
+
When LBM data is axially registered, mbo's writer zero-pads planes so every
|
|
7
|
+
plane sits in a common (Ly, Lx) coordinate system. `ops["yrange"]` /
|
|
8
|
+
`ops["xrange"]` mark the valid (non-padded) region.
|
|
9
|
+
|
|
10
|
+
Upstream's `suite2p.detection.*` is yrange/xrange-aware: `bin_movie` crops
|
|
11
|
+
before computing meanImg / max_proj / Vcorr / cellpose inputs, so padding
|
|
12
|
+
never enters detection. Upstream's `suite2p.extraction.masks` is NOT:
|
|
13
|
+
`create_cell_pix` allocates `np.zeros((Ly, Lx))`, and `create_neuropil_masks`
|
|
14
|
+
treats any pixel with `cell_pix < 0.5` as a valid neuropil candidate. Zero-
|
|
15
|
+
padded pixels satisfy that predicate, so neuropil donuts around
|
|
16
|
+
boundary-adjacent ROIs grow into the padding and pull zeros into `Fneu`.
|
|
17
|
+
The corrupted `Fneu` propagates into `F - neuropil_coefficient * Fneu` and
|
|
18
|
+
every dF/F derived from it.
|
|
19
|
+
|
|
20
|
+
Fix
|
|
21
|
+
---
|
|
22
|
+
Monkeypatch `suite2p.extraction.masks.create_cell_pix` inside a context
|
|
23
|
+
manager scoped to the lbm call only. The replacement:
|
|
24
|
+
|
|
25
|
+
1. Calls upstream's real implementation to produce the cell-pixel mask.
|
|
26
|
+
2. Marks every pixel outside `ops["yrange"]` / `ops["xrange"]` as
|
|
27
|
+
"occupied" (True / 1.0), which makes `create_neuropil_masks`'s
|
|
28
|
+
`cell_pix[y,x] < 0.5` predicate return False for those pixels, so
|
|
29
|
+
donuts grow only into the valid region.
|
|
30
|
+
|
|
31
|
+
The patch is applied *only* for the duration of the `with` block and
|
|
32
|
+
restored on exit, regardless of whether the wrapped code succeeds or
|
|
33
|
+
raises. External users of suite2p see no change; only our call path is
|
|
34
|
+
affected.
|
|
35
|
+
|
|
36
|
+
Why this rather than rebuilding neuropil_masks externally and passing
|
|
37
|
+
them to `extraction_wrapper(neuropil_masks=...)`
|
|
38
|
+
-------------------------------------------------------------------
|
|
39
|
+
The external-build approach would require us to bypass upstream's
|
|
40
|
+
`pipeline()` and re-orchestrate detection → classification → extraction →
|
|
41
|
+
deconvolution ourselves, just to inject the `neuropil_masks=` kwarg.
|
|
42
|
+
Monkeypatching a single leaf function is ~15 lines, keeps us on the
|
|
43
|
+
upstream orchestration path, and is trivially reversible.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
from __future__ import annotations
|
|
47
|
+
|
|
48
|
+
import contextlib
|
|
49
|
+
import numpy as np
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@contextlib.contextmanager
|
|
53
|
+
def padding_aware_extraction(ops):
|
|
54
|
+
"""
|
|
55
|
+
Context manager: inside the block, upstream's neuropil-mask builder
|
|
56
|
+
treats pixels outside ``ops["yrange"]`` / ``ops["xrange"]`` as
|
|
57
|
+
"occupied", preventing neuropil donuts from extending into the
|
|
58
|
+
zero-padded axial-alignment border.
|
|
59
|
+
|
|
60
|
+
Safe to call unconditionally: if no yrange/xrange are present on ops,
|
|
61
|
+
or if they cover the full frame, the patch is a no-op.
|
|
62
|
+
|
|
63
|
+
Parameters
|
|
64
|
+
----------
|
|
65
|
+
ops : dict
|
|
66
|
+
Flat suite2p ops dict. Reads ``ops["yrange"]`` and
|
|
67
|
+
``ops["xrange"]``; does not mutate.
|
|
68
|
+
|
|
69
|
+
Yields
|
|
70
|
+
------
|
|
71
|
+
None
|
|
72
|
+
|
|
73
|
+
Examples
|
|
74
|
+
--------
|
|
75
|
+
>>> with padding_aware_extraction(ops):
|
|
76
|
+
... reg_outputs, detect_outputs, stat, F, Fneu, ... = pipeline(
|
|
77
|
+
... save_path=save_path, f_reg=f_reg, ..., settings=settings,
|
|
78
|
+
... )
|
|
79
|
+
"""
|
|
80
|
+
yrange = ops.get("yrange")
|
|
81
|
+
xrange = ops.get("xrange")
|
|
82
|
+
if not yrange or not xrange:
|
|
83
|
+
# no crop information — nothing to protect against
|
|
84
|
+
yield
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
y0, y1 = int(yrange[0]), int(yrange[1])
|
|
89
|
+
x0, x1 = int(xrange[0]), int(xrange[1])
|
|
90
|
+
except (TypeError, ValueError):
|
|
91
|
+
yield
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
# import here so a missing suite2p doesn't break import of this module
|
|
95
|
+
try:
|
|
96
|
+
from suite2p.extraction import masks as _m
|
|
97
|
+
except ImportError:
|
|
98
|
+
yield
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
original_create_cell_pix = getattr(_m, "create_cell_pix", None)
|
|
102
|
+
if original_create_cell_pix is None:
|
|
103
|
+
# upstream moved or inlined create_cell_pix — no safe patch point.
|
|
104
|
+
# fall through without modification rather than silently corrupting.
|
|
105
|
+
yield
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
def _padding_aware_create_cell_pix(stats, Ly, Lx, lam_percentile=50.0):
|
|
109
|
+
"""Drop-in replacement that adds the padding mask to upstream's result."""
|
|
110
|
+
cell_pix = original_create_cell_pix(stats, Ly, Lx, lam_percentile)
|
|
111
|
+
# upstream returns either bool array or float >0.5 mask; normalize
|
|
112
|
+
# to a bool copy so our additions don't alter any internal cache.
|
|
113
|
+
cell_pix = np.asarray(cell_pix).copy()
|
|
114
|
+
if cell_pix.dtype != bool:
|
|
115
|
+
cell_pix = cell_pix > 0.5
|
|
116
|
+
|
|
117
|
+
# mark the region OUTSIDE the valid window as occupied so the
|
|
118
|
+
# neuropil donut never extends into zero-padded pixels.
|
|
119
|
+
_y0 = max(0, min(y0, Ly))
|
|
120
|
+
_y1 = max(_y0, min(y1, Ly))
|
|
121
|
+
_x0 = max(0, min(x0, Lx))
|
|
122
|
+
_x1 = max(_x0, min(x1, Lx))
|
|
123
|
+
if _y0 > 0:
|
|
124
|
+
cell_pix[:_y0, :] = True
|
|
125
|
+
if _y1 < Ly:
|
|
126
|
+
cell_pix[_y1:, :] = True
|
|
127
|
+
if _x0 > 0:
|
|
128
|
+
cell_pix[:, :_x0] = True
|
|
129
|
+
if _x1 < Lx:
|
|
130
|
+
cell_pix[:, _x1:] = True
|
|
131
|
+
return cell_pix
|
|
132
|
+
|
|
133
|
+
_m.create_cell_pix = _padding_aware_create_cell_pix
|
|
134
|
+
try:
|
|
135
|
+
yield
|
|
136
|
+
finally:
|
|
137
|
+
# always restore, even on exception, so external callers of
|
|
138
|
+
# suite2p.extraction.masks.create_cell_pix see the unpatched
|
|
139
|
+
# upstream function.
|
|
140
|
+
_m.create_cell_pix = original_create_cell_pix
|