Skip to content

Dataset

timenet.dataset source

The in-memory TimeF model a connector populates during convert().

TimeAxis module-attribute source

Every shape a series' time axis can have.

AxisType source

Bases: StrEnum

Name which shape a series' time axis has.

TimeF stores this value and dispatches on it before it reads any shape-specific column. TimeF never infers the case from which columns came back null.

IRREGULAR class-attribute instance-attribute source

IRREGULAR = 'irregular'

One stored time offset per value.

ORDINAL class-attribute instance-attribute source

ORDINAL = 'ordinal'

Order only: no cadence, no time offsets, no place on any timeline.

REGULAR class-attribute instance-attribute source

REGULAR = 'regular'

Time offsets computed from a period and an origin.

IrregularAxis dataclass source

A placement no formula produces, so this axis stores every time offset.

This axis holds only the pair a builder can state and the writer can verify without a read. That pair is the first and the last stored time offset. The time offsets themselves live in the shared stored axis. Reach them through :attr:~timenet.dataset.Signal.time_offsets_us.

That split is the point. Two ints compare and hash, so the axis goes whole into the writer's series identity and round-trips as a value through the records struct. An axis holding the array does neither: a tuple comparison against an ndarray field raises instead of answering.

The endpoints are metadata about the stream, not an identity for it. Two series whose time offsets differ only in the middle carry equal axes. Nothing can use axis equality to conclude the time offsets agree. Compare the streams instead.

This axis has no time_offset_us and no index_at_or_after on purpose. Both need a read, and a read is a series-level operation. :class:OrdinalAxis sets the precedent: an axis that cannot answer in constant time does not offer the method.

axis_type class-attribute source

The stored discriminator.

first_us instance-attribute source

first_us: int

Time offset of the first value, in microseconds from the record's relative zero.

last_us instance-attribute source

last_us: int

Time offset of the last value. The writer checks it against the stream at write time, so it is verified metadata, not an unbacked claim.

spanning classmethod source

spanning(time_offsets_us: ndarray | Sequence[int]) -> Self

Build the axis describing a stream of time offsets.

Parameters:

Name Type Description Default
time_offsets_us ndarray | Sequence[int]

The per-value time offsets, in microseconds from the record's relative zero.

required

Returns:

Type Description
Self

The axis carrying that stream's endpoints, after :func:to_time_offsets_us has vetted it.

OrdinalAxis dataclass source

An Axis to indicate an order without a cadence, time offsets, or place on any timeline.

axis_type class-attribute source

axis_type: AxisType = AxisType.ORDINAL

The stored discriminator.

Record dataclass source

Bases: SupportsAnnotate

One logical unit of time-series data: a recording, a session, a sensor bundle, a market window.

You create a record with :meth:~timenet.dataset.TimeFDataset.add_record. The record is mutable, so you can add annotations after construction.

Use metadata for untyped JSON details. Record-level facts, such as a subject's age or the recording device, are :class:~timenet.types.Annotation objects with no span. Such an annotation can also state a unit, and it travels with every window drawn later from the record.

annotations class-attribute instance-attribute source

annotations: tuple[Annotation, ...] = ()

Annotations attached to the record.

has_absolute_time property source

has_absolute_time: bool

Whether this record's relative timeline has a Unix-time anchor.

id property source

The record's id, unique among the records of its dataset.

:meth:~timenet.dataset.TimeFDataset.add_record sets it, and the reader sets it on read-back.

Raises:

Type Description
TimeFValidationError

If the record is not in a dataset yet.

metadata class-attribute instance-attribute source

metadata: JsonMapping = field(default_factory=dict)

Optional JSON-compatible recording metadata.

signals property source

signals: tuple[Signal, ...]

Every signal in this record's hierarchy.

sources class-attribute instance-attribute source

sources: tuple[Source, ...] = ()

The root sources that belong to this recording, each with a distinct name.

start_time class-attribute instance-attribute source

start_time: TimeOrigin = field(default_factory=TimeOrigin)

The common relative zero, with an optional absolute timestamp.

time_span class-attribute instance-attribute source

time_span: TimeInterval | None = None

The session's overall span on the source recording timeline: an :class:~timenet.types.TimeInterval covering the whole record, or None. Declare it when the series have gaps and an event may fall in one, for example a note taken while every sensor was briefly off. This checks an unscoped span against it, rather than against the union of the series' windows. Its time_series must be None, and it must contain every series' window.

add_annotations source

add_annotations(
    annotations: Iterable[Annotation],
    *,
    warn_when_outside: bool = True,
) -> tuple[Annotation, ...]

Attach several annotations to the record, all together or not at all.

The whole batch is validated before any of it is attached: if one annotation fails a check, the call raises and leaves the record unchanged. To keep the annotations before a failure attached, loop :meth:annotate instead.

Parameters:

Name Type Description Default
annotations Iterable[Annotation]

The annotations to attach. Pass a single one to :meth:annotate.

required
warn_when_outside bool

As on :meth:annotate.

True

Returns:

Type Description
tuple[Annotation, ...]

New occurrences that share the input annotations' reusable content, in the order given.

Raises:

Type Description
TimeFValidationError

as documented on :meth:annotate.

annotate source

