tomojax.alignment.api
Public alignment configuration, execution, schedules and geometry helpers.
| Name | Summary |
|---|---|
align | Run single-resolution alignment, returning its least-motion estimate. |
MODES | |
AlignConfig | Configure reconstruction, pose updates and alignment schedules. |
AlignInfo | Diagnostics from a single-resolution alignment solve. |
AlignMultiresInfo | Diagnostics from a multiresolution alignment solve. |
AlignMultiresResumeState | Saved multiresolution alignment progress. |
AlignResumeState | Saved single-resolution alignment progress. |
AlignmentLossSpec | |
AlignmentMode | |
AlignmentPlan | What an alignment run executes: its configuration and resolution levels. |
AlignmentSchedule | Unresolved alignment schedule declaration. |
AlignmentStage | One declared stage in an alignment schedule. |
CenterEstimate | Centre geometry and the opposing-view evidence behind it. |
CenterPair | Opposing-view constraint, in native detector pixels. |
HuberLossSpec | Convex robust projection loss for fixed-volume Gauss-Newton alignment. |
L2LossSpec | Plain squared-error projection loss. |
L2OtsuLossSpec | Squared-error loss weighted by a soft Otsu foreground mask. |
OuterStat | |
PoseTranslationFrame | |
ProjectionMatchingConfig | Joint translation alignment of axial parallel-beam scans. |
QualityTier | |
align_multires | Run multiresolution alignment. |
alignment_plan | Return the configuration and levels that run mode at quality. |
apply_pose_updates | Apply the same explicit translation convention to a stack of views. |
coupled_pose_config | Return the recommended configuration for per-view pose alignment. |
estimate_center | Estimate an axial parallel detector's effective u-centre placement. |
estimate_center_report | Estimate an axial parallel centre and retain pair and row diagnostics. |
implied_detector_offset | Return the detector-u centre offset implied by recovered poses, and the fit residual. |
least_motion_estimate | Move an alignment result (volume and poses) to its least-motion estimate. |
match_projections | Estimate translations from native projection texture. |
orbit_heights | Each orbit's height above the first, from the data's consistency alone. |
save_alignment_params_csv | Write a CSV sidecar, adding an explicit frame column for detector poses. |
save_alignment_params_json | Write per-view alignment parameters as a named JSON sidecar. |
se3_from_pose_params | Build a 4x4 transform from [alpha, beta, phi, dx, dz] or with dy appended. |
align
align(
geometry: Geometry,
grid: Grid,
detector: Detector,
projections: jnp.ndarray,
*,
config: AlignConfig | None = None,
init_x: jnp.ndarray | None = None,
init_pose_params: jnp.ndarray | None = None,
observer: ObserverCallback | None = None,
resume_state: AlignResumeState | None = None,
checkpoint_callback: AlignCheckpointCallback | None = None,
det_grid_override: tuple[jnp.ndarray, jnp.ndarray] | None = None,
) -> tuple[jnp.ndarray, jnp.ndarray, AlignInfo]Run single-resolution alignment, returning its least-motion estimate.
See align_multires; init_x only starts the volume estimate.
Parameters
geometry(Geometry): Nominal scan geometry with view angles and any existing per-view poses.grid(Grid): Reconstruction grid with physical voxel spacing in(x, y, z)order.detector(Detector): Detector shape and placement in the same length unit as the grid.projections(array-like): Measured line integrals with shape(views, nv, nu).config(AlignConfig or None, optional): Expert solver settings. None uses AlignConfig defaults.init_x(array-like or None, optional): Initial volume of shape(nx, ny, nz). None initializes reconstruction.init_pose_params(array-like or None, optional): Initial pose corrections in radians and physical length units, with columns(alpha, beta, phi, dx, dz[, dy]). None starts from zero.observer(callable or None, optional): Receives(volume, pose_params, outer_stat)after outer iterations. Returns "continue", "advance_level", "stop_run" or None to continue.resume_state(AlignResumeState or None, optional): Previously saved progress; None starts a new solve.checkpoint_callback(callable or None, optional): Receives a AlignResumeState to persist after outer iterations.det_grid_override(tuple of array-like or None, optional): Explicit detector coordinates(u, v)of shape(nv, nu). None uses the geometry's detector grid.
Returns
volume(jax.Array): Reconstructed volume in(x, y, z)order, in the returned motion gauge.pose_params(jax.Array): Per-view corrections with columns(alpha, beta, phi, dx, dz, dy). Angles are radians, translations physical lengths in the configured frame.info(AlignInfo): Loss history, work, stopping, geometry and gauge diagnostics.
Raises
- ValueError: If shapes, solver settings or requested degrees of freedom are incompatible.
AlignInfo
class AlignInfo()Diagnostics from a single-resolution alignment solve.
Attributes
loss(list[float]): Objective values recorded in execution order.loss_kind(str): Name of the active projection-domain loss.reconstruction(str): Inner reconstruction method.lipschitz(float | None): Most recent data-gradient Lipschitz estimate, or None.outer_stats(list[OuterStat]): Per-outer-iteration diagnostic dictionaries.stopped_by_observer(bool): Whether an observer stopped the solve.observer_action(ObserverAction): Last normalized observer action.wall_time_total(float): Total elapsed solver time in seconds.quality(str): Alignment quality policy.profile_policy(MetadataDict): Effective reconstruction/projector policy and its provenance.pose_model(str): Per-view, polynomial or spline motion model.pose_translation_frame(str): Object or detector frame for physical translations.pose_model_variables(int): Number of variables in the chosen motion model.per_view_variables(int): Number of variables in an independent per-view model.pose_model_basis_shape(list[int]): Shape of the motion-model basis.active_dofs(list[str]): All active parameter names.active_pose_dofs(list[str]): Active per-view pose parameter names.active_geometry_dofs(list[str]): Active setup-geometry parameter names.objective_kind(str): Main objective model used by the run.objective_kinds(list[str]): Objective models used across the executed stages.objective_provenance(MetadataDict | None): Objective implementation provenance, when available.backend_provenance(MetadataDict | None): Backend implementation provenance, when available.optimizer_kind(str): Pose optimizer used.completed_outer_iterations(int): Number of completed outer iterations.small_impr_streak(int): Successive outer iterations with small improvement.motion_coeffs(jax.Array | None): Motion-model coefficients, or None for independent per-view motion.gauge_fix(str): Gauge-fixing rule applied to the result.gauge_fix_dofs(list[str]): Parameter names affected by gauge fixing.gauge_fix_final(GaugeFixSummary): Final gauge-fixing diagnostic record.gauge(NotRequired[MetadataDict]): Common rigid motion removed from the returned volume/pose pair.
AlignMultiresInfo
class AlignMultiresInfo()Diagnostics from a multiresolution alignment solve.
Attributes
loss(list[float]): Objective values recorded in execution order.factors(list[int]): Resolution factors actually executed.factors_skipped(list[int]): Finer resolution factors skipped for device-memory capacity.factors_skipped_reason(str | None): Reason finer levels were skipped, or None.loss_kind(str | None): Name of the active projection-domain loss.reconstruction(str): Inner reconstruction method.outer_stats(list[OuterStat]): Per-outer-iteration diagnostic dictionaries.stopped_by_observer(bool): Whether an observer stopped the solve.observer_action(ObserverAction): Last normalized observer action.total_outer_iterations(int): Total completed outer iterations across levels.wall_time_total(float): Total elapsed solver time in seconds.quality(str): Alignment quality policy.profile_policy(MetadataDict): Effective reconstruction/projector policy and its provenance.pose_model(str): Per-view, polynomial or spline motion model.pose_translation_frame(str): Object or detector frame for physical translations.pose_model_variables(int | None): Number of variables in the chosen motion model.per_view_variables(int | None): Number of variables in an independent per-view model.pose_model_basis_shape(list[int] | None): Shape of the motion-model basis.active_dofs(list[str]): All active parameter names.active_pose_dofs(list[str]): Active per-view pose parameter names.active_geometry_dofs(list[str]): Active setup-geometry parameter names.schedule(MetadataDict): Resolved schedule metadata.schedule_name(str): Resolved schedule name.schedule_stages(list[MetadataDict]): Resolved stage descriptions in execution order.gauge_policy(str): Requested policy for parameter gauge couplings.gauge_decision(MetadataDict): Validated decision on gauge couplings.objective_kind(str | None): Main objective model used by the run.objective_kinds(list[str]): Objective models used across the executed stages.objective_provenance(MetadataDict | None): Objective implementation provenance, when available.backend_provenance(MetadataDict | None): Backend implementation provenance, when available.gauge_fix(str): Gauge-fixing rule applied to the result.gauge_fix_dofs(list[str]): Parameter names affected by gauge fixing.gauge_fix_final(GaugeFixSummary | None): Final gauge-fixing diagnostic record.geometry_dofs(list[str]): Setup-geometry parameter names reported by the run.geometry_calibration_state(MetadataDict | None): Final persisted setup-geometry state, when present.geometry_calibration_diagnostics(MetadataDict | None): Diagnostics supporting the setup-geometry estimate.gauge(MetadataDict | None): Common rigid motion removed from the returned volume/pose pair.
AlignMultiresResumeState
class AlignMultiresResumeState(
x: jnp.ndarray,
pose_params: jnp.ndarray,
motion_coeffs: jnp.ndarray | None = None,
level_index: int = 0,
level_factor: int = 1,
completed_outer_iterations_in_level: int = 0,
global_outer_iterations_completed: int = 0,
prev_factor: int | None = None,
loss: list[float] = list(),
outer_stats: list[OuterStat] = list(),
lipschitz: float | None = None,
small_impr_streak: int = 0,
elapsed_offset: float = 0.0,
level_complete: bool = False,
run_complete: bool = False,
factors_skipped_reason: str | None = None,
geometry_calibration_state: dict[str, object] | None = None,
stage_index: int = 0,
stage_name: str | None = None,
stage_completed: bool = False,
completed_outer_iterations_in_stage: int = 0,
pose_translation_frame: str = 'object',
ray_integrator: str = 'sampled',
)Saved multiresolution alignment progress.
Parameters
x(jax.Array): Current reconstruction in (x, y, z) order on the current level grid.pose_params(jax.Array): Per-view corrections, columns (alpha, beta, phi, dx, dz, dy); angles are radians and translations physical lengths.motion_coeffs(jax.Array | None, optional)- Coefficients of a polynomial or spline motion model; None for independent per-view: parameters.
level_index(int, optional): Zero-based index of the current resolution level. Default is 0.level_factor(int, optional): Current coarsening factor relative to the native grid and detector. Default is 1.completed_outer_iterations_in_level(int, optional): Number of outer iterations already completed in this level. Default is 0.global_outer_iterations_completed(int, optional): Number of outer iterations already completed across levels. Default is 0.prev_factor(int | None, optional): Previously completed level factor, or None before the first level.loss(list[float], optional): Recorded objective values in iteration order; defaults to an empty list.outer_stats(list[OuterStat], optional): Per-outer-iteration diagnostics in execution order.lipschitz(float | None, optional): Last inner reconstruction Lipschitz estimate, or None if not yet estimated.small_impr_streak(int, optional): Number of successive outer iterations with small improvement. Default is 0.elapsed_offset(float, optional): Elapsed time in seconds before resuming this state. Default is 0.0.level_complete(bool, optional): Whether the current level has completed. Default is False.run_complete(bool, optional): Whether the complete alignment run has finished. Default is False.factors_skipped_reason(str | None, optional): Reason finer levels were skipped, or None when none were skipped.geometry_calibration_state(dict[str, object] | None, optional): Serialized setup-geometry calibration, or None when absent.stage_index(int, optional): Zero-based current schedule-stage index. Default is 0.stage_name(str | None, optional): Name of the current stage, or None before choosing a stage.stage_completed(bool, optional): Whether the current schedule stage has completed. Default is False.completed_outer_iterations_in_stage(int, optional): Outer iterations already completed in this stage. Default is 0.pose_translation_frame(str, optional): Basis for physical translations: "object" or "detector". Default is 'object'.ray_integrator(str, optional): Projection model used by the saved run. Default is 'sampled'.
AlignResumeState
class AlignResumeState(
x: jnp.ndarray,
pose_params: jnp.ndarray,
motion_coeffs: jnp.ndarray | None = None,
start_outer_iter: int = 0,
run_complete: bool = False,
loss: list[float] = list(),
outer_stats: list[OuterStat] = list(),
lipschitz: float | None = None,
small_impr_streak: int = 0,
elapsed_offset: float = 0.0,
pose_translation_frame: str = 'object',
ray_integrator: str = 'sampled',
)Saved single-resolution alignment progress.
Parameters
x(jax.Array): Current reconstruction in (x, y, z) order on the current level grid.pose_params(jax.Array): Per-view corrections, columns (alpha, beta, phi, dx, dz, dy); angles are radians and translations physical lengths.motion_coeffs(jax.Array | None, optional)- Coefficients of a polynomial or spline motion model; None for independent per-view: parameters.
start_outer_iter(int, optional): Number of completed outer iterations to resume after. Default is 0.run_complete(bool, optional): Whether the solver reached its iteration limit or stopping criterion. Default is False; observer interruptions can resume.loss(list[float], optional): Recorded objective values in iteration order; defaults to an empty list.outer_stats(list[OuterStat], optional): Per-outer-iteration diagnostics in execution order.lipschitz(float | None, optional): Last inner reconstruction Lipschitz estimate, or None if not yet estimated.small_impr_streak(int, optional): Number of successive outer iterations with small improvement. Default is 0.elapsed_offset(float, optional): Elapsed time in seconds before resuming this state. Default is 0.0.pose_translation_frame(str, optional): Basis for physical translations: "object" or "detector". Default is 'object'.ray_integrator(str, optional): Projection model used by the saved run. Default is 'sampled'.
AlignmentLossSpec
Defined in src/tomojax/alignment/_objectives/loss_specs.py:43
AlignmentMode
Defined in src/tomojax/alignment/_modes.py:44
AlignmentSchedule
class AlignmentSchedule(
name: str,
stages: tuple[AlignmentStage, ...],
metadata: dict[str, object] = dict(),
)Unresolved alignment schedule declaration.
Parameters
name(str): Public name used to identify this declaration.stages(tuple[AlignmentStage, ...]): Ordered stage declarations to execute.metadata(dict[str, object], optional): Associated JSON-compatible metadata.
AlignmentSchedule.validate
validate() -> AlignmentScheduleValidate schedule invariants and return this schedule.
Returns
- AlignmentSchedule: This schedule, unchanged, after validation.
Raises
- ValueError: If stages are empty or parameter/objective/optimizer combinations are invalid.
AlignmentSchedule.active_dofs
@property
active_dofs: tuple[str, ...]Return active DOFs from all stages in first-seen order.
Returns
- tuple of str: Distinct active parameter names in first-seen order.
AlignmentSchedule.to_dict
to_dict() -> dict[str, object]Return a JSON-compatible schedule description.
Returns
- dict: Declared stages and metadata in JSON-compatible form.
AlignmentStage
class AlignmentStage(
name: str,
active_dofs: tuple[str, ...],
objective_kind: ObjectiveKind,
optimizer: OptimizerKind,
gauge_policy: GaugePolicy = 'reject',
maxiter: int = 12,
early_stop: bool = True,
stage_role: StageRole = 'refine',
differentiability: DifferentiabilityRequirement = 'gradient_safe',
quality_tier: StageQualityTier = 'fast',
speed_claim_eligible: bool = True,
)One declared stage in an alignment schedule.
Parameters
name(str): Public name used to identify this declaration.active_dofs(tuple[str, ...]): Public parameter names optimized by this stage.objective_kind(ObjectiveKind): Objective model: "fixed_volume", "joint_volume_pose", "bilevel_cv", "all_data_bilevel" or "projection_consistency".optimizer(OptimizerKind): Optimizer for the chosen objective: "lbfgs", "adam", "gd", "gn", "validation_lm" or "spectral". The schedule validates supported combinations.gauge_policy(GaugePolicy, optional): Gauge policy: "reject", "anchor_mean", "prior_required" or "diagnose_only". Default is 'reject'.maxiter(int, optional): Maximum optimizer iterations in this stage. Default is 12.early_stop(bool, optional): Whether this stage may stop on small improvement. Default is True.stage_role(StageRole, optional): Role in the schedule: "proposal", "setup", "reconstruction", "refine" or "verify". Default is 'refine'.differentiability(DifferentiabilityRequirement, optional): Required path: "gradient_safe", "performance_only" or "not_required". Default is 'gradient_safe'.quality_tier(StageQualityTier, optional): Stage quality tier, "fast", "reference" or "verify". Default is 'fast'.speed_claim_eligible(bool, optional): Whether this stage is eligible for performance comparisons. Default is True.
AlignmentStage.active_view
active_view() -> ActiveParameterViewReturn this stage's active parameters split by owner.
Returns
- ActiveParameterView: Active parameters split into setup and pose owners.
CenterEstimate
class CenterEstimate(
geometry: ParallelGeometry,
pairs: tuple[CenterPair, ...],
row_positions_px: tuple[float, ...],
row_offsets_px: tuple[tuple[float | None, ...], ...],
row_slope_px_per_row: float | None,
pair_scatter_px: float,
consistency_pvalue: float | None,
calibration_views: tuple[int, ...] | None = None,
)Centre geometry and the opposing-view evidence behind it.
The reported centre is the median pair location, fixing the median
opposing-pair mean shift to zero, not the mean motion over all views.
Changing the sampled pairs can change that gauge when the sample moves.
pair_scatter_px describes
disagreement, not the standard error of that median. consistency_pvalue
is a conditional inverse-variance heterogeneity diagnostic; correlated
pairs and ambiguous matches invalidate its chi-square reference. Apparent
row slope is in horizontal pixels per detector row, not a calibrated 3D
rotation-axis tilt. Arbitrary sample motion aliases the physical centre:
no absolute-centre confidence interval is identifiable without a motion
assumption. Pair intervals are local matching diagnostics; global coverage
is explicitly uncalibrated even when the pairs do not disagree.
Parameters
geometry(ParallelGeometry): Geometry with the effective median pair centre in physical detector units.pairs(tuple of CenterPair): Opposing-view constraints and their conditional uncertainties.row_positions_px(tuple of float): Mean original detector-row index of each sampled row band.row_offsets_px(tuple of tuple): Pair-by-row-band centre locations, or None for unusable bands.row_slope_px_per_row(float or None): Median pair slope, or None when fewer than two row bands are usable.pair_scatter_px(float): Sample standard deviation of pair centre locations, not their mean error.consistency_pvalue(float or None): Conditional chi-square diagnostic, or None without two informative pairs.calibration_views(tuple of int or None, optional): Eligible original view indices; None means all acquisition views. Pair contributors are a subset, and retain original acquisition indices.
CenterEstimate.to_dict
to_dict() -> dict[str, object]Return the estimate and diagnostics without serializing the geometry.
Returns
- dict: JSON-native pair constraints, row trend and consistency diagnostics.
pair_mean_shift_constraints_pxgives the reported centre minus each pair offset, in the same order aspairs. In the linearized rigid-match model, a pair offset is the physical centre minus half the sum of its two weighted detector-u sample shifts. The weights and view indices are stored in each pair'sfirstandsecond. These constraints share the same fitted centre and are correlated; they are not per-view poses or independently calibrated intervals. Common centre/shift changes and the null space of the weighted pair averages remain unresolved. Large or discontinuous motion, wrong matching modes and model mismatch invalidate the linearization.
CenterPair
class CenterPair(
first: tuple[tuple[int, float], ...],
second: tuple[tuple[int, float], ...],
angular_mismatch_deg: float,
offset_px: float,
local_sigma_px: float,
local_interval90_px: tuple[float, float],
alternatives_px: tuple[float, ...],
relative_peak_heights: tuple[float, ...],
)Opposing-view constraint, in native detector pixels.
first and second are (view index, angular interpolation weight)
tuples. A small-motion linearization constrains the sum of opposing
shifts, not separate poses. Angular resampling blends images: with large
or discontinuous motion its correlation location is not an exact weighted
average of the contributing shifts. local_sigma_px and
local_interval90_px describe only the selected matching mode.
Alternatives and their correlation heights expose competing modes;
global coverage is uncalibrated, not included in the local interval.
Parameters
first,second(tuple of (int, float)): View indices and angular interpolation weights at each end.angular_mismatch_deg(float): Angular departure of the nearest acquired pair from exact opposition.offset_px(float): Detector-centre placement inferred from this pair, in detector pixels.local_sigma_px(float): Local matching scale; infinity denotes no local information. Global coverage is uncalibrated.local_interval90_px(tuple of float): Nominal local 90% interval, not a calibrated global centre interval.alternatives_px(tuple of float): Other correlation-peak locations, in detector-centre pixels.relative_peak_heights(tuple of float): Correlation heights of alternatives relative to the selected peak.
CenterPair.to_dict
to_dict() -> dict[str, object]Return JSON-native constraints, with null for unbounded uncertainty.
Returns
- dict: Pair constraints, conditional uncertainty and alternative modes.
HuberLossSpec
class HuberLossSpec(delta: float = 1.0)Convex robust projection loss for fixed-volume Gauss-Newton alignment.
Parameters
delta(float, optional): Positive residual threshold in projection units. Residuals above this threshold have bounded influence. Default is 1.0; choose it for the noise scale of the measured projections. Joint GN is not supported.
L2LossSpec
class L2LossSpec()Plain squared-error projection loss.
L2OtsuLossSpec
class L2OtsuLossSpec(temp: float = 0.5)Squared-error loss weighted by a soft Otsu foreground mask.
Parameters
temp(float, optional): Soft-mask sigmoid temperature; smaller values sharpen the foreground weighting. Default is 0.5.
OuterStat
Defined in src/tomojax/alignment/_observer.py:10
PoseTranslationFrame
Defined in src/tomojax/alignment/_geometry/parametrizations.py:13
QualityTier
Defined in src/tomojax/alignment/_profiles.py:11
apply_pose_updates
apply_pose_updates(
nominal: jnp.ndarray,
pose_params: jnp.ndarray,
*,
translation_frame: PoseTranslationFrame = 'object',
) -> jnp.ndarrayApply the same explicit translation convention to a stack of views.
Parameters
nominal(array-like): Nominal object-to-world transforms with shape (views, 4, 4).pose_params(array-like): Per-view corrections with columns (alpha, beta, phi, dx, dz[, dy]); angles are radians and translations physical lengths.translation_frame({"object", "detector"}, optional): Basis for physical translations; detector means lab x/y/z axes, not pixels. Default is 'object'.
Returns
- jax.Array: Updated object-to-world transforms with shape (views, 4, 4).
Raises
- ValueError: If translation_frame is not "object" or "detector".
coupled_pose_config
coupled_pose_config(**overrides: object) -> AlignConfigReturn the recommended configuration for per-view pose alignment.
This is what tomojax align --mode pose runs: each Gauss-Newton step
solves the free voxels and every view's pose together, with Joseph
plane sampling, an unregularised least-squares fit, fp32 gathers and up to
30 early-stopped outer iterations, after a global search for each view's
detector shift. Pass keyword overrides for any
AlignConfig field. AlignConfig() itself keeps the older
alternating defaults for compatibility.
Parameters
**overrides(object): Named AlignConfig fields replacing the recommended defaults.
Returns
- AlignConfig: Joint Gauss-Newton pose-alignment configuration.
Raises
- TypeError: If a keyword does not name an AlignConfig field.
- ValueError: If the resulting settings are inconsistent or invalid.
estimate_center
estimate_center(
geometry: Geometry,
projections: np.ndarray | jax.Array,
*,
views: slice | Sequence[int] | np.ndarray | None = None,
) -> ParallelGeometryEstimate an axial parallel detector's effective u-centre placement.
Opposing projections agree after detector-u reflection and a shift of twice
the centre offset. Gradient correlations of up to 64 corresponding rows are summed,
retaining signed phase contrast rather than assuming positive absorption.
At most sixteen near-opposite pairs (within two degrees), spread across the
scan, and their angular neighbors are read. Pairs within half a detector-edge
pixel of the best angular match are eligible. Linear angular resampling
removes the mismatch. Nothing is reconstructed. Non-axial and posed
geometries raise. The result is an absolute placement in physical units,
not an increment to the input geometry. It fixes the median sampled-pair
mean motion to zero; physical centre and common sample motion cannot be
separated from these observations alone. Use estimate_center_report
to retain the conditional constraints and unresolved-centre status.
Parameters
geometry(Geometry): Scan geometry with its view angles and physical detector placement.projections(array-like): Projections with shape (views, nv, nu), in geometry view order.views(slice, sequence of int, numpy.ndarray or None, optional): Eligible original acquisition views, as inestimate_center_report. None uses all views; the returned geometry retains all views.
Returns
- ParallelGeometry: Geometry with the effective detector-u centre in physical units, conditional on the median opposing-pair mean-shift-zero gauge.
Raises
- ValueError: If the scan is non-axial, posed, lacks usable near-opposite projections, or has incompatible data.
estimate_center_report
estimate_center_report(
geometry: Geometry,
projections: np.ndarray | jax.Array,
*,
views: slice | Sequence[int] | np.ndarray | None = None,
) -> CenterEstimateEstimate an axial parallel centre and retain pair and row diagnostics.
At most sixteen near-opposite pairs and 64 rows are sampled. Gradient correlations select matching modes; a symmetric fit on overlapping support estimates each location. Eight detector bands give conditional sandwich standard errors with leverage correction. Up to eight row bands measure the apparent row-centre trend. No reconstruction is performed.
Parameters
geometry(Geometry): Unposed axial parallel geometry, including angles in degrees.projections(array-like): Corrected line integrals shaped (views, rows, columns).views(slice, sequence of int, numpy.ndarray or None, optional): Eligible acquisition views: forward slice, increasing indices or boolean mask. None uses all views. Both pair anchors and angular interpolation contributors come only from this subset. The returned geometry and pair indices stay in the original acquisition coordinates; no full-stack copy is made. Exclude validation views from all earlier fitted corrections too.
Returns
- CenterEstimate: Geometry, weighted view-pair constraints, conditional 90% intervals, alternative correlation peaks, pair disagreement and row-centre slope. Global coverage is uncalibrated: sample motion and wrong-mode selection are outside the local intervals, including for a single opposing pair.
Raises
- ValueError: If geometry is unsupported, usable opposing data are absent, or near-opposite pairs lack angular neighbours within two degrees. Exact opposing views do not require angular interpolation.
implied_detector_offset
implied_detector_offset(nominal: np.ndarray, aligned: np.ndarray) -> tuple[float, float]Return the detector-u centre offset implied by recovered poses, and the fit residual.
A detector-centre (centre-of-rotation) offset displaces every view's image by
the same amount along u, while a rigid object translation displaces it by a
view-dependent amount. Fitting each view's u displacement of the object origin
as -offset + (R_i t)_x separates the two over the scan. Both returns are
physical lengths, with the sign of Detector.center.
Parameters
nominal(array-like): Nominal object-to-world transforms with shape (views, 4, 4).aligned(numpy.ndarray): Aligned object-to-world transforms with shape (views, 4, 4).
Returns
offset(float): Detector-u offset relative to nominal in physical length units, with Detector.center sign.residual(float): Root-mean-square fit residual in physical length units.
least_motion_estimate
least_motion_estimate(
volume: np.ndarray | jax.Array,
params: np.ndarray,
*,
nominal: np.ndarray,
grid: Grid,
translation_frame: PoseTranslationFrame,
active: Collection[str],
cone_beam: bool,
detector_offset: bool = False,
) -> tuple[np.ndarray, np.ndarray, Gauge | None]Move an alignment result (volume and poses) to its least-motion estimate.
cone_beam says the geometry is a cone beam, where along-beam dy is
visible; parameters not in active keep their values. Returns the moved
volume and poses and the gauge applied; a detector offset in it belongs in
the detector centre (Detector.center[0] += gauge.detector_offset).
The motion is a symmetry only for an object inside the grid. If moving the volume along it, by at least a voxel, would push part of the object out (more than 5% of its integral; the faint background a reconstruction leaves everywhere does not count), the grid edge already fixes the estimate: it is returned unchanged with gauge None.
Parameters
volume(array-like): Reconstructed volume in (x, y, z) order.params(array-like): Per-view pose table with five or six columns in radians and physical lengths.nominal(array-like): Nominal object-to-world transforms with shape (views, 4, 4).grid(Grid): Volume grid with physical voxel spacing.translation_frame({"object", "detector"}): Basis for physical translations; detector means lab x/y/z axes, not pixels.active(collection of str): Active pose parameter names; other parameters are left unchanged.cone_beam(bool): Whether along-beam translation dy is observable in a cone beam.detector_offset(bool, optional): Allow constant detector-u displacement to move into the detector centre. Default is False.
Returns
volume(numpy.ndarray): Volume in the least-motion gauge, or unchanged when the grid edge fixes it.params(numpy.ndarray): Per-view pose corrections in the same gauge.gauge(Gauge or None): Applied common motion and detector offset, or None if no change was made.
match_projections
match_projections(
geometry: ScanGeometry,
projections: np.ndarray | jax.Array,
*,
config: ProjectionMatchingConfig,
) -> tuple[np.ndarray, dict[str, object]]Estimate translations from native projection texture.
Owns the sparse alignment grid and temporary volumes. Only the coupled likelihood profiles detector backgrounds; input projections and the final inverse are unchanged.
Parameters
geometry(ParallelGeometry): Unposed axial parallel-beam geometry of the scan.projections(array-like): Line integrals of shape(views, nv, nu), at least 20 rows and columns.config(ProjectionMatchingConfig): Refinement settings.
Returns
poses(numpy.ndarray): Per-view pose table(views, 6)in the detector translation frame.info(dict): Solver record: timings, iterations and the estimator's settings.
Raises
- ValueError: If the geometry is not unposed axial parallel beam, or the detector is too small.
orbit_heights
orbit_heights(
geometry: Geometry,
projections: np.ndarray,
*,
pairs: int = 32,
reach: float | None = None,
) -> OrbitHeights | NoneEach orbit's height above the first, from the data's consistency alone.
geometry is a multi-orbit ConeSegments and projections its
(views, rows, columns) data. Each orbit is compared with every orbit
already placed, in view pairs a quarter and a sixth of a turn apart: its
height is scanned over +-reach (by default a sixteenth of the
detector's height at the axis) in steps of two pixels at the axis on a
quarter of the pairs, then on all of them in quarter steps around the
lowest, refined by a quadratic through the lowest costs. The estimate is
good to about half a pixel at the axis: a starting point for alignment.
None for a single orbit.
Parameters
geometry(Geometry): Scan geometry with its view angles and physical detector placement.projections(array-like): Line integrals with shape (views, nv, nu), in geometry view order.pairs(int, optional): Number of view pairs used for each height search. Default is 32.reach(float or None, optional): Search half-width in physical length units. None uses a sixteenth of detector height at the axis.
Returns
- OrbitHeights or None: Relative heights and confidence diagnostics; None for a single orbit.
Raises
- ValueError: If the projection stack does not match the geometry.
save_alignment_params_csv
save_alignment_params_csv(
path: str | Path,
pose_params: np.ndarray,
*,
du: float,
dv: float,
translation_frame: str = 'object',
) -> NoneWrite a CSV sidecar, adding an explicit frame column for detector poses.
Parameters
path(str or path-like): Checkpoint or sidecar file path.pose_params(array-like): Per-view corrections with columns (alpha, beta, phi, dx, dz[, dy]); angles are radians and translations physical lengths.du(float): Physical detector-u pixel spacing, used for pixel-unit exports.dv(float): Physical detector-v pixel spacing, used for pixel-unit exports.translation_frame({"object", "detector"}, optional): Basis for physical translations; detector means lab x/y/z axes, not pixels. Default is 'object'.
Raises
- ValueError: If the pose table, detector spacings or translation frame are invalid.
save_alignment_params_json
save_alignment_params_json(
path: str | Path,
pose_params: np.ndarray,
*,
du: float,
dv: float,
gauge_metadata: dict[str, Any] | None = None,
translation_frame: str = 'object',
) -> NoneWrite per-view alignment parameters as a named JSON sidecar.
Parameters
path(str or path-like): Checkpoint or sidecar file path.pose_params(array-like): Per-view corrections with columns (alpha, beta, phi, dx, dz[, dy]); angles are radians and translations physical lengths.du(float): Physical detector-u pixel spacing, used for pixel-unit exports.dv(float): Physical detector-v pixel spacing, used for pixel-unit exports.gauge_metadata(dict or None, optional): Gauge information to include in the exported record.translation_frame({"object", "detector"}, optional): Basis for physical translations; detector means lab x/y/z axes, not pixels. Default is 'object'.
Raises
- ValueError: If the pose table, detector spacings or translation frame are invalid.
se3_from_pose_params
se3_from_pose_params(pose_params: jnp.ndarray) -> jnp.ndarrayBuild a 4x4 transform from [alpha, beta, phi, dx, dz] or with dy appended.
Translations are (dx, dy, dz) in world/object units; five values mean dy = 0.
Parameters
pose_params(array-like): One pose vector (alpha, beta, phi, dx, dz[, dy]); angles in radians, translations physical lengths.
Returns
- jax.Array: Float32 rigid transform of shape (4, 4), with rotation Ry(beta) Rx(alpha) Rz(phi).