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.
Files changed (73) hide show
  1. {cellfinder-1.4.0 → cellfinder-1.9.0}/.github/workflows/test_and_deploy.yml +47 -5
  2. {cellfinder-1.4.0 → cellfinder-1.9.0}/.github/workflows/test_include_guard.yaml +1 -1
  3. {cellfinder-1.4.0 → cellfinder-1.9.0}/PKG-INFO +16 -12
  4. {cellfinder-1.4.0 → cellfinder-1.9.0}/README.md +7 -5
  5. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/cli_migration_warning.py +3 -1
  6. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/classify.py +51 -5
  7. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/tools.py +13 -3
  8. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/detect.py +94 -59
  9. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/plane/plane_filter.py +107 -10
  10. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/setup_filters.py +51 -12
  11. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/ball_filter.py +9 -10
  12. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/structure_detection.py +5 -0
  13. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/structure_splitting.py +3 -2
  14. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/volume_filter.py +1 -1
  15. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/download/download.py +2 -1
  16. cellfinder-1.9.0/cellfinder/core/main.py +247 -0
  17. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/threading.py +4 -3
  18. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/tools.py +1 -1
  19. cellfinder-1.4.0/cellfinder/core/train/train_yml.py → cellfinder-1.9.0/cellfinder/core/train/train_yaml.py +6 -15
  20. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/curation.py +72 -21
  21. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/detect/detect.py +88 -29
  22. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/detect/detect_containers.py +41 -9
  23. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/detect/thread_worker.py +26 -16
  24. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/input_container.py +14 -4
  25. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/train/train.py +5 -9
  26. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/train/train_containers.py +2 -4
  27. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/utils.py +6 -1
  28. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/PKG-INFO +16 -12
  29. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/SOURCES.txt +1 -1
  30. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/entry_points.txt +1 -1
  31. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/requires.txt +4 -3
  32. {cellfinder-1.4.0 → cellfinder-1.9.0}/pyproject.toml +16 -9
  33. cellfinder-1.4.0/cellfinder/core/main.py +0 -115
  34. {cellfinder-1.4.0 → cellfinder-1.9.0}/.gitignore +0 -0
  35. {cellfinder-1.4.0 → cellfinder-1.9.0}/.napari/config.yml +0 -0
  36. {cellfinder-1.4.0 → cellfinder-1.9.0}/CITATION.cff +0 -0
  37. {cellfinder-1.4.0 → cellfinder-1.9.0}/LICENSE +0 -0
  38. {cellfinder-1.4.0 → cellfinder-1.9.0}/MANIFEST.in +0 -0
  39. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/__init__.py +0 -0
  40. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/__init__.py +0 -0
  41. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/__init__.py +0 -0
  42. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/augment.py +0 -0
  43. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/cube_generator.py +0 -0
  44. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/classify/resnet.py +0 -0
  45. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/config/__init__.py +0 -0
  46. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/config/cellfinder.conf +0 -0
  47. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/__init__.py +0 -0
  48. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/__init__.py +0 -0
  49. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/plane/__init__.py +0 -0
  50. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/plane/classical_filter.py +0 -0
  51. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/plane/tile_walker.py +0 -0
  52. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/detect/filters/volume/__init__.py +0 -0
  53. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/download/__init__.py +0 -0
  54. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/download/cli.py +0 -0
  55. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/IO.py +0 -0
  56. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/__init__.py +0 -0
  57. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/array_operations.py +0 -0
  58. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/geometry.py +0 -0
  59. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/image_processing.py +0 -0
  60. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/prep.py +0 -0
  61. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/source_files.py +0 -0
  62. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/system.py +0 -0
  63. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/tools/tiff.py +0 -0
  64. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/train/__init__.py +0 -0
  65. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/core/types.py +0 -0
  66. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/__init__.py +0 -0
  67. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/detect/__init__.py +0 -0
  68. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/napari.yaml +0 -0
  69. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/sample_data.py +0 -0
  70. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder/napari/train/__init__.py +0 -0
  71. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/dependency_links.txt +0 -0
  72. {cellfinder-1.4.0 → cellfinder-1.9.0}/cellfinder.egg-info/top_level.txt +0 -0
  73. {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.10", "3.11", "3.12"]
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.12"
57
+ python-version: "3.13"
58
58
  - os: windows-latest
59
- python-version: "3.12"
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: neuroinformatics-unit/actions/upload_pypi@v2
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
- secret-pypi-key: ${{ secrets.TWINE_API_KEY }}
245
+ user: __token__
246
+ password: ${{ secrets.TWINE_API_KEY }}
@@ -22,7 +22,7 @@ jobs:
22
22
  - name: Setup Python
23
23
  uses: actions/setup-python@v4
24
24
  with:
25
- python-version: '3.12'
25
+ python-version: '3.13'
26
26
 
27
27
  - name: Install cellfinder via pip
28
28
  run: python -m pip install -e "."
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: cellfinder
3
- Version: 1.4.0
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.10
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.7
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!=2.4,>=2.1.0
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
  [![Python Version](https://img.shields.io/pypi/pyversions/cellfinder.svg)](https://pypi.org/project/cellfinder)
60
62
  [![PyPI](https://img.shields.io/pypi/v/cellfinder.svg)](https://pypi.org/project/cellfinder)
61
- [![Downloads](https://pepy.tech/badge/cellfinder)](https://pepy.tech/project/cellfinder)
63
+ [![Anaconda version](https://anaconda.org/conda-forge/cellfinder/badges/version.svg)](https://anaconda.org/conda-forge/cellfinder)
64
+ [![Napari hub](https://img.shields.io/endpoint?url=https://npe2api-git-add-shields-napari.vercel.app/api/shields/cellfinder)](https://napari-hub.org/plugins/cellfinder.html)
65
+ [![PyPI Downloads](https://pepy.tech/badge/cellfinder)](https://pepy.tech/project/cellfinder)
62
66
  [![Wheel](https://img.shields.io/pypi/wheel/cellfinder.svg)](https://pypi.org/project/cellfinder)
63
67
  [![Development Status](https://img.shields.io/pypi/status/cellfinder.svg)](https://github.com/brainglobe/cellfinder)
64
68
  [![Tests](https://img.shields.io/github/actions/workflow/status/brainglobe/cellfinder/test_and_deploy.yml?branch=main)](https://github.com/brainglobe/cellfinder/actions)
65
69
  [![codecov](https://codecov.io/gh/brainglobe/cellfinder/branch/main/graph/badge.svg?token=nx1lhNI7ox)](https://codecov.io/gh/brainglobe/cellfinder)
66
- [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black)
67
- [![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
70
+ [![Code style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/format.json)](https://github.com/astral-sh/ruff)[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
68
71
  [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
69
72
  [![Contributions](https://img.shields.io/badge/Contributions-Welcome-brightgreen.svg)](https://brainglobe.info/community/developers/index.html)
70
- [![Twitter](https://img.shields.io/twitter/follow/brain_globe?style=social)](https://twitter.com/brain_globe)
71
-
73
+ [![image.sc forum](https://img.shields.io/badge/dynamic/json.svg?label=forum&url=https%3A%2F%2Fforum.image.sc%2Ftags%2Fbrainglobe.json&query=%24.topic_list.tags.0.topic_count&colorB=brightgreen&suffix=%20topics&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAABPklEQVR42m3SyyqFURTA8Y2BER0TDyExZ+aSPIKUlPIITFzKeQWXwhBlQrmFgUzMMFLKZeguBu5y+//17dP3nc5vuPdee6299gohUYYaDGOyyACq4JmQVoFujOMR77hNfOAGM+hBOQqB9TjHD36xhAa04RCuuXeKOvwHVWIKL9jCK2bRiV284QgL8MwEjAneeo9VNOEaBhzALGtoRy02cIcWhE34jj5YxgW+E5Z4iTPkMYpPLCNY3hdOYEfNbKYdmNngZ1jyEzw7h7AIb3fRTQ95OAZ6yQpGYHMMtOTgouktYwxuXsHgWLLl+4x++Kx1FJrjLTagA77bTPvYgw1rRqY56e+w7GNYsqX6JfPwi7aR+Y5SA+BXtKIRfkfJAYgj14tpOF6+I46c4/cAM3UhM3JxyKsxiOIhH0IO6SH/A1Kb1WBeUjbkAAAAAElFTkSuQmCC)](https://forum.image.sc/tag/brainglobe)
74
+ [![Bluesky](https://img.shields.io/badge/Bluesky-0285FF?logo=bluesky&logoColor=fff)](https://bsky.app/profile/brainglobe.info)
75
+ [![Mastodon](https://img.shields.io/badge/Mastodon-6364FF?logo=mastodon&logoColor=fff)](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
  [![Python Version](https://img.shields.io/pypi/pyversions/cellfinder.svg)](https://pypi.org/project/cellfinder)
2
2
  [![PyPI](https://img.shields.io/pypi/v/cellfinder.svg)](https://pypi.org/project/cellfinder)
3
- [![Downloads](https://pepy.tech/badge/cellfinder)](https://pepy.tech/project/cellfinder)
3
+ [![Anaconda version](https://anaconda.org/conda-forge/cellfinder/badges/version.svg)](https://anaconda.org/conda-forge/cellfinder)
4
+ [![Napari hub](https://img.shields.io/endpoint?url=https://npe2api-git-add-shields-napari.vercel.app/api/shields/cellfinder)](https://napari-hub.org/plugins/cellfinder.html)
5
+ [![PyPI Downloads](https://pepy.tech/badge/cellfinder)](https://pepy.tech/project/cellfinder)
4
6
  [![Wheel](https://img.shields.io/pypi/wheel/cellfinder.svg)](https://pypi.org/project/cellfinder)
5
7
  [![Development Status](https://img.shields.io/pypi/status/cellfinder.svg)](https://github.com/brainglobe/cellfinder)
6
8
  [![Tests](https://img.shields.io/github/actions/workflow/status/brainglobe/cellfinder/test_and_deploy.yml?branch=main)](https://github.com/brainglobe/cellfinder/actions)
7
9
  [![codecov](https://codecov.io/gh/brainglobe/cellfinder/branch/main/graph/badge.svg?token=nx1lhNI7ox)](https://codecov.io/gh/brainglobe/cellfinder)
8
- [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black)
9
- [![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
10
+ [![Code style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/format.json)](https://github.com/astral-sh/ruff)[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
10
11
  [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
11
12
  [![Contributions](https://img.shields.io/badge/Contributions-Welcome-brightgreen.svg)](https://brainglobe.info/community/developers/index.html)
12
- [![Twitter](https://img.shields.io/twitter/follow/brain_globe?style=social)](https://twitter.com/brain_globe)
13
-
13
+ [![image.sc forum](https://img.shields.io/badge/dynamic/json.svg?label=forum&url=https%3A%2F%2Fforum.image.sc%2Ftags%2Fbrainglobe.json&query=%24.topic_list.tags.0.topic_count&colorB=brightgreen&suffix=%20topics&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAABPklEQVR42m3SyyqFURTA8Y2BER0TDyExZ+aSPIKUlPIITFzKeQWXwhBlQrmFgUzMMFLKZeguBu5y+//17dP3nc5vuPdee6299gohUYYaDGOyyACq4JmQVoFujOMR77hNfOAGM+hBOQqB9TjHD36xhAa04RCuuXeKOvwHVWIKL9jCK2bRiV284QgL8MwEjAneeo9VNOEaBhzALGtoRy02cIcWhE34jj5YxgW+E5Z4iTPkMYpPLCNY3hdOYEfNbKYdmNngZ1jyEzw7h7AIb3fRTQ95OAZ6yQpGYHMMtOTgouktYwxuXsHgWLLl+4x++Kx1FJrjLTagA77bTPvYgw1rRqY56e+w7GNYsqX6JfPwi7aR+Y5SA+BXtKIRfkfJAYgj14tpOF6+I46c4/cAM3UhM3JxyKsxiOIhH0IO6SH/A1Kb1WBeUjbkAAAAAElFTkSuQmCC)](https://forum.image.sc/tag/brainglobe)
14
+ [![Bluesky](https://img.shields.io/badge/Bluesky-0285FF?logo=bluesky&logoColor=fff)](https://bsky.app/profile/brainglobe.info)
15
+ [![Mastodon](https://img.shields.io/badge/Mastodon-6364FF?logo=mastodon&logoColor=fff)](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
- print(
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.train_yml import depth_type, models
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[int, int, int],
23
- network_voxel_sizes: Tuple[int, int, int],
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
- print(
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
- print(
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("`model_weights` must be provided")
51
- model.load_weights(model_weights)
52
- return model
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 = "cpu",
52
- use_scipy: bool = True,
53
- split_ball_xy_size: int = 3,
54
- split_ball_z_size: int = 3,
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
- split_soma_diameter: int = 7,
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
- Index of the starting plane for detection.
70
-
70
+ First plane index to process (inclusive, to process a subset of the
71
+ data).
71
72
  end_plane : int
72
- Index of the ending plane for detection.
73
-
74
- voxel_sizes : Tuple[float, float, float]
75
- Tuple of voxel sizes in each dimension (z, y, x).
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
- Diameter of the soma in physical units.
79
-
78
+ The expected in-plane (xy) soma diameter (microns).
80
79
  max_cluster_size : float
81
- Maximum size of a cluster in physical units.
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
- Size of the XY ball used for filtering in physical units.
85
-
84
+ 3d filter's in-plane (xy) filter ball size (microns).
86
85
  ball_z_size : float
87
- Size of the Z ball used for filtering in physical units.
88
-
86
+ 3d filter's axial (z) filter ball size (microns).
89
87
  ball_overlap_fraction : float
90
- Fraction of overlap allowed between balls.
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
- Spread factor for soma size.
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
- Number of free CPU cores available for parallel processing.
97
-
96
+ How many CPU cores to leave free.
98
97
  log_sigma_size : float
99
- Size of the sigma for the log filter.
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
- Number of standard deviations above the mean threshold.
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
- batch_size : int, optional
117
- The number of planes to process in each batch. Defaults to 1.
118
- For CPU, there's no benefit for a larger batch size. Only a memory
119
- usage increase. For CUDA, the larger the batch size the better the
120
- performance. Until it fills up the GPU memory - after which it
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. By default, it's "cpu".
125
- To run on a gpu, specify the PyTorch device name, such as "cuda" to
126
- run on the first GPU.
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 cells.
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 * settings.z_pixel_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.debug(s)
235
- print(s)
270
+ logger.info(s)
236
271
  return cells