annotate(
    annotation: Annotation,
    *,
    warn_when_outside: bool = True,
) -> Annotation

Attach an annotation to the record and return it.

Parameters:

Name Type Description Default
annotation Annotation

The annotation to attach.

required
warn_when_outside bool

Warn and keep the span when it leaves its window, rather than raise.

True

Returns:

Type Description
Annotation

A new occurrence that shares the input annotation's reusable content.

Raises:

Type Description
TimeFValidationError

If the annotation's span references a series not on this record. If a scoped span names a timeless series. If the span falls outside the window its scope selects: the intersection of named series, the record's time_span, or the union of the series' windows and warn_when_outside is False.

time_interval source

time_interval(
    start: datetime,
    end: datetime,
    *,
    time_series: tuple[Signal, ...] | None = None,
) -> TimeInterval

Build a :class:~timenet.types.TimeInterval between two wall-clock moments on this timeline.

The Record must have a known absolute timestamp.

Parameters:

Name Type Description Default
start datetime

Wall-clock start, timezone-aware.

required
end datetime

Wall-clock end, exclusive and timezone-aware.

required
time_series tuple[Signal, ...] | None

Series the interval is scoped to. None covers every series.

None

Returns:

Type Description
TimeInterval

The half-open interval, in microseconds from this record's relative zero.

time_point source

time_point(
    at: datetime,
    *,
    time_series: tuple[Signal, ...] | None = None,
) -> TimePoint

Build a :class:~timenet.types.TimePoint at a wall-clock moment on this record's timeline.

The Record must have a known absolute timestamp.

Parameters:

Name Type Description Default
at datetime

The wall-clock moment, timezone-aware.

required
time_series tuple[Signal, ...] | None

Series the point is scoped to. None covers every series.

None

Returns:

Type Description
TimePoint

The point, in microseconds from this record's relative zero.

to_arrow source

to_arrow() -> Array

Read the sole signal's values as an Arrow array, for the common single-signal record.

Returns:

Type Description
Array

The single :class:Signal' values as a 1-D Arrow array.

Raises:

Type Description
ValueError

If the record has more than one signal, read signals[i] explicitly then.

to_numpy source

to_numpy() -> ndarray

Read the sole signal's values as NumPy, without building Arrow when they are NumPy.

Returns:

Type Description
ndarray

The single :class:Signal' values as an np.ndarray.

Raises:

Type Description
TimeFValidationError

If the record does not have exactly one signal.

walk_annotations source

walk_annotations() -> Iterable[Annotation]

Yield annotation occurrences from this Record, its Sources, and its Signals.

walk_signals source

walk_signals() -> Iterable[Signal]

Yield every signal in deterministic source and signal order.

walk_sources source

walk_sources() -> Iterable[Source]

Yield all sources in deterministic depth-first order.

Yields:

Type Description
Iterable[Source]

Every source in the record.

Raises:

Type Description
TimeFValidationError

If a source is attached twice or the hierarchy contains a cycle.

RegularAxis dataclass source

A constant cadence with an offset from the record's relative zero.

The origin is an index into the cadence, not a time, because a window rarely starts on a whole microsecond. At 44.1 kHz only 3 of 1000 window starts do, so a microsecond origin is inexact for almost every window. An index is exact for all of them.

axis_type class-attribute source

axis_type: AxisType = AxisType.REGULAR

The stored discriminator. Each shape declares its own tag, so a new shape must declare one too.

offset_us class-attribute instance-attribute source

offset_us: int = 0

Whole microseconds from the record origin to the cadence's zero.

period_us instance-attribute source

period_us: Fraction

Microseconds between values. It is a :class:~fractions.Fraction because not every real rate is a whole number of microseconds: 360 Hz is 25000/9 and 256 Hz is 15625/4. TimeF stores it as its numerator and denominator.

start_index class-attribute instance-attribute source

start_index: int = 0

Index of this series' first value on the cadence. It is non-zero for a window cut from a longer recording, which keeps a span written against the recording meaningful on the window.

at_index source

at_index(index: int) -> Self

Return the axis of a window that starts index values into this one.

This is exact at every rate, because the origin it moves is an index, not a derived time.

Parameters:

Name Type Description Default
index int

How many values into this axis the window starts.

required

Returns:

Type Description
Self

The window's axis, which shares this period.

from_rate_hz classmethod source

from_rate_hz(
    rate_hz: int | Fraction, *, offset_us: int = 0
) -> Self

Build the axis of a regularly sampled series from its exact rate.

This method does not accept a float. Every real sampling rate is a whole number of values per second, so write 500.0 as 500. A rate that is not whole has no single reading: 29.97 fps is 2997/100 by its spelling and 30000/1001 by its intent. Those two drift 3.6 ms apart over an hour. State which one with a :class:~fractions.Fraction, and build the Fraction from a string, not a float. Fraction(29.97) is the binary expansion (1054475631502295/35184372088832), and Fraction("29.97") is 2997/100.

Parameters:

Name Type Description Default
rate_hz int | Fraction

Values per second.

required
offset_us int

Whole microseconds from the record origin to the cadence's zero.

0

Returns:

Type Description
Self

The axis whose period is one sampling period of rate_hz.

Raises:

Type Description
TimeFValidationError

If rate_hz is not a positive integer or Fraction.

