tomojax.geometry.api
Expert geometry helpers: axis order, calibration state and detector grids.
The geometry classes and field-of-view helpers users call are exported by
tomojax.geometry; this module holds what alignment, IO and the solvers
build on.
| Name | Summary |
|---|---|
DISK_VOLUME_AXES | |
INTERNAL_VOLUME_AXES | |
VOLUME_AXES_ATTR | |
CalibrationState | Grouped calibration state for instrument, scan, and residual geometry. |
CalibrationVariable | One calibration variable with explicit frame, status, unit, and gauge metadata. |
GeometryState | Scanner setup, per-view pose and acquisition model together. |
axes_to_perm | Return permutation bringing src axis order into dst order. |
axis_pose_stack | Build a traced-safe stack of world-from-object poses for an axis direction. |
axis_unit_from_rotations | Apply x/y calibration rotations to a nominal lab-frame axis. |
build_calibrated_geometry_metadata_patch | Build detector and geometry metadata updates from a calibration state. |
detector_grid_from_calibration | Build a detector grid from centre offsets and detector-plane roll. |
detector_grid_from_geometry_inputs | Return a replay detector grid when saved metadata contains a detector roll. |
infer_disk_axes | Infer on-disk axis order using grid heuristics. |
is_cone_beam | Whether a geometry traces diverging rays. |
nominal_axis_unit_from_inputs | Resolve the nominal lab-frame rotation axis from persisted geometry metadata. |
transpose_volume | Transpose a volume from src axis order to dst order. |
validate_calibration_gauges | Validate hard gauge conflicts for estimated calibration variables. |
view_frames | Return source, detector centre and pixel steps for each cone-beam view. |
DISK_VOLUME_AXES
DISK_VOLUME_AXES = 'zyx'INTERNAL_VOLUME_AXES
INTERNAL_VOLUME_AXES = 'xyz'VOLUME_AXES_ATTR
VOLUME_AXES_ATTR = 'volume_axes_order'CalibrationState
class CalibrationState(
detector: tuple[CalibrationVariable, ...] = tuple(),
scan: tuple[CalibrationVariable, ...] = tuple(),
object_residual: tuple[CalibrationVariable, ...] = tuple(),
world_residual: tuple[CalibrationVariable, ...] = tuple(),
detector_plane_residual: tuple[CalibrationVariable, ...] = tuple(),
angle_residual: tuple[CalibrationVariable, ...] = tuple(),
)Grouped calibration state for instrument, scan, and residual geometry.
Parameters
detector(tuple of CalibrationVariable, optional): Instrument detector calibration.scan(tuple of CalibrationVariable, optional): Scan-level acquisition calibration.object_residual(tuple of CalibrationVariable, optional): Object-frame residual corrections.world_residual(tuple of CalibrationVariable, optional): World-frame residual corrections.detector_plane_residual(tuple of CalibrationVariable, optional): Detector-plane residual corrections.angle_residual(tuple of CalibrationVariable, optional): Angular residual corrections.
Raises
- ValueError: If variable names are not unique across sections.
CalibrationState.variables
variables() -> tuple[CalibrationVariable, ...]Return all calibration variables in stable section order.
Returns
- tuple of CalibrationVariable: Variables in detector, scan, object, world, detector-plane and angle section order.
CalibrationState.variables_by_name
variables_by_name() -> dict[str, CalibrationVariable]Return calibration variables keyed by name.
Returns
- dict: Variables keyed by their unique names.
CalibrationState.estimated_names
estimated_names() -> set[str]Return names of variables marked as estimated.
Returns
- set of str: Names whose status is estimated.
CalibrationState.to_dict
to_dict() -> dict[str, JsonValue]Return this state as JSON-compatible metadata.
Returns
- dict: JSON-compatible calibration metadata.
CalibrationState.from_dict
@classmethod
from_dict(payload: Mapping[str, object]) -> CalibrationStateBuild grouped calibration state from JSON-like metadata.
Parameters
payload(mapping): JSON-like calibration metadata.
Returns
- CalibrationState: Calibration record described by the metadata.
Raises
- ValueError: If a variable status, frame or name constraint is invalid.
- KeyError: If required variable fields are missing.
- TypeError: If a section is not a list of variables.
CalibrationVariable
class CalibrationVariable(
name: str,
value: JsonValue,
unit: str,
status: VariableStatus,
frame: CalibrationFrame,
gauge: str | None = None,
uncertainty: JsonValue | None = None,
description: str | None = None,
)One calibration variable with explicit frame, status, unit, and gauge metadata.
Parameters
name(str): Unique calibration variable name.value(JSON-compatible value): Scalar, vector or structured value of the variable.unit(str): Physical or dimensionless unit label.status({'estimated', 'supplied', 'frozen', 'derived'}): How the variable was obtained or constrained.frame(str): Coordinate frame: detector, scan, object, world, detector_plane, angle or metadata.gauge(str or None, optional): Gauge convention identifying an otherwise coupled degree of freedom.uncertainty(JSON-compatible value or None, optional): Uncertainty or diagnostic information.description(str or None, optional): Human-readable explanation of the variable.
Raises
- ValueError: If status or frame is not recognized.
CalibrationVariable.to_dict
to_dict() -> dict[str, JsonValue]Return this variable as JSON-compatible metadata.
Returns
- dict: JSON-compatible calibration metadata.
CalibrationVariable.from_dict
@classmethod
from_dict(payload: Mapping[str, object]) -> CalibrationVariableBuild a calibration variable from JSON-like metadata.
Parameters
payload(mapping): JSON-like calibration metadata.
Returns
- CalibrationVariable: Calibration record described by the metadata.
Raises
- ValueError: If a variable status, frame or name constraint is invalid.
- KeyError: If required variable fields are missing.
GeometryState
class GeometryState(
setup: SetupParameters,
pose: PoseParameters,
acquisition: AcquisitionParameters = AcquisitionParameters.parallel(),
)Scanner setup, per-view pose and acquisition model together.
Parameters
setup(SetupParameters): Global scanner calibration parameters.pose(PoseParameters): Per-view nominal angles and corrections.acquisition(AcquisitionParameters, optional): Acquisition model; defaults to axial parallel beams.
GeometryState.zeros
@classmethod
zeros(n_views: int) -> GeometryStateConstruct an uncorrected geometry state.
Parameters
n_views(int): Number of views.
Returns
- GeometryState: Default setup and parallel acquisition with zero pose vectors.
Examples
from tomojax.geometry.api import GeometryState
state = GeometryState.zeros(3)
state.theta_total_rad().tolist()
# [0.0, 0.0, 0.0]GeometryState.theta_total_rad
theta_total_rad() -> NDArray[np.float64]Return the complete rotation angle of each view.
Returns
- numpy.ndarray: Scaled nominal angles plus global offset and per-view residual, in radians.
axes_to_perm
axes_to_perm(src: str, dst: str) -> tuple[int, int, int]Return permutation bringing src axis order into dst order.
Parameters
src,dst(str): Source and destination permutations of xyz, case-insensitive.
Returns
- tuple of int: Axis permutation for numpy.transpose or jax.numpy.transpose.
Raises
- ValueError: If an axis order is not a permutation of xyz.
axis_pose_stack
axis_pose_stack(angles: object, axis_unit_lab: object) -> jnp.ndarrayBuild a traced-safe stack of world-from-object poses for an axis direction.
Cache the compiled pose map so eager alignment calls do not repeatedly trace the nested axis-alignment conditionals or dispatch its small ops.
Parameters
angles(array-like): One-dimensional view angles in degrees.axis_unit_lab(array-like): Three-component lab-frame rotation axis.
Returns
- jax.Array: Float32 world-from-object transforms, shape (views, 4, 4).
axis_unit_from_rotations
axis_unit_from_rotations(
nominal_axis_unit: object,
*,
axis_rot_x_deg: object,
axis_rot_y_deg: object,
) -> jnp.ndarrayApply x/y calibration rotations to a nominal lab-frame axis.
Parameters
nominal_axis_unit(array-like): Three-component nominal lab-frame unit axis.axis_rot_x_deg,axis_rot_y_deg(array-like): Scalar x and y calibration rotations in degrees, applied in that order.
Returns
- jax.Array: Calibrated lab-frame unit axis, in float32.
build_calibrated_geometry_metadata_patch
build_calibrated_geometry_metadata_patch(
*,
calibration_state: CalibrationState | Mapping[str, object],
detector: Mapping[str, object],
geometry_meta: Mapping[str, object] | None = None,
) -> CalibratedGeometryMetadataPatchBuild detector and geometry metadata updates from a calibration state.
Parameters
calibration_state(CalibrationState or mapping): Grouped calibration values or their serialized representation.detector(mapping): Original detector metadata with nu, nv, du and dv.geometry_meta(mapping or None, optional): Original geometry metadata to preserve and update.
Returns
- CalibratedGeometryMetadataPatch: Detector offsets converted from pixels to physical lengths, with calibration provenance.
Raises
- ValueError: If required detector metadata or calibration values are invalid.
- TypeError: If detector dimensions or calibration offsets are not numeric.
detector_grid_from_calibration
detector_grid_from_calibration(
detector: Detector,
*,
det_u_px: object = 0.0,
det_v_px: object = 0.0,
detector_roll_deg: object = 0.0,
native_du: float | None = None,
native_dv: float | None = None,
) -> tuple[jnp.ndarray, jnp.ndarray]Build a detector grid from centre offsets and detector-plane roll.
Parameters
detector(Detector): Detector dimensions and sampling; its centre is replaced by calibration offsets.det_u_px,det_v_px(array-like, optional): Scalar detector-centre offsets in native pixels, after rotation.detector_roll_deg(array-like, optional): Scalar detector-plane roll in degrees.native_du,native_dv(float or None, optional): Native pixel pitches converting offsets to physical lengths; default to detector pitches.
Returns
- tuple of jax.Array: Flattened detector-plane u and v coordinates in physical units, each shape (nv * nu,), with detector-u varying fastest.
detector_grid_from_geometry_inputs
detector_grid_from_geometry_inputs(
detector: Detector,
geometry_inputs: object,
) -> tuple[jnp.ndarray, jnp.ndarray] | NoneReturn a replay detector grid when saved metadata contains a detector roll.
A zero roll returns None: the canonical grid is identical, and solvers use their fast batched operators only without an explicit grid.
Parameters
detector(Detector): Detector geometry with physical centre offsets.geometry_inputs(mapping or object): Metadata with optional detector_roll_deg.
Returns
- tuple of jax.Array or None: Rolled detector grids, or None when roll is absent or zero.
infer_disk_axes
infer_disk_axes(vol_shape: Sequence[int], grid: GridLike | None) -> str | NoneInfer on-disk axis order using grid heuristics.
Returns "xyz", "zyx", or None if ambiguous.
Parameters
vol_shape(sequence of int): On-disk volume dimensions.grid(Grid, dict or None): Grid dimensions used to distinguish xyz from zyx.
Returns
- str or None: Inferred xyz or zyx order; None when missing, inconsistent or ambiguous.
is_cone_beam
is_cone_beam(geometry: object) -> boolWhether a geometry traces diverging rays.
Parameters
geometry(object): Any geometry, including posed or segmented cone-beam geometries.
Returns
- bool: True for a cone beam or cone segments, False for parallel rays.
nominal_axis_unit_from_inputs
nominal_axis_unit_from_inputs(geometry_inputs: Mapping[str, object]) -> np.ndarrayResolve the nominal lab-frame rotation axis from persisted geometry metadata.
Parameters
geometry_inputs(mapping): Persisted axis vector or geometry type and laminography tilt.
Returns
- numpy.ndarray: Normalized three-component lab-frame axis.
Raises
- ValueError: If the axis is not finite and nonzero, or the tilt convention is invalid.
transpose_volume
transpose_volume(volume: object, src: str, dst: str) -> objectTranspose a volume from src axis order to dst order.
Keeps numpy arrays as numpy and JAX arrays as JAX when possible.
Parameters
volume(array-like): Three-dimensional volume to transpose.src,dst(str): Source and destination permutations of xyz, case-insensitive.
Returns
- numpy.ndarray or jax.Array: Volume in the requested order, preserving NumPy/JAX storage where possible.
Raises
- ValueError: If axis orders or volume dimensions are invalid.
validate_calibration_gauges
validate_calibration_gauges(
variables: CalibrationState | Iterable[CalibrationVariable] | Mapping[str, object],
*,
hard_fail: bool = True,
) -> tuple[GaugeConflict, ...]Validate hard gauge conflicts for estimated calibration variables.
Parameters
variables(CalibrationState, iterable of CalibrationVariable or mapping): Calibration variables or a mapping of names to statuses.hard_fail(bool, optional): Raise on coupled estimated variables; False returns conflicts instead.
Returns
- tuple of GaugeConflict: Conflicting estimated variable pairs, empty when gauges are determined.
Raises
- ValueError: If gauge conflicts exist and hard_fail is True.
view_frames
view_frames(geometry: ScanGeometry) -> np.ndarrayReturn source, detector centre and pixel steps for each cone-beam view.
Rows are [source, centre, u * du, v * dv] (ASTRA's cone_vec order):
pixel (row r, column c) of view i lies at ``centre + (c - nu / 2 + 1/2) u
- (r - nv / 2 + 1/2) v``. Every segment of a
ConeSegments, in order, with the corrections of any pose wrapper around it.
Parameters
geometry(ScanGeometry): Cone-beam geometry, including segments and pose wrappers.
Returns
- numpy.ndarray: Object-frame source, detector centre and pixel vectors, shape (views, 12).
Raises
- ValueError: If geometry is not cone-beam.