lbm_suite2p_python 2.3.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.3.0/lbm_suite2p_python.egg-info → lbm_suite2p_python-2.3.1}/PKG-INFO +9 -6
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/__init__.py +19 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/default_ops.py +1 -2
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/postprocessing.py +115 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/run_lsp.py +257 -33
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/zplane.py +772 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1/lbm_suite2p_python.egg-info}/PKG-INFO +9 -6
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python.egg-info/requires.txt +10 -5
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/pyproject.toml +13 -11
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/LICENSE.md +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/MANIFEST.in +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/README.md +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/__main__.py +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/_benchmarking.py +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/merging.py +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/utils.py +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python/volume.py +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python.egg-info/SOURCES.txt +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python.egg-info/dependency_links.txt +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python.egg-info/entry_points.txt +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/lbm_suite2p_python.egg-info/top_level.txt +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/setup.cfg +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.1}/tests/test_pipeline_parameters.py +0 -0
- {lbm_suite2p_python-2.3.0 → lbm_suite2p_python-2.3.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: 2.3.
|
|
3
|
+
Version: 2.3.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
|
|
@@ -12,15 +12,18 @@ Requires-Python: <3.12.10,>=3.12.7
|
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE.md
|
|
14
14
|
Requires-Dist: mbo_utilities>=2.3.0
|
|
15
|
-
Requires-Dist:
|
|
15
|
+
Requires-Dist: fastplotlib
|
|
16
|
+
Provides-Extra: suite2p
|
|
17
|
+
Requires-Dist: suite2p_mbo>=2.0.0; extra == "suite2p"
|
|
16
18
|
Provides-Extra: rastermap
|
|
17
19
|
Requires-Dist: rastermap; extra == "rastermap"
|
|
18
20
|
Provides-Extra: cellpose
|
|
19
|
-
Requires-Dist: cellpose
|
|
20
|
-
|
|
21
|
-
Requires-Dist:
|
|
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"
|
|
22
25
|
Provides-Extra: all
|
|
23
|
-
Requires-Dist: lbm_suite2p_python[cellpose,rastermap]; extra == "all"
|
|
26
|
+
Requires-Dist: lbm_suite2p_python[cellpose,rastermap,suite2p,torch]; extra == "all"
|
|
24
27
|
Dynamic: license-file
|
|
25
28
|
|
|
26
29
|
# LBM-Suite2p-Python
|
|
@@ -19,6 +19,7 @@ __all__ = [
|
|
|
19
19
|
"run_plane",
|
|
20
20
|
"grid_search",
|
|
21
21
|
"consolidate_volume",
|
|
22
|
+
"add_processing_step",
|
|
22
23
|
"plot_traces",
|
|
23
24
|
"plot_masks",
|
|
24
25
|
"plot_rastermap",
|
|
@@ -36,6 +37,7 @@ __all__ = [
|
|
|
36
37
|
"plot_plane_diagnostics",
|
|
37
38
|
"plot_trace_analysis",
|
|
38
39
|
"plot_zplane_figures",
|
|
40
|
+
"plot_mask_comparison",
|
|
39
41
|
"create_volume_summary_table",
|
|
40
42
|
"dff_rolling_percentile",
|
|
41
43
|
"dff_median_filter",
|
|
@@ -45,4 +47,21 @@ __all__ = [
|
|
|
45
47
|
"load_ops",
|
|
46
48
|
"load_planar_results",
|
|
47
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",
|
|
48
64
|
]
|
|
65
|
+
|
|
66
|
+
# Re-export with public name
|
|
67
|
+
from lbm_suite2p_python.run_lsp import _add_processing_step as add_processing_step
|
|
@@ -130,8 +130,7 @@ def s2p_ops():
|
|
|
130
130
|
"cellprob_threshold": -6, # cellprob_threshold for cellpose
|
|
131
131
|
"flow_threshold": 0, # flow_threshold for cellpose
|
|
132
132
|
"spatial_hp_cp": 0.5, # high-pass image spatially by a multiple of the diameter
|
|
133
|
-
"pretrained_model":
|
|
134
|
-
"cpsam", # path to pretrained model or model type string in Cellpose (can be user model)
|
|
133
|
+
"pretrained_model": "cpsam", # cellpose model to use for anatomical detection
|
|
135
134
|
|
|
136
135
|
# classification parameters
|
|
137
136
|
"soma_crop":
|
|
@@ -39,6 +39,121 @@ def filter_by_diameter(iscell, stat, ops, min_mult=0.3, max_mult=3.0):
|
|
|
39
39
|
return iscell
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
def filter_by_max_diameter(
|
|
43
|
+
iscell,
|
|
44
|
+
stat,
|
|
45
|
+
max_diameter_um: float = None,
|
|
46
|
+
max_diameter_px: float = None,
|
|
47
|
+
pixel_size_um: float = None,
|
|
48
|
+
ops: dict = None,
|
|
49
|
+
):
|
|
50
|
+
"""
|
|
51
|
+
Filter cells by maximum diameter in microns or pixels.
|
|
52
|
+
|
|
53
|
+
Sets iscell=False for ROIs whose diameter exceeds the specified threshold.
|
|
54
|
+
Diameter is computed as 2 * radius from the ellipse fit.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
iscell : np.ndarray
|
|
59
|
+
Cell classification array (n_rois,) or (n_rois, 2).
|
|
60
|
+
stat : np.ndarray or list
|
|
61
|
+
Suite2p stat array with ROI statistics.
|
|
62
|
+
max_diameter_um : float, optional
|
|
63
|
+
Maximum allowed diameter in microns. Requires pixel_size_um or ops
|
|
64
|
+
with pixel resolution info.
|
|
65
|
+
max_diameter_px : float, optional
|
|
66
|
+
Maximum allowed diameter in pixels. Used if max_diameter_um not given.
|
|
67
|
+
pixel_size_um : float, optional
|
|
68
|
+
Pixel size in microns. If None, attempts to read from ops.
|
|
69
|
+
ops : dict, optional
|
|
70
|
+
Suite2p ops dictionary. Used to get pixel resolution if pixel_size_um
|
|
71
|
+
not provided. Looks for 'umPerPix' or 'diameter' keys.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
iscell_filtered : np.ndarray
|
|
76
|
+
Updated iscell array with large ROIs marked as rejected.
|
|
77
|
+
removed_mask : np.ndarray
|
|
78
|
+
Boolean mask of ROIs that were removed (True = removed).
|
|
79
|
+
diameters_px : np.ndarray
|
|
80
|
+
Diameter of each ROI in pixels.
|
|
81
|
+
threshold_px : float
|
|
82
|
+
The threshold used in pixels.
|
|
83
|
+
|
|
84
|
+
Examples
|
|
85
|
+
--------
|
|
86
|
+
>>> # Filter by max 22 microns diameter
|
|
87
|
+
>>> iscell_filtered, removed, diameters, thresh = filter_by_max_diameter(
|
|
88
|
+
... iscell, stat, max_diameter_um=22, ops=ops
|
|
89
|
+
... )
|
|
90
|
+
|
|
91
|
+
>>> # Filter by max 15 pixels diameter
|
|
92
|
+
>>> iscell_filtered, removed, diameters, thresh = filter_by_max_diameter(
|
|
93
|
+
... iscell, stat, max_diameter_px=15
|
|
94
|
+
... )
|
|
95
|
+
|
|
96
|
+
>>> # Plot the removed cells
|
|
97
|
+
>>> from lbm_suite2p_python import plot_filtered_cells
|
|
98
|
+
>>> fig = plot_filtered_cells(stat, iscell_filtered, removed, ops=ops)
|
|
99
|
+
"""
|
|
100
|
+
iscell = _normalize_iscell(iscell)
|
|
101
|
+
|
|
102
|
+
if max_diameter_um is None and max_diameter_px is None:
|
|
103
|
+
raise ValueError("Must specify either max_diameter_um or max_diameter_px")
|
|
104
|
+
|
|
105
|
+
# Get radii from stat
|
|
106
|
+
if "radius" not in stat[0]:
|
|
107
|
+
# Compute radius if not present
|
|
108
|
+
radii = []
|
|
109
|
+
for s in stat:
|
|
110
|
+
npix = len(s["xpix"])
|
|
111
|
+
# Approximate radius from area: r = sqrt(npix / pi)
|
|
112
|
+
radii.append(np.sqrt(npix / np.pi))
|
|
113
|
+
radii = np.array(radii)
|
|
114
|
+
else:
|
|
115
|
+
radii = np.array([s["radius"] for s in stat])
|
|
116
|
+
|
|
117
|
+
diameters_px = 2 * radii
|
|
118
|
+
|
|
119
|
+
# Convert to pixels if given in microns
|
|
120
|
+
if max_diameter_um is not None:
|
|
121
|
+
# Get pixel size
|
|
122
|
+
if pixel_size_um is None and ops is not None:
|
|
123
|
+
# Try various keys for pixel resolution
|
|
124
|
+
if "umPerPix" in ops:
|
|
125
|
+
pixel_size_um = ops["umPerPix"]
|
|
126
|
+
elif "um_per_pixel" in ops:
|
|
127
|
+
pixel_size_um = ops["um_per_pixel"]
|
|
128
|
+
elif "pixel_resolution" in ops and ops["pixel_resolution"]:
|
|
129
|
+
pr = ops["pixel_resolution"]
|
|
130
|
+
if isinstance(pr, (list, tuple)) and len(pr) >= 2:
|
|
131
|
+
pixel_size_um = np.mean([pr[0], pr[1]])
|
|
132
|
+
else:
|
|
133
|
+
pixel_size_um = float(pr)
|
|
134
|
+
elif "umPerPixX" in ops and "umPerPixY" in ops:
|
|
135
|
+
pixel_size_um = np.mean([ops["umPerPixX"], ops["umPerPixY"]])
|
|
136
|
+
|
|
137
|
+
if pixel_size_um is None:
|
|
138
|
+
raise ValueError(
|
|
139
|
+
"Cannot convert microns to pixels: pixel_size_um not provided "
|
|
140
|
+
"and could not be found in ops. Use max_diameter_px instead."
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
max_diameter_px = max_diameter_um / pixel_size_um
|
|
144
|
+
|
|
145
|
+
# Apply filter
|
|
146
|
+
valid = diameters_px <= max_diameter_px
|
|
147
|
+
removed_mask = ~valid & iscell # ROIs that were cells but got filtered out
|
|
148
|
+
n_rejected = removed_mask.sum()
|
|
149
|
+
|
|
150
|
+
if n_rejected > 0:
|
|
151
|
+
print(f"Filtered {n_rejected} ROIs with diameter > {max_diameter_px:.1f} px")
|
|
152
|
+
|
|
153
|
+
iscell_filtered = iscell & valid
|
|
154
|
+
return iscell_filtered, removed_mask, diameters_px, max_diameter_px
|
|
155
|
+
|
|
156
|
+
|
|
42
157
|
def filter_by_area(iscell, stat, min_mult=0.25, max_mult=4.0):
|
|
43
158
|
"""
|
|
44
159
|
Filter cells by total area (in pixels).
|