index_at_or_after source

index_at_or_after(time_offset_us: int) -> int

Return the first value at or after a time offset.

Parameters:

Name Type Description Default
time_offset_us int

The time offset, in microseconds from the record's relative zero.

required

Returns:

Type Description
int

The index within this series, which is negative if the time offset precedes its first value.

time_offset_us source

time_offset_us(index: int) -> int

Return the time offset of one value, floored to whole microseconds.

This floor pairs with the ceiling in :meth:index_at_or_after. The two are exactly inverse at every period of one microsecond or coarser, including the non-integral ones.

Parameters:

Name Type Description Default
index int

The value's index within this series.

required

Returns:

Type Description
int

Microseconds from the record's relative zero.

Signal dataclass source

Bases: SupportsAnnotate

Reference to one logical stream of time-series data, with optional windowing and lazy values.

Each Signal has exactly one owning Source. Several Signals can share an immutable TimeAxis or TimeSeriesSpec. Consumers read values through :meth:to_arrow or :meth:to_numpy, which apply the spec. The values sit behind an internal :class:~timenet.types.ArrayHandle: the constructor holds them in memory, and :meth:from_loader takes a handle or a callable.

annotations class-attribute instance-attribute source

annotations: tuple[Annotation, ...] = ()

Annotations attached directly to this signal.

id property source

The signal's id, unique among the signals of its dataset.

:meth:~timenet.dataset.TimeFDataset.add_record sets it, and the reader sets it on read-back.

Raises:

Type Description
TimeFValidationError

If the signal's record is not in a dataset yet.

is_ordinal property source

is_ordinal: bool

Whether this series counts steps only and has no timeline, so time spans cannot place it.

metadata class-attribute instance-attribute source

metadata: JsonMapping = field(default_factory=dict)

Optional JSON-compatible signal metadata.

n_values instance-attribute source

n_values: int

The number of values the series holds, one per timestep. If spec gives each timestep a shape, the series counts one value per timestep, not one per scalar. This matches the count a chunk's n_values reports.

name instance-attribute source

name: str

Human-readable signal name within the source.

span_us property source

span_us: tuple[int, int] | None

The half-open microsecond window this series covers, or None if it has no timeline.

The axis derives this window, so the window and the axis cannot disagree. The dispatch ends in :func:~typing.assert_never, so a new axis shape breaks this method at type-check time.

Returns:

Type Description
tuple[int, int] | None

(first time_offset, one past the last) in microseconds, or None for an ordinal series.

spec instance-attribute source

Measurement-modality contract: type tag, units, dtype, and per-timestep shape.

time_axis instance-attribute source

time_axis: TimeAxis

Where this series' values sit in time. A :class:~timenet.dataset.axis.RegularAxis gives a cadence, an :class:~timenet.dataset.axis.IrregularAxis stores per-value time offsets, and an :class:~timenet.dataset.axis.OrdinalAxis marks a sequence with no time at all.

annotate source

annotate(annotation: Annotation) -> Annotation

Attach one annotation and return it.

Parameters:

Name Type Description Default
annotation Annotation

The annotation to attach.

required

Returns:

Type Description
Annotation

The attached annotation.

from_irregular classmethod source

from_irregular(
    values: ndarray
    | Sequence[bool | int | float | str | None]
    | Array,
    *,
    time_offsets_us: ndarray | Sequence[int],
    spec: TimeSeriesSpec,
    name: str,
    full_validation: bool = True,
) -> Signal

Build an irregular series from materialized values and their time offsets.

The axis endpoints come from the stream itself, so the two cannot disagree. You cannot state a first or last time offset that the time offsets do not have. To convert wall-clock moments, use :func:~timenet.dataset.axis.time_offsets_from_datetimes before you call. Numeric NumPy values and normalized time offsets retain their buffers for NumPy reads, which return read-only arrays. Arrow conversion happens only on an Arrow read. Treat retained input buffers as read-only.

Parameters:

Name Type Description Default
values ndarray | Sequence[bool | int | float | str | None] | Array

The signal values to convert to the spec's dtype. Text and enum specs take strings. Python None marks a missing timestep when spec.nullable is true.

required
time_offsets_us ndarray | Sequence[int]

One time offset per value, in microseconds from the record's relative zero.

required
spec TimeSeriesSpec

The series' measurement-modality spec.

required
name str

The signal name.

required
full_validation bool

Check timestamp ordering by default. Set to False only for previously validated timestamps to skip that scan. Both modes check type, shape, integer range, endpoints, and one timestamp per value. Conversion can still allocate when needed.

True

Returns:

Type Description
Signal

The constructed :class:Signal.

Raises:

Type Description
TimeFValidationError

If the time offsets are unusable, or there is not exactly one per value.

from_loader classmethod source

from_loader(
    *,
    spec: TimeSeriesSpec,
    time_axis: TimeAxis,
    name: str,
    loader: ArrayHandle | Callable[[], Array],
    n_values: int,
    time_offsets_loader: ArrayHandle
    | Callable[[], Array]
    | None = None,
    annotations: tuple[Annotation, ...] = (),
    metadata: JsonMapping | None = None,
) -> Signal

Build a signal whose values are loaded only when they are read.

