lbm_suite2p_python 3.1.1__tar.gz → 3.2.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 (32) hide show
  1. {lbm_suite2p_python-3.1.1/lbm_suite2p_python.egg-info → lbm_suite2p_python-3.2.0}/PKG-INFO +1 -1
  2. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/cellpose.py +6 -6
  3. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/conversion.py +2 -2
  4. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/default_ops.py +96 -84
  5. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/run_lsp.py +46 -15
  6. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0/lbm_suite2p_python.egg-info}/PKG-INFO +1 -1
  7. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/pyproject.toml +106 -106
  8. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/LICENSE.md +0 -0
  9. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/MANIFEST.in +0 -0
  10. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/README.md +0 -0
  11. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/__init__.py +0 -0
  12. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/__main__.py +0 -0
  13. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/_benchmarking.py +0 -0
  14. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/cli.py +0 -0
  15. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/db_settings.py +0 -0
  16. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/grid_search.py +0 -0
  17. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/gui.py +0 -0
  18. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/merging.py +0 -0
  19. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/postprocessing.py +0 -0
  20. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/utils.py +0 -0
  21. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/volume.py +0 -0
  22. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python/zplane.py +0 -0
  23. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python.egg-info/SOURCES.txt +0 -0
  24. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python.egg-info/dependency_links.txt +0 -0
  25. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python.egg-info/entry_points.txt +0 -0
  26. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python.egg-info/requires.txt +0 -0
  27. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/lbm_suite2p_python.egg-info/top_level.txt +0 -0
  28. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/setup.cfg +0 -0
  29. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/tests/test_frame_count_aliases.py +0 -0
  30. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/tests/test_pipeline_parameters.py +0 -0
  31. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/tests/test_refactored_pipeline.py +0 -0
  32. {lbm_suite2p_python-3.1.1 → lbm_suite2p_python-3.2.0}/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.1.1
3
+ Version: 3.2.0
4
4
  Summary: Calcium Imaging Pipeline built with Suite2p, Cellpose and Rastermap
5
5
  License-Expression: BSD-3-Clause
6
6
  Project-URL: homepage, https://github.com/MillerBrainObservatory/LBM-Suite2p-Python
