Records¶
A Record is one observation unit. It can represent a patient visit, a machine run, or a market
window.
Each Record owns a hierarchy of Sources and Signals:
flowchart TB
R["Record"]
D["Source: device"]
S1["Source: sensor"]
S2["Source: sensor"]
A["Signal"]
B["Signal"]
R --> D
D --> S1
D --> S2
S1 --> A
S2 --> B
A Source represents a device, sensor, or subsystem. It can contain child Sources and direct Signals. A Signal is always a leaf.
Create a Record¶
Build the hierarchy from the leaves upward:
from timenet.dataset import Record, Source
accelerometer = Source(
name="Accelerometer",
signals=(acceleration_x, acceleration_y, acceleration_z),
)
imu = Source(
name="IMU",
sources=(accelerometer,),
)
record = Record(
sources=(imu,),
metadata={"site": "lab-a", "run": "run-001"},
)
dataset.add_record(record=record)
dataset.add_record() gives the Record and each of its Signals a read-only int64 id. A Source
has no ID. Keep upstream identifiers, such as the run name above,
in metadata or an annotation.
record.signals returns every Signal in deterministic hierarchy order. Use walk_sources() or
walk_signals() when you need an iterator.
Each Source and Signal has one owner. TimeNet rejects cycles and objects attached in more than one place.
The root Sources of a Record must have distinct names, and so must the child Sources of a Source.
Store context¶
Use metadata for JSON-compatible details that do not need a typed schema. Examples include an
internal site code or source-specific import data.
Use an Annotation for a typed, searchable fact. Examples include age, condition, firmware version, or an event on the timeline.
Sources and Signals also support metadata and annotate().
Add time information¶
Each Record has one TimeOrigin. All Signal offsets and time annotations use this common
relative zero. The connector aligns the data before it constructs the Record.
from datetime import datetime, timezone
from timenet.dataset import Record, Source
from timenet.types import TimeOrigin
origin = TimeOrigin(datetime(2026, 1, 1, tzinfo=timezone.utc))
record = Record(
start_time=origin,
sources=(
Source(name="sensor A", signals=(signal_a,)),
Source(name="sensor B", signals=(signal_b,)),
),
)
record.start_time.timestamp is whole Unix microseconds or None. A missing absolute timestamp
does not prevent relative alignment. The default is a fresh TimeOrigin(None) for each Record.
Related Records can explicitly share one origin, including an unknown origin. Separate unknown origins do not imply alignment. A converter must not invent a date, timezone, or synchronization.
A regular axis stores a cadence and an offset from the Record origin. An irregular axis stores each offset. An ordinal axis records order only, with no assumed elapsed time.
time_span can declare a session interval that contains all Signal windows. This field permits
events during gaps when every sensor is off.
Connect tasks¶
A Task refers directly to its input Records. Registering a Task does not change those Records.
from timenet.types import ClassificationTask, Label, LabelSet
CONDITION = LabelSet(
name="condition",
labels=(Label(name="healthy"), Label(name="faulty")),
)
task = ClassificationTask(
inputs=(record,),
targets=("healthy",),
label_set=CONDITION,
)
dataset.add_task(task=task)
Use dataset.tasks_for(record) to resolve the Task objects for one Record.