loader and time_offsets_loader each take a value handle, which the signal keeps as it is, or a plain callable returning an Arrow array, which the signal calls on every read. A callable with its own read_steps() is rejected: subclass ArrayHandle to keep its range reads.

Returns:

Type Description
Signal

A signal backed by loader without reading it.

from_values classmethod source

from_values(
    values: ndarray
    | Sequence[bool | int | float | str | None],
    *,
    spec: TimeSeriesSpec,
    name: str,
    time_axis: TimeAxis,
) -> Signal

Build a series from already-materialized values and hold them in memory in the spec's dtype.

Numeric NumPy arrays retain their buffers when dtype and layout already match the spec. NumPy reads return fresh read-only views; treat the input buffers as read-only while in use. Arrow conversion happens only on an Arrow read. Other inputs become Arrow arrays immediately. The array length sets n_values.

For files or remote sources, use :meth:from_loader and supply the length. That constructor does not read the values immediately.

Parameters:

Name Type Description Default
values ndarray | Sequence[bool | int | float | str | None]

The signal values to convert to the spec's dtype. Text and enum specs take strings. Python None marks a missing timestep when spec.nullable is true.

required
spec TimeSeriesSpec

The series' measurement-modality spec.

required
name str

The signal name.

required
time_axis TimeAxis

Where the values sit in time.

required

Returns:

Type Description
Signal

The constructed :class:Signal.

is_selected_by source

is_selected_by(span: Span) -> bool

Return whether span applies to this series.

A step span selects only the series it counts on. A time span with no time_series selects every series, and a time span with time_series set selects only the series it lists. Series are compared by identity, not by name, so a span does not select a slice of a series it names: the slice is a new series.

This checks the scope only, not the time.

Parameters:

Name Type Description Default
span Span

A time or step span, point or interval.

required

Returns:

Type Description
bool

True if the span applies to this series.

Raises:

Type Description
TimeFValidationError

If span is neither a time span nor a step span.

overlaps_with source

overlaps_with(span: TimeSpan) -> bool

Return whether at least one value of this series falls inside span.

A value is inside when its time offset falls in [start_us, exclusive_end), the rule :meth:slice uses, so for a time interval slice(span, clip=True) keeps a value whenever this returns True. This compares times only and ignores the span's time_series: ask :meth:is_selected_by whether the span applies to this series.

Parameters:

Name Type Description Default
span TimeSpan

A time interval or time point on the record timeline.

required

Returns:

Type Description
bool

True if a value of this series falls inside the span.

Raises:

Type Description
TimeFValidationError

If span is not a :class:~timenet.types.TimeSpan. If the series is ordinal: it has no timeline, so check :attr:is_ordinal first.

read_steps source

read_steps(start: int, stop: int) -> Array

Read a half-open temporal step range as Arrow without forcing a NumPy conversion.

A series whose stored values were loaded, or that holds its values in memory, is sliced. An unloaded stored series reads only the chunks that intersect the range, and one from a loader callable is read in full first.

Parameters:

Name Type Description Default
start int

First temporal step, inclusive.

required
stop int

Last temporal step, exclusive.

required

Returns:

Type Description
Array

A primitive Arrow array for scalar series or a fixed-shape tensor array for N-D series.

Raises:

Type Description
TimeFValidationError

If the range is negative or reversed.

slice source

slice(span: Span, *, clip: bool = False) -> Signal

Return a new lazy series that holds only the steps span covers.

The span must hold at least one value. A step span must count on this series. A time span is placed by time only, so ask :meth:is_selected_by first when the scope matters. The slice keeps the name, spec, metadata, and place on the timeline, drops annotations, and reads no values until it is read::

if signal.overlaps_with(interval):
    part = signal.slice(interval, clip=True)

The "Cut a window" docs show how to cut every signal of a record.

Parameters:

Name Type Description Default
span Span

The interval to keep: a time interval within :attr:span_us, or a step interval on this series that ends at or before :attr:n_values.

required
clip bool

Keep the part of the span inside this series instead of raising when the span reaches past it.

False

Returns:

Type Description
Signal

A lazy :class:Signal that holds the steps the span covers.

Raises:

Type Description
TimeFValidationError

If span is a point, a step span on another series, or a time span on an ordinal series. If the span reaches past this series and clip is false, or covers no step of this series.

step_range source

step_range(span: Span) -> tuple[int, int]

Return the half-open step range (start, stop) of this series that span covers.

The bridge to step-based forecasting libraries: stop - start is the horizon h that GluonTS, Nixtla, and fev speak in. The pair feeds :meth:read_steps to read the ground truth. A step span already counts in this series' own steps, so it is the range, bounded by the series' length. The axis locates a time span instead: the steps whose time offsets fall in [start_us, end_us), each rounded up to the next step. An ordinal series has no timeline, so a time span has no answer on it.

Parameters:

Name Type Description Default
span Span

The interval to locate. A step span must name this series.

required

Returns:

Type Description
tuple[int, int]

(start, stop) step indices, half-open, from this series' first step.

Raises:

Type Description
TimeFValidationError

If span is a point. If a step span does not name this series or runs past its length. If an ordinal series receives a time span, or the span resolves past the series' steps. If the located range is empty.

time_offsets_us source

time_offsets_us() -> ndarray

Read this series' per-value time offsets.

