RecordTensor

class RecordTensor(owner: Module, name: str, step_time: float, duration: float, value: Tensor | Parameter | None, constraints: dict[int, int] | None = None, persist_data: bool = True, persist_constraints: bool = False, persist_temporal: bool = False, strict: bool = True, live: bool = False, inclusive: bool = False)[source]

Bases: ShapedTensor

Tensor attribute with recorded history.

Read Operations: peek(), pop(), read(), readrange(), select()

Write Operations: push(), write(), writerange(), insert()

Parameters:
  • owner (Module) – module to which this attribute will belong.

  • name (str) – name of the attribute.

  • step_time (float) – length of time between stored values in the record.

  • duration (float) – length of time over which prior values are stored.

  • value (torch.Tensor | nn.Parameter | None) – tensor-like data for the attribute.

  • constraints (dict[int, int] | None, optional) – constraints given as a dictionary of dimensions to their corresponding size. Defaults to None.

  • persist_data (bool, optional) – if the data should persist across the state dictionary, only used with buffers. Defaults to True.

  • persist_constraints (bool, optional) – if the constraints should persist across the state dictionary. Defaults to False.

  • persist_temporal (bool, optional) – if temporal information (step time and duration) should persist across the state dictionary. Defaults to False.

  • strict (bool, optional) – if each dimension must specify a unique dimension for the tensor. Defaults to True.

  • live (bool, optional) – if constraint validity should be tested on assignment. Defaults to False.

  • inclusive (bool, optional) – if the duration should represent the maximum time which can be sampled. Defaults to False.

Note

While the last dimension of a selector tensor is used to index times, the underlying storage uses the first dimension such that each time slice is stored contiguously.

LinkedAttributes

alias of RecordTensorAttributes

align(index: int = 0) None[source]

Aligns the storage such that the oldest observation is at a specified index.

Parameters:

index (int, optional) – index to align to. Defaults to 0.

Raises:

RuntimeError – cannot align when storage is uninitialized (ignored).

property attributes: RecordTensorAttributes

Names of the dependent attributes created.

This is a named tuple with attributes data, constraints, dt, duration, and pointer.

Returns:

names of the created attributes in the containing module.

Return type:

RecordTensor.LinkedAttributes

property constraints: dict[int, int]

Dictionary of registered constraints.

Each key corresponds to a dimension of the tensor, and its associated value is the size of that dimension. This shifts the dimensions of negative constraints to make the record size transparent.

Returns:

dictionary of constraints.

Return type:

dict[int, int]

classmethod create(owner: Module, name: str, step_time: float, duration: float, value: Tensor | Parameter | None, constraints: dict[int, int] | None = None, persist_data: bool = True, persist_constraints: bool = False, persist_temporal: bool = False, strict: bool = True, live: bool = False, inclusive: bool = False) None[source]

Creates a record tensor and adds it as an attribute.

The following two calls are equivalent.

module.name = RecordTensor(owner, name, step_time, duration, value)
RecordTensor.create(module, name, step_time, duration, value)
Parameters:
  • owner (Module) – module to which this attribute will belong.

  • name (str) – name of the attribute.

  • step_time (float) – length of time between stored values in the record.

  • duration (float) – length of time over which prior values are stored.

  • value (torch.Tensor | nn.Parameter | None) – tensor-like data for the attribute.

  • constraints (dict[int, int] | None, optional) – constraints given as a dictionary of dimensions to their corresponding size. Defaults to None.

  • persist_data (bool, optional) – if the data should persist across the state dictionary, only used with buffers. Defaults to True.

  • persist_constraints (bool, optional) – if the constraints should persist across the state dictionary. Defaults to False.

  • persist_temporal (bool, optional) – if temporal information (step time and duration) should persist across the state dictionary. Defaults to False.

  • strict (bool, optional) – if each dimension must specify a unique dimension for the tensor. Defaults to True.

  • live (bool, optional) – if constraint validity should be tested on assignment. Defaults to False.

  • inclusive (bool, optional) – if the duration should represent the maximum time which can be sampled. Defaults to False.

decr(pos: int = 1) None[source]

Moves the pointer backward.

Parameters:

pos (int, optional) – number of steps by which to move the pointer backward. Defaults to 1.

Returns:

new location of the pointer.

Return type:

int

Raises:

RuntimeError – cannot modify the pointer when the storage is uninitialized (ignored).

deinitialize(use_uninitialized: bool = False) Tensor | Parameter[source]

Deinitializes the storage tensor.

This either assigns an empty tensor with shape [0] as the value or either UninitializedBuffer or UninitializedParameter. The device, data type, and gradient requirement will be preserved.

