Skip to content

Inspect a pipeline

Introspection is how you verify that a pipeline formed the segments you intended. It is also where several names need careful interpretation.

Human-readable plan

import torch

from fuse_augmentations import Compose

torch.manual_seed(7)
augment = Compose.from_params(rotation=(-15.0, 15.0), hflip_p=0.5)
images = torch.rand(2, 3, 32, 32)

print(augment.fusion_plan)
Human-readable plan for the configured pipeline
fused(_DirectParamTransform, _DirectFlipTransform)

The plan distinguishes fused, exact, projective, color, crop-resize, and passthrough segments. A backend change, projective/affine transition, unsupported transform, or spatial-kernel operation can split the chain.

Structured descriptors

for segment in augment.fusion_plan_descriptors:
    print(
        segment.kind,
        segment.transforms,
        segment.backend,
        segment.barrier,
        segment.split_reason,
        segment.refused,
    )
Structured descriptor fields for the configured segment
fused ('_DirectParamTransform', '_DirectFlipTransform') None None None None

Descriptors are frozen and dictionary-serializable, which makes them suitable for experiment metadata. Store the dependency versions and pipeline configuration beside them.

n_warps_saved is an estimate

n_warps_saved summarizes collapsed operations across segments. It is useful for comparing plans, but it is not a literal count of native interpolation calls in every case: an exact flip may be counted even though the native operation was already a lossless tensor reversal.

Use it as a planning metric, then profile the real workload.

Matrix lifetime and scope

output, matrix = augment(images, return_matrix=True)

The matrix is the actual forward pixel-centre matrix for the last supported matrix-producing segment in that call. Fused affine/projective segments, exact D4/flip/quarter-turn segments, and direct deterministic letterbox publish a (B, 3, 3) matrix. It is not automatically the transform of an entire pipeline containing multiple backend segments, a projective boundary, a crop boundary, or passthrough operations.

The transform_matrix property exposes the same mutable last-call state and is None before a call or when the latest call produced no supported geometry. It is not safe as shared cross-thread request state. Prefer return_matrix=True when the matrix must stay paired with its output.

Matrices map source pixel centres to output pixel centres. Use the target helpers with the inverse matrix for coordinate recovery; AABB helpers perform their pixel-edge conversion internally. For a pipeline deliberately constrained to one supported matrix segment, the returned matrix can route coordinates or be stored as augmentation provenance. A matrix from a multi-segment pipeline still describes only its last supported segment.

Native NumPy single-image exact calls preserve the native layout, including rectangular outputs when a 90-degree or transpose operation swaps height and width, and publish the same actual-call matrix. Uniform BCHW exact D4/90-degree/transpose batches also support rectangular inputs and swap the common output shape. A batch whose samples would produce heterogeneous spatial shapes is refused; use a uniform exact draw (for example same_on_batch=True) or separate those samples.

Test-time de-augmentation with inverse

Pair a return_matrix=True output with inverse(prediction, matrix=...) to map a prediction back into the original geometric frame:

translate_pipe = Compose.from_params(translate_x=(2.0, 2.0))
translate_images = torch.rand(1, 3, 8, 8)
augmented, matrix = translate_pipe(translate_images, return_matrix=True)
recovered = translate_pipe.inverse(augmented, matrix=matrix)

Pass the matrix returned by the same forward call rather than reading transform_matrix. inverse does not read that mutable property, so pairing a call's own matrix this way is safe under concurrent calls.

inverse supports one fused affine or projective image segment, including a chain already fused into that segment. Exact D4/flip/quarter-turn and deterministic letterbox calls still publish coordinate provenance, but their images are not accepted by this inverse API. It raises ValueError instead of guessing for:

  • crop-resize segments (CropResizeSegment, _FusedGeoCropSegment) — crop-resize discards pixels outside the crop;
  • non-geometric segments (FusedColorSegment, FusedLUTSegment, FusedGaussianBlurSegment) — color, LUT, and blur segments carry no geometric matrix;
  • passthrough segments — no recorded matrix;
  • exact-only segments (ExactAffineSegment) — exact pixels cannot be reconstructed through this image inverse, even though the segment records a forward coordinate matrix;
  • standalone deterministic letterbox segments — padding and resizing are not restored by the image inverse;
  • multi-segment pipelines — return_matrix records only the last segment's matrix;
  • a missing paired matrix argument.

Auxiliary targets recover at different fidelities. Keypoints and masks recover to sampling precision. Bounding boxes are axis-aligned (AABB), so a forward-then-inverse box is exact only for axis-aligned transforms (flip, scale, translation) and inflates under a rotation, shear, or projective warp.