Only an irregular series has this. A regular axis computes its time offsets without a read, and an ordinal one has none. So neither has a stream to return.

Returns:

Type Description
ndarray

One int64 microsecond time offset per value.

Raises:

Type Description
TimeFValidationError

If this series' axis is not an :class:~timenet.dataset.axis.IrregularAxis.

to_arrow source

to_arrow() -> Array

Read the series' values as an Arrow array.

Returns:

Type Description
Array

A primitive array for scalar values or a fixed-shape tensor array for N-D values.

to_numpy source

to_numpy() -> Shaped[ndarray, ' time *value']

Read the series' values as a read-only NumPy array.

Returns:

Type Description
Shaped[ndarray, ' time *value']

The series' values with shape (n_steps, *spec.value_shape).

Raises:

Type Description
TimeFNullValuesError

If a timestep is missing or only partially present. Use :meth:to_arrow to preserve missingness. A nullable spec without actual nulls remains supported, as do NaN and infinity values.

SignalSelection dataclass source

A validated set of signals selected from one source subtree.

signals instance-attribute source

signals: tuple[Signal, ...]

Selected descendant signals in caller order.

source instance-attribute source

source: Source

Source whose descendant Signals can be selected.

annotate source

annotate(annotation: Annotation) -> tuple[Annotation, ...]

Attach one annotation content item to the selected signals.

Timed and static annotations create one occurrence per selected Signal. Each occurrence shares the original content. All selected Signals are validated before any annotation is attached.

Returns:

Type Description
tuple[Annotation, ...]

The attached occurrences in selection order.

from_source classmethod source

from_source(
    source: Source,
    *,
    signals: tuple[Signal, ...] | None,
    signal_names: tuple[str, ...] | None,
) -> SignalSelection

Resolve an object or name selection against a source subtree.

Returns:

Type Description
SignalSelection

The validated selection.

Raises:

Type Description
TimeFValidationError

If selectors are missing, mixed, duplicated, ambiguous, or unknown.

Source dataclass source

Bases: SupportsAnnotate

A device, sensor, or subsystem that contains child sources and signals.

annotations class-attribute instance-attribute source

annotations: tuple[Annotation, ...] = ()

Annotations attached to this source.

metadata class-attribute instance-attribute source

metadata: JsonMapping = field(default_factory=dict)

Optional JSON-compatible source metadata.

name instance-attribute source

name: str

Human-readable source name.

signals class-attribute instance-attribute source

signals: tuple[Signal, ...] = ()

Signals produced directly by this source.

sources class-attribute instance-attribute source

sources: tuple[Source, ...] = ()

Direct child sources, each with a distinct name. Their order has no semantic meaning.

annotate source

annotate(annotation: Annotation) -> Annotation

Attach one annotation and return it.

Returns:

Type Description
Annotation

The attached annotation.

select source

select(
    *,
    signals: tuple[Signal, ...] | None = None,
    signal_names: tuple[str, ...] | None = None,
) -> SignalSelection

Select descendant signals by object or by human-readable name.

Returns:

Type Description
SignalSelection

A selection that can be annotated as one declarative operation.

walk_signals source

walk_signals() -> Iterator[Signal]

Yield every descendant signal in deterministic source and signal order.

Yields:

Type Description
Signal

Signals from this source and every descendant source.

walk_sources source

walk_sources() -> Iterator[Source]

Yield this source and all descendants in deterministic depth-first order.

Yields:

Type Description
Source

This source followed by its descendants, sorted by name at each level.

Raises:

Type Description
TimeFValidationError

If the graph contains a cycle or one source has two parents.

TimeFDataset source

Bases: SupportsAnnotate

Holds records and their tasks as Python objects. It does not do I/O. The writer handles persistence.

annotations property source

annotations: tuple[Annotation, ...]

Annotations attached to the dataset itself.

has_task_stream property source

has_task_stream: bool

Whether tasks stream from a source (see :meth:set_task_stream) rather than the _tasks list.

last_ids property source

last_ids: dict[ObjectKind, EntityId]

The last id used per kind. A written version stores it, so later edits never reuse an id.

lineage property source

lineage: Mapping[str, ParentDatasetCard]

The card of every ancestor release, parents included, keyed by org/name@version.

The mapping is read-only. :meth:import_from adds to it.

metadata property source

metadata: DatasetMetadata

The dataset's descriptive identity.

parent_cards property source

parent_cards: Mapping[ParentAlias, ParentDatasetCard]

A copy of the card of each parent this dataset imports from, by parent alias.

The mapping is read-only. :meth:import_from adds to it.

records property source

records: tuple[Record, ...]

All records of the dataset.

For a dataset read from a release, the records come in the release's record order, as :meth:~timenet.reader.TimeFReader.record_ids lists it. Records added later follow them. For a dataset built in memory, the records come in the order in which they were added.

schema property source

schema: DatasetSchema | None

The derived schema, or None until :meth:derive_schema is called.

tasks property source

tasks: tuple[Task, ...]

All tasks in insertion order.

add_record source

add_record(*, record: Record) -> Record

Register and return a complete record.

The record and each of its signals get the next id of their kind.

Parameters:

Name Type Description Default
record Record

The complete record hierarchy to register.

required

Returns:

