toupy.tomo package¶
Submodules¶
toupy.tomo.cone_projector module¶
Cone-beam forward projector.
Computes the cone-beam Radon transform (line integrals along divergent rays) of a 3-D volume for a circular source orbit.
Primary use-cases:
Consistency checks — compare measured projections with the re-projection of the FDK reconstruction to quantify residual reconstruction artefacts.
Iterative reconstruction — the forward model is the mandatory companion to the FDK back-projector in a SART-style cone-beam update step.
The function signature mirrors projector()
for the parallel-beam case.
- GPU pathstub analogous to
radon_cuda(); will delegate to a CuPy CUDA ray-casting kernel.
CPU path : NumPy reference using trilinear interpolation.
- toupy.tomo.cone_projector.cone_project(volume: ndarray, geometry: ConeBeamGeometry, cuda: bool = False) ndarray[source]¶
Compute the cone-beam forward projection of a 3-D volume.
For each projection angle θ in
geometry.anglesand each detector pixel(u_i, v_j)the function evaluates the line integral along the cone ray from the point source through the voxel grid to the detector.The perspective-projection mapping of a voxel at object-space coordinates
(x, y, z)onto the detector at angle θ is:\[U(\theta) = \mathrm{SOD} + x\sin\theta - y\cos\theta\]\[u_d = \frac{\mathrm{SDD}}{U}\,(x\cos\theta + y\sin\theta), \qquad v_d = \frac{\mathrm{SDD}}{U}\, z\]The voxel grid is assumed isotropic with pitch
geometry.effective_pixel_size, centred at the origin (the rotation axis).- Parameters:
volume (ndarray, shape (n_v, N, N)) – The 3-D volume to project. Axis order:
(z, y, x)where z is the rotation (axial) direction and (y, x) is the transaxial plane.Nis the transaxial voxel count and may differ fromgeometry.n_u; the coordinate mapping is scaled accordingly.geometry (ConeBeamGeometry) – Validated acquisition geometry. Provides SOD, SDD,
det_pixel_size, and the set of projection angles.cuda (bool, optional) – If
True, attempt to use the CuPy GPU path. Falls back to CPU with awarningswarning when CuPy is unavailable. DefaultFalse.
- Returns:
projections – Simulated cone-beam projections. Axis order matches the input convention expected by
fdk_weight().- Return type:
- Raises:
ValueError – If
volume.ndim != 3.ValueError – If
volume.shape[0] != geometry.n_v(axial size mismatch between the volume and the detector).
See also
toupy.tomo.radon.projectorParallel-beam forward projector (2-D).
toupy.tomo.fdk.fdk_reconstructPaired cone-beam reconstruction.
Notes
This forward projector is the exact adjoint of
fdk_backproject()(without the(SOD/U)²weighting applied in the back-projector). For a consistent SART-style iterative solver, the weighting must be applied symmetrically in both the forward and back steps, or the normal equations must be formed explicitly.
toupy.tomo.fdk module¶
Feldkamp–Davis–Kress (FDK) cone-beam reconstruction.
Implements the three-step FDK pipeline from:
Feldkamp, L. A., Davis, L. C., & Kress, J. W. (1984). Practical cone-beam algorithm. Journal of the Optical Society of America A, 1(6), 612–619. https://doi.org/10.1364/JOSAA.1.000612
- Step 1 —
fdk_weight(): Multiply each projection pixel (u, v) by the cosine factor
SOD / sqrt(SOD² + u² + v²), where u and v are centred physical detector coordinates.- Step 2 —
fdk_filter(): Apply a 1-D ramp (or windowed-ramp) filter row-by-row along the horizontal detector direction u. Reuses
compute_filter().- Step 3 —
fdk_backproject(): 3-D divergent-ray back-projection. For each output voxel (x, y, z) and each projection angle θ, compute the detector coordinates at which the cone ray through the voxel intersects the detector, interpolate the filtered projection, and accumulate weighted by
(SOD / U)²where U is the perspective-projection denominator (see function docstring).- GPU pathstub for a CuPy/CUDA implementation, falls back to CPU with a
warning (same pattern as
mod_iradon_cuda()).
CPU path : NumPy reference implementation (loops over angles).
Public API¶
fdk_weight, fdk_filter, fdk_backproject, fdk_reconstruct
- toupy.tomo.fdk.fdk_backproject(projections_filtered: ndarray, geometry: ConeBeamGeometry, output_size: int | None = None) ndarray[source]¶
3-D cone-beam back-projection (Step 3 of FDK).
For each output voxel at object-space coordinates (x, y, z) and for each projection angle θ, the perspective-projection denominator is:
\[U(\theta) = \mathrm{SOD} + x\sin\theta - y\cos\theta\]The detector coordinates of the cone ray through the voxel are:
\[u_d = \frac{\mathrm{SDD}}{U}\, (x\cos\theta + y\sin\theta)\]\[v_d = \frac{\mathrm{SDD}}{U}\, z\]The filtered projection value at
(u_d, v_d)is obtained by bilinear interpolation and accumulated into the voxel, weighted by the solid-angle correction factor(SOD / U)². The final volume is scaled byπ / n_angles:\[f(x, y, z) = \frac{\pi}{N_\theta} \sum_{k=1}^{N_\theta} \left(\frac{\mathrm{SOD}}{U_k}\right)^2 p_f^{\theta_k}(u_d, v_d)\]- Parameters:
projections_filtered (ndarray, shape (n_angles, n_v, n_u)) – Output of
fdk_filter().geometry (ConeBeamGeometry) – Acquisition geometry.
geometry.anglessupplies θ values in degrees;geometry.u_coords()andgeometry.v_coords()supply the centred detector coordinates for interpolation.output_size (int, optional) – Side length N (in voxels) of the square transaxial output grid. Defaults to
geometry.n_u(one detector column per voxel, ateffective_pixel_sizesampling).
- Returns:
volume – Reconstructed 3-D volume. Axis order:
(z, y, x)where z is the rotation axis. The rotation axis voxel is at index(n_v//2, N//2, N//2).- Return type:
ndarray, shape (n_v, N, N)
Notes
The
(SOD/U)²weighting is the cone-beam analogue of thecos²(γ)factor in 2-D fan-beam backprojection. It corrects for the solid-angle element of each voxel as seen from the source.The CPU reference uses bilinear interpolation via
scipy.interpolate.RegularGridInterpolator. A future CUDA kernel (stub infdk_reconstruct()) will use texture-memory interpolation for speed.
- toupy.tomo.fdk.fdk_filter(projections_weighted: ndarray, filter_type: str = 'ram-lak', freqcutoff: float = 1.0) ndarray[source]¶
Apply a 1-D ramp filter row-by-row to cosine-weighted projections.
This is Step 2 of the FDK algorithm. Each detector row (fixed v, varying u) is independently filtered along the u direction using an FFT-based convolution with the chosen ramp kernel. The filter is computed by
compute_filter(), so all filter types supported by the parallel-beam FBP are available here.- Parameters:
projections_weighted (ndarray, shape (n_angles, n_v, n_u)) – Output of
fdk_weight().filter_type (str, optional) – Frequency-domain filter name. One of
'ram-lak'(default),'shepp-logan','cosine','hamming','hann', orNone(no filtering, useful for debugging).freqcutoff (float, optional) – Normalised frequency cutoff in
(0, 1]. Default1.0(no cutoff beyond Nyquist).
- Returns:
projections_filtered – Ramp-filtered projections, same shape and dtype as input.
- Return type:
Notes
The filter is applied in the Fourier domain row-by-row:
\[p_f(u) = \mathcal{F}^{-1}\!\left[ \mathcal{F}[p_w](\xi)\, H(\xi) \right]\]where \(H(\xi)\) is the chosen window function. This step is mathematically identical to the FBP filtering step; only the geometry of the subsequent back-projection differs.
- toupy.tomo.fdk.fdk_reconstruct(projections: ndarray, geometry: ConeBeamGeometry, filter_type: str = 'ram-lak', freqcutoff: float = 1.0, output_size: int | None = None, cuda: bool = False) ndarray[source]¶
Full FDK cone-beam reconstruction pipeline.
Chains
fdk_weight()→fdk_filter()→fdk_backproject()in sequence, mirroring the interface ofmod_iradon()for the parallel-beam case.An optional GPU path (
cuda=True) is stubbed out; when CuPy is unavailable it falls back to the CPU path with awarningsmessage, exactly asmod_iradon_cuda()does.- Parameters:
projections (ndarray, shape (n_angles, n_v, n_u)) – Raw cone-beam projections (Beer-Lambert log-normalised line integrals).
geometry (ConeBeamGeometry) – Acquisition geometry.
validate()is called internally; no need to call it again before passing in.filter_type (str, optional) – Ramp-filter window forwarded to
fdk_filter(). Default'ram-lak'.freqcutoff (float, optional) – Normalised frequency cutoff forwarded to
fdk_filter(). Default1.0.output_size (int, optional) – Transaxial reconstruction grid side length N, forwarded to
fdk_backproject(). Defaults togeometry.n_u.cuda (bool, optional) – If
True, attempt to use the CuPy GPU back-projector. Falls back to CPU with awarningswarning when CuPy is unavailable. DefaultFalse.
- Returns:
volume – Reconstructed 3-D volume.
- Return type:
ndarray, shape (n_v, N, N)
- Raises:
ValueError – If
projections.ndim != 3or its trailing dimensions are inconsistent withgeometry.n_vandgeometry.n_u.
See also
toupy.tomo.iradon.mod_iradonParallel-beam FBP (2-D, single slice).
toupy.tomo.iradon.mod_iradon_cudaGPU parallel-beam FBP.
toupy.tomo.tomorecons.fdk_tomo_reconsHigh-level wrapper with interactive display and optional saving.
Notes
The
π / N_θscale factor is absorbed intofdk_backproject(). It differs from theπ / (2 N_θ)factor in parallel-beam FBP because FDK sums over a full 360° orbit while the parallel-beam formula assumes 180°.
- toupy.tomo.fdk.fdk_weight(projections: ndarray, geometry: ConeBeamGeometry) ndarray[source]¶
Apply FDK cosine weights to a stack of cone-beam projections.
This is Step 1 of the FDK algorithm. Each pixel at detector position (u, v) is multiplied by the angle-independent cosine factor:
\[w(u, v) = \frac{\mathrm{SOD}}{\sqrt{\mathrm{SOD}^2 + u^2 + v^2}}\]The weight map is computed once and broadcast over the angle axis because the geometry is fixed across all views.
- Parameters:
projections (ndarray, shape (n_angles, n_v, n_u)) – Raw cone-beam projections. Axis order: angle first, detector row (v) second, detector column (u) last. Values are typically Beer-Lambert log-normalised line integrals.
geometry (ConeBeamGeometry) – Fully validated acquisition geometry.
geometry.u_coords()andgeometry.v_coords()supply the centred physical detector coordinates used to evaluatew(u, v).
- Returns:
projections_weighted – Cosine-weighted projections, same shape and dtype as projections.
- Return type:
- Raises:
ValueError – If
projections.shape[1:]does not match(geometry.n_v, geometry.n_u).
Notes
The weight approaches 1 on the central beam axis (u = v = 0) and decreases toward the detector periphery, compensating for the longer effective path length of oblique cone rays. This is the exact extension of the
cos(γ)factor in the fan-beam Parker weighting to the 2-D detector case.
toupy.tomo.geometry module¶
Cone-beam acquisition geometry descriptor.
ConeBeamGeometry is a plain dataclass that encodes every metric
parameter of a circular-orbit cone-beam CT setup. It is intentionally
kept free of reconstruction imports so that the registration sub-package
can import it without pulling in NumPy FFT or CuPy.
Typical usage:
from toupy.tomo.geometry import ConeBeamGeometry
import numpy as np
geom = ConeBeamGeometry(
SOD=500.0, SDD=1000.0,
det_pixel_size=0.1,
n_u=1024, n_v=512,
angles=np.linspace(0, 360, 720, endpoint=False),
)
geom.validate()
u = geom.u_coords() # shape (1024,)
v = geom.v_coords() # shape (512,)
- class toupy.tomo.geometry.ConeBeamGeometry(SOD: float, SDD: float, det_pixel_size: float, n_u: int, n_v: int, angles: ndarray = <factory>)[source]¶
Bases:
objectCircular-orbit cone-beam acquisition geometry.
All distances are expected in consistent physical units (e.g. mm or µm). Angles are in degrees.
- Parameters:
SOD (float) – Source-to-object distance (source to rotation axis), in physical length units. Must satisfy
SOD < SDD.SDD (float) – Source-to-detector distance, in the same units as
SOD.det_pixel_size (float) – Physical pitch of one detector pixel (square pixels assumed), in the same units as
SOD/SDD. Must be strictly positive.n_u (int) – Number of detector columns (horizontal / transaxial direction). Must be a positive integer.
n_v (int) – Number of detector rows (vertical / axial direction). Must be a positive integer.
angles (ndarray, shape (n_angles,)) – Projection angles in degrees. Arbitrary spacing is allowed; the FDK weighting step uses them only to iterate over views.
- magnification¶
Geometric magnification
SDD / SOD. A voxel at the rotation axis appears enlarged by this factor on the detector.- Type:
- effective_pixel_size¶
Physical size of one object-space pixel at the rotation axis,
det_pixel_size / magnification. Use this value to set the reconstruction voxel size.- Type:
Examples
>>> import numpy as np >>> from toupy.tomo.geometry import ConeBeamGeometry >>> geom = ConeBeamGeometry( ... SOD=500.0, SDD=1000.0, det_pixel_size=0.055, ... n_u=2048, n_v=2048, ... angles=np.linspace(0, 360, 1800, endpoint=False), ... ) >>> geom.validate() >>> print(geom.magnification) # 2.0 >>> print(geom.effective_pixel_size) # 0.0275
- property effective_pixel_size: float¶
Object-space pixel size at the rotation axis.
Defined as
det_pixel_size / magnification, i.e. the physical extent of one detector pixel back-projected to the object plane. Use this as the reconstruction voxel pitch.- Returns:
Effective voxel pitch in the same units as
det_pixel_size.- Return type:
- property magnification: float¶
Geometric magnification factor
SDD / SOD.- Returns:
The ratio of source-to-detector distance to source-to-object distance. Always > 1 for a valid geometry (
SDD > SOD).- Return type:
- Raises:
ZeroDivisionError – If
SODis zero (caught earlier byvalidate()).
- u_coords() ndarray[source]¶
Centred horizontal (transaxial) detector coordinate array.
Returns a 1-D array of length
n_ucontaining the physical detector-plane u-coordinates of each column centre, measured from the beam axis. The coordinate of columniis:u_i = (i - (n_u - 1) / 2) * det_pixel_size
- Returns:
u – Detector u-coordinates in physical units, centred on zero.
- Return type:
ndarray, shape (n_u,)
- v_coords() ndarray[source]¶
Centred vertical (axial) detector coordinate array.
Analogous to
u_coords()but along the vertical detector axis. The coordinate of rowjis:v_j = (j - (n_v - 1) / 2) * det_pixel_size
- Returns:
v – Detector v-coordinates in physical units, centred on zero.
- Return type:
ndarray, shape (n_v,)
- validate() None[source]¶
Check self-consistency of all geometry fields.
Should be called once after construction, before passing the geometry object to any reconstruction or registration function.
- Raises:
ValueError – With a descriptive message for each invalid condition: *
SOD <= 0— source-to-object distance must be positive. *SDD <= 0— source-to-detector distance must be positive. *SOD >= SDD— the detector must lie beyond the object; equivalently,magnification > 1must hold. *det_pixel_size <= 0— pixel pitch must be positive. *n_u <= 0orn_v <= 0— detector dimensions must be positive integers. *len(angles) == 0— at least one projection angle is required.
toupy.tomo.iradon module¶
Filtered Back-Projection and SART reconstruction.
GPU path : CuPy + a custom CUDA kernel CPU path : pure NumPy/SciPy, identical to the original mod_iradon.
- The public API is unchanged:
compute_angle_weights, compute_filter, mod_iradon, mod_iradon_cuda, backprojector, reconsSART
- toupy.tomo.iradon.backprojector(sinogram, theta, **params)[source]¶
Wrapper that dispatches to the GPU or CPU FBP implementation.
- Parameters:
sinogram (ndarray shape (nbins, nangles))
theta (ndarray)
params (dict) –
params["opencl"]— repurposed asparams["cuda"]: set True to use the CUDA path. The keyopenclis still accepted as an alias for backwards compatibility. All other keys are forwarded to the chosen implementation.
- Returns:
recons
- Return type:
ndarray shape (output_size, output_size)
- toupy.tomo.iradon.compute_angle_weights(theta)[source]¶
Compute per-angle weights for non-equally-spaced angular distributions.
- Parameters:
theta (ndarray) – Angles in degrees.
- Returns:
weights – Weight for each angle, proportional to the angular distance to its neighbours. Forked from odtbrain.util.compute_angle_weights_1d.
- Return type:
ndarray
- toupy.tomo.iradon.compute_filter(nbins, filter_type='ram-lak', derivatives=False, freqcutoff=1)[source]¶
Compute the frequency-domain filter for FBP reconstruction.
- Parameters:
nbins (int) – Number of detector bins (sinogram rows).
filter_type (str, optional) – One of
ram-lak,shepp-logan,cosine,hamming,hann. Default isram-lak.derivatives (bool, optional) – Use a Hilbert filter suited for derivative projections. Default False.
freqcutoff (float, optional) – Normalised frequency cutoff in [0, 1]. Default 1 (no cutoff).
- Returns:
fourier_filter
- Return type:
ndarray shape (projection_size_padded, 1) complex64
- toupy.tomo.iradon.mod_iradon(radon_image, theta=None, output_size=None, filter_type='ram-lak', derivatives=False, interpolation='linear', circle=False, freqcutoff=1)[source]¶
Inverse Radon transform — CPU path (pure NumPy/SciPy).
Reconstruct an image from its Radon transform using filtered back-projection.
- Parameters:
radon_image (ndarray shape (nbins, nangles)) – Sinogram. Each column corresponds to one projection angle.
theta (ndarray, optional) – Projection angles in degrees. Defaults to
nanglesevenly-spaced values in [0, 180).output_size (int, optional) – Side length of the square output image.
filter_type (str, optional) – See
compute_filter().derivatives (bool, optional) – Set True if the sinogram contains projection derivatives.
interpolation (str, optional) –
linear(default),nearest, orcubic.circle (bool, optional) – Zero pixels outside the inscribed circle.
freqcutoff (float, optional) – Normalised frequency cutoff.
- Returns:
reconstructed
- Return type:
ndarray shape (output_size, output_size)
- toupy.tomo.iradon.mod_iradon_cuda(radon_image, theta=None, output_size=None, filter_type='ram-lak', derivatives=False, circle=False, freqcutoff=1)[source]¶
Inverse Radon transform — CUDA/GPU path.
Falls back to
mod_iradon()automatically if CuPy is unavailable.- Parameters:
radon_image (ndarray shape (nbins, nangles)) – Sinogram on CPU. Converted to float32 internally.
theta (ndarray, optional) – Projection angles in degrees.
output_size (int, optional) – Side length of the square output image.
filter_type (str, optional) – See
compute_filter().derivatives (bool, optional) – Set True if the sinogram contains projection derivatives.
circle (bool, optional) – Zero pixels outside the inscribed circle.
freqcutoff (float, optional) – Normalised frequency cutoff.
- Returns:
reconstructed
- Return type:
ndarray shape (output_size, output_size) float32
toupy.tomo.radon module¶
Forward Radon transform (projection).
GPU path : CuPy + the CUDA kernel defined in iradon.py CPU path : skimage.transform.radon (unchanged fallback).
Public API is unchanged: projector()
- toupy.tomo.radon.projector(recons, theta, **params)[source]¶
Wrapper to choose between CUDA and CPU forward Radon transform.
- Parameters:
recons (ndarray shape (N, N)) – Tomographic slice to project.
theta (ndarray) – Projection angles in degrees.
params (dict) –
params["cuda"]— True → use GPU path.params["opencl"]— accepted as alias for backwards compatibility.
- Returns:
sinogram
- Return type:
ndarray shape (N, nangles)
- toupy.tomo.radon.radon_cuda(recons, theta)[source]¶
Forward Radon transform — CUDA/GPU path.
Falls back to
skimage.transform.radonautomatically if CuPy is unavailable.- Parameters:
recons (ndarray shape (N, N)) – The tomographic slice to project. Converted to float32 internally.
theta (ndarray) – Projection angles in degrees.
- Returns:
sinogram – The computed sinogram, in the same layout as skimage’s radon output (each column = one projection).
- Return type:
ndarray shape (N, nangles)
toupy.tomo.tomorecons module¶
- toupy.tomo.tomorecons.fdk_tomo_recons(projections, geometry: ConeBeamGeometry, **params)[source]¶
High-level FDK cone-beam reconstruction wrapper.
Mirrors
tomo_recons()for cone-beam geometry. Validates the geometry, applies optional pre-processing, calls the three-step FDK pipeline, and optionally displays the central reconstructed slice.- Parameters:
projections (ndarray, shape (n_angles, n_v, n_u)) – Flat-field-corrected, Beer-Lambert log-normalised cone-beam projections.
geometry (ConeBeamGeometry) – Validated acquisition geometry.
**params –
Algorithm parameters. Recognised keys:
- filtertypestr
Ramp-filter window (forwarded to
fdk_filter()). Default'ram-lak'.- freqcutofffloat
Normalised frequency cutoff in
(0, 1]. Default1.- output_sizeint or None
Transaxial reconstruction grid side length.
Noneusesgeometry.n_u.- cudabool
Use CuPy GPU path. Default
False.- circlebool
Multiply the reconstructed volume by a cylindrical mask to suppress border artefacts. Default
False.- showreconsbool
Display the central axial slice after reconstruction. Default
False.- colormapstr
Colormap for display. Default
'bone'.- vmin_plotfloat or None
Display window minimum.
- vmax_plotfloat or None
Display window maximum.
- autosavebool
Save the volume to disk without prompting. Default
False.
- Returns:
volume – Reconstructed 3-D volume.
- Return type:
ndarray, shape (n_v, N, N)
- Raises:
ValueError – If
projections.ndim != 3or shape is inconsistent withgeometry.
See also
tomo_reconsParallel-beam (2-D) slice reconstruction wrapper.
full_tomo_reconsSlice-by-slice parallel-beam full reconstruction.
toupy.tomo.fdk.fdk_reconstructBare FDK pipeline (no display/save).
- toupy.tomo.tomorecons.full_tomo_recons(input_stack, theta, **params)[source]¶
Full tomographic reconstruction
- Parameters:
input_stack (ndarray) – A 3-dimensional array containing the stack of projections. The order should be
[projection_num, row, column]theta (ndarray) – A 1-dimensional array of thetas
params (dict) – Dictionary containing additional parameters
params["algorithm"] (str) – Choice of algorithm. Two algorithm implemented: “FBP” and “SART”
params["slicenum"] (int) – Slice number
params["filtertype"] (str) – Filter to use for FBP
params["freqcutoff"] (float) – Frequency cutoff (between 0 and 1)
params["circle"] (bool) – Multiply the reconstructed slice by a circle to remove borders
params["derivatives"] (bool) – If the projections are derivatives. Only for FBP.
params["calc_derivatives"] (bool) – Calculate derivatives of the sinogram if not done yet.
params["opencl"] (bool) – Implement the tomographic reconstruction in CUDA
params["autosave"] (bool) – Save the data at the end without asking
params["vmin_plot"] (float) – Minimum value for the gray level at each display
params["vmax_plot"] (float) – Maximum value for the gray level at each display
params["colormap"] (str) – Colormap
params["showrecons"] (bool) – If to show the reconstructed slices
- Returns:
tomogram – A 3-dimensional array containing the full reconstructed tomogram.
- Return type:
ndarray
- toupy.tomo.tomorecons.tomo_recons(sinogram, theta, **params)[source]¶
Wrapper to select tomographic algorithm
- sinogramndarray
A 2-dimensional array containing the sinogram
- thetandarray
A 1-dimensional array of thetas
- paramsdict
Dictionary containing additional parameters
- params[“algorithm”]str
Choice of algorithm. Two algorithm implemented: “FBP” and “SART”
- params[“slicenum”]int
Slice number
- params[“filtertype”]str
Name of the filter to be applied in frequency domain filtering. The options are: ram-lak, shepp-logan, cosine, hamming, hann. Assign None to use no filter.
- params[“freqcutoff”]float
Frequency cutoff (between 0 and 1)
- params[“circle”]bool
Multiply the reconstructed slice by a circle to remove borders
- params[“weight_angles”]bool
If True, weights each projection with a factor proportional to the angular distance between the neighboring projections.
\[\Delta \phi_0 \longmapsto \Delta \phi_j =\]
rac{phi_{j+1} - phi_{j-1}}{2}
- params[“derivatives”]bool
If the projections are derivatives. Only for FBP.
- params[“calc_derivatives”]bool
Calculate derivatives of the sinogram if not done yet.
- params[“opencl”]bool
Implement the tomographic reconstruction in opencl as implemented in Silx
- params[“autosave”]bool
Save the data at the end without asking
- params[“vmin_plot”]float
Minimum value for the gray level at each display
- params[“vmax_plot”]float
Maximum value for the gray level at each display
- params[“colormap”]str
Colormap
- params[“showrecons”]bool
If to show the reconstructed slices
- reconsndarray
A 2-dimensional array containing the reconstructed slice.
toupy.tomo.tv_recons module¶
Total-Variation (TV) regularised tomographic reconstruction.
Implements the Chambolle-Pock primal-dual algorithm (CP) to solve:
min_{x >= 0} (1/2) ||A x - b||^2 + lambda * TV(x)
where A is the Radon forward operator, b is the (possibly noisy) sinogram, and TV is the isotropic discrete total-variation.
The algorithm is an exact first-order method and handles the non-smooth TV term via proximal splitting. It is well-suited to ptychographic tomography, where the phase sinogram is noisy or has limited angular sampling.
- Reference:
Chambolle, A., & Pock, T. (2011). A first-order primal-dual algorithm for convex problems with applications to imaging. Journal of Mathematical Imaging and Vision, 40(1), 120–145. https://doi.org/10.1007/s10107-010-0436-y
Sidky, E. Y., & Pan, X. (2008). Image reconstruction in circular cone-beam computed tomography by constrained, total-variation minimization. Physics in Medicine & Biology, 53(17), 4777. https://doi.org/10.1088/0031-9155/53/17/014
GPU notes¶
Both public functions accept cuda=True. In GPU mode all primal and
dual variables reside on the device as CuPy float32 arrays throughout
the iteration; only the final reconstruction is transferred back to the
host. The Radon forward and backward operators reuse the CUDA kernels
compiled in toupy.tomo.iradon; no additional compilation is
required.
The step-size estimate is also computed entirely on the GPU via a five-step power iteration, so the first call is slightly slower than subsequent calls (kernel reuse).
- toupy.tomo.tv_recons.chambolle_pock_tv(sinogram, theta, lam=0.01, n_iter=100, output_size=None, cuda=False, verbose=False)[source]¶
Chambolle-Pock TV-regularised reconstruction.
Solves the primal-dual saddle-point problem:
\[\min_{x \ge 0}\; \max_{p,q}\; \langle K x,\, (p, q) \rangle - G^*(p, q) + F(x)\]where \(K = (A,\, \nabla)\) stacks the Radon operator and the gradient, \(G^*\) is the convex conjugate of the data and TV terms, and \(F\) is the non-negativity indicator.
- Parameters:
sinogram (ndarray, shape (n_pixels, n_angles)) – Measured sinogram with axes (detector pixel, angle).
theta (array_like, shape (n_angles,)) – Projection angles [degrees].
lam (float, optional) – TV regularisation weight. Default 1e-2.
n_iter (int, optional) – Number of Chambolle-Pock iterations. Default 100.
output_size (int or None, optional) – Side length of the square reconstruction grid. When
Nonethe value is inferred from the sinogram asround(n_pixels / sqrt(2)), matchingskimage.transform.radonwithcircle=False.cuda (bool, optional) – Run on GPU via CuPy. All primal/dual variables reside on the device throughout the iteration; only the final image is transferred back. Falls back to CPU with a warning when CuPy is unavailable. Default False.
verbose (bool, optional) – Print cost every 10 iterations. Default False.
- Returns:
x – Reconstructed image. Always returned as a CPU numpy array.
- Return type:
ndarray, shape (output_size, output_size)
See also
tv_reconstructionHigh-level wrapper with FBP warm-start.
- toupy.tomo.tv_recons.tv_reconstruction(sinogram, theta, lam=0.01, n_iter=100, output_size=None, init='fbp', cuda=False, verbose=False)[source]¶
TV-regularised tomographic reconstruction.
High-level wrapper around
chambolle_pock_tv()with an optional FBP warm-start and the same sinogram-axis convention used throughout toupy (detector pixels along axis 0).- Parameters:
sinogram (ndarray, shape (n_pixels, n_angles)) – Sinogram — same axis convention as
mod_iradon().theta (array_like, shape (n_angles,)) – Projection angles in degrees.
lam (float, optional) – TV regularisation weight. Default 1e-2.
n_iter (int, optional) – Number of Chambolle-Pock iterations. Default 100.
output_size (int or None, optional) – Side length of the square reconstruction grid.
Noneinfers from the sinogram (matchesskimage.transform.radon).init ({'fbp', 'zeros'}, optional) – Initialisation strategy.
'fbp'uses a Ram-Lak FBP as the starting point (recommended; faster convergence).'zeros'starts from the zero image. Default'fbp'.cuda (bool, optional) – Run on GPU via CuPy. Default False.
verbose (bool, optional) – Print cost every 10 iterations. Default False.
- Returns:
recons – Reconstructed image.
- Return type:
ndarray, shape (n, n)
Notes
The TV weight lam should be tuned to the noise level. A cross-validation or L-curve approach is recommended for quantitative work.
Examples
>>> import numpy as np >>> from skimage.transform import radon >>> from toupy.simulation import phantom >>> from toupy.tomo import tv_reconstruction >>> img = phantom(256) >>> theta = np.linspace(0, 180, 180, endpoint=False) >>> sino = radon(img, theta=theta, circle=False) >>> recons = tv_reconstruction(sino, theta, lam=0.01, n_iter=50)