If the storage tensor is already not initialized, it will still be reassigned. If it is None, the defaults of will be used and it will be reassigned either with UninitializedBuffer() or torch.empty(0).

Parameters:

use_uninitialized (bool, optional) – if an uninitialized buffer or uninitialized parameter should be used. Defaults to False.

Returns:

deinitialized storage.

Return type:

torch.Tensor | nn.Parameter

property dt: float

Length of time between recorded observations.

In the same units as duration.

If the step time is changed such that the record size needs to change, a reconstrain() operation will be performed automatically, preserving the newest entires. Stored values may no longer be logically valid, but will still be accessible.

Parameters:

value (float) – new time step length.

Returns:

length of the time step.

Return type:

float

property duration: float

Length of time over which prior values are stored.

In the same units as dt.

If the step time is changed such that the record size needs to change, a reconstrain() operation will be performed automatically, preserving the newest entires.

Parameters:

value (float) – new length of the record.

Returns:

length of the record as the length of time.

Return type:

float

Note

If duration is not evenly divided by dt, then the number of observations stored will be rounded up. This property will always return the duration set although the range of accessible values may be larger.

property inclusive: bool

If the duration represents the maximum accessible range.

Parameters:

value (bool) – inclusivity of observations.

Returns:

if the duration represents the maximum accessible range.

Return type:

bool

Note

duration will remain the same but its interpretation may change. If inclusive is set to a different value, recordsz will change and the storage will be rebuilt.

incr(pos: int = 1) int[source]

Moves the pointer forward.

Parameters:

pos (int, optional) – number of steps by which to move the pointer forward. Defaults to 1.

Returns:

new location of the pointer.

Return type:

int

Raises:

RuntimeError – cannot modify the pointer when the storage is uninitialized (ignored).

initialize(shape: tuple[int, ...], device: device | None = None, dtype: dtype | None = None, fill: Any = 0) Tensor | Parameter[source]

Initializes the storage tensor.

Parameters:
  • shape (tuple[int, ...]) – shape, excluding the record dimension, of the storage tensor.

  • device (torch.device | None, optional) – overrides the device on which to place the tensor when not None. Defaults to None.

  • dtype (torch.dtype | None, optional) – overrides data tyoe of the tensor when not None. Defaults to None.

  • fill (Any, optional) – value with which to fill the tensor. Defaults to 0.

Returns:

initialized buffer or parameter.

Return type:

torch.Tensor | nn.Parameter

insert(obs: Tensor, time: Tensor | float, extrap: Extrapolation | None = None, *, tolerance: float = 1e-06, offset: int = 0, inplace: bool = False, extrap_kwargs: dict[str, Any] | None = None) None[source]

Inserts new elements into the record tensor by time.

If time is a scalar and is within tolerance of an integer index, then the observation will be written without ever attempting extrapolation.

If time is a tensor, interpolation will be called regardless, and the time passed into the extrapolation call will be set to either 0 or dt. Extrapolation results are then overwritten with exact values before writing.

The dtype of elements inserted into the underlying storage will be cast back to the data type of the storage after extrapolation.

Parameters:
  • obs (torch.Tensor) – observation to write at the specified times.

  • time (torch.Tensor | float) – time at which to write each element of the observation.

  • extrap (Extrapolation | None, optional) – function to interpolate from the observation to its neighbors, nearest when None. Defaults to None.

  • tolerance (float, optional) – maximum difference in time from a discrete sample to consider a time co-occurring with the sample. Defaults to 1e-6.

  • offset (int, optional) – number of steps before the pointer. Defaults to 0.

  • inplace (bool, optional) – if the operation should be performed in-place with torch.no_grad. Defaults to False.

  • extrap_kwargs (dict[str, Any] | None, optional) – dictionary of keyword arguments to pass to extrap. Defaults to None.

Raises:
  • RuntimeError – cannot insert into uninitialized (ignored) storage.

  • ValueError – shape of obs must match the shape of an observation.

  • ValueError – shape of time must match the shape of an observation.

  • ValueError – all elements of time must be within the range of observation times plus the tolerance.

Shape

obs, time:

\(S_0 \times \cdots\)

Where:
  • \(S_0, \ldots\) are the dimensions of each observation, given by shape.

Tip

Limitations on torch.scatter() make it risky to insert multiple observations at once and is therefore unsupported. To write multiple values at once, consider using writerange().

property latest: Tensor | None

Most recent stored observation.

When used as a getter, this is an alias for peek().

When used as a setter, this is an alias for push() with inplace set to False.

When used as a deleter, this is an alias for decr() with pos set to 1.

Parameters:

value (torch.Tensor) – observation to push.

Returns:

