Getting data in#
Write a matrix from memory, ingest a file from disk, or stream while a test runs.
A .mat file#
Load the file and write its matrix to a dataset.
load("<file>.mat"); % a datetime vector t and an N-by-3 matrix V
c = nominal.Client.fromProfile();
a = c.getOrCreateAsset("airframe-7");
ds = a.getOrCreateDataset("Flight 12");
ds.write(["rpm" "egt" "psi"], t, V);
A CSV or Parquet file#
Nominal parses the file, so pass its path and the name of its time column.
ds = a.getOrCreateDataset("Flight 12");
job = c.ingest("<file>.csv", TimestampColumn="<time column>", Dataset=ds);
job.wait(); % raises if the ingest fails
Timestamps default to ISO 8601. For a numeric time column, say how to read it:
job = c.ingest("<file>.csv", TimestampColumn="<time column>", Kind="epoch", Unit="milliseconds", Dataset=ds);
A live stream#
Open a stream once and push blocks as they fill.
s = ds.stream();
chans = [s.channel("rpm"), s.channel("egt"), s.channel("psi")];
while acquiring
[t, block] = readFromDAQ(); % t is N-by-1, block is N-by-3
s.push(chans, t, block);
end
delete(s); % flushes and waits until the data lands
Streaming covers timestamps, tags and closing the stream.
Which script produced the data#
Record provenance as properties and labels on the dataset.
ds.update(Properties=struct(script="reduce_flight.m", ...
version="2.4.1", ...
matlab=string(version("-release")), ...
operator=c.whoAmI()), ...
Labels=["flight-test" "reduced"]);
Units on channels#
Declare units before writing, so the first plot comes out labelled. setChannelMetadata works
on channels that have no data yet.
ds.setChannelMetadata("rpm", "double", Unit="1/min");
ds.setChannelMetadata("egt", "double", Unit="Cel", Description="Exhaust gas temp");
Units are UCUM symbols: Cel not C, 1/min not rpm, and [psi] in brackets. Nominal keeps
a symbol that isn’t UCUM for display, but can’t convert it.
Bracketing a test as a run#
A run marks the time window of a test on an asset. It shows every data source on the asset, including datasets added later, so there is nothing to attach.
r = a.run("burn-12"); % starts now
% ... the test runs ...
r = r.finish(); % ends now
A run can cover more than one asset, such as a test chamber and the unit in it:
r = chamber.run("test-42");
r = r.addAsset(dut);
A run with no asset#
Simulation output has no physical system behind it. Keep one dataset per model, tag each execution’s points, and create a run per execution from the dataset.
tags = dictionary(["model" "execution-id"], ["A" "7"]);
ds.write("thrust", t, V, Tags=tags);
r = c.createRun("Model A, execution 7", ds, Tags=tags, ...
StartTime=int64(0), EndTime=int64(60e9));
One dataset covering several units#
Create the dataset on its own, tag the points by unit, and give each unit’s asset its own slice.
ds = c.createDataset("bench telemetry");
ds.write("rpm", t, V, Tags=struct(UUT="A"));
unitA.addDataset(ds, Tags=struct(UUT="A"));
unitB.addDataset(ds, Tags=struct(UUT="B"));
ds.assets() % both units
Flagging something that happened#
Events mark a moment or an interval on an asset.
c.createEvent(a.Rid, "overspeed", Type="error", ...
Timestamp=datetime("now", TimeZone="UTC"), Duration=seconds(3));