Repository navigation
Expand file tree
/
Copy pathpyproject.toml
More file actions
273 lines (256 loc) · 10.2 KB
/
Copy pathpyproject.toml
File metadata and controls
273 lines (256 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
[build-system]
requires = ['setuptools >= 61.0.0']
build-backend = 'setuptools.build_meta'
[project]
name = 'fastsurfer'
version = '2.7.0.dev0'
description = 'A fast and accurate deep-learning based neuroimaging pipeline'
readme = 'README.md'
license = { file = 'LICENSE' }
requires-python = '>=3.12'
authors = [{ name = 'FastSurfer Developers' }]
maintainers = [{ name = 'FastSurfer Developers' }]
keywords = [
'python',
'Deep learning',
'Segmentation',
'Brain segmentation',
'Brain analysis',
'volumetry',
]
classifiers = [
'Operating System :: Microsoft :: Windows',
'Operating System :: Unix',
'Operating System :: MacOS',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: 3.14',
'Natural Language :: English',
'License :: OSI Approved :: Apache Software License',
'Intended Audience :: Science/Research',
]
dependencies = [
'h5py>=3.7',
'lapy>=1.5.0',
'libigl>=2.6.0', # needed for the cortical ribbon
'matplotlib>=3.7.1',
'meshpy>=2025.1.1', # needed for FastSurfer-CC
'monai>=1.4.0', # needed for FastSurfer-CC
'neuroreg>=0.6.2', # needed for registration / etiv
'nibabel>=5.4.0', # needed to fix a bug in nibabel
'numpy>=1.25',
'packaging',
'pandas>=1.5.3',
'pip>=25.0',
'pyrr>=0.10.3', # needed for FastSurfer-CC
'pyyaml>=6.0',
'requests>=2.31.0',
'scikit-image>=0.19.3',
'scikit-learn>=1.2.2',
'scipy>=1.10.1,!=1.13.0',
'simpleitk>=2.2.1',
'tensorboard>=2.12.1',
'torch==2.14.*', # pinned to 2.14
'torchio>=0.18.83',
'torchvision>=0.29.0,<0.30.0',
'tqdm>=4.65',
'yacs>=0.1.8',
]
[project.optional-dependencies]
qc = [
'whippersnappy>=2.1',
]
lit = [
'neurolit>=0.7.0',
]
container = [
'fastsurfer[qc]',
'fastsurfer[lit]',
]
doc = [
'fastsurfer[qc]',
'furo!=2023.8.17',
'memory-profiler',
'myst-parser',
'numpydoc',
# sphinx 8 handles importing of files differently in some manner and will cause the
# build of the doc to fail. This will need to be addressed before we up to sphinx 8.
'sphinx>=7.3,<8',
'sphinxcontrib-bibtex',
'sphinxcontrib-programoutput',
# 0.6.0 breaks parallel builds; 0.6.1 emits warnings for unrelated MyST links.
'sphinx-argparse<0.6',
'sphinx-copybutton',
'sphinx-design',
'sphinx-gallery',
'sphinx-issues',
'pypandoc',
'nbsphinx',
'IPython', # For syntax highlighting in notebooks
'ipykernel',
]
style = [
'bibclean',
'codespell',
'pydocstyle[toml]',
'ruff',
'ty',
]
pipelinetest = [
'pytest>=8.2.2',
]
all = [
'fastsurfer[doc]',
'fastsurfer[style]',
'fastsurfer[qc]',
'fastsurfer[lit]',
'fastsurfer[pipelinetest]',
]
full = [
'fastsurfer[all]',
]
[project.urls]
homepage = 'https://fastsurfer.org'
documentation = 'https://deep-mi.org/FastSurfer/stable'
source = 'https://github.com/Deep-MI/FastSurfer'
tracker = 'https://github.com/Deep-MI/FastSurfer/issues'
[tool.python]
# The single exact python version FastSurfer is built and shipped with.
#
# Who uses it today:
# - tools/Docker/Dockerfile reads this key from the pyproject.toml in the build context, with
# tools/read_toml.py run by uv.
# - tools/macos_build/build_release_package.sh reads it to fetch the relocatable standalone
# CPython it bundles into the installer, and substitutes it into the paths that name the
# version: python/bin/python<version>, python/lib/python<version>/site-packages.
# - tools/update_requirements.sh reads it to resolve requirements.txt for this version.
# - .github/workflows/deploy.yml reads it for the key of the uv cache of the macOS package build.
# - One place keeps a hardcoded copy because it cannot read this file: the python-version in
# .github/workflows/pipelinetest.yaml (that step provides the interpreter which then reads
# this file). test/lint/test_python_version.py asserts it against this key.
# - doc/conf.py reads this key for {{ PYTHON_VERSION }} in the documentation, from the release
# the documentation refers to.
# - NOT .github/workflows/unittest.yaml, which pins the requires-python floor on purpose.
#
# This key is deliberately separate from project.requires-python, which answers a different
# question: requires-python is the support *floor*, a range, and is what pip enforces for anyone
# doing `pip install fastsurfer`. This key is the one *exact* version we build against, which a
# range cannot express -- wheels are cp3XX-tagged, so anything shipping a pre-resolved
# environment needs an exact version.
#
# Raising this version also requires updating the following:
# - requirements.txt, regenerated for the new interpreter (tools/update_requirements.sh)
# - the hardcoded copy listed above (CI will fail if you miss it)
version = "3.14"
[tool.freesurfer]
version = "8.2.0"
# The following URLs use the {version} placeholder, which should be replaced
# with the actual version string using Python's .format(version=...).
# tools/Docker/Dockerfile reads version and urls.linux from this file.
# FreeSurfer 8 ships packages, not tarballs. On linux the Rocky 8 rpm: its binaries are
# self-contained, while the Ubuntu debs link the system ITK, VTK and Qt and leave out the talairach
# (4dfp) tools. On macOS the arm64 pkg, the only architecture the FastSurfer package is built for.
[tool.freesurfer.urls]
linux = "https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/{version}/freesurfer-Rocky8-{version}-1.x86_64.rpm"
macOS = "https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/{version}/freesurfer-macOS-darwin_arm64-{version}.pkg"
[tool.cuda]
# The default CUDA version of the docker images, which the `latest` image is built for. The PyTorch
# backend is cu<version without dots> (13.2 -> cu132), and the --device alias cuda of
# tools/Docker/build.py resolves to it.
#
# Who uses it today:
# - tools/Docker/build.py, for --device cuda and the tag fastsurfer:dev.
# - tools/update_requirements.sh, for the install example in the header of requirements.txt.
# - doc/conf.py reads this key for {{ CUDA_VERSION }} and {{ CUDA_STRING }} in the documentation,
# from the release the documentation refers to.
#
# Raising this version (or tool.rocm.version) also requires that the torch pinned in
# project.dependencies ships wheels for the backend, and that DeviceType and AllDeviceType in
# tools/Docker/build.py list it.
version = "13.2"
[tool.rocm]
# The default ROCm version of the docker images. The PyTorch backend is rocm<version> (7.2 ->
# rocm7.2), and the --device alias rocm of tools/Docker/build.py resolves to it. PyTorch also
# publishes builds for newer ROCm versions than uv's --torch-backend accepts (rocm7.14 for torch
# 2.14), so this is the newest one uv can install.
version = "7.2"
[tool.docker]
# The default base images of the docker images that tools/Docker/build.py builds: build_base for the
# stages that build the python environment and FreeSurfer, runtime_base for the runtime image.
#
# Who uses it today:
# - tools/Docker/build.py, as the defaults of --build_base_image and --runtime_base_image.
# - doc/conf.py reads runtime_base for {{ UBUNTU_VERSION }} in the documentation, from the release
# the documentation refers to, so it has to be an ubuntu image.
# - tools/Docker/Dockerfile keeps copies as the defaults of ARG BUILD_BASE_IMAGE and
# ARG RUNTIME_BASE_IMAGE, for a direct `docker build`.
build_base = "ubuntu:24.04"
runtime_base = "ubuntu:24.04"
[tool.setuptools.packages.find]
# an explicit `packages = [...]` list is not recursive, so it silently dropped every subpackage
# (FastSurferCNN.utils, CerebNet.models, ...) and, since it was added, CorpusCallosum as well
include = ['FastSurferCNN*', 'CerebNet*', 'CorpusCallosum*', 'HypVINN*', 'recon_surf*']
# PyPI: tools/Docker/fastsurfer_startup.{py,pth,start} are not packaged (build_venv copies them); a
# wheel has to put them at the site-packages root via a build_py override in setup.py. The hook then
# runs in every non-editable install, and the .pth, needed below python 3.15, must go before 3.20.
[tool.setuptools.package-data]
# without this, only .py files are installed, and the package cannot find its own configs at
# runtime (checkpoint_paths.yaml, the network configs, the color lookup tables, ...).
# The shell scripts are needed because Python code reads them, e.g.
# recon_surf/long_compat_segmentHA.py parses recon-surf.sh for the supported FreeSurfer version
# while building its argument parser.
'*' = ['*.yaml', '*.tsv', '*.txt', '*.json', '*.csv', '*.sh']
[tool.pydocstyle]
convention = 'numpy'
ignore-decorators = '(copy_doc|property|.*setter|.*getter|pyqtSlot|Slot)'
match = '^(?!setup|__init__|test_).*\.py'
# match-dir is a single regex matched against each directory name while walking (not a list): an
# allow-list of the package roots would also prune their subdirectories (utils, models, config,
# ...), so exclude the non-package directories instead
match-dir = '^(?!\.|__pycache__$|build$|checkpoints$|doc$|Documentation$|env$|test$|tools$|Tutorial$).*'
add_ignore = 'D100,D104,D107'
[tool.ruff]
line-length = 120
target-version = "py312"
# recon_surf/fs_time is python, but carries no .py suffix because the pipeline invokes it as a
# command; without this ruff would skip it
extend-include = ["recon_surf/fs_time"]
extend-exclude = [
"build",
"checkpoints",
"doc",
"env",
]
[tool.ruff.lint]
# https://docs.astral.sh/ruff/linter/#rule-selection
select = [
"E", # pycodestyle
"F", # Pyflakes
"UP", # pyupgrade
"B", # flake8-bugbear
"I", # isort
# "SIM", # flake8-simplify
"NPY201", # numpy 2
]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"Tutorial/*.ipynb" = ["E501"] # exclude "Line too long"
"FastSurferCNN/utils/logging.py" = ["F401"] # exclude "Imported but unused"
"FastSurferCNN/utils/parser_defaults.py" = ["F401"] # exclude "Imported but unused"
[tool.pytest.ini_options]
minversion = '6.0'
addopts = '--durations 20 --verbose'
filterwarnings = []
[tool.coverage.run]
branch = true
cover_pylib = false
omit = [
'**/__init__.py',
]
[tool.coverage.report]
exclude_lines = [
'pragma: no cover',
'if __name__ == .__main__.:',
]
precision = 2