Chickenpox temporal data¶
The first external temporal caller is the Hungary chickenpox signal published with PyTorch Geometric Temporal. It is small, public, fixed-topology, and used by that project's T-GCN and GConvGRU examples.
Source contract¶
Tinymesh downloads the dataset at PyTorch Geometric Temporal revision
fe555bc
and verifies SHA-256
724b48cfb274b2ecbb855bdb99b970b5ef9dd3671694fa477435dc1e08293735.
The source contains:
521 ordered weekly rows x 20 counties
102 directed edges, including 20 self-loops
one name -> row mapping for stable node identity
With four lags, lowering is:
source FX [521, 20]
|
+--> x[t, node] = FX[t:t+4, node] -> [517, 20, 4]
|
+--> y[t, node] = FX[t+4, node] -> [517, 20, 1]
source edges + node rows
|
+--> one Graph + unit edge weights
The loader preserves source edge order and self-loops. A model may request a different loop convention, but that is an explicit graph transform rather than a hidden data mutation.
The data boundary¶
StaticGraphTemporalSignal owns one Graph, stable node IDs, stacked x and
y tensors, and optional COO-aligned scalar edge weights. Integer indexing
returns (x_t, y_t); contiguous slicing and split() reuse the same graph and
edge weights.
from tinymesh.datasets import chickenpox
signal = chickenpox(lags=4, device="CPU")
train, test = signal.split(0.8)
x, y = train[0]
print(x.shape, y.shape)
# (20, 4) (20, 1)
The tensor axes are fixed:
This container now pays rent: it rejects time, node, edge, dtype, and device misalignment that a tuple of tensors could not name. It does not invent dates, masks, or irregular-time semantics absent from this source.
Reference parity¶
Against torch-geometric-temporal==0.56.2, all 517 feature and target
snapshots match under NumPy's default assert_allclose; edge indices and unit
weights match in source order. The full pinned-source witness reports the same
contract on CPU and Metal:
uv run --locked python -m experiments.run chickenpox_data DEV=CPU
uv run --locked python -m experiments.run chickenpox_data DEV=METAL
{
"device": "CPU",
"nodes": 20,
"edges": 102,
"self_loops": 20,
"snapshots": 517,
"train_snapshots": 413,
"test_snapshots": 104,
"x_shape": [20, 4],
"y_shape": [20, 1]
}
Causal window batches¶
For recurrent models, load one feature lag and make temporal history explicit:
signal = chickenpox(lags=1, device="CPU")
values, target = next(signal.batches(batch_size=32, history=8))
print(values.shape, target.shape)
# (32, 8, 20, 1) (32, 20, 1)
Each sample contains eight consecutive node fields and predicts the week after
the last field. The final short batch is retained. Topology is not repeated:
every batch reuses signal.graph.
PyG's TemporalDataLoader batches continuous edge events, not ordered fields
over one fixed graph. At the pinned revision, PyG Temporal's IndexDataset
uses a PyTorch DataLoader to gather an input sequence and an equally long
future target sequence. Tinymesh instead exposes sequence-to-one windows
directly from the signal because that is the first current model caller:
PyG Temporal IndexDataset input [B, L, N, F] -> target [B, L, N, F]
Tinymesh batches input [B, L, N, F] -> target [B, N, Y]
This is not a generic worker, shuffle, prefetch, or multiple-graph loader. It is the smallest deterministic window contract over resident tinygrad tensors. The Chickenpox forecast records the first end-to-end training result and its limits.
The cross-dataset network measurement confirms that the 20-node graph is one strong component: every ordered non-self node pair is reachable, with mean directed distance 2.51 and diameter 6. These are topology facts, not evidence that the graph improves a forecast.