Antennas

Reference for AntennaState, ReceiverGrid, AntennaPattern and antenna_orientation_matrix - transmitter and receiver endpoints in a Core scene.

The antenna classes live in witwin.core.antenna and are exported from witwin.core. For examples, see Place antennas and receiver grids.

from witwin.core import AntennaPattern, AntennaState, ReceiverGrid, antenna_orientation_matrix

Vector fields accept a sequence (converted to a float32 tensor) or a tensor (stored as is). All tensor fields of one endpoint must be on one device, otherwise ValueError.

AntennaState#

class AntennaState(
    antenna_id: AntennaId | int,
    role: Literal["tx", "rx"],
    position,
    *,
    orientation=None,
    polarization=None,
    element_positions=None,
    weights=None,
    synthetic_array: bool = True,
    pattern: AntennaPattern | str = "isotropic",
    power_w: ScalarLike | None = None,
    metadata: Mapping[str, Any] | None = None,
)

A solver-neutral transmitter or receiver. Immutable (frozen dataclass).

antenna_idAntennaId | intrequired

The endpoint's ID, reserved so that automatic IDs skip it. Must be at least 0. Unique within a scene.

role'tx' | 'rx'required

Transmitter or receiver. Other values raise ValueError.

position3 floats | Tensor (3,)required

World position in metres. Must be floating point.

orientationNone | 3 or 4 values | Tensor (3,) or (4,)default None

Local-to-world rotation. (3,) is Euler (yaw, pitch, roll) in radians, intrinsic Z-Y-X; (4,) is a unit quaternion (w, x, y, z). None is the identity. Other shapes raise ValueError.

polarization3 floats | Tensor (3,) | Nonedefault None

Polarization vector in the local frame.

element_positionsTensor (A, 3) | Nonedefault None

Array element positions in the local frame, in metres.

weightsTensor (A,) | Nonedefault None

Per-element weights, real or complex. Must have one value per element when element_positions is set.

synthetic_arraybooldefault True

A flag for solvers that controls how they model an array. See the solver's documentation.

patternAntennaPattern | strdefault 'isotropic'

A pattern kind string or an AntennaPattern. Other types raise TypeError.

power_wScalarLike | Nonedefault None

Transmit power in watts. A tensor must be 0-d and floating point.

metadataMapping[str, Any] | Nonedefault None

Free-form data, stored as a read-only mapping.

All arguments are attributes with the same names.

AntennaState.orientation_matrix#

orientation_matrix() -> torch.Tensor

Returns the (3, 3) local-to-world rotation, computed from orientation in its dtype. Without an orientation it returns the identity on the device and in the dtype of position. Keeps autograd.

AntennaState.polarization_world#

polarization_world() -> torch.Tensor | None

Returns orientation_matrix() @ polarization (world frame), or None without a polarization. Keeps autograd.

ReceiverGrid#

class ReceiverGrid(
    antenna_id: AntennaId | int,
    origin,
    x_axis,
    y_axis,
    shape,
    spacing,
    *,
    orientation=None,
    polarization=None,
    element_positions=None,
    weights=None,
    synthetic_array: bool = True,
    pattern: AntennaPattern | str = "isotropic",
    metadata: Mapping[str, Any] | None = None,
)

A row-major planar grid of receiver samples that counts as one "rx" endpoint with one ID. Subclass of AntennaState.

antenna_idAntennaId | intrequired

The grid's endpoint ID.

origin3 floats | Tensor (3,)required

World position of sample (0, 0). Stored as position.

x_axis3 floats | Tensor (3,)required

World direction of increasing row index. Not normalised.

y_axis3 floats | Tensor (3,)required

World direction of increasing column index. Not normalised.

shapetuple[int, int]required

(rows, columns), both positive integers.

spacing2 floats | Tensor (2,)required

(row spacing, column spacing) in metres. Python values must be positive.

The keyword-only arguments are as for AntennaState. The role is always "rx" and there is no power_w.

MemberDescription
originProperty: the same tensor as position.
x_axis, y_axis, spacingThe tensors given (or converted on the device and dtype of origin).
shape(rows, columns) as a tuple of int.
points()(rows * columns, 3) world positions: sample (r, c) is origin + r * spacing[0] * x_axis + c * spacing[1] * y_axis, row-major. Keeps autograd.

AntennaPattern#

@dataclass(frozen=True, slots=True)
class AntennaPattern:
    kind: str = "isotropic"
    custom: Callable[[torch.Tensor], torch.Tensor] | None = None

The pattern identity of an endpoint. kind is "isotropic", "vertical", "horizontal" or "custom". custom must be a callable exactly when kind == "custom". Otherwise ValueError. Core never calls custom; the solver defines its argument.

antenna_orientation_matrix#

antenna_orientation_matrix(orientation: torch.Tensor | None, *, reference: torch.Tensor) -> torch.Tensor

Returns the (3, 3) local-to-world rotation for an antenna orientation.

orientationTensor (3,) | Tensor (4,) | Nonerequired

Euler (yaw, pitch, roll) or quaternion (w, x, y, z).

referencetorch.Tensorrequired

A tensor whose device and dtype the identity matrix takes when orientation is None.

import math
 
import torch
 
from witwin.core import antenna_orientation_matrix
 
R = antenna_orientation_matrix(torch.tensor([math.pi / 2, 0.0, 0.0]), reference=torch.zeros(3))
print((R @ torch.tensor([1.0, 0.0, 0.0])).round(decimals=3))
tensor([-0., 1., 0.])