diffct 2.2.1__tar.gz → 2.4.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-2.2.1 → diffct-2.4.0}/CHANGELOG.md +64 -0
- {diffct-2.2.1 → diffct-2.4.0}/CITATION.cff +5 -5
- {diffct-2.2.1 → diffct-2.4.0}/PKG-INFO +33 -24
- {diffct-2.2.1 → diffct-2.4.0}/README.md +30 -21
- {diffct-2.2.1 → diffct-2.4.0}/diffct/__init__.py +17 -1
- diffct-2.4.0/diffct/_solver_state.py +301 -0
- diffct-2.4.0/diffct/_solver_tv.py +110 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/analytical.py +55 -34
- diffct-2.4.0/diffct/analytical_execution.py +427 -0
- diffct-2.4.0/diffct/backends.py +765 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/chunking.py +34 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/constants.py +10 -5
- diffct-2.4.0/diffct/distribution.py +197 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/geometry.py +93 -17
- diffct-2.4.0/diffct/kernels/__init__.py +52 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/kernels/cone_beam.py +21 -8
- diffct-2.4.0/diffct/kernels/surface_geometry.py +130 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/operators.py +880 -388
- {diffct-2.2.1 → diffct-2.4.0}/diffct/projectors.py +94 -46
- {diffct-2.2.1 → diffct-2.4.0}/diffct/reconstruction.py +108 -24
- diffct-2.4.0/diffct/solvers.py +325 -0
- diffct-2.4.0/diffct/streaming.py +140 -0
- diffct-2.4.0/diffct/surface_gradients.py +117 -0
- diffct-2.4.0/diffct/surfaces.py +146 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/utils.py +9 -1
- diffct-2.4.0/docs/video/README.md +244 -0
- {diffct-2.2.1 → diffct-2.4.0}/examples/README.md +18 -3
- diffct-2.4.0/examples/_block_cgls.py +265 -0
- diffct-2.4.0/examples/_common.py +296 -0
- diffct-2.4.0/examples/data/preprocess_walnut.py +329 -0
- diffct-2.4.0/examples/walnut_reconstruction.py +143 -0
- {diffct-2.2.1 → diffct-2.4.0}/pyproject.toml +4 -4
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_analytical_autograd.py +2 -2
- diffct-2.4.0/tests/test_analytical_distribution.py +159 -0
- diffct-2.4.0/tests/test_analytical_weight_distribution.py +83 -0
- diffct-2.4.0/tests/test_angular_low_precision.py +70 -0
- diffct-2.4.0/tests/test_batch_execution_edges.py +205 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_block_storage.py +80 -20
- diffct-2.4.0/tests/test_call_trajectory.py +252 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_chunked_projector.py +40 -25
- diffct-2.4.0/tests/test_cone_backprojection_transpose.py +189 -0
- diffct-2.4.0/tests/test_cpu_install.py +100 -0
- diffct-2.4.0/tests/test_distributed_training_transforms.py +233 -0
- diffct-2.4.0/tests/test_execution_features.py +618 -0
- diffct-2.4.0/tests/test_geometry_conversions.py +178 -0
- diffct-2.4.0/tests/test_lazy_native_observers.py +142 -0
- diffct-2.4.0/tests/test_native_surface_transforms.py +110 -0
- diffct-2.4.0/tests/test_native_volume_layout.py +328 -0
- diffct-2.4.0/tests/test_native_volume_layout_distributed.py +79 -0
- diffct-2.4.0/tests/test_parallel3d.py +376 -0
- diffct-2.4.0/tests/test_parallel3d_surface_oracle.py +149 -0
- diffct-2.4.0/tests/test_partition_lifecycle.py +197 -0
- diffct-2.4.0/tests/test_plan_memory_bounds.py +252 -0
- diffct-2.4.0/tests/test_portable_distributed_geometry.py +206 -0
- diffct-2.4.0/tests/test_portable_endpoint_precision.py +68 -0
- diffct-2.4.0/tests/test_portable_execution_bounds.py +203 -0
- diffct-2.4.0/tests/test_portable_numeric_regressions.py +185 -0
- diffct-2.4.0/tests/test_portable_surface_admission.py +85 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_projector_api.py +1 -1
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_reconstruction_api.py +176 -0
- diffct-2.4.0/tests/test_reference_backend.py +473 -0
- diffct-2.4.0/tests/test_review_230.py +99 -0
- diffct-2.4.0/tests/test_review_regressions.py +345 -0
- diffct-2.4.0/tests/test_solver_admission_regressions.py +273 -0
- diffct-2.4.0/tests/test_solver_api.py +710 -0
- diffct-2.4.0/tests/test_solver_checkpoint_edges.py +287 -0
- diffct-2.4.0/tests/test_solver_collective_failures.py +225 -0
- diffct-2.4.0/tests/test_surface_collective_failures.py +521 -0
- diffct-2.4.0/tests/test_surface_composition_kernel.py +358 -0
- diffct-2.4.0/tests/test_surface_compute_shards.py +564 -0
- diffct-2.4.0/tests/test_surface_geometry_cudasim.py +514 -0
- diffct-2.4.0/tests/test_surface_gradient_replay.py +226 -0
- diffct-2.4.0/tests/test_surface_native_regressions.py +281 -0
- diffct-2.4.0/tests/test_surface_pipeline_contracts.py +388 -0
- diffct-2.4.0/tests/test_surface_trajectory_transform.py +142 -0
- diffct-2.4.0/tests/test_training_transforms.py +95 -0
- diffct-2.4.0/tests/test_trajectory_admission_cost.py +257 -0
- diffct-2.4.0/tests/test_trajectory_surface_integration.py +615 -0
- diffct-2.4.0/tests/test_tv_zero_dependency.py +75 -0
- diffct-2.4.0/tests/test_two_far_endpoints.py +84 -0
- diffct-2.2.1/diffct/kernels/__init__.py +0 -51
- diffct-2.2.1/diffct/streaming.py +0 -48
- diffct-2.2.1/diffct/surfaces.py +0 -103
- diffct-2.2.1/docs/video/README.md +0 -119
- {diffct-2.2.1 → diffct-2.4.0}/.gitignore +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/LICENSE +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/NOTICE +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/differentiable.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/kernels/analytical_transpose.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/kernels/fan_beam.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/kernels/geometry_vjp.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/kernels/parallel_beam.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/pipeline.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/diffct/storage.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/examples/data/NOTICE +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/formal/README.md +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/pytest.ini +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/__init__.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/_phantoms.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/benchmarks/README.md +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/benchmarks/__init__.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/benchmarks/_common.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/benchmarks/test_bench_cone.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/benchmarks/test_bench_fan.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/benchmarks/test_bench_parallel.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/distributed_projector_check.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_adjoint_inner_product.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_allocator_capacity.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_analytical_regressions.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_axis_aligned_chords.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_batched_surfaces.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_block_cgls.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_cgls_state_admission.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_completed_transfer_reuse.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_cone_projector_autograd.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_cuda_exit_deallocations.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_cuda_sink_lifetimes.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_cuda_smoke.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_detector_surface_dtypes.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_detector_surface_mapping.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_detector_surface_units.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_detector_surfaces.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_example_psnr.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_execution_buffers.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_execution_schedules.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_fbp_fan_accuracy.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_fbp_fan_offsets.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_fbp_parallel_accuracy.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_fdk_cone_accuracy.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_fdk_cone_offsets.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_geometry_autograd.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_geometry_gradients.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_gradcheck.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_multi_gpu_exit.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_output_pipeline_overlap.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_projector_degenerate_geometry.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_projector_geometry_devices.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_ramp_filter_windows.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_release_2_0_1.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_spatial_partition.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_transfer_pipeline.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_transfer_retirement_lifetimes.py +0 -0
- {diffct-2.2.1 → diffct-2.4.0}/tests/test_weights.py +0 -0
|
@@ -7,6 +7,70 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.4.0] - 2026-10-20
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Per-call `trajectory` overrides on `Projector` operations, preserving the constructor default and each call's geometry graph without rebuilding the projector (#29).
|
|
15
|
+
- Angle-tensor inputs for circular trajectory helpers and differentiable `transform_trajectory` rigid transforms (#29).
|
|
16
|
+
- `beam="parallel3d"` and `circular_trajectory_3d_parallel`, using infinite parallel rays and the PyTorch backend on CPU and CUDA, with data and first-order geometry gradients (#29).
|
|
17
|
+
- `Projector(native_volume_layout=True)` returns native full-CUDA cone backprojections of unbatched flat-detector inputs as `(D, H, W)` tensors with the kernels' `(W, H, D)`-contiguous strides instead of contiguous copies, and native cone projections accept such tensors without copying. An iterative solver that keeps its volumes in this layout saves two whole-volume copies per normal-operator application on one device. The default is unchanged (#27).
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- The native cone backprojection kernel steps through the z crossings of each xy cell in an inner loop and groups adjacent detector rows in a warp, so the atomic additions of a warp hit neighbouring voxels of one column. Each ray's segments and arithmetic are unchanged; backprojection takes 1.25–1.8x less time on large cone and helical problems, depending on the geometry (#35).
|
|
22
|
+
- Projector execution planning takes no allocator snapshot when a full launch clearly fits: lower bounds of the memory limits come from `mem_get_info` and one statistics query, and the exact planner runs only when they do not suffice. Plans are unchanged. Host time per call for small problems drops by about 1 ms. Distributed operators keep the exact planner (#26).
|
|
23
|
+
- Distributed calls and solvers check rank agreement with one fixed-size collective per request instead of Python object exchanges, skip the callback protocol when no callback is given, and accumulate solver norms on the device with one host read per norm. Results are unchanged (#34).
|
|
24
|
+
- The introduction video explains 2.3.0 tiled execution and view, space and hybrid partitions with a computed walnut example; the README GIF is 12 MB instead of 22 MB (#25).
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Detector surfaces expand world points on each compute device after view sharding, preserving native composition precision. Memory planning uses local view counts and composition dtypes. Streamed execution accepts CPU or CUDA offsets from both surface interfaces (#30).
|
|
29
|
+
- Surface snapshots preserve gradient connections on CPU. Streamed composition and geometry backward use bounded fragments. Distributed calls check callback layouts and propagate validation errors before numerical work (#30).
|
|
30
|
+
- Native surface admission sizes validation batches from available memory and staging limits, replacing fixed one-view batches (#32).
|
|
31
|
+
- Rigid trajectory transforms accept valid surface detector frames whose reference center coincides with the source or whose reference plane is edge-on (#29).
|
|
32
|
+
- Call-time trajectory validation checks flat detectors by corners and coordinate bounds, with exact pixel checks for ambiguous views. Frames stage once per validation device. Native surface validation uses bounded batches on each compute device after view sharding (#29).
|
|
33
|
+
|
|
34
|
+
## [2.3.0] - 2026-10-14
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- `backend="auto"`, `"numba"` or `"torch"` and `precision="fast"`, `"float32"` or `"float64"` on `Projector`, `fbp` and `fdk`. These settings are opt-in. Default calls keep native FP32 execution where compatible.
|
|
39
|
+
- `backend="auto"` selects the PyTorch backend for `precision="float32"`, `precision="float64"`, per-axis `voxel_spacing` and hybrid partitions. An incompatible explicit `backend="numba"` request raises an error.
|
|
40
|
+
- `backend="torch"` runs on CPU, NVIDIA CUDA and PyTorch ROCm. `precision="float64"` runs the data operations in FP64.
|
|
41
|
+
- Portable FP32 ray setup clips rays and locates tile entries in FP64. Traversal measures distances from each entry, so distant endpoints keep voxel widths.
|
|
42
|
+
- Per-axis `voxel_spacing`, such as `(dy, dx)` or `(dz, dy, dx)`, in tensor axis order.
|
|
43
|
+
- Leading batch and channel dimensions for projection and adjoint, including empty batches.
|
|
44
|
+
- Data gradients, JVP, `vmap`, `jacrev`, `jacfwd` and second data derivatives for the PyTorch projector. Dense Jacobians need a single-process projector.
|
|
45
|
+
- `view_chunk_size` and `volume_chunk_shape` on `fbp` and `fdk` stream view batches and spatial tiles. `devices` schedules tiles across local devices.
|
|
46
|
+
- `fbp_into` and `fdk_into` write into `TensorStore`, `NpyStore` or compatible block stores.
|
|
47
|
+
- `partition="hybrid"` with `partition_grid=(view_ranks, space_ranks)` for projectors and analytical reconstruction. Uneven and empty shards are supported.
|
|
48
|
+
- `cgls`, `sirt`, `tv_reconstruction` and `SolverResult`, with residual thresholds, residual history, callbacks and optional `x0`.
|
|
49
|
+
- `cgls_into` keeps solver state in mapped files. It rejects non-finite measurements in bounded blocks before any output write.
|
|
50
|
+
- `checkpoint_directory` and `resume` for `cgls`, `sirt` and `tv_reconstruction`. Fingerprints bind the acquisition, measurements, precision, ownership and settings.
|
|
51
|
+
- `total_variation` with `reduction="mean"` or `"sum"`. Spatial and hybrid runs exchange neighbouring faces.
|
|
52
|
+
- `docs/EXECUTION.md` documents precision, memory bounds, distributed loss replica divisors and checkpoint contracts.
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
|
|
56
|
+
- Importing `diffct` and using `backend="torch"` no longer loads Numba CUDA or requires a CUDA runtime. Native execution initializes them on first use.
|
|
57
|
+
- `pip install diffct` is enough for `backend="torch"`. Native Numba execution needs the CUDA extras `diffct[cu12]` or `diffct[cu13]`.
|
|
58
|
+
- Distributed PyTorch-backend projectors require the same `volume_chunk_shape`, `view_chunk_size` and `detector_chunk_shape` on every rank.
|
|
59
|
+
- The source distribution includes the four example helpers used by its shipped tests.
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- Parker short-scan distance and detector-u offset checks bound position and
|
|
64
|
+
detector-axis rounding per component along the checked direction, not by the
|
|
65
|
+
absolute coordinate size.
|
|
66
|
+
A bfloat16 or float16 detector-v axis made a 50-unit change in detector distance
|
|
67
|
+
pass, and the Parker weights then used the first view's distance.
|
|
68
|
+
- Fan and cone normalization in the analytical gather and its transpose uses each view's SID and SDD. Inactive views no longer rescale active views.
|
|
69
|
+
- `angular_integration_weights` and `parker_weights` keep FP32 and FP64 input precision. FP16 and BF16 angles are computed in FP32.
|
|
70
|
+
- Angular gaps come directly from sorted neighbouring angles. Float32 neighbours one ulp apart no longer get a zero weight, and Parker rows no longer depend on the input order.
|
|
71
|
+
- Valid low-precision Parker short scans keep finite weights and angle gradients.
|
|
72
|
+
- Output stores that overlap internally raise before any I/O. Disjoint interleaved `TensorStore` slices are accepted.
|
|
73
|
+
|
|
10
74
|
## [2.2.1] - 2026-10-13
|
|
11
75
|
|
|
12
76
|
### Added
|
|
@@ -13,8 +13,8 @@ authors:
|
|
|
13
13
|
given-names: Yipeng
|
|
14
14
|
email: yipeng.sun@fau.de
|
|
15
15
|
alias: sypsyp97
|
|
16
|
-
version: 2.
|
|
17
|
-
date-released: "2026-10-
|
|
16
|
+
version: 2.4.0
|
|
17
|
+
date-released: "2026-10-20"
|
|
18
18
|
license: Apache-2.0
|
|
19
19
|
repository-code: "https://github.com/sypsyp97/diffct"
|
|
20
20
|
url: "https://sypsyp97.github.io/diffct/"
|
|
@@ -43,9 +43,9 @@ preferred-citation:
|
|
|
43
43
|
- family-names: Maier
|
|
44
44
|
given-names: Andreas
|
|
45
45
|
year: 2026
|
|
46
|
-
month:
|
|
46
|
+
month: 10
|
|
47
47
|
journal: Preprints
|
|
48
48
|
publisher:
|
|
49
49
|
name: Preprints
|
|
50
|
-
doi: 10.20944/preprints202605.1446.
|
|
51
|
-
url: "https://doi.org/10.20944/preprints202605.1446.
|
|
50
|
+
doi: 10.20944/preprints202605.1446.v2
|
|
51
|
+
url: "https://doi.org/10.20944/preprints202605.1446.v2"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: diffct
|
|
3
|
-
Version: 2.
|
|
4
|
-
Summary: Differentiable
|
|
3
|
+
Version: 2.4.0
|
|
4
|
+
Summary: Differentiable CT projection and reconstruction: precision modes, streaming, distributed execution and geometry gradients
|
|
5
5
|
Project-URL: Homepage, https://github.com/sypsyp97/diffct
|
|
6
6
|
Project-URL: Documentation, https://sypsyp97.github.io/diffct/
|
|
7
7
|
Project-URL: Changelog, https://github.com/sypsyp97/diffct/blob/main/CHANGELOG.md
|
|
@@ -10,7 +10,7 @@ Author-email: Yipeng Sun <yipeng.sun@fau.de>
|
|
|
10
10
|
License-Expression: Apache-2.0
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
License-File: NOTICE
|
|
13
|
-
Keywords: CT reconstruction,CUDA,PyTorch,computed tomography,differentiable programming
|
|
13
|
+
Keywords: CT reconstruction,CUDA,PyTorch,ROCm,computed tomography,differentiable programming
|
|
14
14
|
Classifier: Development Status :: 5 - Production/Stable
|
|
15
15
|
Classifier: Environment :: GPU :: NVIDIA CUDA
|
|
16
16
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -47,13 +47,13 @@ Description-Content-Type: text/markdown
|
|
|
47
47
|
</p>
|
|
48
48
|
|
|
49
49
|
<p align="center">
|
|
50
|
-
<img src="https://raw.githubusercontent.com/sypsyp97/diffct/
|
|
50
|
+
<img src="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/diffct_intro.gif" width="100%" alt="diffct intro: projection, sinogram, trajectories, multi-GPU split, reconstruction and geometry calibration">
|
|
51
51
|
</p>
|
|
52
52
|
|
|
53
53
|
<p align="center">
|
|
54
|
-
<a href="https://github.com/sypsyp97/diffct/blob/
|
|
55
|
-
<a href="https://www.preprints.org/manuscript/202605.1446/
|
|
56
|
-
<a href="https://doi.org/10.20944/preprints202605.1446.
|
|
54
|
+
<a href="https://github.com/sypsyp97/diffct/blob/main/docs/assets/diffct_intro.mp4">Intro video (MP4)</a> ·
|
|
55
|
+
<a href="https://www.preprints.org/manuscript/202605.1446/v2">Technical report</a> ·
|
|
56
|
+
<a href="https://doi.org/10.20944/preprints202605.1446.v2">DOI</a>
|
|
57
57
|
</p>
|
|
58
58
|
|
|
59
59
|
<p align="center">
|
|
@@ -68,36 +68,40 @@ Description-Content-Type: text/markdown
|
|
|
68
68
|
> **Version 2.0** replaces the circular-orbit API of 1.x with per-view trajectories. Code written for 1.x needs changes; see the [migration notes](https://github.com/sypsyp97/diffct/blob/main/docs/MIGRATION.md).
|
|
69
69
|
> For Apple Silicon, use the [MLX port by Linda-Sophie Schneider](https://github.com/Linda-SophieSchneider/DiffCT-MLX).
|
|
70
70
|
|
|
71
|
+
This README describes the source checkout, including [unreleased APIs](CHANGELOG.md#unreleased). Per-call trajectories, angle-tensor circular helpers, `transform_trajectory`, `parallel3d` and `native_volume_layout` require installation from source.
|
|
72
|
+
|
|
71
73
|
## Why diffct
|
|
72
74
|
|
|
73
75
|
To our knowledge, diffct is the only open-source GPU CT library that combines arbitrary per-view trajectories, autograd through the volume, first-order gradients through the acquisition geometry, and built-in multi-GPU and multi-node execution. We compared it with LEAP, TIGRE, ASTRA/tomosipo, DiffDRR and others in October 2026.
|
|
74
76
|
|
|
75
|
-
- **Arbitrary trajectories.** Each view has its own source, detector centre and detector axes. Circular, helical, saddle, sinusoidal, random and calibrated scans use the same code. Trajectory tensors with `requires_grad=True` receive geometry gradients for calibration.
|
|
77
|
+
- **Arbitrary trajectories.** Each view has its own ray direction or source, detector centre and detector axes. Circular, helical, saddle, sinusoidal, random and calibrated scans use the same code. Trajectory tensors with `requires_grad=True` receive geometry gradients for calibration.
|
|
76
78
|
- **Curved detectors.** `ParameterizedSurface` defines native arc, cylindrical or arbitrary pixels from global coordinates and explicit parameters, sampled in bounded view/pixel batches. Legacy `detector_surface(u, v)` callbacks remain available. Projection and matched backprojection support first-order surface gradients. See [the surface API](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#parameterized-detector-surfaces).
|
|
77
79
|
- **Matched operators.** `project()` and `backproject()` form an exact adjoint pair for the cell-constant Siddon model. Both support PyTorch autograd, with volume/sinogram gradients and Hessian-vector products.
|
|
78
80
|
- **Large volumes.** Automatic spatial, view and pixel blocks with bounded transfer buffers control working memory. `project_into`/`backproject_into` accept caller-owned tensor or disk stores; tensor autograd keeps complete data on its input device. See [chunked execution](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#chunked-execution).
|
|
79
|
-
- **Multi-GPU and multi-node.** Use `devices=[0, 1, 2, 3]` in one process, or torchrun and NCCL across ranks.
|
|
81
|
+
- **Multi-GPU and multi-node.** Use `devices=[0, 1, 2, 3]` in one process, or torchrun and NCCL across ranks. Views, space and hybrid partitions control replication of volumes and projections. Speedup depends on workload and communication costs.
|
|
82
|
+
- **Precision and training.** Explicit native/PyTorch backends, FP32/FP64 modes, per-axis voxel spacing, leading batch/channel dimensions and data `torch.func` transforms. The portable path supports CPU and PyTorch CUDA/ROCm devices; see [execution contracts](docs/EXECUTION.md).
|
|
83
|
+
- **Solver API.** `cgls`, `sirt` and `tv_reconstruction` report residual history, tolerances and callbacks, with scan/data fingerprints and complete checkpoint state. `cgls_into` keeps state in bounded mapped blocks.
|
|
80
84
|
- **Differentiable FBP and FDK.** `fbp`, `fdk` and approximate `helical_fdk` compose the public filters, weights and analytical backprojectors. Their backward kernels transpose the actual interpolation stencil; custom filters and weights can be learned. See the [analytical guide](docs/source/analytical_learning.rst).
|
|
81
85
|
|
|
82
86
|
Capabilities, limits and isocenter rules: [docs/REFERENCE.md](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#capabilities-and-limits).
|
|
83
87
|
|
|
84
88
|
## Install
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
For the native path, install NVIDIA CUDA PyTorch first, then diffct with the matching CUDA major extra:
|
|
87
91
|
|
|
88
92
|
```bash
|
|
89
93
|
pip install "diffct[cu12]" # PyTorch built for CUDA 12
|
|
90
94
|
pip install "diffct[cu13]" # PyTorch built for CUDA 13
|
|
91
95
|
```
|
|
92
96
|
|
|
93
|
-
The extra installs the CUDA compiler libraries
|
|
97
|
+
The extra installs the CUDA compiler libraries Numba needs. For CPU or PyTorch ROCm execution, install the appropriate PyTorch build and plain `pip install diffct`, then select `backend="torch"`. Importing diffct and using this backend require no CUDA runtime; Numba CUDA initializes when native execution is used. Plain installation also works for native execution when a compatible CUDA Toolkit is already present.
|
|
94
98
|
|
|
95
99
|
From source, with the examples:
|
|
96
100
|
|
|
97
101
|
```bash
|
|
98
102
|
git clone https://github.com/sypsyp97/diffct.git
|
|
99
103
|
cd diffct && pip install -e ".[cu12]"
|
|
100
|
-
python examples/quickstart.py #
|
|
104
|
+
python examples/quickstart.py # prints adjoint mismatch and gradients for each beam
|
|
101
105
|
```
|
|
102
106
|
|
|
103
107
|
<details>
|
|
@@ -136,7 +140,11 @@ loss.backward() # x.grad = A^T (A x - y)
|
|
|
136
140
|
|
|
137
141
|
**Custom or calibrated trajectories.** Pass calibrated tensors directly instead of a generator; no circular fit is needed. See [REFERENCE](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#custom-or-calibrated-trajectories).
|
|
138
142
|
|
|
139
|
-
**Geometry gradients.**
|
|
143
|
+
**Geometry gradients.** Reuse one projector with `A.project(volume, trajectory=current)` or `A.backproject(sinogram, trajectory=current)`. Circular helpers accept learnable angle tensors, and `transform_trajectory` applies differentiable rigid transforms. Omitting the override keeps the constructor trajectory. See [REFERENCE](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#geometry-gradients).
|
|
144
|
+
|
|
145
|
+
**3D parallel beams.** Use `circular_trajectory_3d_parallel(...)` and `beam="parallel3d"`. The PyTorch backend provides matched projection and backprojection on CPU and CUDA.
|
|
146
|
+
|
|
147
|
+
**Native volume layout.** For unbatched, flat-detector cone operations, set `native_volume_layout=True` to avoid volume layout copies. This applies to the native full-CUDA path on one compute device. Shapes stay `(D, H, W)`; the returned strides follow the kernel layout. The default is `False`. See [chunked execution](docs/REFERENCE.md#chunked-execution) for limits.
|
|
140
148
|
|
|
141
149
|
**Several GPUs and nodes.** See [REFERENCE](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#several-gpus-and-nodes) and [DISTRIBUTED.md](https://github.com/sypsyp97/diffct/blob/main/docs/DISTRIBUTED.md).
|
|
142
150
|
|
|
@@ -169,18 +177,18 @@ volume slabs use `--partition space` under torchrun. Run
|
|
|
169
177
|
|
|
170
178
|
<p align="center">
|
|
171
179
|
<picture>
|
|
172
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/scaling_dark.png?v=2.
|
|
173
|
-
<img src="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/scaling_light.png?v=2.
|
|
180
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/scaling_dark.png?v=2.4.0">
|
|
181
|
+
<img src="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/scaling_light.png?v=2.4.0" width="100%" alt="Time per forward, adjoint and CGLS iteration on 1, 4 and 8 GPUs, 512^3 volume">
|
|
174
182
|
</picture>
|
|
175
183
|
</p>
|
|
176
184
|
|
|
177
185
|
| 512³ volume | 1 GPU | 4 GPUs, 1 node | 8 GPUs, 2 nodes |
|
|
178
186
|
|---|---:|---:|---:|
|
|
179
|
-
| Forward projection | 493.
|
|
180
|
-
| Adjoint (backprojection) |
|
|
181
|
-
| CGLS iteration |
|
|
187
|
+
| Forward projection | 493.40 ms | 131.78 ms (3.7×) | 72.42 ms (6.8×) |
|
|
188
|
+
| Adjoint (backprojection) | 1118.98 ms | 293.01 ms (3.8×) | 232.50 ms (4.8×) |
|
|
189
|
+
| CGLS iteration | 1744.92 ms | 465.62 ms (3.7×) | 337.98 ms (5.2×) |
|
|
182
190
|
|
|
183
|
-
diffct 2.
|
|
191
|
+
diffct 2.4.0, FP32, A100 64 GB GPUs; circular cone beam, 360 views, 1024×768 detector, pitch 1.25. Default memory settings, without an imposed allocator cap.
|
|
184
192
|
|
|
185
193
|
Projection times are medians of seven samples after three warmups. CGLS uses three ten-iteration solves after a two-iteration warmup; the median includes initialization and is divided by ten. Timings use synchronized wall time and the slowest rank. Raw samples and configuration: [scaling.json](https://github.com/sypsyp97/diffct/blob/main/docs/assets/scaling.json).
|
|
186
194
|
|
|
@@ -220,12 +228,13 @@ Walnut data: Meaney 2022, Zenodo 6986012, CC BY 4.0; see [examples/data/NOTICE](
|
|
|
220
228
|
|
|
221
229
|
## Examples
|
|
222
230
|
|
|
223
|
-
`quickstart.py`, `curved_detector.py`, `chunked_reconstruction.py`, `disk_reconstruction.py`, `benchmark_execution.py`, `analytical_reconstruction.py`, `learnable_reconstruction.py`, `helical_fdk.py`, `iterative_reconstruction.py`, `walnut_reconstruction.py`, `geometry_calibration.py`, `benchmark_projector.py`, `benchmark_scaling.py`, `plot_trajectory.py`, and the Slurm template `slurm/multi_node.sbatch`. Launch modes and distributed-loss rules are in [examples/README.md](https://github.com/sypsyp97/diffct/blob/main/examples/README.md).
|
|
231
|
+
`quickstart.py`, `curved_detector.py`, `chunked_reconstruction.py`, `disk_reconstruction.py`, `benchmark_execution.py`, `benchmark_trajectory_admission.py`, `analytical_reconstruction.py`, `learnable_reconstruction.py`, `helical_fdk.py`, `iterative_reconstruction.py`, `walnut_reconstruction.py`, `geometry_calibration.py`, `benchmark_projector.py`, `benchmark_scaling.py`, `plot_trajectory.py`, and the Slurm template `slurm/multi_node.sbatch`. Launch modes and distributed-loss rules are in [examples/README.md](https://github.com/sypsyp97/diffct/blob/main/examples/README.md).
|
|
224
232
|
|
|
225
233
|
## Documentation
|
|
226
234
|
|
|
227
235
|
| Document | Contents |
|
|
228
236
|
|---|---|
|
|
237
|
+
| [Precision, training and reconstruction](docs/EXECUTION.md) | Backend modes, batch/spacing contracts, analytical storage, hybrid loss scaling and solver checkpoints |
|
|
229
238
|
| [Trajectory guide](https://github.com/sypsyp97/diffct/blob/main/docs/source/trajectories.rst) | Trajectory tuples and `Projector` usage |
|
|
230
239
|
| [docs/REFERENCE.md](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md) | Capabilities and limits, custom trajectories, geometry gradients, multi-GPU details, geometry and units |
|
|
231
240
|
| [docs/DISTRIBUTED.md](https://github.com/sypsyp97/diffct/blob/main/docs/DISTRIBUTED.md) | Execution/memory choices, distributed loss rules, Slurm and cross-node checks |
|
|
@@ -250,12 +259,12 @@ If you use this library in your research, please cite the software and the techn
|
|
|
250
259
|
}
|
|
251
260
|
|
|
252
261
|
@article{202605.1446,
|
|
253
|
-
doi = {10.20944/preprints202605.1446.
|
|
254
|
-
url = {https://doi.org/10.20944/preprints202605.1446.
|
|
262
|
+
doi = {10.20944/preprints202605.1446.v2},
|
|
263
|
+
url = {https://doi.org/10.20944/preprints202605.1446.v2},
|
|
255
264
|
year = 2026,
|
|
256
|
-
month = {
|
|
265
|
+
month = {Oct},
|
|
257
266
|
publisher = {Preprints},
|
|
258
|
-
author = {Yipeng Sun and Linda-Sophie Schneider and Chengze
|
|
267
|
+
author = {Yipeng Sun and Linda-Sophie Schneider and Chengze Ye and Andreas Maier},
|
|
259
268
|
title = {diffct: Differentiable CT Operators from Circular Orbits to Arbitrary Trajectories},
|
|
260
269
|
journal = {Preprints}
|
|
261
270
|
}
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
19
|
-
<img src="https://raw.githubusercontent.com/sypsyp97/diffct/
|
|
19
|
+
<img src="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/diffct_intro.gif" width="100%" alt="diffct intro: projection, sinogram, trajectories, multi-GPU split, reconstruction and geometry calibration">
|
|
20
20
|
</p>
|
|
21
21
|
|
|
22
22
|
<p align="center">
|
|
23
|
-
<a href="https://github.com/sypsyp97/diffct/blob/
|
|
24
|
-
<a href="https://www.preprints.org/manuscript/202605.1446/
|
|
25
|
-
<a href="https://doi.org/10.20944/preprints202605.1446.
|
|
23
|
+
<a href="https://github.com/sypsyp97/diffct/blob/main/docs/assets/diffct_intro.mp4">Intro video (MP4)</a> ·
|
|
24
|
+
<a href="https://www.preprints.org/manuscript/202605.1446/v2">Technical report</a> ·
|
|
25
|
+
<a href="https://doi.org/10.20944/preprints202605.1446.v2">DOI</a>
|
|
26
26
|
</p>
|
|
27
27
|
|
|
28
28
|
<p align="center">
|
|
@@ -37,36 +37,40 @@
|
|
|
37
37
|
> **Version 2.0** replaces the circular-orbit API of 1.x with per-view trajectories. Code written for 1.x needs changes; see the [migration notes](https://github.com/sypsyp97/diffct/blob/main/docs/MIGRATION.md).
|
|
38
38
|
> For Apple Silicon, use the [MLX port by Linda-Sophie Schneider](https://github.com/Linda-SophieSchneider/DiffCT-MLX).
|
|
39
39
|
|
|
40
|
+
This README describes the source checkout, including [unreleased APIs](CHANGELOG.md#unreleased). Per-call trajectories, angle-tensor circular helpers, `transform_trajectory`, `parallel3d` and `native_volume_layout` require installation from source.
|
|
41
|
+
|
|
40
42
|
## Why diffct
|
|
41
43
|
|
|
42
44
|
To our knowledge, diffct is the only open-source GPU CT library that combines arbitrary per-view trajectories, autograd through the volume, first-order gradients through the acquisition geometry, and built-in multi-GPU and multi-node execution. We compared it with LEAP, TIGRE, ASTRA/tomosipo, DiffDRR and others in October 2026.
|
|
43
45
|
|
|
44
|
-
- **Arbitrary trajectories.** Each view has its own source, detector centre and detector axes. Circular, helical, saddle, sinusoidal, random and calibrated scans use the same code. Trajectory tensors with `requires_grad=True` receive geometry gradients for calibration.
|
|
46
|
+
- **Arbitrary trajectories.** Each view has its own ray direction or source, detector centre and detector axes. Circular, helical, saddle, sinusoidal, random and calibrated scans use the same code. Trajectory tensors with `requires_grad=True` receive geometry gradients for calibration.
|
|
45
47
|
- **Curved detectors.** `ParameterizedSurface` defines native arc, cylindrical or arbitrary pixels from global coordinates and explicit parameters, sampled in bounded view/pixel batches. Legacy `detector_surface(u, v)` callbacks remain available. Projection and matched backprojection support first-order surface gradients. See [the surface API](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#parameterized-detector-surfaces).
|
|
46
48
|
- **Matched operators.** `project()` and `backproject()` form an exact adjoint pair for the cell-constant Siddon model. Both support PyTorch autograd, with volume/sinogram gradients and Hessian-vector products.
|
|
47
49
|
- **Large volumes.** Automatic spatial, view and pixel blocks with bounded transfer buffers control working memory. `project_into`/`backproject_into` accept caller-owned tensor or disk stores; tensor autograd keeps complete data on its input device. See [chunked execution](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#chunked-execution).
|
|
48
|
-
- **Multi-GPU and multi-node.** Use `devices=[0, 1, 2, 3]` in one process, or torchrun and NCCL across ranks.
|
|
50
|
+
- **Multi-GPU and multi-node.** Use `devices=[0, 1, 2, 3]` in one process, or torchrun and NCCL across ranks. Views, space and hybrid partitions control replication of volumes and projections. Speedup depends on workload and communication costs.
|
|
51
|
+
- **Precision and training.** Explicit native/PyTorch backends, FP32/FP64 modes, per-axis voxel spacing, leading batch/channel dimensions and data `torch.func` transforms. The portable path supports CPU and PyTorch CUDA/ROCm devices; see [execution contracts](docs/EXECUTION.md).
|
|
52
|
+
- **Solver API.** `cgls`, `sirt` and `tv_reconstruction` report residual history, tolerances and callbacks, with scan/data fingerprints and complete checkpoint state. `cgls_into` keeps state in bounded mapped blocks.
|
|
49
53
|
- **Differentiable FBP and FDK.** `fbp`, `fdk` and approximate `helical_fdk` compose the public filters, weights and analytical backprojectors. Their backward kernels transpose the actual interpolation stencil; custom filters and weights can be learned. See the [analytical guide](docs/source/analytical_learning.rst).
|
|
50
54
|
|
|
51
55
|
Capabilities, limits and isocenter rules: [docs/REFERENCE.md](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#capabilities-and-limits).
|
|
52
56
|
|
|
53
57
|
## Install
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
For the native path, install NVIDIA CUDA PyTorch first, then diffct with the matching CUDA major extra:
|
|
56
60
|
|
|
57
61
|
```bash
|
|
58
62
|
pip install "diffct[cu12]" # PyTorch built for CUDA 12
|
|
59
63
|
pip install "diffct[cu13]" # PyTorch built for CUDA 13
|
|
60
64
|
```
|
|
61
65
|
|
|
62
|
-
The extra installs the CUDA compiler libraries
|
|
66
|
+
The extra installs the CUDA compiler libraries Numba needs. For CPU or PyTorch ROCm execution, install the appropriate PyTorch build and plain `pip install diffct`, then select `backend="torch"`. Importing diffct and using this backend require no CUDA runtime; Numba CUDA initializes when native execution is used. Plain installation also works for native execution when a compatible CUDA Toolkit is already present.
|
|
63
67
|
|
|
64
68
|
From source, with the examples:
|
|
65
69
|
|
|
66
70
|
```bash
|
|
67
71
|
git clone https://github.com/sypsyp97/diffct.git
|
|
68
72
|
cd diffct && pip install -e ".[cu12]"
|
|
69
|
-
python examples/quickstart.py #
|
|
73
|
+
python examples/quickstart.py # prints adjoint mismatch and gradients for each beam
|
|
70
74
|
```
|
|
71
75
|
|
|
72
76
|
<details>
|
|
@@ -105,7 +109,11 @@ loss.backward() # x.grad = A^T (A x - y)
|
|
|
105
109
|
|
|
106
110
|
**Custom or calibrated trajectories.** Pass calibrated tensors directly instead of a generator; no circular fit is needed. See [REFERENCE](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#custom-or-calibrated-trajectories).
|
|
107
111
|
|
|
108
|
-
**Geometry gradients.**
|
|
112
|
+
**Geometry gradients.** Reuse one projector with `A.project(volume, trajectory=current)` or `A.backproject(sinogram, trajectory=current)`. Circular helpers accept learnable angle tensors, and `transform_trajectory` applies differentiable rigid transforms. Omitting the override keeps the constructor trajectory. See [REFERENCE](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#geometry-gradients).
|
|
113
|
+
|
|
114
|
+
**3D parallel beams.** Use `circular_trajectory_3d_parallel(...)` and `beam="parallel3d"`. The PyTorch backend provides matched projection and backprojection on CPU and CUDA.
|
|
115
|
+
|
|
116
|
+
**Native volume layout.** For unbatched, flat-detector cone operations, set `native_volume_layout=True` to avoid volume layout copies. This applies to the native full-CUDA path on one compute device. Shapes stay `(D, H, W)`; the returned strides follow the kernel layout. The default is `False`. See [chunked execution](docs/REFERENCE.md#chunked-execution) for limits.
|
|
109
117
|
|
|
110
118
|
**Several GPUs and nodes.** See [REFERENCE](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md#several-gpus-and-nodes) and [DISTRIBUTED.md](https://github.com/sypsyp97/diffct/blob/main/docs/DISTRIBUTED.md).
|
|
111
119
|
|
|
@@ -138,18 +146,18 @@ volume slabs use `--partition space` under torchrun. Run
|
|
|
138
146
|
|
|
139
147
|
<p align="center">
|
|
140
148
|
<picture>
|
|
141
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/scaling_dark.png?v=2.
|
|
142
|
-
<img src="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/scaling_light.png?v=2.
|
|
149
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/scaling_dark.png?v=2.4.0">
|
|
150
|
+
<img src="https://raw.githubusercontent.com/sypsyp97/diffct/main/docs/assets/scaling_light.png?v=2.4.0" width="100%" alt="Time per forward, adjoint and CGLS iteration on 1, 4 and 8 GPUs, 512^3 volume">
|
|
143
151
|
</picture>
|
|
144
152
|
</p>
|
|
145
153
|
|
|
146
154
|
| 512³ volume | 1 GPU | 4 GPUs, 1 node | 8 GPUs, 2 nodes |
|
|
147
155
|
|---|---:|---:|---:|
|
|
148
|
-
| Forward projection | 493.
|
|
149
|
-
| Adjoint (backprojection) |
|
|
150
|
-
| CGLS iteration |
|
|
156
|
+
| Forward projection | 493.40 ms | 131.78 ms (3.7×) | 72.42 ms (6.8×) |
|
|
157
|
+
| Adjoint (backprojection) | 1118.98 ms | 293.01 ms (3.8×) | 232.50 ms (4.8×) |
|
|
158
|
+
| CGLS iteration | 1744.92 ms | 465.62 ms (3.7×) | 337.98 ms (5.2×) |
|
|
151
159
|
|
|
152
|
-
diffct 2.
|
|
160
|
+
diffct 2.4.0, FP32, A100 64 GB GPUs; circular cone beam, 360 views, 1024×768 detector, pitch 1.25. Default memory settings, without an imposed allocator cap.
|
|
153
161
|
|
|
154
162
|
Projection times are medians of seven samples after three warmups. CGLS uses three ten-iteration solves after a two-iteration warmup; the median includes initialization and is divided by ten. Timings use synchronized wall time and the slowest rank. Raw samples and configuration: [scaling.json](https://github.com/sypsyp97/diffct/blob/main/docs/assets/scaling.json).
|
|
155
163
|
|
|
@@ -189,12 +197,13 @@ Walnut data: Meaney 2022, Zenodo 6986012, CC BY 4.0; see [examples/data/NOTICE](
|
|
|
189
197
|
|
|
190
198
|
## Examples
|
|
191
199
|
|
|
192
|
-
`quickstart.py`, `curved_detector.py`, `chunked_reconstruction.py`, `disk_reconstruction.py`, `benchmark_execution.py`, `analytical_reconstruction.py`, `learnable_reconstruction.py`, `helical_fdk.py`, `iterative_reconstruction.py`, `walnut_reconstruction.py`, `geometry_calibration.py`, `benchmark_projector.py`, `benchmark_scaling.py`, `plot_trajectory.py`, and the Slurm template `slurm/multi_node.sbatch`. Launch modes and distributed-loss rules are in [examples/README.md](https://github.com/sypsyp97/diffct/blob/main/examples/README.md).
|
|
200
|
+
`quickstart.py`, `curved_detector.py`, `chunked_reconstruction.py`, `disk_reconstruction.py`, `benchmark_execution.py`, `benchmark_trajectory_admission.py`, `analytical_reconstruction.py`, `learnable_reconstruction.py`, `helical_fdk.py`, `iterative_reconstruction.py`, `walnut_reconstruction.py`, `geometry_calibration.py`, `benchmark_projector.py`, `benchmark_scaling.py`, `plot_trajectory.py`, and the Slurm template `slurm/multi_node.sbatch`. Launch modes and distributed-loss rules are in [examples/README.md](https://github.com/sypsyp97/diffct/blob/main/examples/README.md).
|
|
193
201
|
|
|
194
202
|
## Documentation
|
|
195
203
|
|
|
196
204
|
| Document | Contents |
|
|
197
205
|
|---|---|
|
|
206
|
+
| [Precision, training and reconstruction](docs/EXECUTION.md) | Backend modes, batch/spacing contracts, analytical storage, hybrid loss scaling and solver checkpoints |
|
|
198
207
|
| [Trajectory guide](https://github.com/sypsyp97/diffct/blob/main/docs/source/trajectories.rst) | Trajectory tuples and `Projector` usage |
|
|
199
208
|
| [docs/REFERENCE.md](https://github.com/sypsyp97/diffct/blob/main/docs/REFERENCE.md) | Capabilities and limits, custom trajectories, geometry gradients, multi-GPU details, geometry and units |
|
|
200
209
|
| [docs/DISTRIBUTED.md](https://github.com/sypsyp97/diffct/blob/main/docs/DISTRIBUTED.md) | Execution/memory choices, distributed loss rules, Slurm and cross-node checks |
|
|
@@ -219,12 +228,12 @@ If you use this library in your research, please cite the software and the techn
|
|
|
219
228
|
}
|
|
220
229
|
|
|
221
230
|
@article{202605.1446,
|
|
222
|
-
doi = {10.20944/preprints202605.1446.
|
|
223
|
-
url = {https://doi.org/10.20944/preprints202605.1446.
|
|
231
|
+
doi = {10.20944/preprints202605.1446.v2},
|
|
232
|
+
url = {https://doi.org/10.20944/preprints202605.1446.v2},
|
|
224
233
|
year = 2026,
|
|
225
|
-
month = {
|
|
234
|
+
month = {Oct},
|
|
226
235
|
publisher = {Preprints},
|
|
227
|
-
author = {Yipeng Sun and Linda-Sophie Schneider and Chengze
|
|
236
|
+
author = {Yipeng Sun and Linda-Sophie Schneider and Chengze Ye and Andreas Maier},
|
|
228
237
|
title = {diffct: Differentiable CT Operators from Circular Orbits to Arbitrary Trajectories},
|
|
229
238
|
journal = {Preprints}
|
|
230
239
|
}
|
|
@@ -20,12 +20,18 @@ from .surfaces import ParameterizedSurface
|
|
|
20
20
|
from .reconstruction import (
|
|
21
21
|
fbp,
|
|
22
22
|
fdk,
|
|
23
|
+
fbp_into,
|
|
24
|
+
fdk_into,
|
|
23
25
|
helical_fdk,
|
|
24
26
|
helical_view_weights,
|
|
25
27
|
helical_weighted_backproject,
|
|
26
28
|
)
|
|
27
29
|
|
|
30
|
+
from .solvers import SolverResult, cgls, sirt, tv_reconstruction, cgls_into, total_variation
|
|
31
|
+
|
|
28
32
|
from .geometry import (
|
|
33
|
+
transform_trajectory,
|
|
34
|
+
circular_trajectory_3d_parallel,
|
|
29
35
|
circular_trajectory_3d,
|
|
30
36
|
random_trajectory_3d,
|
|
31
37
|
spiral_trajectory_3d,
|
|
@@ -58,7 +64,7 @@ try:
|
|
|
58
64
|
except ImportError:
|
|
59
65
|
pass
|
|
60
66
|
|
|
61
|
-
__version__ = '2.
|
|
67
|
+
__version__ = '2.4.0'
|
|
62
68
|
|
|
63
69
|
__all__ = [
|
|
64
70
|
'Projector',
|
|
@@ -67,6 +73,14 @@ __all__ = [
|
|
|
67
73
|
'ParameterizedSurface',
|
|
68
74
|
'fbp',
|
|
69
75
|
'fdk',
|
|
76
|
+
'fbp_into',
|
|
77
|
+
'fdk_into',
|
|
78
|
+
'SolverResult',
|
|
79
|
+
'cgls',
|
|
80
|
+
'sirt',
|
|
81
|
+
'tv_reconstruction',
|
|
82
|
+
'cgls_into',
|
|
83
|
+
'total_variation',
|
|
70
84
|
'helical_fdk',
|
|
71
85
|
'helical_view_weights',
|
|
72
86
|
'helical_weighted_backproject',
|
|
@@ -76,6 +90,8 @@ __all__ = [
|
|
|
76
90
|
'FanBackprojectorFunction',
|
|
77
91
|
'ConeProjectorFunction',
|
|
78
92
|
'ConeBackprojectorFunction',
|
|
93
|
+
'transform_trajectory',
|
|
94
|
+
'circular_trajectory_3d_parallel',
|
|
79
95
|
'circular_trajectory_3d',
|
|
80
96
|
'random_trajectory_3d',
|
|
81
97
|
'spiral_trajectory_3d',
|