Reconstruct a real parallel or laminography scan
Measured geometry for parallel and laminography scans, including TIFF stacks.
Start with measured geometry and corrected absorption projections. This guide assumes an installed checkout and uses example dimensions and spacings that must be replaced with your acquisition values. TomoJAX models parallel rays, including tilted-axis laminography; for lab cone-beam CT, see lab cone-beam CT.
Check an existing NeXus dataset
uv run --no-sync tomojax inspect scan.nxsThe report ends with Valid: yes, or lists the issues that would stop a
reconstruction. Confirm the number and order of views, angles in degrees, detector dimensions
and pitch, volume grid and pitch, and the geometry type. For laminography, check
tilt_deg and tilt_about in geometry metadata. tilt_deg is a departure from
the nominal tomography axis, not an angle to the beam. Missing laminography
tilt requires an explicit geometry= with the measured tilt or axis; no 30°
default is inserted.
For raw NXtomo or Data Exchange frames with flats and darks, follow
preprocessing. Nonstandard HDF5
layouts can name their datasets with --data-path, --angles-path and
--image-key-path (or data_path=... in tj.load_frames). Structural
validation does not establish correct physical geometry.
Prepare TIFF data
A TIFF directory is read in natural filename order (view2 before view10);
frames within each file keep their stored order. The angle sidecar must match
that order. It can be a one-dimensional .npy array or text/CSV with degrees in
the first column. Leading headers, blank lines, and # comments are allowed.
After numeric rows begin, malformed rows are errors; empty or nonfinite angles
are rejected. Angles are not sorted automatically.
Already-corrected absorption projections
For a parallel scan, package an attenuation stack with explicit geometry:
uv run --no-sync tomojax import ./projections --angles angles.csv \
--pixel-size 0.65 --geometry parallel --config calibration.toml -o corrected.nxscalibration.toml must contain detector_center = [u, v], in physical
length units. import does not apply flat/dark correction or a logarithm.
It records the supplied detector and no grid. The grid is chosen at reconstruction, with
voxels of the detector pitch by default. tomojax recon --grid 256 256 128
resamples the selected field of view to 256 × 256 × 128 voxels; their spacing
changes to preserve that physical extent. tomojax align --mode cor estimates a
centre-of-rotation offset. Detector and voxel pitch share a physical length
unit; Python's Detector.center also uses physical lengths, so an offset
of 2 pixels at pitch 0.65 is a center of 1.3.
Raw intensities with flat and dark frames
tj.load_frames reads TIFF frames with their flats, darks and a measured
geometry. Save the following as a script and adapt the paths and acquisition
values:
import tomojax as tj
from tomojax.io.api import load_angles
angles = load_angles("angles.csv")
geometry = tj.LaminographyGeometry(
tj.Grid(nx=256, ny=256, nz=128, vx=0.65, vy=0.65, vz=0.65),
tj.Detector(nu=256, nv=128, du=0.65, dv=0.65),
angles,
tilt_deg=30.0,
tilt_about="x",
)
frames = tj.load_frames("projections", flats="flats", darks="darks", geometry=geometry)
scan = frames.corrected()
tj.save("corrected.nxs", scan)
print(scan)This writes line integrals, recording the correction. Use
tj.ParallelGeometry(grid, detector, angles) for ordinary parallel
tomography. Do not pass already-log-transformed data into this raw-intensity
path.
For already-corrected laminography projections, the command-line import reads the measured tilt and centre from TOML. For example (replace all calibration values with those of the acquisition):
# calibration.toml
geometry = "lamino"
pixel_size = [0.65]
detector_center = [0.0, 0.0]
tilt_deg = 30.0
tilt_about = "x"uv run --no-sync tomojax import ./corrected-projections --angles angles.csv \
--config calibration.toml -o corrected-lamino.nxsUse the Python raw-intensity workflow above when the frames still need flat/dark correction. Missing tilt or centre is an error, not a default calibration.
Replace 30° with the measured tilt. To check that it was kept, run
uv run --no-sync python -c "import tomojax as tj; print(tj.load('corrected-lamino.nxs').geometry.tilt_deg)",
which prints the tilt in degrees.
For an already-corrected dataset that needs explicit laminography metadata:
from tomojax.io import load_dataset, save_dataset
scan = load_dataset("corrected.nxs")
scan.geometry_type = "lamino"
scan.geometry_metadata.update(tilt_deg=30.0, tilt_about="x")
save_dataset("corrected-lamino.nxs", scan)Again replace 30° with the measured tilt, keep the original dataset, and check
the new file with tomojax inspect before reconstructing it.
Reconstruct with the recorded geometry
For tilted or irregular-angle data, try an iterative reconstruction:
uv run --no-sync tomojax recon corrected.nxs -o recon.nxs \
--method fista --iterations 50 --tv-weight 0.005 --nonnegative --roi off \
--manifest recon-manifest.json
uv run --no-sync tomojax inspect recon.nxs --preview previewsUse corrected-lamino.nxs as input if you created that file above. previews/
holds PNGs of the central projection and the volume's central slices
(slice_z.png, slice_y.png, slice_x.png). The iteration budget and TV
weight are illustrative. Inspect residuals and image features,
and assess sensitivity to regularisation before quantitative use. Positivity
is appropriate only when the object model permits nonnegative attenuation.
Laminography leaves a cone of frequencies around the rotation axis unmeasured.
FBP reconstructs every measured frequency exactly and leaves the cone empty, which
elongates features along the axis. Iterative reconstruction can fill part of the
cone only from the volume bounds or the object prior.
Reconstruct scans larger than GPU memory
FBP streams projections from host memory and automatically reconstructs in host slabs when the volume would exceed the device-memory budget. See large scans and several GPUs for which solvers stream and how to share a scan among GPUs.
Evaluate alignment after reconstruction
If a geometry-checked, corrected scan still shows motion artefacts, follow the alignment guide. Save an unaligned reconstruction for comparison. Check residuals, multiple slice planes, and recovered parameters; image sharpness alone cannot establish physical calibration. Recovery remains data-dependent, especially for truncated or periodic objects; a lower training residual alone does not establish correct alignment.
Automatic NeXus laminography
Recognised Diamond/GDA NeXus layouts need no dataset paths. The laminography example uses the same default workflow as Python and the CLI:
scan = tj.load_frames("scan.nxs").corrected()
result = tj.align(scan)
print(result.info["automatic"])
tj.save("aligned.nxs", result)tomojax align scan.nxs -o aligned.nxsMissing axis metadata triggers a data-driven signed-axis search, not an assumed
tilt. Automatic unposed laminography uses a bounded working detector, excludes
internal validation views from candidate setup and motion fitting, and selects a region
before reconstructing all input views. Resolved regions compare the motion seed
with joint refinement; broad regions compare it with zero motion. A candidate
must improve both ordinary and high-pass held projection error to be retained.
The selected image and poses then initialize joint refinement on all native
detector samples at the input voxel pitch, retaining the selected physical support.
The image itself must still fit the device; a broad unresolved support can exceed capacity.
Pass an explicit grid= to tj.align or tj.reconstruct to choose the physical
region and final sampling while retaining automatic setup and motion. The outcome
labels this region as supplied, not inferred physical support.
Inspect the saved automatic outcome: an unresolved support or unsupported setup
is reported as limited, with reasons. Held consistency does not establish
physical pose or support truth. An unknown-axis estimate at a finite search
boundary, or providing less than one working pixel of depth parallax across the
detector field, is declined rather than used to infer a reconstruction region.
Independent evaluation must reserve additional
views before calling the workflow. Explicit mode and reconstruction method
retain direct control; automatic reconstruction of a posed scan does not reset
its corrections.