cellfinder 1.4.0__tar.gz → 1.9.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.
- {cellfinder-1.4.0 → cellfinder-1.9.0}/.github/workflows/test_and_deploy.yml +47 -5
- {cellfinder-1.4.0 → cellfinder-1.9.0}/.github/workflows/test_include_guard.yaml +1 -1
- {cellfinder-1.4.0 → cellfinder-1.9.0}/PKG-INFO +16 -12
- {cellfinder-1.4.0 → cellfinder-1.9.0}/README.md +7 -5
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/cli_migration_warning.py +3 -1
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/classify.py +51 -5
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/tools.py +13 -3
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/detect.py +94 -59
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/plane/plane_filter.py +107 -10
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/setup_filters.py +51 -12
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/ball_filter.py +9 -10
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/structure_detection.py +5 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/structure_splitting.py +3 -2
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/volume_filter.py +1 -1
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/download/download.py +2 -1
- cellfinder-1.9.0/cellfinder/core/main.py +247 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/threading.py +4 -3
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/tools.py +1 -1
- cellfinder-1.4.0/cellfinder/core/train/train_yml.py → cellfinder-1.9.0/cellfinder/core/train/train_yaml.py +6 -15
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/curation.py +72 -21
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/detect/detect.py +88 -29
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/detect/detect_containers.py +41 -9
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/detect/thread_worker.py +26 -16
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/input_container.py +14 -4
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/train/train.py +5 -9
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/train/train_containers.py +2 -4
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/utils.py +6 -1
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/PKG-INFO +16 -12
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/SOURCES.txt +1 -1
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/entry_points.txt +1 -1
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/requires.txt +4 -3
- {cellfinder-1.4.0 → cellfinder-1.9.0}/pyproject.toml +16 -9
- cellfinder-1.4.0/cellfinder/core/main.py +0 -115
- {cellfinder-1.4.0 → cellfinder-1.9.0}/.gitignore +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/.napari/config.yml +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/CITATION.cff +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/LICENSE +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/MANIFEST.in +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/augment.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/cube_generator.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/resnet.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/config/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/config/cellfinder.conf +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/plane/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/plane/classical_filter.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/plane/tile_walker.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/download/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/download/cli.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/IO.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/array_operations.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/geometry.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/image_processing.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/prep.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/source_files.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/system.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/tiff.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/train/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/types.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/detect/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/napari.yaml +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/sample_data.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/train/__init__.py +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/dependency_links.txt +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/top_level.txt +0 -0
- {cellfinder-1.4.0 → cellfinder-1.9.0}/setup.cfg +0 -0
|
@@ -50,15 +50,25 @@ jobs:
|
|
|
50
50
|
matrix:
|
|
51
51
|
# Run all supported Python versions on linux
|
|
52
52
|
os: [ubuntu-latest]
|
|
53
|
-
python-version: ["3.
|
|
53
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
54
54
|
# Include one windows and one macOS (arm based) run
|
|
55
55
|
include:
|
|
56
56
|
- os: macos-latest
|
|
57
|
-
python-version: "3.
|
|
57
|
+
python-version: "3.13"
|
|
58
58
|
- os: windows-latest
|
|
59
|
-
python-version: "3.
|
|
59
|
+
python-version: "3.13"
|
|
60
60
|
|
|
61
61
|
steps:
|
|
62
|
+
# Free up disk space on ubuntu runners
|
|
63
|
+
- name: Free Disk Space
|
|
64
|
+
if: matrix.os == 'ubuntu-latest'
|
|
65
|
+
uses: endersonmenezes/free-disk-space@6c4664f43348c8c7011b53488d5ca65e9fc5cd1a # v3
|
|
66
|
+
with:
|
|
67
|
+
remove_android: true
|
|
68
|
+
remove_dotnet: true
|
|
69
|
+
rm_cmd: 'rmz'
|
|
70
|
+
rmz_version: '3.1.1'
|
|
71
|
+
|
|
62
72
|
- uses: actions/checkout@v4
|
|
63
73
|
- name: Cache pooch data
|
|
64
74
|
uses: actions/cache@v4
|
|
@@ -86,6 +96,15 @@ jobs:
|
|
|
86
96
|
secret-codecov-token: ${{ secrets.CODECOV_TOKEN }}
|
|
87
97
|
use-xvfb: true
|
|
88
98
|
|
|
99
|
+
# Run tests on napari main if this is a scheduled run
|
|
100
|
+
- name: Run tests on napari main
|
|
101
|
+
if: github.event_name == 'schedule'
|
|
102
|
+
uses: neuroinformatics-unit/actions/test@v2
|
|
103
|
+
with:
|
|
104
|
+
python-version: ${{ matrix.python-version }}
|
|
105
|
+
secret-codecov-token: ${{ secrets.CODECOV_TOKEN }}
|
|
106
|
+
tox-args: '-e napari-dev'
|
|
107
|
+
|
|
89
108
|
- name: Notify slack on scheduled failure
|
|
90
109
|
if: failure() && github.event_name == 'schedule'
|
|
91
110
|
uses: ravsamhq/notify-slack-action@v2
|
|
@@ -107,6 +126,15 @@ jobs:
|
|
|
107
126
|
BRAINGLOBE_TEST_DATA_DIR: "~/.pooch_cache"
|
|
108
127
|
|
|
109
128
|
steps:
|
|
129
|
+
# Free up disk space on ubuntu runners
|
|
130
|
+
- name: Free Disk Space
|
|
131
|
+
uses: endersonmenezes/free-disk-space@6c4664f43348c8c7011b53488d5ca65e9fc5cd1a # v3
|
|
132
|
+
with:
|
|
133
|
+
remove_android: true
|
|
134
|
+
remove_dotnet: true
|
|
135
|
+
rm_cmd: 'rmz'
|
|
136
|
+
rmz_version: '3.1.1'
|
|
137
|
+
|
|
110
138
|
- uses: actions/checkout@v4
|
|
111
139
|
- name: Cache brainglobe directory
|
|
112
140
|
uses: actions/cache@v3
|
|
@@ -154,6 +182,15 @@ jobs:
|
|
|
154
182
|
KERAS_BACKEND: torch
|
|
155
183
|
CELLFINDER_TEST_DEVICE: cpu
|
|
156
184
|
steps:
|
|
185
|
+
# Free up disk space on ubuntu runners
|
|
186
|
+
- name: Free Disk Space
|
|
187
|
+
uses: endersonmenezes/free-disk-space@6c4664f43348c8c7011b53488d5ca65e9fc5cd1a # v3
|
|
188
|
+
with:
|
|
189
|
+
remove_android: true
|
|
190
|
+
remove_dotnet: true
|
|
191
|
+
rm_cmd: 'rmz'
|
|
192
|
+
rmz_version: '3.1.1'
|
|
193
|
+
|
|
157
194
|
- name: Cache brainglobe directory
|
|
158
195
|
uses: actions/cache@v3
|
|
159
196
|
with:
|
|
@@ -199,6 +236,11 @@ jobs:
|
|
|
199
236
|
if: github.event_name == 'push' && github.ref_type == 'tag'
|
|
200
237
|
runs-on: ubuntu-latest
|
|
201
238
|
steps:
|
|
202
|
-
- uses:
|
|
239
|
+
- uses: actions/download-artifact@v4
|
|
240
|
+
with:
|
|
241
|
+
name: artifact
|
|
242
|
+
path: dist
|
|
243
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
203
244
|
with:
|
|
204
|
-
|
|
245
|
+
user: __token__
|
|
246
|
+
password: ${{ secrets.TWINE_API_KEY }}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: cellfinder
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9.0
|
|
4
4
|
Summary: Automated 3D cell detection in large microscopy images
|
|
5
5
|
Author-email: "Adam Tyson, Christian Niedworok, Charly Rousseau" <code@adamltyson.com>
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -16,26 +16,27 @@ Classifier: Intended Audience :: Science/Research
|
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python
|
|
18
18
|
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
22
|
Classifier: Topic :: Scientific/Engineering :: Image Recognition
|
|
23
|
-
Requires-Python: >=3.
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE
|
|
26
26
|
Requires-Dist: brainglobe-utils>=0.5.0
|
|
27
27
|
Requires-Dist: brainglobe-napari-io>=0.3.4
|
|
28
28
|
Requires-Dist: dask[array]
|
|
29
|
-
Requires-Dist: fancylog>=0.0
|
|
29
|
+
Requires-Dist: fancylog>=0.6.0
|
|
30
30
|
Requires-Dist: natsort
|
|
31
31
|
Requires-Dist: numba
|
|
32
32
|
Requires-Dist: numpy
|
|
33
33
|
Requires-Dist: scikit-image
|
|
34
34
|
Requires-Dist: scikit-learn
|
|
35
35
|
Requires-Dist: keras>=3.7.0
|
|
36
|
-
Requires-Dist: torch
|
|
36
|
+
Requires-Dist: torch>=2.4.1
|
|
37
37
|
Requires-Dist: tifffile
|
|
38
38
|
Requires-Dist: tqdm
|
|
39
|
+
Requires-Dist: qt-niu
|
|
39
40
|
Provides-Extra: dev
|
|
40
41
|
Requires-Dist: black; extra == "dev"
|
|
41
42
|
Requires-Dist: pre-commit; extra == "dev"
|
|
@@ -52,23 +53,26 @@ Requires-Dist: brainglobe-napari-io; extra == "napari"
|
|
|
52
53
|
Requires-Dist: magicgui; extra == "napari"
|
|
53
54
|
Requires-Dist: napari-ndtiffs; extra == "napari"
|
|
54
55
|
Requires-Dist: napari-plugin-engine>=0.1.4; extra == "napari"
|
|
55
|
-
Requires-Dist: napari[pyqt5]; extra == "napari"
|
|
56
|
+
Requires-Dist: napari[pyqt5]>=0.6.5; extra == "napari"
|
|
56
57
|
Requires-Dist: pooch>=1; extra == "napari"
|
|
57
58
|
Requires-Dist: qtpy; extra == "napari"
|
|
59
|
+
Dynamic: license-file
|
|
58
60
|
|
|
59
61
|
[](https://pypi.org/project/cellfinder)
|
|
60
62
|
[](https://pypi.org/project/cellfinder)
|
|
61
|
-
[](https://anaconda.org/conda-forge/cellfinder)
|
|
64
|
+
[](https://napari-hub.org/plugins/cellfinder.html)
|
|
65
|
+
[](https://pepy.tech/project/cellfinder)
|
|
62
66
|
[](https://pypi.org/project/cellfinder)
|
|
63
67
|
[](https://github.com/brainglobe/cellfinder)
|
|
64
68
|
[](https://github.com/brainglobe/cellfinder/actions)
|
|
65
69
|
[](https://codecov.io/gh/brainglobe/cellfinder)
|
|
66
|
-
[](https://pycqa.github.io/isort/)
|
|
70
|
+
[](https://github.com/astral-sh/ruff)[](https://pycqa.github.io/isort/)
|
|
68
71
|
[](https://github.com/pre-commit/pre-commit)
|
|
69
72
|
[](https://brainglobe.info/community/developers/index.html)
|
|
70
|
-
[](https://forum.image.sc/tag/brainglobe)
|
|
74
|
+
[](https://bsky.app/profile/brainglobe.info)
|
|
75
|
+
[](https://mastodon.online/@brainglobe)
|
|
72
76
|
# cellfinder
|
|
73
77
|
|
|
74
78
|
cellfinder is software for automated 3D cell detection in very large 3D images (e.g., serial two-photon or lightsheet volumes of whole mouse brains).
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
[](https://pypi.org/project/cellfinder)
|
|
2
2
|
[](https://pypi.org/project/cellfinder)
|
|
3
|
-
[](https://anaconda.org/conda-forge/cellfinder)
|
|
4
|
+
[](https://napari-hub.org/plugins/cellfinder.html)
|
|
5
|
+
[](https://pepy.tech/project/cellfinder)
|
|
4
6
|
[](https://pypi.org/project/cellfinder)
|
|
5
7
|
[](https://github.com/brainglobe/cellfinder)
|
|
6
8
|
[](https://github.com/brainglobe/cellfinder/actions)
|
|
7
9
|
[](https://codecov.io/gh/brainglobe/cellfinder)
|
|
8
|
-
[](https://pycqa.github.io/isort/)
|
|
10
|
+
[](https://github.com/astral-sh/ruff)[](https://pycqa.github.io/isort/)
|
|
10
11
|
[](https://github.com/pre-commit/pre-commit)
|
|
11
12
|
[](https://brainglobe.info/community/developers/index.html)
|
|
12
|
-
[](https://forum.image.sc/tag/brainglobe)
|
|
14
|
+
[](https://bsky.app/profile/brainglobe.info)
|
|
15
|
+
[](https://mastodon.online/@brainglobe)
|
|
14
16
|
# cellfinder
|
|
15
17
|
|
|
16
18
|
cellfinder is software for automated 3D cell detection in very large 3D images (e.g., serial two-photon or lightsheet volumes of whole mouse brains).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
|
|
3
|
+
from cellfinder.core import logger
|
|
4
|
+
|
|
3
5
|
BRAINGLOBE_WORKFLOWS = "https://github.com/brainglobe/brainglobe-workflows"
|
|
4
6
|
NEW_NAME = "brainmapper"
|
|
5
7
|
BLOG_POST = "https://brainglobe.info/blog/version1/core_and_napari_merge.html"
|
|
@@ -36,7 +38,7 @@ def cli_catch() -> None:
|
|
|
36
38
|
),
|
|
37
39
|
)
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
logger.warning(
|
|
40
42
|
"Hey, it looks like you're trying to run the old command-line tool.",
|
|
41
43
|
"This workflow has been renamed and moved -",
|
|
42
44
|
" you can now find it in the brainglobe-workflows package:\n",
|
|
@@ -11,7 +11,7 @@ from brainglobe_utils.general.system import get_num_processes
|
|
|
11
11
|
from cellfinder.core import logger, types
|
|
12
12
|
from cellfinder.core.classify.cube_generator import CubeGeneratorFromFile
|
|
13
13
|
from cellfinder.core.classify.tools import get_model
|
|
14
|
-
from cellfinder.core.train.
|
|
14
|
+
from cellfinder.core.train.train_yaml import depth_type, models
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def main(
|
|
@@ -19,8 +19,8 @@ def main(
|
|
|
19
19
|
signal_array: types.array,
|
|
20
20
|
background_array: types.array,
|
|
21
21
|
n_free_cpus: int,
|
|
22
|
-
voxel_sizes: Tuple[
|
|
23
|
-
network_voxel_sizes: Tuple[
|
|
22
|
+
voxel_sizes: Tuple[float, float, float],
|
|
23
|
+
network_voxel_sizes: Tuple[float, float, float],
|
|
24
24
|
batch_size: int,
|
|
25
25
|
cube_height: int,
|
|
26
26
|
cube_width: int,
|
|
@@ -29,12 +29,58 @@ def main(
|
|
|
29
29
|
model_weights: Optional[os.PathLike],
|
|
30
30
|
network_depth: depth_type,
|
|
31
31
|
max_workers: int = 3,
|
|
32
|
+
pin_memory: bool = False,
|
|
32
33
|
*,
|
|
33
34
|
callback: Optional[Callable[[int], None]] = None,
|
|
34
35
|
) -> List[Cell]:
|
|
35
36
|
"""
|
|
36
37
|
Parameters
|
|
37
38
|
----------
|
|
39
|
+
|
|
40
|
+
points: List of Cell objects
|
|
41
|
+
The potential cells to classify.
|
|
42
|
+
signal_array : numpy.ndarray or dask array
|
|
43
|
+
3D array representing the signal data in z, y, x order.
|
|
44
|
+
background_array : numpy.ndarray or dask array
|
|
45
|
+
3D array representing the signal data in z, y, x order.
|
|
46
|
+
n_free_cpus : int
|
|
47
|
+
How many CPU cores to leave free.
|
|
48
|
+
voxel_sizes : 3-tuple of floats
|
|
49
|
+
Size of your voxels in the z, y, and x dimensions.
|
|
50
|
+
network_voxel_sizes : 3-tuple of floats
|
|
51
|
+
Size of the pre-trained network's voxels in the z, y, and x dimensions.
|
|
52
|
+
batch_size : int
|
|
53
|
+
How many potential cells to classify at one time. The GPU/CPU
|
|
54
|
+
memory must be able to contain at once this many data cubes for
|
|
55
|
+
the models. For performance-critical applications, tune to maximize
|
|
56
|
+
memory usage without running out. Check your GPU/CPU memory to verify
|
|
57
|
+
it's not full.
|
|
58
|
+
cube_height: int
|
|
59
|
+
The height of the data cube centered on the cell used for
|
|
60
|
+
classification. Defaults to `50`.
|
|
61
|
+
cube_width: int
|
|
62
|
+
The width of the data cube centered on the cell used for
|
|
63
|
+
classification. Defaults to `50`.
|
|
64
|
+
cube_depth: int
|
|
65
|
+
The depth of the data cube centered on the cell used for
|
|
66
|
+
classification. Defaults to `20`.
|
|
67
|
+
trained_model : Optional[Path]
|
|
68
|
+
Trained model file path (home directory (default) -> pretrained
|
|
69
|
+
weights).
|
|
70
|
+
model_weights : Optional[Path]
|
|
71
|
+
Model weights path (home directory (default) -> pretrained
|
|
72
|
+
weights).
|
|
73
|
+
network_depth: str
|
|
74
|
+
The network depth to use during classification. Defaults to `"50"`.
|
|
75
|
+
max_workers: int
|
|
76
|
+
The number of sub-processes to use for data loading / processing.
|
|
77
|
+
Defaults to 8.
|
|
78
|
+
pin_memory: bool
|
|
79
|
+
Pins data to be sent to the GPU to the CPU memory. This allows faster
|
|
80
|
+
GPU data speeds, but can only be used if the data used by the GPU can
|
|
81
|
+
stay in the CPU RAM while the GPU uses it. I.e. there's enough RAM.
|
|
82
|
+
Otherwise, if there's a risk of the RAM being paged, it shouldn't be
|
|
83
|
+
used. Defaults to False.
|
|
38
84
|
callback : Callable[int], optional
|
|
39
85
|
A callback function that is called during classification. Called with
|
|
40
86
|
the batch number once that batch has been classified.
|
|
@@ -70,7 +116,7 @@ def main(
|
|
|
70
116
|
)
|
|
71
117
|
|
|
72
118
|
if trained_model and Path(trained_model).suffix == ".h5":
|
|
73
|
-
|
|
119
|
+
logger.warning(
|
|
74
120
|
"Weights provided in place of the model, "
|
|
75
121
|
"loading weights into default model."
|
|
76
122
|
)
|
|
@@ -103,7 +149,7 @@ def main(
|
|
|
103
149
|
points_list.append(cell)
|
|
104
150
|
|
|
105
151
|
time_elapsed = datetime.now() - start_time
|
|
106
|
-
|
|
152
|
+
logger.info(
|
|
107
153
|
"Classfication complete - all points done in : {}".format(time_elapsed)
|
|
108
154
|
)
|
|
109
155
|
|
|
@@ -47,9 +47,19 @@ def get_model(
|
|
|
47
47
|
f"Setting model weights according to: {model_weights}",
|
|
48
48
|
)
|
|
49
49
|
if model_weights is None:
|
|
50
|
-
raise OSError(
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
raise OSError(
|
|
51
|
+
"`model_weights` must be provided for inference "
|
|
52
|
+
"or continued training."
|
|
53
|
+
)
|
|
54
|
+
try:
|
|
55
|
+
model.load_weights(model_weights)
|
|
56
|
+
except (OSError, ValueError) as e:
|
|
57
|
+
raise ValueError(
|
|
58
|
+
f"Error loading weights: {model_weights}.\n"
|
|
59
|
+
"Provided weights don't match the model architecture.\n"
|
|
60
|
+
) from e
|
|
61
|
+
|
|
62
|
+
return model
|
|
53
63
|
|
|
54
64
|
|
|
55
65
|
def make_lists(
|
|
@@ -48,12 +48,14 @@ def main(
|
|
|
48
48
|
save_planes: bool = False,
|
|
49
49
|
plane_directory: Optional[str] = None,
|
|
50
50
|
batch_size: Optional[int] = None,
|
|
51
|
-
torch_device: str =
|
|
52
|
-
|
|
53
|
-
split_ball_xy_size:
|
|
54
|
-
split_ball_z_size:
|
|
51
|
+
torch_device: Optional[str] = None,
|
|
52
|
+
pin_memory: bool = False,
|
|
53
|
+
split_ball_xy_size: float = 6,
|
|
54
|
+
split_ball_z_size: float = 15,
|
|
55
55
|
split_ball_overlap_fraction: float = 0.8,
|
|
56
|
-
|
|
56
|
+
n_splitting_iter: int = 10,
|
|
57
|
+
n_sds_above_mean_tiled_thresh: float = 10,
|
|
58
|
+
tiled_thresh_tile_size: float | None = None,
|
|
57
59
|
*,
|
|
58
60
|
callback: Optional[Callable[[int], None]] = None,
|
|
59
61
|
) -> List[Cell]:
|
|
@@ -62,69 +64,94 @@ def main(
|
|
|
62
64
|
|
|
63
65
|
Parameters
|
|
64
66
|
----------
|
|
65
|
-
signal_array : numpy.ndarray
|
|
66
|
-
3D array representing the signal data.
|
|
67
|
-
|
|
67
|
+
signal_array : numpy.ndarray or dask array
|
|
68
|
+
3D array representing the signal data in z, y, x order.
|
|
68
69
|
start_plane : int
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
First plane index to process (inclusive, to process a subset of the
|
|
71
|
+
data).
|
|
71
72
|
end_plane : int
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
voxel_sizes :
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
Last plane index to process (exclusive, to process a subset of the
|
|
74
|
+
data).
|
|
75
|
+
voxel_sizes : 3-tuple of floats
|
|
76
|
+
Size of your voxels in the z, y, and x dimensions (microns).
|
|
77
77
|
soma_diameter : float
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
The expected in-plane (xy) soma diameter (microns).
|
|
80
79
|
max_cluster_size : float
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
Largest detected cell cluster (in cubic um) where splitting
|
|
81
|
+
should be attempted. Clusters above this size will be labeled
|
|
82
|
+
as artifacts.
|
|
83
83
|
ball_xy_size : float
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
3d filter's in-plane (xy) filter ball size (microns).
|
|
86
85
|
ball_z_size : float
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
3d filter's axial (z) filter ball size (microns).
|
|
89
87
|
ball_overlap_fraction : float
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
3d filter's fraction of the ball filter needed to be filled by
|
|
89
|
+
foreground voxels, centered on a voxel, to retain the voxel.
|
|
92
90
|
soma_spread_factor : float
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
Cell spread factor for determining the largest cell volume before
|
|
92
|
+
splitting up cell clusters. Structures with spherical volume of
|
|
93
|
+
diameter `soma_spread_factor * soma_diameter` or less will not be
|
|
94
|
+
split.
|
|
95
95
|
n_free_cpus : int
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
How many CPU cores to leave free.
|
|
98
97
|
log_sigma_size : float
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
Gaussian filter width (as a fraction of soma diameter) used during
|
|
99
|
+
2d in-plane Laplacian of Gaussian filtering.
|
|
101
100
|
n_sds_above_mean_thresh : float
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
Per-plane intensity threshold (the number of standard deviations
|
|
102
|
+
above the mean) of the filtered 2d planes used to mark pixels as
|
|
103
|
+
foreground or background.
|
|
104
104
|
outlier_keep : bool, optional
|
|
105
105
|
Whether to keep outliers during detection. Defaults to False.
|
|
106
|
-
|
|
107
106
|
artifact_keep : bool, optional
|
|
108
107
|
Whether to keep artifacts during detection. Defaults to False.
|
|
109
|
-
|
|
110
108
|
save_planes : bool, optional
|
|
111
109
|
Whether to save the planes during detection. Defaults to False.
|
|
112
|
-
|
|
113
110
|
plane_directory : str, optional
|
|
114
111
|
Directory path to save the planes. Defaults to None.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
The
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
becomes slower.
|
|
122
|
-
|
|
112
|
+
batch_size: int
|
|
113
|
+
The number of planes of the original data volume to process at
|
|
114
|
+
once. The GPU/CPU memory must be able to contain this many planes
|
|
115
|
+
for all the filters. For performance-critical applications, tune to
|
|
116
|
+
maximize memory usage without running out. Check your GPU/CPU memory
|
|
117
|
+
to verify it's not full.
|
|
123
118
|
torch_device : str, optional
|
|
124
|
-
The device on which to run the computation.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
119
|
+
The device on which to run the computation. If not specified (None),
|
|
120
|
+
"cuda" will be used if a GPU is available, otherwise "cpu".
|
|
121
|
+
You can also manually specify "cuda" or "cpu".
|
|
122
|
+
pin_memory: bool
|
|
123
|
+
Pins data to be sent to the GPU to the CPU memory. This allows faster
|
|
124
|
+
GPU data speeds, but can only be used if the data used by the GPU can
|
|
125
|
+
stay in the CPU RAM while the GPU uses it. I.e. there's enough RAM.
|
|
126
|
+
Otherwise, if there's a risk of the RAM being paged, it shouldn't be
|
|
127
|
+
used. Defaults to False.
|
|
128
|
+
split_ball_xy_size: float
|
|
129
|
+
Similar to `ball_xy_size`, except the value to use for the 3d
|
|
130
|
+
filter during cluster splitting.
|
|
131
|
+
split_ball_z_size: float
|
|
132
|
+
Similar to `ball_z_size`, except the value to use for the 3d filter
|
|
133
|
+
during cluster splitting.
|
|
134
|
+
split_ball_overlap_fraction: float
|
|
135
|
+
Similar to `ball_overlap_fraction`, except the value to use for the
|
|
136
|
+
3d filter during cluster splitting.
|
|
137
|
+
n_splitting_iter: int
|
|
138
|
+
The number of iterations to run the 3d filtering on a cluster. Each
|
|
139
|
+
iteration reduces the cluster size by the voxels not retained in
|
|
140
|
+
the previous iteration.
|
|
141
|
+
n_sds_above_mean_tiled_thresh : float
|
|
142
|
+
Per-plane, per-tile intensity threshold (the number of standard
|
|
143
|
+
deviations above the mean) for the filtered 2d planes used to mark
|
|
144
|
+
pixels as foreground or background. When used, (tile size is not zero)
|
|
145
|
+
a pixel is marked as foreground if its intensity is above both the
|
|
146
|
+
per-plane and per-tile threshold. I.e. it's above the set number of
|
|
147
|
+
standard deviations of the per-plane average and of the per-plane
|
|
148
|
+
per-tile average for the tile that contains it.
|
|
149
|
+
tiled_thresh_tile_size : float
|
|
150
|
+
The tile size used to tile the x, y plane to calculate the local
|
|
151
|
+
average intensity for the tiled threshold. The value is multiplied
|
|
152
|
+
by soma diameter (i.e. 1 means one soma diameter). If zero or None, the
|
|
153
|
+
tiled threshold is disabled and only the per-plane threshold is used.
|
|
154
|
+
Tiling is done with 50% overlap when striding.
|
|
128
155
|
callback : Callable[int], optional
|
|
129
156
|
A callback function that is called every time a plane has finished
|
|
130
157
|
being processed. Called with the plane number that has finished.
|
|
@@ -132,9 +159,11 @@ def main(
|
|
|
132
159
|
Returns
|
|
133
160
|
-------
|
|
134
161
|
List[Cell]
|
|
135
|
-
List of detected
|
|
162
|
+
List of detected cell candidates.
|
|
136
163
|
"""
|
|
137
164
|
start_time = datetime.now()
|
|
165
|
+
if torch_device is None:
|
|
166
|
+
torch_device = "cuda" if torch.cuda.is_available() else "cpu"
|
|
138
167
|
if batch_size is None:
|
|
139
168
|
if torch_device == "cpu":
|
|
140
169
|
batch_size = 4
|
|
@@ -155,6 +184,12 @@ def main(
|
|
|
155
184
|
end_plane = min(len(signal_array), end_plane)
|
|
156
185
|
|
|
157
186
|
torch_device = torch_device.lower()
|
|
187
|
+
# Use SciPy filtering on CPU (better performance); use PyTorch on GPU
|
|
188
|
+
if torch_device != "cuda":
|
|
189
|
+
use_scipy = True
|
|
190
|
+
else:
|
|
191
|
+
use_scipy = False
|
|
192
|
+
|
|
158
193
|
batch_size = max(batch_size, 1)
|
|
159
194
|
# brainmapper can pass them in as str
|
|
160
195
|
voxel_sizes = list(map(float, voxel_sizes))
|
|
@@ -174,25 +209,24 @@ def main(
|
|
|
174
209
|
ball_overlap_fraction=ball_overlap_fraction,
|
|
175
210
|
log_sigma_size=log_sigma_size,
|
|
176
211
|
n_sds_above_mean_thresh=n_sds_above_mean_thresh,
|
|
212
|
+
n_sds_above_mean_tiled_thresh=n_sds_above_mean_tiled_thresh,
|
|
213
|
+
tiled_thresh_tile_size=tiled_thresh_tile_size,
|
|
177
214
|
outlier_keep=outlier_keep,
|
|
178
215
|
artifact_keep=artifact_keep,
|
|
179
216
|
save_planes=save_planes,
|
|
180
217
|
plane_directory=plane_directory,
|
|
181
218
|
batch_size=batch_size,
|
|
182
219
|
torch_device=torch_device,
|
|
220
|
+
pin_memory=pin_memory,
|
|
221
|
+
n_splitting_iter=n_splitting_iter,
|
|
183
222
|
)
|
|
184
223
|
|
|
185
224
|
# replicate the settings specific to splitting, before we access anything
|
|
186
225
|
# of the original settings, causing cached properties
|
|
187
226
|
kwargs = dataclasses.asdict(settings)
|
|
188
|
-
kwargs["ball_z_size_um"] = split_ball_z_size
|
|
189
|
-
kwargs["ball_xy_size_um"] =
|
|
190
|
-
split_ball_xy_size * settings.in_plane_pixel_size
|
|
191
|
-
)
|
|
227
|
+
kwargs["ball_z_size_um"] = split_ball_z_size
|
|
228
|
+
kwargs["ball_xy_size_um"] = split_ball_xy_size
|
|
192
229
|
kwargs["ball_overlap_fraction"] = split_ball_overlap_fraction
|
|
193
|
-
kwargs["soma_diameter_um"] = (
|
|
194
|
-
split_soma_diameter * settings.in_plane_pixel_size
|
|
195
|
-
)
|
|
196
230
|
# always run on cpu because copying to gpu overhead is likely slower than
|
|
197
231
|
# any benefit for detection on smallish volumes
|
|
198
232
|
kwargs["torch_device"] = "cpu"
|
|
@@ -212,7 +246,9 @@ def main(
|
|
|
212
246
|
plane_shape=settings.plane_shape,
|
|
213
247
|
clipping_value=settings.clipping_value,
|
|
214
248
|
threshold_value=settings.threshold_value,
|
|
215
|
-
n_sds_above_mean_thresh=n_sds_above_mean_thresh,
|
|
249
|
+
n_sds_above_mean_thresh=settings.n_sds_above_mean_thresh,
|
|
250
|
+
n_sds_above_mean_tiled_thresh=settings.n_sds_above_mean_tiled_thresh,
|
|
251
|
+
tiled_thresh_tile_size=settings.tiled_thresh_tile_size,
|
|
216
252
|
log_sigma_size=log_sigma_size,
|
|
217
253
|
soma_diameter=settings.soma_diameter,
|
|
218
254
|
torch_device=torch_device,
|
|
@@ -231,6 +267,5 @@ def main(
|
|
|
231
267
|
|
|
232
268
|
time_elapsed = datetime.now() - start_time
|
|
233
269
|
s = f"Detection complete. Found {len(cells)} cells in {time_elapsed}"
|
|
234
|
-
logger.
|
|
235
|
-
print(s)
|
|
270
|
+
logger.info(s)
|
|
236
271
|
return cells
|