Path exchange
Backend-neutral propagation path records - PathRecord, interactions, provenance, and derivative payloads - shared by both RayD backends.
The path-exchange module describes one propagation path as plain Python data, independent of the backend that found it. Use it to hand reflection and diffraction paths to a channel model, a file, or another tool. Both backends expose the same API:
from rayd.drjit.path_exchange import PathRecord, reflection_path_record # or rayd.torch.path_exchangeRecords are frozen dataclasses and validate their contents when created. Values are Python floats and tuples, not arrays.
reflection_path_record#
reflection_path_record(
global_primitive_ids: Iterable[int],
*,
segment_lengths: Iterable[float] | None = None,
positions: Iterable[Sequence[float]] | None = None,
normals: Iterable[Sequence[float]] | None = None,
source_index: int = -1,
receiver_index: int = -1,
provenance: PathProvenance = PathProvenance.REFLECTION_TRACE,
total_length: float | None = None,
delay: float | None = None,
aod: Sequence[float] | None = None,
aoa: Sequence[float] | None = None,
field: Sequence[complex] | None = None,
power: float | None = None,
differentiable_fields: PathDerivativeField = PathDerivativeField.NONE,
derivative_mode: PathDerivativeMode = PathDerivativeMode.NONE,
derivative: PathDerivative | None = None,
interaction_derivatives: Iterable[PathInteractionDerivative] = (),
) -> PathRecordBuilds a valid reflection path with one REFLECTION interaction per primitive.
Scene-global reflector ids, in path order. Their count is the path order.
NoneOne length per reflection. When total_length is not given, it is set to their sum.
NoneReflection points, one 3-vector per reflection.
NoneSurface normals, one 3-vector per reflection.
-1Index of the transmitter in your own list; -1 means unknown.
-1Index of the receiver; -1 means unknown.
REFLECTION_TRACEWhich operation produced the path.
NoneTotal path length in scene units.
NonePropagation delay.
NoneAngle-of-departure direction, a 3-vector.
NoneAngle-of-arrival direction, a 3-vector.
NoneComplex field, three components.
NonePath power, finite and non-negative.
NONEFields that carry a derivative. Must be a subset of available_fields.
NONETANGENT (forward) or ADJOINT (reverse) when a derivative payload is attached.
NoneDerivative of the path-level fields.
()Derivatives of interaction positions and normals, one per interaction.
Raises ValueError when positions, normals, or segment_lengths do not match the number of primitives, when a vector does not have three finite components, or when derivative fields and payloads are inconsistent.
from rayd.drjit.path_exchange import reflection_path_record, PathProvenance
rec = reflection_path_record(
[0], segment_lengths=[2.23607], positions=[(0.5, 0.0, 0.0)], normals=[(0.0, 0.0, 1.0)],
source_index=0, receiver_index=0, provenance=PathProvenance.REFLECTION_EPC,
delay=2.23607 / 299792458.0)
print(rec.order, rec.total_length) # 1 2.23607
print(int(rec.available_fields)) # 15: positions, normals, total length, delaydiffraction_path_record#
diffraction_path_record(
global_edge_ids: Iterable[int],
*,
positions=None, normals=None, source_index=-1, receiver_index=-1,
provenance: PathProvenance = PathProvenance.DIFFRACTION_DIRECT,
total_length=None, delay=None, aod=None, aoa=None, field=None, power=None,
differentiable_fields=PathDerivativeField.NONE, derivative_mode=PathDerivativeMode.NONE,
derivative=None, interaction_derivatives=(),
) -> PathRecordBuilds a valid diffraction path with one DIFFRACTION interaction per scene-global edge id. The keyword arguments mean the same as in reflection_path_record; there is no segment_lengths.
Raises ValueError when positions or normals do not match the number of edges.
PathRecord#
PathRecord(
valid: bool, order: int, source_index: int, receiver_index: int, provenance: PathProvenance,
interactions: tuple[PathInteraction, ...] = (),
total_length=None, delay=None, aod=None, aoa=None, field=None, power=None,
fixed_winner: bool = True,
differentiable_fields: PathDerivativeField = PathDerivativeField.NONE,
derivative_mode: PathDerivativeMode = PathDerivativeMode.NONE,
derivative: PathDerivative | None = None,
interaction_derivatives: tuple[PathInteractionDerivative, ...] = (),
)One path. Create it directly for imported paths; the two helpers fill it for you.
| Rule | Error |
|---|---|
order equals len(interactions) | ValueError |
source_index, receiver_index are -1 or non-negative | ValueError |
a valid path has a provenance other than UNKNOWN | ValueError |
derivatives require fixed_winner=True | ValueError |
differentiable_fields is a subset of available_fields | ValueError |
interactions holds PathInteraction records | TypeError |
fixed_winner=True states that the derivatives follow RayD's fixed-winner contract.
Property available_fields -> PathDerivativeField: the fields that are present (interaction positions and normals when every interaction has them, and each non-None path field).
Method as_exchange_dict() -> dict: a JSON-friendly dict with enums as integers.
d = rec.as_exchange_dict()
print(d["provenance"], d["interactions"][0]["global_primitive_id"]) # 2 0PathInteraction#
PathInteraction(kind: PathInteractionKind, global_primitive_id: int = -1, global_edge_id: int = -1,
position: Vec3 | None = None, normal: Vec3 | None = None)One event on the path. A REFLECTION needs a global_primitive_id, a DIFFRACTION needs a global_edge_id, and NONE carries neither.
PathDerivative, PathInteractionDerivative#
PathDerivative(total_length=None, delay=None, aod=None, aoa=None, field=None, power=None)
PathInteractionDerivative(position=None, normal=None)Derivative payloads, in the direction given by derivative_mode. Each listed differentiable_fields entry must have a value; values must be finite.
Enumerations#
| Enum | Members |
|---|---|
PathInteractionKind (IntEnum) | NONE 0, REFLECTION 1, DIFFRACTION 2 |
PathProvenance (IntEnum) | UNKNOWN 0, REFLECTION_TRACE 1, REFLECTION_EPC 2, DIFFRACTION_DIRECT 3, DIFFRACTION_CHAIN 4, IMPORTED 5 |
PathDerivativeMode (IntEnum) | NONE 0, TANGENT 1, ADJOINT 2 |
PathDerivativeField (IntFlag) | NONE 0, INTERACTION_POSITION 1, INTERACTION_NORMAL 2, TOTAL_LENGTH 4, DELAY 8, AOD 16, AOA 32, COMPLEX_FIELD 64, POWER 128 |