Type Description
Record

The same :class:Record instance, with its id and its signals' ids set.

add_task source

add_task(*, task: Task) -> Task

Validate and register one fully constructed task.

The Task owns its input and target object references. Registration verifies those objects against this dataset before it changes the dataset. It does not change the input Records. The task gets the next task id.

Parameters:

Name Type Description Default
task Task

The concrete task to register.

required

Returns:

Type Description
Task

The same task instance.

add_tasks source

add_tasks(*, tasks: Iterable[Task]) -> tuple[Task, ...]

Register several complete tasks, all together or not at all.

The method validates the whole batch before it attaches any task. If one task fails a check, the call raises an error, and the dataset and every task in the batch stay unchanged. To keep the tasks that passed before a failure, call :meth:add_task in a loop instead.

A task can derive from another task in the same batch. To do this, list the parent task in the deriving task's from_tasks field. The batch is checked as a unit, so the order of tasks within tasks does not matter.

Parameters:

Name Type Description Default
tasks Iterable[Task]

The task instances to register. For a single task, use :meth:add_task instead.

required

Returns:

Type Description
tuple[Task, ...]

The registered tasks, in the order given.

annotate source

annotate(annotation: Annotation) -> Annotation

Attach a static annotation to the dataset.

Returns:

Type Description
Annotation

The attached occurrence.

Raises:

Type Description
TimeFValidationError

If the annotation has a time placement, which is ambiguous across records.

derive_schema source

derive_schema() -> DatasetSchema

Walk the dataset's instances and build its :class:DatasetSchema.

This method collects the distinct spec, annotation, and task types. It stores the result on the dataset, and it returns the result.

Returns:

Type Description
DatasetSchema

The derived :class:DatasetSchema.

Raises:

Type Description
TimeFValidationError

If one spec type or annotation key yields conflicting descriptors across records.

describe source

describe(
    *, rows: int = 5, file: TextIO | None = None
) -> None

Print a plain-text summary of the dataset: its identity, counts, specs and columns, and a record preview.

This method works like pandas' describe and info methods. The preview reads only span metadata, not series values. The method checks value dtypes from one series per spec. This method works even before :meth:derive_schema runs, because it computes everything from the records.

Parameters:

Name Type Description Default
rows int

The number of records to show in the preview.

5
file TextIO | None

Where to write the output. The default is sys.stdout.

None

from_parts classmethod source

from_parts(
    *,
    metadata: DatasetMetadata,
    records: Iterable[Record],
    tasks: Iterable[Task],
    schema: DatasetSchema,
    annotations: Iterable[Annotation] = (),
    last_ids: Mapping[ObjectKind, EntityId] | None = None,
    import_state: ImportState | None = None,
) -> TimeFDataset

Build a dataset from parts that are already constructed.

The reader uses this method when it reads a dataset back from disk.

Parameters:

Name Type Description Default
metadata DatasetMetadata

The dataset's descriptive identity.

required
records Iterable[Record]

Fully built records. Their loaders pull data from disk.

required
tasks Iterable[Task]

Fully built tasks, with their from_tasks references resolved.

required
schema DatasetSchema

The schema reconstructed from the manifest.

required
annotations Iterable[Annotation]

Annotations attached directly to the dataset.

()
last_ids Mapping[ObjectKind, EntityId] | None

The id counters of the dataset these parts come from, so new objects never reuse the id of a removed one.

None
import_state ImportState | None

The parent cards, the lineage, and the import map of the dataset these parts come from. The new dataset keeps this object. Without it, the dataset starts with no parent cards, no lineage, and an empty import map.

None

Returns:

Type Description
TimeFDataset

The dataset, built from these parts. The records, signals, and tasks keep the ids they

TimeFDataset

have.

get_all source

get_all() -> tuple[Task, ...]

Return every task whatever its split, in insertion order.

Returns:

Type Description
tuple[Task, ...]

The tasks. A streamed dataset drains its stream and materializes them.

get_split source

get_split(split: Split | str) -> tuple[Task, ...]

Return the tasks of one split, in insertion order.

A dataset partitions its tasks by setting :attr:~timenet.types.Task.split on each one. Records carry no split of their own: a record may serve tasks of several splits. A streamed dataset drains its stream and materializes the selection.

Parameters:

Name Type Description Default
split Split | str

The partition to select, as a :class:~timenet.types.Split or its value.

required

Returns:

Type Description
tuple[Task, ...]

The matching tasks. Empty when the dataset partitions its tasks but none is in split.

Raises:

Type Description
TimeFValidationError

If split is unknown, or if no task of the dataset belongs to any split. Asking a partition of a dataset that has none is a mistake rather than an empty selection, so it fails rather than returning nothing.

get_splits source

get_splits(*splits: Split | str) -> tuple[Task, ...]

Return the union of selected splits without changing task assignments.

Parameters:

Name Type Description Default
*splits Split | str

One or more partitions, such as Split.TRAIN, Split.VALIDATION.

()

Returns:

Type Description
Task

Matching tasks in dataset order. Repeated split names do not duplicate tasks.

...

Tasks without a split are excluded. A streamed dataset is read once to materialize

tuple[Task, ...]

the selection.

Raises:

Type Description
TimeFValidationError

