diffct 1.3.3__tar.gz → 2.0.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.
- {diffct-1.3.3 → diffct-2.0.0}/.gitignore +195 -187
- {diffct-1.3.3 → diffct-2.0.0}/CHANGELOG.md +294 -0
- diffct-2.0.0/CITATION.cff +51 -0
- {diffct-1.3.3 → diffct-2.0.0}/LICENSE +201 -201
- diffct-2.0.0/NOTICE +18 -0
- diffct-2.0.0/PKG-INFO +240 -0
- diffct-2.0.0/README.md +209 -0
- diffct-2.0.0/diffct/__init__.py +83 -0
- diffct-2.0.0/diffct/analytical.py +569 -0
- diffct-2.0.0/diffct/constants.py +72 -0
- diffct-2.0.0/diffct/differentiable.py +74 -0
- diffct-2.0.0/diffct/geometry.py +991 -0
- diffct-2.0.0/diffct/kernels/__init__.py +43 -0
- diffct-2.0.0/diffct/kernels/cone_beam.py +617 -0
- diffct-2.0.0/diffct/kernels/fan_beam.py +451 -0
- diffct-2.0.0/diffct/kernels/geometry_vjp.py +562 -0
- diffct-2.0.0/diffct/kernels/parallel_beam.py +400 -0
- diffct-2.0.0/diffct/operators.py +546 -0
- diffct-2.0.0/diffct/projectors.py +910 -0
- diffct-2.0.0/diffct/utils.py +357 -0
- diffct-2.0.0/docs/video/README.md +22 -0
- diffct-2.0.0/examples/README.md +209 -0
- {diffct-1.3.3 → diffct-2.0.0}/examples/data/NOTICE +45 -45
- diffct-2.0.0/formal/README.md +82 -0
- diffct-2.0.0/pyproject.toml +49 -0
- {diffct-1.3.3 → diffct-2.0.0}/pytest.ini +14 -14
- diffct-2.0.0/tests/_phantoms.py +81 -0
- {diffct-1.3.3 → diffct-2.0.0}/tests/benchmarks/README.md +56 -60
- {diffct-1.3.3 → diffct-2.0.0}/tests/benchmarks/_common.py +57 -62
- {diffct-1.3.3 → diffct-2.0.0}/tests/benchmarks/test_bench_cone.py +137 -145
- {diffct-1.3.3 → diffct-2.0.0}/tests/benchmarks/test_bench_fan.py +121 -127
- {diffct-1.3.3 → diffct-2.0.0}/tests/benchmarks/test_bench_parallel.py +113 -115
- diffct-2.0.0/tests/distributed_projector_check.py +709 -0
- diffct-2.0.0/tests/test_adjoint_inner_product.py +170 -0
- diffct-2.0.0/tests/test_analytical_regressions.py +182 -0
- {diffct-1.3.3 → diffct-2.0.0}/tests/test_cone_projector_autograd.py +76 -91
- diffct-2.0.0/tests/test_cuda_smoke.py +121 -0
- diffct-2.0.0/tests/test_fbp_fan_accuracy.py +92 -0
- diffct-2.0.0/tests/test_fbp_fan_offsets.py +117 -0
- diffct-2.0.0/tests/test_fbp_parallel_accuracy.py +72 -0
- diffct-2.0.0/tests/test_fdk_cone_accuracy.py +114 -0
- diffct-2.0.0/tests/test_fdk_cone_offsets.py +118 -0
- diffct-2.0.0/tests/test_geometry_autograd.py +51 -0
- diffct-2.0.0/tests/test_geometry_gradients.py +402 -0
- diffct-2.0.0/tests/test_gradcheck.py +125 -0
- diffct-2.0.0/tests/test_projector_api.py +796 -0
- diffct-2.0.0/tests/test_projector_degenerate_geometry.py +257 -0
- diffct-2.0.0/tests/test_projector_geometry_devices.py +69 -0
- diffct-2.0.0/tests/test_ramp_filter_windows.py +136 -0
- diffct-2.0.0/tests/test_weights.py +157 -0
- diffct-1.3.3/.git +0 -1
- diffct-1.3.3/.github/workflows/docs.yml +0 -37
- diffct-1.3.3/.github/workflows/release.yml +0 -20
- diffct-1.3.3/PKG-INFO +0 -385
- diffct-1.3.3/README.md +0 -368
- diffct-1.3.3/README.zh.md +0 -335
- diffct-1.3.3/diffct/__init__.py +0 -18
- diffct-1.3.3/diffct/differentiable.py +0 -5400
- diffct-1.3.3/docs/Makefile +0 -20
- diffct-1.3.3/docs/source/api.rst +0 -291
- diffct-1.3.3/docs/source/conf.py +0 -35
- diffct-1.3.3/docs/source/examples.rst +0 -30
- diffct-1.3.3/docs/source/fbp_fan_example.rst +0 -158
- diffct-1.3.3/docs/source/fbp_parallel_example.rst +0 -117
- diffct-1.3.3/docs/source/fdk_cone_example.rst +0 -184
- diffct-1.3.3/docs/source/getting_started.rst +0 -84
- diffct-1.3.3/docs/source/index.rst +0 -67
- diffct-1.3.3/docs/source/iterative_reco_cone_example.rst +0 -131
- diffct-1.3.3/docs/source/iterative_reco_fan_example.rst +0 -90
- diffct-1.3.3/docs/source/iterative_reco_parallel_example.rst +0 -96
- diffct-1.3.3/examples/data/preprocess_walnut.py +0 -303
- diffct-1.3.3/examples/data/walnut_cone.npz +0 -0
- diffct-1.3.3/examples/data/walnut_reco.png +0 -0
- diffct-1.3.3/examples/fbp_fan.py +0 -356
- diffct-1.3.3/examples/fbp_parallel.py +0 -227
- diffct-1.3.3/examples/fdk_cone.py +0 -495
- diffct-1.3.3/examples/iterative_reco_cone.py +0 -219
- diffct-1.3.3/examples/iterative_reco_fan.py +0 -188
- diffct-1.3.3/examples/iterative_reco_parallel.py +0 -135
- diffct-1.3.3/examples/realdata_fbp_fan.py +0 -300
- diffct-1.3.3/examples/realdata_fbp_parallel.py +0 -269
- diffct-1.3.3/examples/realdata_fdk_cone.py +0 -345
- diffct-1.3.3/examples/realdata_walnut_fdk.py +0 -363
- diffct-1.3.3/pyproject.toml +0 -39
- diffct-1.3.3/requirements.txt +0 -5
- diffct-1.3.3/tests/test_adjoint_inner_product.py +0 -286
- diffct-1.3.3/tests/test_cuda_smoke.py +0 -84
- diffct-1.3.3/tests/test_fbp_fan_accuracy.py +0 -147
- diffct-1.3.3/tests/test_fbp_fan_offsets.py +0 -162
- diffct-1.3.3/tests/test_fbp_parallel_accuracy.py +0 -164
- diffct-1.3.3/tests/test_fdk_cone_accuracy.py +0 -197
- diffct-1.3.3/tests/test_fdk_cone_offsets.py +0 -210
- diffct-1.3.3/tests/test_gradcheck.py +0 -209
- diffct-1.3.3/tests/test_ramp_filter_windows.py +0 -217
- diffct-1.3.3/tests/test_weights.py +0 -103
- {diffct-1.3.3/tests/benchmarks → diffct-2.0.0/tests}/__init__.py +0 -0
- /diffct-1.3.3/docs/source/_static/.gitkeep → /diffct-2.0.0/tests/benchmarks/__init__.py +0 -0
|
@@ -1,187 +1,195 @@
|
|
|
1
|
-
# Byte-compiled / optimized / DLL files
|
|
2
|
-
__pycache__/
|
|
3
|
-
*.py[cod]
|
|
4
|
-
*$py.class
|
|
5
|
-
|
|
6
|
-
# C extensions
|
|
7
|
-
*.so
|
|
8
|
-
|
|
9
|
-
# Distribution / packaging
|
|
10
|
-
.Python
|
|
11
|
-
build/
|
|
12
|
-
develop-eggs/
|
|
13
|
-
dist/
|
|
14
|
-
downloads/
|
|
15
|
-
eggs/
|
|
16
|
-
.eggs/
|
|
17
|
-
lib/
|
|
18
|
-
lib64/
|
|
19
|
-
parts/
|
|
20
|
-
sdist/
|
|
21
|
-
var/
|
|
22
|
-
wheels/
|
|
23
|
-
share/python-wheels/
|
|
24
|
-
*.egg-info/
|
|
25
|
-
.installed.cfg
|
|
26
|
-
*.egg
|
|
27
|
-
MANIFEST
|
|
28
|
-
|
|
29
|
-
# PyInstaller
|
|
30
|
-
# Usually these files are written by a python script from a template
|
|
31
|
-
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
-
*.manifest
|
|
33
|
-
*.spec
|
|
34
|
-
|
|
35
|
-
# Installer logs
|
|
36
|
-
pip-log.txt
|
|
37
|
-
pip-delete-this-directory.txt
|
|
38
|
-
|
|
39
|
-
# Unit test / coverage reports
|
|
40
|
-
htmlcov/
|
|
41
|
-
.tox/
|
|
42
|
-
.nox/
|
|
43
|
-
.coverage
|
|
44
|
-
.coverage.*
|
|
45
|
-
.cache
|
|
46
|
-
nosetests.xml
|
|
47
|
-
coverage.xml
|
|
48
|
-
*.cover
|
|
49
|
-
*.py,cover
|
|
50
|
-
.hypothesis/
|
|
51
|
-
.pytest_cache/
|
|
52
|
-
cover/
|
|
53
|
-
|
|
54
|
-
# Translations
|
|
55
|
-
*.mo
|
|
56
|
-
*.pot
|
|
57
|
-
|
|
58
|
-
# Django stuff:
|
|
59
|
-
*.log
|
|
60
|
-
local_settings.py
|
|
61
|
-
db.sqlite3
|
|
62
|
-
db.sqlite3-journal
|
|
63
|
-
|
|
64
|
-
# Flask stuff:
|
|
65
|
-
instance/
|
|
66
|
-
.webassets-cache
|
|
67
|
-
|
|
68
|
-
# Scrapy stuff:
|
|
69
|
-
.scrapy
|
|
70
|
-
|
|
71
|
-
# Sphinx documentation
|
|
72
|
-
docs/_build/
|
|
73
|
-
|
|
74
|
-
# PyBuilder
|
|
75
|
-
.pybuilder/
|
|
76
|
-
target/
|
|
77
|
-
|
|
78
|
-
# Jupyter Notebook
|
|
79
|
-
.ipynb_checkpoints
|
|
80
|
-
|
|
81
|
-
# IPython
|
|
82
|
-
profile_default/
|
|
83
|
-
ipython_config.py
|
|
84
|
-
|
|
85
|
-
# pyenv
|
|
86
|
-
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
-
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
-
# .python-version
|
|
89
|
-
|
|
90
|
-
# pipenv
|
|
91
|
-
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
-
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
-
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
-
# install all needed dependencies.
|
|
95
|
-
#Pipfile.lock
|
|
96
|
-
|
|
97
|
-
# UV
|
|
98
|
-
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
-
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
-
# commonly ignored for libraries.
|
|
101
|
-
#uv.lock
|
|
102
|
-
|
|
103
|
-
# poetry
|
|
104
|
-
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
-
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
-
# commonly ignored for libraries.
|
|
107
|
-
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
-
#poetry.lock
|
|
109
|
-
|
|
110
|
-
# pdm
|
|
111
|
-
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
112
|
-
#pdm.lock
|
|
113
|
-
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
114
|
-
# in version control.
|
|
115
|
-
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
116
|
-
.pdm.toml
|
|
117
|
-
.pdm-python
|
|
118
|
-
.pdm-build/
|
|
119
|
-
|
|
120
|
-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
121
|
-
__pypackages__/
|
|
122
|
-
|
|
123
|
-
# Celery stuff
|
|
124
|
-
celerybeat-schedule
|
|
125
|
-
celerybeat.pid
|
|
126
|
-
|
|
127
|
-
# SageMath parsed files
|
|
128
|
-
*.sage.py
|
|
129
|
-
|
|
130
|
-
# Environments
|
|
131
|
-
.env
|
|
132
|
-
.venv
|
|
133
|
-
env/
|
|
134
|
-
venv/
|
|
135
|
-
ENV/
|
|
136
|
-
env.bak/
|
|
137
|
-
venv.bak/
|
|
138
|
-
|
|
139
|
-
# Spyder project settings
|
|
140
|
-
.spyderproject
|
|
141
|
-
.spyproject
|
|
142
|
-
|
|
143
|
-
# Rope project settings
|
|
144
|
-
.ropeproject
|
|
145
|
-
|
|
146
|
-
# mkdocs documentation
|
|
147
|
-
/site
|
|
148
|
-
|
|
149
|
-
# mypy
|
|
150
|
-
.mypy_cache/
|
|
151
|
-
.dmypy.json
|
|
152
|
-
dmypy.json
|
|
153
|
-
|
|
154
|
-
# Pyre type checker
|
|
155
|
-
.pyre/
|
|
156
|
-
|
|
157
|
-
# pytype static type analyzer
|
|
158
|
-
.pytype/
|
|
159
|
-
|
|
160
|
-
# Cython debug symbols
|
|
161
|
-
cython_debug/
|
|
162
|
-
|
|
163
|
-
# PyCharm
|
|
164
|
-
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
165
|
-
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
166
|
-
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
167
|
-
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
168
|
-
#.idea/
|
|
169
|
-
|
|
170
|
-
# PyPI configuration file
|
|
171
|
-
.pypirc
|
|
172
|
-
|
|
173
|
-
# Roo memory bank
|
|
174
|
-
.vscode
|
|
175
|
-
/memory-bank
|
|
176
|
-
.rooignore
|
|
177
|
-
|
|
178
|
-
# Cline configuration file
|
|
179
|
-
.clinerules-architect
|
|
180
|
-
.clinerules-ask
|
|
181
|
-
.clinerules-code
|
|
182
|
-
.clinerules-debug
|
|
183
|
-
.clinerules-test
|
|
184
|
-
.roomodes
|
|
185
|
-
projectBrief.md
|
|
186
|
-
.kiro
|
|
187
|
-
.claude
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
|
|
110
|
+
# pdm
|
|
111
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
112
|
+
#pdm.lock
|
|
113
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
114
|
+
# in version control.
|
|
115
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
116
|
+
.pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
121
|
+
__pypackages__/
|
|
122
|
+
|
|
123
|
+
# Celery stuff
|
|
124
|
+
celerybeat-schedule
|
|
125
|
+
celerybeat.pid
|
|
126
|
+
|
|
127
|
+
# SageMath parsed files
|
|
128
|
+
*.sage.py
|
|
129
|
+
|
|
130
|
+
# Environments
|
|
131
|
+
.env
|
|
132
|
+
.venv
|
|
133
|
+
env/
|
|
134
|
+
venv/
|
|
135
|
+
ENV/
|
|
136
|
+
env.bak/
|
|
137
|
+
venv.bak/
|
|
138
|
+
|
|
139
|
+
# Spyder project settings
|
|
140
|
+
.spyderproject
|
|
141
|
+
.spyproject
|
|
142
|
+
|
|
143
|
+
# Rope project settings
|
|
144
|
+
.ropeproject
|
|
145
|
+
|
|
146
|
+
# mkdocs documentation
|
|
147
|
+
/site
|
|
148
|
+
|
|
149
|
+
# mypy
|
|
150
|
+
.mypy_cache/
|
|
151
|
+
.dmypy.json
|
|
152
|
+
dmypy.json
|
|
153
|
+
|
|
154
|
+
# Pyre type checker
|
|
155
|
+
.pyre/
|
|
156
|
+
|
|
157
|
+
# pytype static type analyzer
|
|
158
|
+
.pytype/
|
|
159
|
+
|
|
160
|
+
# Cython debug symbols
|
|
161
|
+
cython_debug/
|
|
162
|
+
|
|
163
|
+
# PyCharm
|
|
164
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
165
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
166
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
167
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
168
|
+
#.idea/
|
|
169
|
+
|
|
170
|
+
# PyPI configuration file
|
|
171
|
+
.pypirc
|
|
172
|
+
|
|
173
|
+
# Roo memory bank
|
|
174
|
+
.vscode
|
|
175
|
+
/memory-bank
|
|
176
|
+
.rooignore
|
|
177
|
+
|
|
178
|
+
# Cline configuration file
|
|
179
|
+
.clinerules-architect
|
|
180
|
+
.clinerules-ask
|
|
181
|
+
.clinerules-code
|
|
182
|
+
.clinerules-debug
|
|
183
|
+
.clinerules-test
|
|
184
|
+
.roomodes
|
|
185
|
+
projectBrief.md
|
|
186
|
+
.kiro
|
|
187
|
+
.claude
|
|
188
|
+
|
|
189
|
+
# Local GPU / cluster validation evidence
|
|
190
|
+
.validation/
|
|
191
|
+
|
|
192
|
+
# Manim render output
|
|
193
|
+
docs/video/media/
|
|
194
|
+
docs/video/scenes.txt
|
|
195
|
+
docs/video/palette.png
|
|
@@ -5,6 +5,300 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.0.0] - 2026-10-09
|
|
9
|
+
|
|
10
|
+
Version 2.0.0 replaces the circular-orbit API of 1.x with arbitrary
|
|
11
|
+
per-view trajectories. It breaks the 1.x interface; see
|
|
12
|
+
[docs/MIGRATION.md](docs/MIGRATION.md).
|
|
13
|
+
|
|
14
|
+
### Breaking
|
|
15
|
+
|
|
16
|
+
- ``diffct.Projector`` is the main entry point. Geometry is a tuple of
|
|
17
|
+
per-view tensors (source, detector centre, detector axes) instead of
|
|
18
|
+
scalar ``angles``, ``sid`` and ``sdd``.
|
|
19
|
+
- The low-level ``*ProjectorFunction`` / ``*BackprojectorFunction`` classes
|
|
20
|
+
and the ``*_weighted_backproject`` helpers take per-view geometry tensors.
|
|
21
|
+
- The separable-footprint backends (``sf``, ``sf_tr``, ``sf_tt``) of 1.3.x
|
|
22
|
+
are removed. All projectors use the matched cell-constant Siddon model.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Multi-GPU execution in one process (``devices=[...]``) and one process per
|
|
27
|
+
GPU with torchrun and NCCL, on one or several nodes.
|
|
28
|
+
- Install extras ``diffct[cu12]`` and ``diffct[cu13]`` pull in the matching
|
|
29
|
+
numba-cuda CUDA bindings, so one ``pip install`` gives a working import.
|
|
30
|
+
- Measured walnut example (``examples/walnut_reconstruction.py``), intro video
|
|
31
|
+
and README figures with provenance records in ``docs/assets``.
|
|
32
|
+
- Geometry gradients. Trajectory tensors may require gradients; ``Projector``
|
|
33
|
+
and the low-level Function classes return gradients for source, detector
|
|
34
|
+
centre and detector axes (parallel: ray direction, detector origin and
|
|
35
|
+
axis). CUDA kernels compute the exact derivative of the cell-constant
|
|
36
|
+
Siddon model from the face crossings of each ray. Distributed mode sums
|
|
37
|
+
the gradients over ranks.
|
|
38
|
+
- Second derivatives for volumes and sinograms: backward passes are autograd
|
|
39
|
+
Functions themselves. Second derivatives with respect to the geometry
|
|
40
|
+
raise ``RuntimeError``.
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- Detector arrays are centred: cell ``k`` lies at
|
|
45
|
+
``(k - (N - 1) / 2) * pitch`` from ``det_center`` (or ``det_origin``), as in
|
|
46
|
+
``main``. Earlier dev versions used ``(k - N / 2) * pitch``. The projector,
|
|
47
|
+
the FBP/FDK gathers and ``detector_coordinates_1d`` all changed.
|
|
48
|
+
- Siddon projections are line integrals in physical length. Earlier
|
|
49
|
+
versions returned voxel-length integrals, which differ by the factor
|
|
50
|
+
``voxel_spacing``. Backprojection scales the same way, so the pair stays
|
|
51
|
+
matched. Results with ``voxel_spacing == 1`` do not change.
|
|
52
|
+
- FBP and FDK gather kernels sample at voxel centres,
|
|
53
|
+
``(index + 0.5 - N / 2) * voxel_spacing``, as the cell-constant Siddon
|
|
54
|
+
projector does. Earlier reconstructions were half a voxel off.
|
|
55
|
+
- Siddon projector and backprojector kernels no longer skip ray pieces of
|
|
56
|
+
length ``<= 1e-6``. They skip only pieces of length exactly 0 or less.
|
|
57
|
+
Forward projection is now a continuous function of the geometry: each piece
|
|
58
|
+
changes a projection value by at most cell value x ``1e-6``.
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- Fan and cone rays integrate only from the source to the detector pixel.
|
|
63
|
+
A source or detector inside the volume box gave the full-line integral.
|
|
64
|
+
- Fan and cone ray setup measures the ray parameter from the endpoint
|
|
65
|
+
nearer the volume centre, and the traversal restarts at the volume entry
|
|
66
|
+
point. A distant source gave relative errors up to 5e-3 (source 1e6
|
|
67
|
+
voxels away) and could stop the traversal. Parallel-beam setup runs in
|
|
68
|
+
float64 for a distant detector origin. Projection speed does not change.
|
|
69
|
+
- Ray setup treats a direction component as axis-parallel only below
|
|
70
|
+
1e-20, so a distant source with a small lateral component is no longer
|
|
71
|
+
rejected.
|
|
72
|
+
- Siddon kernels use a finite sentinel instead of infinity, because
|
|
73
|
+
``fastmath`` lets LLVM assume that infinity never occurs.
|
|
74
|
+
- ``Projector`` rejects fan and cone views whose source coincides with the
|
|
75
|
+
detector centre or whose detector is edge-on to the source, and views where
|
|
76
|
+
both lie farther than 1e6 voxels from the volume centre.
|
|
77
|
+
- The traversal treats a direction component as axis-parallel only below
|
|
78
|
+
1e-20. With the earlier 1e-6 limit, a ray that grazed a grid line was
|
|
79
|
+
assigned to the neighbouring row.
|
|
80
|
+
- ``tests/distributed_projector_check.py`` no longer issues a MAX
|
|
81
|
+
all-reduce after a local failure while other ranks wait in a SUM
|
|
82
|
+
all-reduce.
|
|
83
|
+
|
|
84
|
+
## [1.3.0.dev0] - 2026-04-14 (dev branch, not released on PyPI)
|
|
85
|
+
|
|
86
|
+
First sync of the dev (arbitrary-trajectory) branch against the main
|
|
87
|
+
branch's 1.2.10 / 1.2.11 analytical reconstruction overhaul. Brings
|
|
88
|
+
dev up to functional parity with main 1.2.11 except for the 1.3.0
|
|
89
|
+
separable-footprint (SF) projector backends, which rely on closed-form
|
|
90
|
+
circular-orbit geometry and are not yet generalised to arbitrary
|
|
91
|
+
trajectories.
|
|
92
|
+
|
|
93
|
+
### Added
|
|
94
|
+
|
|
95
|
+
#### Analytical reconstruction helpers (``diffct.analytical``)
|
|
96
|
+
|
|
97
|
+
A new module exposes the following helpers, all trajectory-agnostic so
|
|
98
|
+
they work with both the circular trajectories and the arbitrary
|
|
99
|
+
``(src_pos, det_center, det_u_vec[, det_v_vec])`` trajectory arrays
|
|
100
|
+
that dev-branch kernels already accept:
|
|
101
|
+
|
|
102
|
+
- ``detector_coordinates_1d`` — detector cell centre coordinates.
|
|
103
|
+
- ``angular_integration_weights`` — trapezoidal per-view weights for
|
|
104
|
+
the analytical FBP/FDK sum. Optional ``redundant_full_scan`` flag
|
|
105
|
+
absorbs the ``1/2`` redundancy factor for full scans.
|
|
106
|
+
- ``fan_cosine_weights`` / ``cone_cosine_weights`` — per-detector-cell
|
|
107
|
+
``cos(gamma)`` pre-weight for fan / cone FBP pipelines.
|
|
108
|
+
- ``parker_weights`` — Parker short-scan redundancy weights for
|
|
109
|
+
circular fan geometries.
|
|
110
|
+
- ``ramp_filter_1d`` — generic 1D ramp filter with ``sample_spacing``,
|
|
111
|
+
``pad_factor``, ``window`` (``"ram-lak"``, ``"hann"``, ``"hamming"``,
|
|
112
|
+
``"cosine"``, ``"shepp-logan"``), and ``use_rfft`` options, rescaled
|
|
113
|
+
by ``1 / sample_spacing`` so the output is in physical units.
|
|
114
|
+
- ``parallel_weighted_backproject`` / ``fan_weighted_backproject`` /
|
|
115
|
+
``cone_weighted_backproject`` — voxel-driven FBP / FDK backprojection
|
|
116
|
+
wrappers that dispatch to new dedicated gather kernels and apply the
|
|
117
|
+
analytical Fourier-convention constant (``1/(2*pi)`` for parallel,
|
|
118
|
+
``sdd_mean/(2*pi*sid_mean)`` for fan and cone). These are the
|
|
119
|
+
**recommended path for analytical reconstruction** and replace the
|
|
120
|
+
previous pattern of passing a filtered sinogram through
|
|
121
|
+
``*BackprojectorFunction.apply``.
|
|
122
|
+
|
|
123
|
+
#### Voxel-driven FBP / FDK gather kernels
|
|
124
|
+
|
|
125
|
+
Three new CUDA kernels, each under the dedicated ``fastmath=False``
|
|
126
|
+
``_FDK_ACCURACY_DECORATOR`` added to ``diffct.constants``:
|
|
127
|
+
|
|
128
|
+
- ``_parallel_2d_fbp_backproject_kernel`` — no distance weighting.
|
|
129
|
+
- ``_fan_2d_fbp_backproject_kernel`` — ``(|S|/U_n)^2`` weighted,
|
|
130
|
+
where ``U_n`` is the signed distance from the per-view source to
|
|
131
|
+
the voxel along the detector normal.
|
|
132
|
+
- ``_cone_3d_fdk_backproject_kernel`` — same pattern in 3D.
|
|
133
|
+
|
|
134
|
+
Every kernel is voxel-driven: one thread per output pixel/voxel, loops
|
|
135
|
+
over views inside, projects the voxel onto the detector using the
|
|
136
|
+
per-view ``(src_pos, det_center, det_u_vec[, det_v_vec])`` arrays,
|
|
137
|
+
bilinearly samples the filtered sinogram, applies the per-view weight
|
|
138
|
+
and accumulates. They are completely separate from the pure Siddon
|
|
139
|
+
adjoint kernels that back the autograd path; autograd is untouched.
|
|
140
|
+
|
|
141
|
+
#### Tests (``tests/``)
|
|
142
|
+
|
|
143
|
+
The dev branch had no test directory at all prior to this change.
|
|
144
|
+
``pytest.ini`` and ``tests/__init__.py`` are new, plus 58 tests across
|
|
145
|
+
11 files that mirror the main-branch test layout:
|
|
146
|
+
|
|
147
|
+
- ``tests/test_adjoint_inner_product.py`` — ``<A x, y> = <x, A^T y>``
|
|
148
|
+
identity for parallel / fan / cone autograd pairs, plus an extra
|
|
149
|
+
``test_cone_autograd_backward_matches_backprojector_forward`` that
|
|
150
|
+
protects the autograd ``ConeProjectorFunction.backward`` from
|
|
151
|
+
drifting away from the standalone ``ConeBackprojectorFunction``.
|
|
152
|
+
- ``tests/test_gradcheck.py`` — ``torch.autograd.gradcheck`` for every
|
|
153
|
+
projector Function with float32-calibrated tolerances.
|
|
154
|
+
- ``tests/test_weights.py`` — unit tests for ``detector_coordinates_1d``,
|
|
155
|
+
``angular_integration_weights``, ``fan_cosine_weights``,
|
|
156
|
+
``cone_cosine_weights`` and ``parker_weights``.
|
|
157
|
+
- ``tests/test_cuda_smoke.py`` — end-to-end smoke tests for every
|
|
158
|
+
Projector / Backprojector Function pair + the analytical
|
|
159
|
+
``*_weighted_backproject`` wrappers.
|
|
160
|
+
- ``tests/test_cone_projector_autograd.py`` — gradient finiteness and
|
|
161
|
+
sparsity guard for the cone projector Function (circular + spiral
|
|
162
|
+
trajectories).
|
|
163
|
+
- ``tests/test_fbp_parallel_accuracy.py`` /
|
|
164
|
+
``tests/test_fbp_fan_accuracy.py`` /
|
|
165
|
+
``tests/test_fdk_cone_accuracy.py`` — quantitative RMSE and
|
|
166
|
+
amplitude bounds for a full Shepp-Logan FBP / FDK pipeline per
|
|
167
|
+
geometry. These would have tripped on the old dev reconstruction
|
|
168
|
+
path, which silently produced wrong-amplitude volumes.
|
|
169
|
+
- ``tests/test_fbp_fan_offsets.py`` /
|
|
170
|
+
``tests/test_fdk_cone_offsets.py`` — adapted from main's offset
|
|
171
|
+
tests: dev's arbitrary-trajectory kernels have no scalar
|
|
172
|
+
``detector_offset`` / ``center_offset_*`` parameters, so offsets
|
|
173
|
+
are applied by shifting the trajectory arrays directly. Verifies
|
|
174
|
+
that the FBP / FDK gather kernels handle non-centred trajectories.
|
|
175
|
+
- ``tests/test_ramp_filter_windows.py`` — 29 parametrised tests covering
|
|
176
|
+
every ``_ramp_window`` option (DC gain, Nyquist value, non-negativity)
|
|
177
|
+
and the full ``ramp_filter_1d`` end-to-end (shape, DC annihilation,
|
|
178
|
+
rfft vs complex-fft parity, ``sample_spacing`` scaling, high-frequency
|
|
179
|
+
pass-through).
|
|
180
|
+
|
|
181
|
+
#### Benchmark suite (``tests/benchmarks/``)
|
|
182
|
+
|
|
183
|
+
Opt-in ``pytest-benchmark`` suite covering every CUDA kernel in the
|
|
184
|
+
library (forward projector, pure-adjoint backprojector, and the full
|
|
185
|
+
analytical FBP / FDK pipeline) across three sizes for each of the
|
|
186
|
+
three geometries. 27 benchmarks total, excluded from the default
|
|
187
|
+
``pytest tests/`` run via ``--ignore=tests/benchmarks`` in
|
|
188
|
+
``pytest.ini``. Run explicitly with
|
|
189
|
+
``pytest tests/benchmarks/ --benchmark-only``.
|
|
190
|
+
|
|
191
|
+
#### Parker short-scan demos in examples
|
|
192
|
+
|
|
193
|
+
``examples/circular_trajectory/fbp_fan.py`` and
|
|
194
|
+
``examples/circular_trajectory/fdk_cone.py`` now expose an
|
|
195
|
+
``apply_parker`` switch. When enabled, the example switches the
|
|
196
|
+
trajectory to a minimal ``pi + 2*gamma_max`` short scan and applies
|
|
197
|
+
``parker_weights`` to the sinogram before the ramp filter; when
|
|
198
|
+
disabled, the pipeline runs a full ``2*pi`` scan with the ``1/2``
|
|
199
|
+
redundancy factor absorbed by ``angular_integration_weights``. Both
|
|
200
|
+
branches produce correctly amplitude-calibrated reconstructions.
|
|
201
|
+
|
|
202
|
+
#### Documentation (``docs/source/api.rst``)
|
|
203
|
+
|
|
204
|
+
New "Analytical Reconstruction Helpers", "Ramp Filter Options", and
|
|
205
|
+
"Analytical FBP / FDK architecture" sections describe the new
|
|
206
|
+
``diffct.analytical`` module, enumerate every ``ramp_filter_1d``
|
|
207
|
+
option, and explain the analytical scale factors used in each
|
|
208
|
+
``*_weighted_backproject`` wrapper.
|
|
209
|
+
|
|
210
|
+
### Fixed
|
|
211
|
+
|
|
212
|
+
#### FBP / FDK amplitude bugs in the ``circular_trajectory/*.py`` examples
|
|
213
|
+
|
|
214
|
+
Prior to this release the circular-trajectory FBP / FDK examples
|
|
215
|
+
(``examples/circular_trajectory/fbp_parallel.py``,
|
|
216
|
+
``examples/circular_trajectory/fbp_fan.py``,
|
|
217
|
+
``examples/circular_trajectory/fdk_cone.py``) produced amplitude-wrong
|
|
218
|
+
reconstructions because they:
|
|
219
|
+
|
|
220
|
+
- used ``*BackprojectorFunction.apply`` (the pure Siddon adjoint) as if
|
|
221
|
+
it were an FBP gather, so they missed the ``(sid/U)^2`` / ``(|S|/U_n)^2``
|
|
222
|
+
distance weight that the classical FBP / FDK formula requires;
|
|
223
|
+
- hand-rolled a ramp filter missing the ``1/sample_spacing`` scale;
|
|
224
|
+
- multiplied by a standalone ``pi/num_views`` normalisation that only
|
|
225
|
+
absorbs the angular step, not the ``1/(2*pi)`` Fourier-convention
|
|
226
|
+
constant.
|
|
227
|
+
|
|
228
|
+
All three examples now go through the new
|
|
229
|
+
``parallel_weighted_backproject`` / ``fan_weighted_backproject`` /
|
|
230
|
+
``cone_weighted_backproject`` wrappers and end-to-end produce raw MSE
|
|
231
|
+
matching the main branch's 1.2.11 release to within rounding:
|
|
232
|
+
|
|
233
|
+
| Example | Raw MSE | Range |
|
|
234
|
+
|-----------------------------------------|-----------|-------------------|
|
|
235
|
+
| ``circular_trajectory/fbp_parallel.py`` | ~0.00366 | ``[-0.02, 1.00]`` |
|
|
236
|
+
| ``circular_trajectory/fbp_fan.py`` | ~0.00220 | ``[-0.10, 1.01]`` |
|
|
237
|
+
| ``circular_trajectory/fdk_cone.py`` | ~0.00333 | ``[-0.07, 1.00]`` |
|
|
238
|
+
|
|
239
|
+
### Notes on the sync from ``main``
|
|
240
|
+
|
|
241
|
+
The ``main`` branch's 1.2.10 / 1.2.11 / 1.3.0 releases introduced several
|
|
242
|
+
changes which this update brings to the dev branch, adapted where
|
|
243
|
+
necessary for the arbitrary-trajectory kernel API:
|
|
244
|
+
|
|
245
|
+
- ``1.2.10`` FDK / FBP voxel-driven gather, ``ramp_filter_1d`` options,
|
|
246
|
+
analytical constants, and the ``(sid/U)^2`` correctness fix: **ported**.
|
|
247
|
+
Because dev's kernels take per-view ``(src_pos, det_center, u_vec,
|
|
248
|
+
v_vec)`` arrays instead of closed-form ``sin(beta)/cos(beta)`` math,
|
|
249
|
+
the new gather kernels use ``U_n = (P - S) . n`` (where
|
|
250
|
+
``n = u_vec x v_vec``) as the generalisation of the classical ``U``.
|
|
251
|
+
For a canonical circular orbit this reduces to the textbook
|
|
252
|
+
``sid + x*sin(beta) - y*cos(beta)``.
|
|
253
|
+
- ``1.2.10`` cone / fan autograd ``distance_weight=1.0`` bug fix:
|
|
254
|
+
**not applicable**. The dev cone / fan backward kernels were
|
|
255
|
+
already correct (they never had that parameter), so the autograd
|
|
256
|
+
adjoint identity holds on dev and is now protected by
|
|
257
|
+
``tests/test_adjoint_inner_product.py``.
|
|
258
|
+
- ``1.2.11`` gradcheck / ramp window tests / CHANGELOG: **ported**.
|
|
259
|
+
- ``1.2.11`` benchmark suite: **not ported yet** (dev's benchmarks
|
|
260
|
+
directory stays empty).
|
|
261
|
+
- ``1.3.0`` SF-TR / SF-TT projector backends: **not ported**. SF relies
|
|
262
|
+
on closed-form ``sin(beta)/cos(beta)`` math for the trapezoidal
|
|
263
|
+
transaxial / rectangular axial footprints. Generalising SF to
|
|
264
|
+
arbitrary per-view ``(S, C, u_vec, v_vec)`` trajectories is a
|
|
265
|
+
non-trivial research effort (the "separable" part is not separable
|
|
266
|
+
when the detector is not plane-aligned to the voxel axes) and will
|
|
267
|
+
be tackled in a dedicated follow-up.
|
|
268
|
+
|
|
269
|
+
[Unreleased]: https://github.com/sypsyp97/diffct/tree/dev
|
|
270
|
+
|
|
271
|
+
## [1.3.4] - 2026-04-23
|
|
272
|
+
|
|
273
|
+
### Changed
|
|
274
|
+
- **Siddon projectors switched to cell-constant integration.** The 2D
|
|
275
|
+
parallel, 2D fan, and 3D cone Siddon forward/backward kernels in
|
|
276
|
+
`diffct/differentiable.py` now integrate each ray by accumulating
|
|
277
|
+
`d_image[iy, ix] * seg_len` on the traversed pixel/voxel instead of
|
|
278
|
+
sampling the bi-/tri-linear interpolant at the segment midpoint.
|
|
279
|
+
This simplifies the inner loop, removes the interpolation weight
|
|
280
|
+
bookkeeping, and keeps the forward / adjoint pair matched by
|
|
281
|
+
construction (still verified by
|
|
282
|
+
`tests/test_adjoint_inner_product.py`). Kernel docstrings and the
|
|
283
|
+
`"siddon"` backend blurbs in `examples/iterative_reco_*.py` have
|
|
284
|
+
been updated to say *cell-constant Siddon*.
|
|
285
|
+
- **Iterative examples clamp the reconstruction in-place** instead of
|
|
286
|
+
wrapping the forward pass in `nn.ReLU`. `examples/iterative_reco_parallel.py`,
|
|
287
|
+
`iterative_reco_fan.py`, and `iterative_reco_cone.py` now call
|
|
288
|
+
`self.model.reco.clamp_(min=0.0)` under `torch.no_grad()` after each
|
|
289
|
+
optimizer step, so gradients flow through the unclamped volume while
|
|
290
|
+
the stored state stays non-negative.
|
|
291
|
+
- **`examples/iterative_reco_fan.py` default backend** is now
|
|
292
|
+
`"siddon"` (was `"sf"`), matching the parallel and cone iterative
|
|
293
|
+
examples.
|
|
294
|
+
|
|
295
|
+
### Fixed
|
|
296
|
+
- **FDK cone accuracy test tolerance.** `tests/test_fdk_cone_accuracy.py`
|
|
297
|
+
raises the maximum central z-profile error bound from `0.6` to `0.65`
|
|
298
|
+
to reflect the slightly sharper one-sample transition error at
|
|
299
|
+
ellipsoid boundaries under cell-constant forward projection; global
|
|
300
|
+
FDK RMSE is unchanged.
|
|
301
|
+
|
|
8
302
|
## [1.3.3] - 2026-04-23
|
|
9
303
|
|
|
10
304
|
### Fixed
|