Zip (Build Signal)

Shipping
zip_signal

Fuse an X array and a Y array into one Signal (X→timestamps, Y→values), σ optional

Signature

Inputs

  • xVector|SignalX / time axis. Absent ⇒ synthesized from sample_rate, or inherited from a Signal y.
  • yVector|SignalrequiredThe values (the data column). A Vector promotes to a Signal; a Signal's own values are used.
  • sigmaVector|SignalPer-sample standard deviation σ. Stored as variance σ²; overrides any uncertainty y carried.

Outputs

  • signalSignalThe fused Signal with timestamps = X, values = Y, and optional per-sample variance.

Parameters

KeyTypeDefaultNotes
unittextPhysical unit of the output values (the Y axis). Empty = inherit from the Y input.
sample_ratefloat0HzFs stamped on the output. 0 = auto: inferred from X spacing when uniform (best-effort average otherwise), and used to synthesize the axis when no X is wired.
on_mismatchenumerrorone of: error, truncate
sort_by_xbooleanfalseReorder samples by ascending X before building the Signal, turning scattered (X, Y) pairs into a monotonic axis. Y and σ follow their X.

Description

Zip is the Build XY primitive: it takes an X array and a Y array and fuses them into one Signal whose timestamps = X and values = Y — the exact inverse of Unzip (unzip_signal). Because a Signal is stored structure-of-arrays (two parallel Vec<f64>, [[t…],[y…]]), this is a cheap, lossless interleave of two columns.

Each input accepts a Vector (a bare 1-D array) or a Signal (its values are taken as the array), making the node dual-purpose:

  • wire X + Y → a non-uniformly-sampled signal with a custom axis;
  • wire only Y (Vector) → promote a bare array to a Signal on a synthesized uniform axis;
  • wire only Y (Signal) → keep that signal's own timestamps (a relabel).

Uncertainty rides along losslessly: a wired sigma (σ) is stored as variance and overrides any uncertainty y already carried; otherwise a Signal-y's own variances are preserved. When sample_rate = 0, Fs is inferred from the X spacing (exact when uniform, an average across the span otherwise). Length reconciliation follows on_mismatch: error refuses, truncate keeps the shortest. With sort_by_x on, samples are reordered by ascending X — and Y and σ² are permuted by the same index map so uncertainty stays parallel to the data. The node is stateless.

Mathematics

Examples

Build a signal from measured X and Y

Wire time array s into x and V into y. With sample_rate = 0, Zip infers a uniform axis and stamps Hz. The signal output inherits the V unit from Y.

Promote a bare array with uncertainty

Leave x unwired, feed a Vector into y and a σ Vector into sigma. Zip synthesizes an index axis (at the given sample_rate, default ) and stores as the signal's variance.

Scattered pairs into a monotonic axis

With X , Y , σ and sort_by_x = true, the output has X , Y and σ² — Y and σ² followed X through the sort.

Applications

  • Building a non-uniformly-sampled signal from a measured time column and value column (LabVIEW Build XY).
  • Promoting a computed 1-D array into a first-class Signal with an explicit sample rate and unit.
  • Reordering scattered (X, Y) scatter data into a monotonic time series while carrying per-point error bars.
  • Re-attaching per-sample uncertainty to a value stream by wiring a separately computed σ array.

Neat

σ is stored internally as variance (σ²), not σ — so a wired sigma is squared on ingest and truncation / sort permute the σ² array by the SAME index map as the values, keeping uncertainty length-locked to the data.

Fs inference is spacing-aware: a uniform axis yields the exact 1/Δt (within a 1e-6 relative tolerance), while a non-uniform axis falls back to the average rate across the span.

The X port is polymorphic — feeding it a Signal takes that signal's values as the axis, which is how 'only-Y-Signal' inherits its own timestamps.

Known issues

By default a length mismatch across X / Y / σ is a hard error; set on_mismatch = truncate to opt into shortest-wins behavior.

sort_by_x uses a partial comparison that treats NaN X values as equal (no reordering), so a NaN in the axis can leave points unsorted.

With no X and a Vector Y, the synthesized axis uses sample_rate (default 1 Hz) — the resulting timestamps are indices/Fs, not real measurement times.

See also

bundlessignalbuild-xyzipuncertaintystateless