If no splits are supplied, a name is unknown, or the dataset assigns no split to any task. A missing partition otherwise returns no tasks.

get_test source

get_test() -> tuple[Task, ...]

Return the tasks of the test split. See :meth:get_split.

get_train source

get_train() -> tuple[Task, ...]

Return the tasks of the training split. See :meth:get_split.

get_validation source

get_validation() -> tuple[Task, ...]

Return the tasks of the validation split. See :meth:get_split.

import_from source

import_from(
    parent: TimeFReader,
    *,
    alias: ParentAlias | None = None,
    records: Iterable[EntityId] = (),
    signals: Iterable[EntityId] = (),
    tasks: Iterable[EntityId] = (),
    load: LoadPlan = ALL_LAZY,
) -> ImportedDataset

Copy Records, Signals, and tasks from a parent release into this dataset.

The parent must be a release that metadata.parents declares. The call records the parent in :attr:parent_cards and :attr:lineage. It does not change the card of this dataset.

  • records= copies each Record whole, with its Sources, Signals, and annotations.
  • signals= copies each Signal into a copy of its Record and of the Sources above it. Such a partial copy keeps the annotations that its Signals place.
  • tasks= copies each task with the Records and Signals that it references and the tasks that it derives from. Each annotation that a task references points at the matching occurrence on the copy of its owner. If this dataset changed or removed that occurrence, the import attaches a copy of the parent's next to it.

Each copy is this dataset's own object, with new IDs and its own metadata and annotations, so edits do not change the parent. Its Signals keep the parent's value handles, so they read the parent's stored values unless load loads them. A write of this dataset reuses the parent's payloads, so it needs the parent release. Annotations on the parent dataset itself come only with a task that references them.

An import of an object whose copy this dataset holds reuses that copy, with this dataset's edits. If the call needs Signals that the copy of a Record lacks, it adds them to that copy, with the Sources and annotations that they bring. An object whose copy this dataset removed is copied again, under a new ID. An edit such as :func:~timenet.dataset.edit.remove_signals keeps the import state in the dataset it builds, so an import into that dataset works the same way. Imports are safe to repeat: if a call fails partway, repeating it completes it. Select many objects in one call, because each call reads them in batches. docs/timef-dataset.md describes the rules.

Parameters:

Name Type Description Default
parent TimeFReader

A reader of the parent release.

required
alias ParentAlias | None

The parent alias that declares the parent. By default, the alias that the card declares for its release.

None
records Iterable[EntityId]

The parent IDs of the Records to copy whole.

()
signals Iterable[EntityId]

The parent IDs of the Signals to copy.

()
tasks Iterable[EntityId]

The parent IDs of the tasks to copy.

()
load LoadPlan

Which kinds of stored values to load. The import reads the parent tasks and Records without their values. Then it loads these kinds on the copies of the selected and needed tasks, Records, and Signals, and on the annotations that it copies, through their own value handles. This includes copies that this dataset holds already. The other Signals of a partial copy stay as they are. The default loads none.

ALL_LAZY

Returns:

Type Description
ImportedDataset

The copies of the selected Records, Signals, and tasks, by their parent IDs.

Raises:

Type Description
TimeFValidationError

If metadata.parents or alias does not declare the parent, another alias imports the parent or this alias imports another release, a selection is not a collection of positive int64 IDs, the copy of a Record that the call adds to holds sibling Sources of one name or a Signal outside its time_span, tasks is given and this dataset streams its tasks, a task to copy is a TSCorrespondenceTask without candidate_records, or the task copies fail to register.

TimeFNotFoundError

If a selected ID names no parent object. This dataset does not change.

iter_streamed_tasks_validated source

iter_streamed_tasks_validated() -> Iterator[Task]

Yield the streamed tasks, validating each against the dataset before it is written.

The id of a streamed task is the task id counter's value at :meth:set_task_stream plus its position in the stream. Thus every pass over the stream gives the task the same id.

Streamed tasks skip :meth:add_task's checks, so validate each here as it passes through: an undeclared type, an attachment to an unknown record, a dangling reference, a bad answer, or an out-of-window span raises before the task reaches disk. The dataset holds no task list. Thus the cross-task checks (from_tasks derivations) that need every task at once do not run for a stream.

Yields:

Type Description
Task

Each validated task, in the source's order.

Raises:

Type Description
TimeFValidationError

If a streamed task fails one of the per-task checks.

iter_tasks source

iter_tasks(
    *,
    required_modalities: Iterable[InputModality]
    | None = None,
    supported_modalities: Iterable[InputModality]
    | None = None,
    split: Split
    | str
    | Iterable[Split | str]
    | None = None,
) -> Iterator[Task]

Yield the dataset's tasks, from the stream when one is set, else the materialized list.

Parameters:

Name Type Description Default
split Split | str | Iterable[Split | str] | None

One split or an iterable of splits to select, or None for every task. Selection preserves dataset order and original task assignments.

None

Yields:

Type Description
Task

Each task. A streamed dataset re-reads its source on every call.

Raises:

Type Description
TimeFValidationError

If the selection is empty or contains an unknown split.

set_task_stream source

set_task_stream(
    task_types: Sequence[type[Task]],
    source: Callable[[], Iterator[Task]],
) -> None