@@ -390,7 +390,7 @@ def cellpose(
390
390
  # cellpose eval parameters
391
391
  diameter: float = None,
392
392
  flow_threshold: float = 0.0,
393
- cellprob_threshold: float = -6.0,
393
+ cellprob_threshold: float = -4.0,
394
394
  min_size: int = 2,
395
395
  max_size: int = None,
396
396
  max_size_fraction: float = None,
@@ -445,9 +445,9 @@ def cellpose(
445
445
  Use GPU if available.
446
446
  diameter : float, optional
447
447
  Expected cell diameter in pixels. If None, Cellpose auto-estimates.
448
- flow_threshold : float, default 0.4
449
- Maximum allowed error of flows for each mask.
450
- cellprob_threshold : float, default 0.0
448
+ flow_threshold : float, default 0.0
449
+ Maximum allowed error of flows for each mask (0 = flow check off).
450
+ cellprob_threshold : float, default -4.0
451
451
  Probability threshold for cell detection. Lower = more cells.
452
452
  min_size : int, default 2
453
453
  Minimum number of pixels per mask.
@@ -932,8 +932,8 @@ def save_gui_results(
932
932
  flows: tuple = None,
933
933
  styles: np.ndarray = None,
934
934
  diameter: float = None,
935
- cellprob_threshold: float = 0.0,
936
- flow_threshold: float = 0.4,
935
+ cellprob_threshold: float = -4.0,
936
+ flow_threshold: float = 0.0,
937
937
  name: str = None,
938
938
  ) -> Path:
939
939
  """
@@ -622,8 +622,8 @@ def export_for_gui(suite2p_dir, output_path=None, name=None):
622
622
  "filename": str(proj_path),
623
623
  "flows": None,
624
624
  "est_diam": ops.get("diameter"),
625
- "cellprob_threshold": ops.get("cellprob_threshold", 0.0),
626
- "flow_threshold": ops.get("flow_threshold", 0.4),
625
+ "cellprob_threshold": ops.get("cellprob_threshold", -4.0),
626
+ "flow_threshold": ops.get("flow_threshold", 0.0),
627
627
  }
628
628
 
629
629
  seg_file = output_dir / f"{name}_seg.npy"
@@ -1,84 +1,96 @@
1
- """Default ops for the LBM pipeline.
2
-
3
- Historically this module hard-coded a flat ops dict whose values
4
- diverged from suite2p's own defaults in a handful of fields
5
- (`batch_size=500`, `chan2_thres=0.65`, `tau=1.3`, `diameter=4`, etc.).
6
- That divergence made the round-trip through `settings.npy` confusing —
7
- on-disk values that matched the lsp default were flagged as "modified"
8
- against suite2p's schema, and vice versa.
9
-
10
- This module now exposes exactly suite2p's defaults (the values from
11
- `suite2p.default_settings()` + `suite2p.default_db()`), flattened to the
12
- fork's flat-ops shape via the same `db_settings_to_ops` translation
13
- that the rest of lsp uses. There is now ONE source of truth for "what
14
- default means": suite2p's parameter schema. Any LBM-specific tweaks
15
- (diameter, tau, etc.) belong in user code, not in the default.
16
- """
17
-
18
- from mbo_utilities.metadata import get_param, get_voxel_size
19
-
20
-
21
- def s2p_ops() -> dict:
22
- """Suite2p's default ops in flat (fork-style) form.
23
-
24
- Composed from `suite2p.default_settings()` + `suite2p.default_db()`
25
- via `db_settings_to_ops`, so the rename map and per-section
26
- flat-key disambiguation (e.g. extraction.batch_size
27
- extract_batch_size) are applied consistently.
28
- """
29
- from suite2p import default_settings, default_db
30
- from lbm_suite2p_python.db_settings import db_settings_to_ops
31
-
32
- return db_settings_to_ops(default_db(), default_settings())
33
-
34
-
35
- def default_ops(metadata: dict | None = None, ops: dict | None = None) -> dict:
36
- """Return default ops for the LBM Suite2p pipeline.
37
-
38
- Parameters
39
- ----------
40
- metadata : dict, optional
41
- Source-data metadata. When provided, `fs` and the (`dx`, `dy`)
42
- voxel-size pair are pulled in from the metadata and overlaid
43
- onto the suite2p defaults.
44
- ops : dict, optional
45
- A user-supplied ops dict to start from. When None, starts from
46
- `s2p_ops()` (suite2p's defaults).
47
-
48
- Returns
49
- -------
50
- dict
51
- Flat ops dict ready to be passed to `pipeline()` / `run_plane()`.
52
-
53
- Notes
54
- -----
55
- `nplanes=1` and `nchannels=1` are forced at the end. The lsp
56
- pipeline always processes one plane at a time, so these stay fixed
57
- regardless of caller input.
58
-
59
- Examples
60
- --------
61
- >>> import lbm_suite2p_python as lsp
62
- >>> ops = lsp.default_ops()
63
- >>> lsp.run_plane(
64
- ... ops=ops,
65
- ... input_tiff="D:/demo/raw_data/raw_file_00001.tif",
66
- ... save_path="D:/demo/results",
67
- ... save_folder="v1",
68
- ... )
69
- """
70
- if ops is None:
71
- ops = s2p_ops()
72
-
73
- if metadata is not None:
74
- fs = get_param(metadata, "fs")
75
- if fs is not None:
76
- ops["fs"] = fs
77
- voxel = get_voxel_size(metadata)
78
- if voxel.dx != 1.0 or voxel.dy != 1.0:
79
- ops["dx"] = voxel.dx
80
- ops["dy"] = voxel.dy
81
-
82
- ops["nplanes"] = 1
83
- ops["nchannels"] = 1
84
- return ops
1
+ """Default ops for the LBM pipeline.
2
+
3
+ Historically this module hard-coded a flat ops dict whose values
4
+ diverged from suite2p's own defaults in a handful of fields
5
+ (`batch_size=500`, `chan2_thres=0.65`, `tau=1.3`, `diameter=4`, etc.).
6
+ That divergence made the round-trip through `settings.npy` confusing —
7
+ on-disk values that matched the lsp default were flagged as "modified"
8
+ against suite2p's schema, and vice versa.
9
+
10
+ `s2p_ops()` exposes exactly suite2p's defaults (the values from
11
+ `suite2p.default_settings()` + `suite2p.default_db()`), flattened to the
12
+ fork's flat-ops shape via the same `db_settings_to_ops` translation
13
+ that the rest of lsp uses. `default_ops()` then applies a small set of
14
+ LBM detection defaults (`_LBM_DETECTION_DEFAULTS`) on top, so a notebook,
15
+ a bare `pipeline()` / `run_plane()` call, and the GUI all start from the
16
+ same place. An explicit caller-supplied `ops=` is respected, not overlaid.
17
+ """
18
+
19
+ from mbo_utilities.metadata import get_param, get_voxel_size
20
+
21
+
22
+ # LBM detection defaults that intentionally differ from suite2p's schema.
23
+ # default_ops() applies these on top of the suite2p mirror so notebook,
24
+ # function-call, and GUI runs share one set of defaults.
25
+ _LBM_DETECTION_DEFAULTS = {
26
+ "do_regmetrics": False, # PC reg-quality metrics: ~40s/plane on >=1500 frames
27
+ "cellprob_threshold": -4.0, # more permissive than suite2p's 0.0 for LBM data
28
+ "flow_threshold": 0.0, # flow check disabled
29
+ }
30
+
31
+
32
+ def s2p_ops() -> dict:
33
+ """Suite2p's default ops in flat (fork-style) form.
34
+
35
+ Composed from `suite2p.default_settings()` + `suite2p.default_db()`
36
+ via `db_settings_to_ops`, so the rename map and per-section
37
+ flat-key disambiguation (e.g. extraction.batch_size →
38
+ extract_batch_size) are applied consistently.
39
+ """
40
+ from suite2p import default_settings, default_db
41
+ from lbm_suite2p_python.db_settings import db_settings_to_ops
42
+
43
+ return db_settings_to_ops(default_db(), default_settings())
44
+
45
+
46
+ def default_ops(metadata: dict | None = None, ops: dict | None = None) -> dict:
47
+ """Return default ops for the LBM Suite2p pipeline.
48
+
49
+ Parameters
50
+ ----------
51
+ metadata : dict, optional
52
+ Source-data metadata. When provided, `fs` and the (`dx`, `dy`)
53
+ voxel-size pair are pulled in from the metadata and overlaid
54
+ onto the suite2p defaults.
55
+ ops : dict, optional
56
+ A user-supplied ops dict to start from. When None, starts from
57
+ `s2p_ops()` (suite2p's defaults).
58
+
59
+ Returns
60
+ -------
61
+ dict
62
+ Flat ops dict ready to be passed to `pipeline()` / `run_plane()`.
63
+
64
+ Notes
65
+ -----
66
+ `nplanes=1` and `nchannels=1` are forced at the end. The lsp
67
+ pipeline always processes one plane at a time, so these stay fixed
68
+ regardless of caller input.
69
+
70
+ Examples
71
+ --------
72
+ >>> import lbm_suite2p_python as lsp
73
+ >>> ops = lsp.default_ops()
74
+ >>> lsp.run_plane(
75
+ ... ops=ops,
76
+ ... input_tiff="D:/demo/raw_data/raw_file_00001.tif",
77
+ ... save_path="D:/demo/results",
78
+ ... save_folder="v1",
79
+ ... )
80
+ """
81
+ if ops is None:
82
+ ops = s2p_ops()
83
+ ops.update(_LBM_DETECTION_DEFAULTS)
84
+
85
+ if metadata is not None:
86
+ fs = get_param(metadata, "fs")
87
+ if fs is not None:
88
+ ops["fs"] = fs
89
+ voxel = get_voxel_size(metadata)
90
+ if voxel.dx != 1.0 or voxel.dy != 1.0:
91
+ ops["dx"] = voxel.dx
92
+ ops["dy"] = voxel.dy
93
+
94
+ ops["nplanes"] = 1
95
+ ops["nchannels"] = 1
96
+ return ops
@@ -792,6 +792,7 @@ def pipeline(
792
792
  keep_raw: bool = False,
793
793
  force_reg: bool = False,
794
794
  force_detect: bool = False,
795
+ replot: bool = True,
795
796
  num_timepoints: int = None,
796
797
  frame_indices: list | None = None,
797
798
  dff_window_size: int = None,
@@ -854,6 +855,10 @@ def pipeline(
854
855
  Force re-registration even if already complete.
855
856
  force_detect : bool, default False
856
857
  Force ROI detection even if stat.npy exists.
858
+ replot : bool, default True
859
+ Regenerate per-plane figures. Set False to skip per-plane figure
860
+ regeneration (e.g. the volumetric aggregate over already-plotted
861
+ planes); suite2p and the volumetric plots are unaffected.
857
862
  num_timepoints : int, optional
858
863
  Limit processing to first N frames (truncation only). For an
859
864
  explicit set of frames or a strided selection, use
@@ -1028,6 +1033,7 @@ def pipeline(
1028
1033
  keep_raw=keep_raw,
1029
1034
  force_reg=force_reg,
1030
1035
  force_detect=force_detect,
1036
+ replot=replot,
1031
1037
  frame_indices=frame_indices,
1032
1038
  dff_window_size=dff_window_size,
1033
1039
  dff_percentile=dff_percentile,
@@ -1067,6 +1073,7 @@ def pipeline(
1067
1073
  keep_raw=keep_raw,
1068
1074
  force_reg=force_reg,
1069
1075
  force_detect=force_detect,
1076
+ replot=replot,
1070
1077
  frame_indices=frame_indices,
1071
1078
  dff_window_size=dff_window_size,
1072
1079
  dff_percentile=dff_percentile,
@@ -1238,6 +1245,7 @@ def run_volume(
1238
1245
  keep_raw: bool = False,
1239
1246
  force_reg: bool = False,
1240
1247
  force_detect: bool = False,
1248
+ replot: bool = True,
1241
1249
  frame_indices: list | None = None,
1242
1250
  dff_window_size: int = None,
1243
1251
  dff_percentile: int = 20,
@@ -1281,6 +1289,9 @@ def run_volume(
1281
1289
  Force re-registration.
1282
1290
  force_detect : bool, default False
1283
1291
  Force detection.
1292
+ replot : bool, default True
1293
+ Regenerate per-plane figures (passed to run_plane). Set False to skip
1294
+ per-plane figure regeneration during a volumetric aggregate.
1284
1295
  frame_indices : list, default None
1285
1296
  List of frame indices to process.
1286
1297
  dff_window_size, dff_percentile, dff_smooth_window : optional
@@ -1418,6 +1429,7 @@ def run_volume(
1418
1429
  keep_raw=keep_raw,
1419
1430
  force_reg=force_reg,
1420
1431
  force_detect=force_detect,
1432
+ replot=replot,
1421
1433
  frame_indices=frame_indices,
1422
1434
  dff_window_size=dff_window_size,
1423
1435
  dff_percentile=dff_percentile,
@@ -2270,6 +2282,7 @@ def run_plane(
2270
2282
  keep_reg: bool = True,
2271
2283
  force_reg: bool = False,
2272
2284
  force_detect: bool = False,
2285
+ replot: bool = True,
2273
2286
  frame_indices: list | None = None,
2274
2287
  dff_window_size: int = None,
2275
2288
  dff_percentile: int = 20,
@@ -2314,6 +2327,9 @@ def run_plane(
2314
2327
  If True, force a new registration.
2315
2328
  force_detect : bool, default False
2316
2329
  If True, force ROI detection.
2330
+ replot : bool, default True
2331
+ Generate per-plane figures. Set False to skip figure generation
2332
+ (keeps ROI stats; only the figures are skipped).
2317
2333
  dff_window_size : int, optional
2318
2334
  Frames for rolling percentile baseline. Default: auto-calculated (~10*tau*fs).
2319
2335
  dff_percentile : int, default 20
@@ -3143,7 +3159,7 @@ def run_plane(
3143
3159
  except Exception as _e:
3144
3160
  print(f" Warning: persisting post-processing kwargs failed: {_e}")
3145
3161
 
3146
- # 3b. ROI statistics
3162
+ # 3b. ROI statistics (cheap; feeds the volumetric aggregate, so always run).
3147
3163
  try:
3148
3164
  from lbm_suite2p_python.postprocessing import compute_roi_stats
3149
3165
 
@@ -3152,20 +3168,35 @@ def run_plane(
3152
3168
  except Exception as e:
3153
3169
  print(f" Warning: ROI stats computation failed: {e}")
3154
3170
 
3155
- # 4. Plots and Cleanup
3156
- try:
3157
- plot_zplane_figures(
3158
- plane_dir,
3159
- dff_percentile=dff_percentile,
3160
- dff_window_size=dff_window_size,
3161
- dff_smooth_window=dff_smooth_window,
3162
- norm_method=norm_method,
3163
- correct_neuropil=correct_neuropil,
3164
- run_rastermap=rastermap_kwargs is not None,
3165
- rastermap_kwargs=rastermap_kwargs,
3166
- )
3167
- except Exception as e:
3168
- print(f" Warning: Plot generation failed: {e}")
3171
+ # 4. Per-plane figures. Timed as the "plots" step (recorded in
3172
+ # processing_history). Skipped when replot=False — e.g. the volumetric
3173
+ # aggregate re-running already-plotted planes, where regenerating the
3174
+ # per-plane figures is the dominant redundant cost.
3175
+ if replot:
3176
+ plot_start = time.time()
3177
+ try:
3178
+ plot_zplane_figures(
3179
+ plane_dir,
3180
+ dff_percentile=dff_percentile,
3181
+ dff_window_size=dff_window_size,
3182
+ dff_smooth_window=dff_smooth_window,
3183
+ norm_method=norm_method,
3184
+ correct_neuropil=correct_neuropil,
3185
+ run_rastermap=rastermap_kwargs is not None,
3186
+ rastermap_kwargs=rastermap_kwargs,
3187
+ )
3188
+ except Exception as e:
3189
+ print(f" Warning: Plot generation failed: {e}")
3190
+
3191
+ if ops_file.exists():
3192
+ try:
3193
+ _t_ops = load_ops(ops_file)
3194
+ _add_processing_step(_t_ops, "plots", duration_seconds=time.time() - plot_start)
3195
+ save_ops_db_settings(ops_file, _t_ops)
3196
+ except Exception as _e:
3197
+ print(f" Warning: recording plot timing failed: {_e}")
3198
+ else:
3199
+ print(" replot=False: keeping existing per-plane figures")
3169
3200
 
3170
3201
  if save_json:
3171
3202
  ops_to_json(ops_file)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lbm_suite2p_python
3
- Version: 3.1.1
3
+ Version: 3.2.0
4
4
  Summary: Calcium Imaging Pipeline built with Suite2p, Cellpose and Rastermap
5
5
  License-Expression: BSD-3-Clause
6
6
  Project-URL: homepage, https://github.com/MillerBrainObservatory/LBM-Suite2p-Python
@@ -1,106 +1,106 @@
1
- [build-system]
2
- requires = ["setuptools>=61", "wheel"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "lbm_suite2p_python"
7
- version = "3.1.1"
8
- description = "Calcium Imaging Pipeline built with Suite2p, Cellpose and Rastermap"
9
- readme = "README.md"
10
- license = "BSD-3-Clause"
11
- requires-python = ">=3.12.7,<3.14"
12
- keywords = ["Pipeline", "Numpy", "Microscopy", "ScanImage", "Suite2p", "tiff"]
13
- urls = {homepage = "https://github.com/MillerBrainObservatory/LBM-Suite2p-Python"}
14
- classifiers=[
15
- "Development Status :: 3 - Alpha",
16
- "Intended Audience :: Science/Research",
17
- "Programming Language :: Python :: 3 :: Only",
18
- ]
19
-
20
- dependencies = [
21
- "mbo_utilities>=3.2.1",
22
- "suite2p>=1.0.0.1",
23
- "setuptools<81",
24
- ]
25
-
26
- [project.scripts]
27
- lsp = "lbm_suite2p_python.__main__:main"
28
- cellpose-gui = "lbm_suite2p_python.gui:main"
29
-
30
- [project.optional-dependencies]
31
- rastermap = [
32
- "rastermap",
33
- ]
34
- # Cellpose for anatomical cell detection (requires PyTorch)
35
- cellpose = [
36
- "cellpose>=4.0.6",
37
- ]
38
- # All optional dependencies
39
- all = [
40
- "lbm_suite2p_python[rastermap,cellpose]",
41
- ]
42
-
43
- [dependency-groups]
44
- dev = [
45
- "pytest>=8.0.0",
46
- ]
47
- docs = [
48
- "docutils>=0.21.2",
49
- "myst-nb>=1.2.0",
50
- "sphinx>=8.1.3",
51
- "roman-numerals-py>=2.0.0,<3.0.0", # 3.x is broken
52
- "sphinx-autodoc2>=0.5.0",
53
- "sphinx-copybutton>=0.5.2",
54
- "sphinx_togglebutton",
55
- "sphinx-design>=0.6.1",
56
- "sphinxcontrib-bibtex",
57
- "sphinx-tippy",
58
- "sphinx_book_theme",
59
- "numpydoc",
60
- "ipykernel",
61
- "sphinxcontrib-images",
62
- "sphinxcontrib-video",
63
- "jupytext",
64
- "scikit-image",
65
- "scipy",
66
- "pandas",
67
- "suite2p",
68
- ]
69
-
70
- # https://github.com/charliermarsh/ruff
71
- [tool.ruff]
72
- line-length = 88
73
- src = ["lbm_suite2p_python"]
74
- exclude = ["docs", "exclude", "demos", "scripts", "dev"]
75
-
76
- [tool.ruff.lint]
77
- pydocstyle = { convention = "numpy" }
78
- select = ["ALL"]
79
- ignore = [
80
- "D401", # First line should be in imperative mood (remove to opt in)
81
- "COM812", # Missing trailing comma (conflicts with ruff format)
82
- "ISC001", # Import sorting (conflicts with ruff format)
83
- "FIX002", # Fixable issue
84
- "DOC201", # TODO enable in follow-up PR; no doc for return type.
85
- "FBT", # TODO: enable in follow-up PR; require bool options to be keyword-only.
86
- ]
87
-
88
- [tool.ruff.lint.per-file-ignores]
89
- "docs/*.py" = ["D"]
90
-
91
- [tool.setuptools.exclude-package-data]
92
- "*" = ["data/*"]
93
-
94
- [tool.setuptools.packages.find]
95
- where = ["."]
96
- include = ["lbm_suite2p_python*"]
97
-
98
- [tool.coverage.report]
99
- exclude_lines = [
100
- "pragma: no cover",
101
- "if TYPE_CHECKING:",
102
- "@overload",
103
- "except ImportError",
104
- "\\.\\.\\.",
105
- "raise NotImplementedError()"
106
- ]
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "lbm_suite2p_python"
7
+ version = "3.2.0"
8
+ description = "Calcium Imaging Pipeline built with Suite2p, Cellpose and Rastermap"
9
+ readme = "README.md"
10
+ license = "BSD-3-Clause"
11
+ requires-python = ">=3.12.7,<3.14"
12
+ keywords = ["Pipeline", "Numpy", "Microscopy", "ScanImage", "Suite2p", "tiff"]
13
+ urls = {homepage = "https://github.com/MillerBrainObservatory/LBM-Suite2p-Python"}
14
+ classifiers=[
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Science/Research",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ ]
19
+
20
+ dependencies = [
21
+ "mbo_utilities>=3.2.1",
22
+ "suite2p>=1.0.0.1",
23
+ "setuptools<81",
24
+ ]
25
+
26
+ [project.scripts]
27
+ lsp = "lbm_suite2p_python.__main__:main"
28
+ cellpose-gui = "lbm_suite2p_python.gui:main"
29
+
30
+ [project.optional-dependencies]
31
+ rastermap = [
32
+ "rastermap",
33
+ ]
34
+ # Cellpose for anatomical cell detection (requires PyTorch)
35
+ cellpose = [
36
+ "cellpose>=4.0.6",
37
+ ]
38
+ # All optional dependencies
39
+ all = [
40
+ "lbm_suite2p_python[rastermap,cellpose]",
41
+ ]
42
+
43
+ [dependency-groups]
44
+ dev = [
45
+ "pytest>=8.0.0",
46
+ ]
47
+ docs = [
48
+ "docutils>=0.21.2",
49
+ "myst-nb>=1.2.0",
50
+ "sphinx>=8.1.3",
51
+ "roman-numerals-py>=2.0.0,<3.0.0", # 3.x is broken
52
+ "sphinx-autodoc2>=0.5.0",
53
+ "sphinx-copybutton>=0.5.2",
54
+ "sphinx_togglebutton",
55
+ "sphinx-design>=0.6.1",
56
+ "sphinxcontrib-bibtex",
57
+ "sphinx-tippy",
58
+ "sphinx_book_theme",
59
+ "numpydoc",
60
+ "ipykernel",
61
+ "sphinxcontrib-images",
62
+ "sphinxcontrib-video",
63
+ "jupytext",
64
+ "scikit-image",
65
+ "scipy",
66
+ "pandas",
67
+ "suite2p",
68
+ ]
69
+
70
+ # https://github.com/charliermarsh/ruff
71
+ [tool.ruff]
72
+ line-length = 88
73
+ src = ["lbm_suite2p_python"]
74
+ exclude = ["docs", "exclude", "demos", "scripts", "dev"]
75
+
76
+ [tool.ruff.lint]
77
+ pydocstyle = { convention = "numpy" }
78
+ select = ["ALL"]
79
+ ignore = [
80
+ "D401", # First line should be in imperative mood (remove to opt in)
81
+ "COM812", # Missing trailing comma (conflicts with ruff format)
82
+ "ISC001", # Import sorting (conflicts with ruff format)
83
+ "FIX002", # Fixable issue
84
+ "DOC201", # TODO enable in follow-up PR; no doc for return type.
85
+ "FBT", # TODO: enable in follow-up PR; require bool options to be keyword-only.
86
+ ]
87
+
88
+ [tool.ruff.lint.per-file-ignores]
89
+ "docs/*.py" = ["D"]
90
+
91
+ [tool.setuptools.exclude-package-data]
92
+ "*" = ["data/*"]
93
+
94
+ [tool.setuptools.packages.find]
95
+ where = ["."]
96
+ include = ["lbm_suite2p_python*"]
97
+
98
+ [tool.coverage.report]
99
+ exclude_lines = [
100
+ "pragma: no cover",
101
+ "if TYPE_CHECKING:",
102
+ "@overload",
103
+ "except ImportError",
104
+ "\\.\\.\\.",
105
+ "raise NotImplementedError()"
106
+ ]