Core
The data model: XTensor itself (dimension names,
axis descriptors, coordinates, renaming, and dtype/device conversion), and
ExtendedTensor, the generic name-aware
torch.Tensor subclass base it's built on.
Everything else XTensor supports — reductions, combining, gather/scatter/
indexing, shape, data units — has its own page; see the API overview.
fiery.xtensor.XTensor
Bases: ExtendedTensor
A tensor with named dimensions and, optionally, per-dimension coordinate
labels -- an xarray-like DataArray over a
live torch.Tensor.
- Dimensions are named through
names(self-managed in_axis_names, independent of PyTorch's experimental builtin named-tensor feature, so the class works even where that API has been removed). - Coordinates label the positions along a named dimension. They live
in
coords-- a mapping dim name -> labels -- keyed by dimension name, so they follow their dimension through reshaping/reordering with no positional bookkeeping. A labelled dimension must be named. - Axis descriptors may enrich a name with extra fields -- any custom
key you like (
typeis the OME-NGFF convention shown in examples;orientationis the one field with built-in behaviour) -- passed as a dict in place of a bare name ({"name": "x", "type": "space"}).namesstays the ergonomic view (bare names);axesreturns the full descriptors. The extra fields live in_axis_meta, keyed by dimension name, so they follow the dimension like coordinates do.
Select by label with sel, by integer position with isel, or reach a
single label by attribute (x.red).
Attributes
names
property
writable
The name of each axis (None for unnamed axes). On assignment a single
... expands to a run of unnamed axes, so x.names = ("b", ..., "w")
names only the ends and leaves the middle unnamed.
axes
property
writable
Each axis as a descriptor dict {"name": ..., **extra} (or None
for an unnamed axis). The extra fields -- any custom key (type by
OME-NGFF convention, orientation, ...) -- come from _axis_meta,
keyed by dimension name.
coords
property
writable
The coordinates, as a {dim name: coordinate} dict. A coordinate is a
tuple of labels, or a compact numeric coordinate ({spacing[,
origin]}, whose ["value"] key materialises the positions).
Only entries that are still valid are returned -- every dim a coordinate spans must still be named on this tensor (and, for labels, its size must match the label count) -- so stale metadata propagated onto a shape-changing op is hidden.
A dimension coordinate spans just the dim it is keyed under (it
is that dim's index, so .sel(name=...) works); a
non-dimension coordinate (its key is not itself a dim name)
rides along some other dim(s) instead, and is not an index. A
non-dimension coordinate may span several dims at once: a
compact affine map (spacing is a vector, one component per
spanned dim, origin a single scalar shared across them), or an
explicit grid of values with no regular spacing (e.g. lat(y,
x)), one tensor axis per spanned dim.
Methods:
rename
Return a view with renamed axes (self-managed; not the builtin op).
Call positionally (x.rename("a", "b")), with None to clear all
names (x.rename(None)), or with a mapping to rename specific axes
(x.rename(old="new")). A single ... keeps the axes it spans
unchanged (x.rename("A", ..., "Z")). Coordinates follow their
(renamed) dimension.
refine_names
refine_names(*names: str | None) -> Self
Return a view with names assigned to (only) the unnamed axes.
Naming an already-named axis to a different name is an error; a
given None keeps the current name. A single ... keeps the names
of the axes it spans. Self-managed (not the builtin op).
swap_dims
Promote a non-dimension coordinate to be its dim's index, demoting
the previous index to ride along under its old key -- xarray's
swap_dims. {old_dim: new_name} (positionally or as keywords):
new_name must already be a non-dimension coordinate riding
old_dim alone (coords={..., new_name: (old_dim, values)}).
The axis itself is renamed old_dim -> new_name (so .names and any
axis descriptor follow, like rename);
every other coordinate riding old_dim keeps its own key and simply
rides the renamed axis.
swap_dims_
In-place variant of swap_dims.
align_to
align_to(*names: str) -> Self
Return a view with the axes permuted into the given name order.
A single ... stands for all the other axes, in their current
order (e.g. x.align_to(..., "channel")). Self-managed.
align_as
align_as(other: XTensor) -> Self
Return a view aligned to other's named axes.
This tensor's axes are permuted into other's order, and a size-1
axis is inserted for every name that only other has. Every axis of
self must be named and present in other. Self-managed.
to
to(*args: Any, units: Any = _UNSET, names: Any = _UNSET, coords: Any = _UNSET, **kwargs: Any) -> Self
Same as torch.Tensor.to (dtype/device, positional or keyword), plus
units=/names=/coords= overrides.
x.to(torch.float64) # exactly as before
x.to(units="mm") # convert the data unit
x.to(ureg.mm) # ... same, from a backend unit
x.to(torch.float64, names=("b", "t"))
units= converts (like to_units, so a unit must already be
set), matching what .to() means everywhere else -- unlike
as_xtensor(x, units=...), which annotates. names=/coords= are
the instance-method form of
as_xtensor's overrides of the same
name, and replace wholesale. A bare positional backend
Unit/Quantity is sugar for units= with that same object; unlike
the positional form, units= also accepts a plain unit string (a
positional string stays torch.Tensor.to's own device spelling,
"cuda"/"cpu").
to_
to_(*args: Any, units: Any = _UNSET, names: Any = _UNSET, coords: Any = _UNSET, **kwargs: Any) -> Self
In-place .to(), with the same units=/names=/coords=
overrides, each going through an already in-place path -- but "in
place" doesn't mean "always succeeds": a dtype/device change raises
unless the request already matches this tensor's current dtype and
device (a no-op), even if forced through copy=True; units=
inherits to_units_'s own restrictions (no unit set, or a leaf
tensor requiring grad); names=/coords= inherit their setters'
own validation (a length mismatch, an invalid coordinate spec).
Applied names=, then coords=, then units= last -- each of the
first two either fully applies or raises before mutating anything,
so the data rescale from units= never happens unless every other
override already succeeded.
fiery.xtensor.ExtendedTensor
Bases: Tensor
A torch.Tensor subclass with extended, name-aware behaviour.
Selected torch functions are overridden through the __torch_function__
protocol; the overrides live in a per-subclass registry, populated by the
overrides decorator. Any op
without an override still propagates the subclass's own metadata
attributes from its first tensor argument onto the result.
Methods:
overrides
classmethod
Decorator to register a function override.
func may be None (an op that does not exist in the running
PyTorch version); in that case the override is silently skipped so
that we never overload a function that is missing from this
PyTorch build.