value of the most recently recorded observation.

Return type:

torch.Tensor | None

peek() Tensor | None[source]

Retrieves the most recently pushed observation.

If the state is uninitialized, then None will be returned. Otherwise this is an alias for self.read(offset=1).

Returns:

most recently pushed observation.

Return type:

torch.Tensor | None

property pointer: int

Current index of the pointer.

The location of the pointer indicates the location of the next observation which will be overwritten.

Returns:

current index of the pointer.

Return type:

int

pop() Tensor | None[source]

Retrieves the most recently pushed observation and decrements the pointer.

If the state is uninitialized, then None will be returned and the pointer will be unaltered.

Returns:

most recently pushed observation.

Return type:

torch.Tensor | None

Important

Unlike a pop-operation on most data structures, this does not affect the underlying storage. It only moves the pointer back so the next push() will overwrite that value.

push(obs: Tensor, inplace: bool = False) None[source]

Records an observation to the current location and advances the pointer.

This is an alias for the following code.

self.write(value, offset=0, inplace=inplace)
self.incr(pos=1)

If the storage is uninitialized, then it will be made automatically. The data type and gradient requirement will be preserved, but the storage will be put on the same device as obs. If inplace is False, the data type may be promoted to that of obs by PyTorch. Storage will be zero-filled.

Parameters:
  • obs (torch.Tensor) – observation to write.

  • inplace (bool, optional) – if the operation should be performed in-place with torch.no_grad. Defaults to False.

read(offset: int = 1) Tensor[source]

Reads the observation at an index relative to the pointer.

The pointer specifies the next observation to overwrite, and the offset specifies the number of observations back from which to read. The default value offset=1 will return the most recently pushed observation.

Parameters:

offset (int, optional) – number of steps before the pointer. Defaults to 1.

Raises:

RuntimeError – cannot read from uninitialized (ignored) storage.

Returns:

observation at the specified index.

Return type:

torch.Tensor

Shape

return:

\(S_0 \times \cdots\)

Where:
  • \(S_0, \ldots\) are the dimensions of each observation, given by shape.

readrange(length: int, offset: int | Tensor = 1, forward: bool = False) Tensor[source]

Reads multiple sequential observations.

When forward is False, then length observations will be read from the following interval.

[pointer - offset - length + 1, pointer - offset]

When forward is True, then length observations will be read from the following interval.

[pointer - offset, pointer - offset + length - 1]
Parameters:
  • length (int) – number of observations to read.

  • offset (int | torch.Tensor, optional) – number of steps before the pointer. Defaults to 1.

  • forward (bool, optional) – if the offset pointer indicates the index of the first observation. Defaults to False.

Raises:
  • RuntimeError – cannot read from uninitialized (ignored) storage.

  • ValueError – shape of offset must match the shape of an observation.

Returns:

observations at the specified indices.

Return type:

torch.Tensor

Shape

offset:

\(S_0 \times \cdots\)

return:

\(S_0 \times \cdots \times L\)

Where:
  • \(S_0, \ldots\) are the dimensions of each observation, given by shape.

  • \(L\), the number of observations, given by length.

reconstrain(dim: int, size: int | None) Tensor | Parameter | None[source]

Add, edit, or remove a constraint.

Like ShapedTensor.reconstrain(), except dim is modified to account for the record dimension. Negative values of dim will have 1 subtracted from them.

Parameters:
  • dim (int) – dimension on which to modify the constraint.

  • size (int | None) – new size for the specified dimension.

Returns:

newly constrained value.

Return type:

torch.Tensor | nn.Parameter | None

property recordsz: int

Number of observations stored.

\[N = \max\left(\left\lceil \frac{T}{\Delta t} \right\rceil + [\text{incl}], 1\right)\]

For duration \(T\), dt \(\Delta t\), and inclusive \(\text{incl}\).

Returns:

length of the record as the number of observations.

Return type:

int

reset(fill: Any | None = 0) None[source]

Fills the storage with a given value and aligns it to zero.

Parameters:

fill (Any | None, optional) – value with which to fill the storage, or if None no fill will be applied. Defaults to 0.

select(time: Tensor | float, interp: Interpolation | None = None, *, tolerance: float = 1e-06, offset: int = 1, interp_kwargs: dict[str, Any] | None = None) Tensor[source]

Selects previously observed elements of the record tensor by time.

If time is a scalar and is within tolerance of an integer index, then a observation will be returned without ever attempting interpolation.

If time is a tensor, interpolation will be called regardless, and the time passed into the interpolation call will be set to either 0 or dt. Interpolation results are then overwritten with exact values before returning.