Provide tasks as a re-iterable stream instead of materializing them in the dataset.

For a dataset with far more tasks than records (many questions over few recordings), holding every task in memory does not scale. A streaming connector builds the bounded records. Then it gives the tasks through source. The writer streams them to disk without a list.

Parameters:

Name Type Description Default
task_types Sequence[type[Task]]

The task classes the stream yields, so :meth:derive_schema records them. Every yielded task must be one of these types.

required
source Callable[[], Iterator[Task]]

A callable returning a fresh iterator over the tasks each time it is called. The writer calls it more than once (a peek for id storage, then the write), so it must re-read its source rather than exhaust a one-shot generator.

required

Raises:

Type Description
TimeFValidationError

If tasks were already added with :meth:add_task. A dataset either streams its tasks or materializes them, never both, or the writer would drop one set.

tasks_for source

tasks_for(record: Record) -> tuple[Task, ...]
tasks_for(
    record: Record, task_type: type[TTask]
) -> tuple[TTask, ...]
tasks_for(
    record: Record, task_type: type[Task] = Task
) -> tuple[Task, ...]

Return the tasks that take a record as input, optionally filtered by type.

Tasks reference their records, so this method scans the tasks for the ones whose inputs hold this record.

Parameters:

Name Type Description Default
record Record

The record whose tasks to find.

required
task_type type[Task]

Keep only tasks of this subclass. The default keeps every task on the record.

Task

Returns:

Type Description
tuple[Task, ...]

The record's tasks of task_type, in insertion order.

Raises:

Type Description
TimeFValidationError

If record is not registered in this dataset.

tasks_of source

tasks_of(task_type: type[TTask]) -> tuple[TTask, ...]

Return every task of a given type, in insertion order.

Parameters:

Name Type Description Default
task_type type[TTask]

The task subclass to keep, for example :class:~timenet.types.ClassificationTask.

required

Returns:

Type Description
tuple[TTask, ...]

The matching tasks.

to_features_and_targets source

to_features_and_targets(
    *,
    task: type[Task] | None = ...,
    output: Literal["arrow"] = ...,
    features: Literal["timestep", "series"] = ...,
    split: Split | str | None = ...,
) -> tuple[Array, Array]
to_features_and_targets(
    *,
    task: type[Task] | None = ...,
    output: Literal["numpy"],
    features: Literal["timestep", "series"] = ...,
    split: Split | str | None = ...,
) -> tuple[ndarray, ndarray]
to_features_and_targets(
    *,
    task: type[Task] | None = None,
    output: Literal["arrow", "numpy"] = "arrow",
    features: Literal["timestep", "series"] = "timestep",
    split: Split | str | None = None,
) -> tuple[Array, Array] | tuple[ndarray, ndarray]

Build an (X, y) training pair. By default, this method defers materialization.

This method requires every record to carry exactly one task of task. It pairs the values of that task's sole signal with the task's only scalar target. With split, only the tasks of that split count, and a record that has none of them is left out rather than rejected, so one call builds (X_train, y_train) and another (X_test, y_test). The features argument chooses the shape of X:

  • "timestep" (the default): one feature per point, in a rectangular matrix. This needs equal-length records. The result is an Arrow FixedSizeListArray[T], or a NumPy (n, T) array of float32 values.
  • "series": one sequence feature per record, so variable-length series work too. The result is an Arrow ListArray, or a NumPy (n,) object array of 1-D arrays.

With output="arrow" (the default), the method builds these arrays straight from the series loaders, with no NumPy copy in between. With output="numpy", the method materializes them. y is always the targets, as an Arrow string array or a 1-D NumPy array.

Parameters:

Name Type Description Default
task type[Task] | None

The task type to read targets from, for example :class:~timenet.types.ClassificationTask. Omit this argument to infer the type when the dataset has exactly one task type that carries an inline target.

None
output Literal['arrow', 'numpy']

Use "arrow" to keep the deferred Arrow arrays, or "numpy" to materialize them.

'arrow'
features Literal['timestep', 'series']

Use "timestep" for a rectangular per-point matrix, or "series" for one variable-length sequence per record.

'timestep'
split Split | str | None

Keep only the tasks of this split, or None for every task.

None

Returns:

Type Description
tuple[Array, Array] | tuple[ndarray, ndarray]

(X, y) as two Arrow arrays when output="arrow", or two NumPy arrays when

tuple[Array, Array] | tuple[ndarray, ndarray]

output="numpy".

Raises:

Type Description
TimeFValidationError

This error occurs if output or features is invalid. It also occurs if task is omitted and the dataset has zero or several task types with inline targets. It also occurs if a matched task carries no inline target, for example if its answer is a produced series or is stored as target annotations. It also occurs if a matched record is not single signal, or if features="timestep" is asked of records that are not all the same length. It also occurs if the dataset has no records, or if any record does not carry exactly one task of task.

write source

write(
    *,
    path: str | Path,
    values_backend: ValuesBackend = PARQUET,
) -> Path

Write this dataset as one immutable TimeF version.

Parameters:

Name Type Description Default
path str | Path

Registry root under which the dataset ID and version directories are created.

required
values_backend ValuesBackend

Typed values-plane backend selection.

PARQUET

Returns:

Type Description
Path

The committed version directory.