Parameters:
  • time (torch.Tensor | float) – time at which to read each element from the underlying storage.

  • interp (Interpolation | None, optional) – function to interpolate between neighboring observations, nearest when None. Defaults to None.

  • tolerance (float, optional) – maximum difference in time from a discrete sample to consider a time co-occurring with the sample. Defaults to 1e-6.

  • offset (int, optional) – number of steps before the pointer. Defaults to 1.

  • interp_kwargs (dict[str, Any] | None, optional) – dictionary of keyword arguments to pass to interp. Defaults to None.

Raises:
  • RuntimeError – cannot select from uninitialized (ignored) storage.

  • ValueErrortime must have the same number of dimensions as an observation or that number plus one.

  • ValueError – all elements of time must be within the range of observation times plus the tolerance.

Returns:

interpolated values selected at a prior times.

Return type:

torch.Tensor

Shape

time:

\(S_0 \times \cdots \times [D]\)

return:

\(S_0 \times \cdots \times [D]\)

Where:
  • \(S_0, \ldots\) are the dimensions of each observation, given by shape.

  • \(D\) are the number of distinct observations to select.

property shape: tuple[int, ...] | None

Shape of the observations.

Returns:

shape of the observations, None when storage is uninitialized (ignored).

Return type:

tuple[int, …] | None

property value: Tensor | Parameter | None

Record storage tensor.

When created as a Parameter, assignment to None is prevented. If the current value is a Parameter but the assigned value is a Tensor, it will automatically assign to the data attribute of value.

When used as a deleter, this acts as an alias for self.deinitialize(use_uninitialized=False).

Parameters:

(value (value) – torch.Tensor | nn.Parameter | None): value to set the storage tensor to.

Returns:

storage tensor.

Return type:

torch.Tensor | nn.Parameter | None

Shape

value, return:

\(N \times S_0 \times \cdots\)

Where:
  • \(N\) is the number of observations the storage can hold, equal to recordsz.

  • \(S_0, \ldots\) are the dimensions of each observation, given by shape.

Caution

This should be used for setting properties of the underlying storage (device, data type, etc.) and for advanced initialization/deinitialization. General read/write access should generally be performed through the provided if possible.

Note

If after assigning the new value, ignored is True, the pointer will be moved to 0, otherwise it will not be changed.

write(obs: Tensor, offset: int = 0, inplace: bool = False) None[source]

Writes an observation at an index relative to the pointer.

The pointer specifies the next observation to overwrite, and the offset specifies the number of observations back from which to write. The default value offset=0 overwrite the oldest observation.

Parameters:
  • obs (torch.Tensor) – observation to write at the specified offset.

  • offset (int, optional) – number of steps before the pointer. Defaults to 0.

  • inplace (bool, optional) – if the operation should be performed in-place with torch.no_grad. Defaults to False.

Raises:
  • RuntimeError – cannot write to uninitialized (ignored) storage.

  • ValueError – shape of value must match the shape of an observation.

Shape

obs:

\(S_0 \times \cdots\)

Where:
  • \(S_0, \ldots\) are the dimensions of each observation, given by shape.

Important

The dtype of obs is not changed, so when inplace is set to False, this may cause the data type of the stored tensor to change.

writerange(obs: Tensor, offset: int | Tensor = 0, forward: bool = False, inplace: bool = False) None[source]

Writes multiple sequential observations.

When forward is False, then length observations will be written to the following interval.

[pointer - offset - length + 1, pointer - offset]

When forward is True, then length observations will be written to the following interval.

[pointer - offset, pointer - offset + length - 1]
Parameters:
  • obs (torch.Tensor) – observation to write at the specified offsets.

  • offset (int | torch.Tensor, optional) – number of steps before the pointer. Defaults to 0.

  • forward (bool, optional) – if the offset pointer indicates the index of the first observation. Defaults to False.

  • inplace (bool, optional) – if the operation should be performed in-place with torch.no_grad. Defaults to False.

Raises:
  • RuntimeError – cannot write to uninitialized (ignored) storage.

  • ValueError – written observations need to have a shape compatible with storage.

  • ValueError – cannot write more observations to storage than storage records.

  • ValueError – shape of offset must match the shape of an observation.

Important

The dtype of obs is not changed, offset is not a tensor, and inplace is set to False, this may cause the data type of the stored tensor to change. When offset is a tensor, a scatter() operation is performed so the data type will first be converted tot hat of the underlying storage.

Shape

obs:

\(S_0 \times \cdots \times L\)

offset:

\(S_0 \times \cdots\)

return:

\(S_0 \times \cdots \times L\)

Where:
  • \(S_0, \ldots\) are the dimensions of each observation, given by shape.

  • \(L\), the number of observations.