Client#

class nominal.Client#

An authenticated connection to Nominal.

Two ways to authenticate, matching the Python client:

c = nominal.Client.fromProfile();          % credentials on disk
c = nominal.Client.fromToken("<api-key>"); % API key in hand

Prefer fromProfile. It reads the same ~/.config/nominal/config.yml that the nom CLI and the Python client use, and no key ends up in a script.

nominal.Client(token, Workspace=rid, BaseUrl=url) is the constructor both call. Both options are optional. An unset base URL means Nominal production. Surrounding whitespace is trimmed from all three.

Example:

c  = nominal.Client.fromProfile();
a  = c.getOrCreateAsset("engine-3");
ds = a.getOrCreateDataset("telemetry", "tlm");
s  = ds.stream();

delete(c) closes the connection.

Constructor Summary
Property Summary
WorkspaceRid#

Workspace this client is scoped to, or “” if unscoped.

BaseUrl#

Base URL this client connects to.

Method Summary
whoAmI()#

Display name of the authenticated user.

Makes a request to Nominal, so it doubles as a credential check.

Returns:

string – The user’s display name.

assets(filter)#

Assets you can see, as a table.

c.assets("engine")
a = c.assetByRid(c.assets("engine").Rid(1));

With no argument it fetches EVERY asset in the workspace in one call. There is no page size to pass, so filter.

Parameters:

filter

Keep only assets whose name contains this (case-insensitive substring). Use it to find a RID from a name.

Returns:

table – Variables Name, Rid and Description, ordered by name.

datasets(filter)#

Datasets you can see, as a table.

ds = c.datasetByRid(c.datasets("telemetry").Rid(1));
ds.channels()                    % what is inside it

With no argument it fetches EVERY dataset in the workspace in one call. There is no page size to pass, so filter.

Parameters:

filter

Keep only datasets whose name contains this.

Returns:

table – Variables Name and Rid, ordered by name.

runs(filter, options)#

Runs matching every filter given, as a table.

t = c.runs("<search text>", Labels="<label>", StartAfter=t0);
r = c.runByRid(t.Rid(1));

Every label must be on the run, and every property must match. With no filter at all it fetches EVERY run in the workspace.

Parameters:

filter

Keep only runs whose name contains this.

Options:
  • Labels – String array. Keeps runs carrying all of them.

  • Properties – A struct, dictionary or containers.Map. Keeps runs where every key has that value.

  • StartAfter – Zoned datetime or int64 nanoseconds. Keeps runs starting at or after it.

  • EndBefore – Zoned datetime or int64 nanoseconds. Keeps runs ending at or before it.

Returns:

table –

Variables Name, Rid, Number, StartTime and EndTime

(NaT while open), ordered by start time.

getOrCreateAsset(name)#

Fetch an asset by name, creating it if absent.

A typo creates a new empty asset rather than erroring, so check the name. Names are not unique in Nominal, and if several match, the first is returned. Use assetByRid when you know the RID, and assets(name) to look without creating.

Returns:

nominal.Asset – The existing or new asset.

createAsset(name)#

Create an asset, even if one of that name exists.

Names are not unique in Nominal, so this always makes a new one. Use getOrCreateAsset to reuse an existing asset.

Returns:

nominal.Asset – The new asset.

createDataset(name)#

Create a dataset attached to no asset.

ds = c.createDataset("bench telemetry");
assetA.addDataset(ds, Tags=struct(UUT="A"));
assetB.addDataset(ds, Tags=struct(UUT="B"));

Always makes a new one, whatever its name. Attach it with asset.addDataset, to as many assets as need it.

Returns:

nominal.Dataset – The new dataset, attached to no asset.

assetByRid(rid)#

Fetch an asset by RID.

Returns:

nominal.Asset – The asset.

datasetByRid(rid)#

Fetch a dataset by RID.

Returns:

nominal.Dataset – The dataset.

createEvent(assetRids, name, options)#

Flag a moment or interval on one or more assets.

e = c.createEvent(rids, "overspeed", Type="error", ...
                  Timestamp=t, Duration=seconds(10));
e = c.createEvent(rids, "step 3", Type="success", ...
                  Properties=struct(status="pass", output=4.2));
Parameters:

assetRids

String array of asset RIDs. At least one is required.

Options:
  • Type – “info” (the default), “flag”, “error” or “success”.

  • Timestamp – Zoned datetime or int64 nanoseconds. Defaults to now.

  • Duration – A duration, or int64 nanoseconds. Defaults to zero, meaning an instantaneous event.

  • Properties – A struct, or a dictionary for keys that aren’t valid field names.

Returns:

nominal.Event – The new event.

runByRid(rid)#

Fetch a run by RID.

Returns:

nominal.Run – The run.

createRun(name, dataset, refName, options)#

Create a run from a dataset, with no asset of its own.

r = c.createRun("Model A, execution 7", ds, ...
                Tags=dictionary(["model" "execution-id"], ["A" "7"]), ...
                StartTime=int64(0), EndTime=int64(60e9));

For data with no physical system behind it, such as one dataset per simulation model and one run per execution. The run sees only the series carrying every one of Tags. It adds nothing to the asset list.

Use asset.run for a run on an asset you have.

Parameters:
  • name

    Run name.

  • dataset

    The nominal.Dataset the run reads.

  • refName

    The dataset’s name within the run. Defaults to “default”.

Options:
  • Tags – A struct, or a dictionary for keys that aren’t valid field names. Omit for the whole dataset.

  • StartTime – Zoned datetime or int64 nanoseconds. Defaults to now. int64(0) is the epoch.

  • EndTime – Zoned datetime or int64 nanoseconds. Omit to leave the run open.

Returns:

nominal.Run – The new run.

ingest(path, options)#

Upload a CSV or Parquet file and start ingesting it.

job = c.ingest("flight12.csv", TimestampColumn="time", ...
               NewDataset="Flight 12");
job = c.ingest("run.parquet", TimestampColumn="t", ...
               Dataset=ds, Kind="epoch", Unit="milliseconds");

Blocks while the file uploads. The ingest itself continues afterwards. Call job.wait() if you need it finished.

Parameters:

path

The file. .parquet is read as Parquet, anything else as CSV.

Options:
  • TimestampColumn – Name of the column holding time. Required.

  • Dataset – An existing dataset to add to. Give either this or NewDataset.

  • NewDataset – Name of a dataset to create, attached to no asset. Attach it afterwards with asset.addDataset.

  • Kind – How to read the timestamp column: “iso8601” (the default), “epoch” or “relative”.

  • Unit – For “epoch” and “relative” timestamps: “nanoseconds”, “microseconds”, “milliseconds”, “seconds” (the default), “minutes” or “hours”.

  • Tags – Stamped on every point in the file. A struct, or a dictionary for keys that aren’t valid field names.

Returns:

nominal.IngestJob – Carries DatasetRid whichever of Dataset or NewDataset was given.

query(sql, options)#

Run a SQL query and return the result as a table.

t = c.query("SELECT ts, channel, value FROM points_double " + ...
            "WHERE dataset_rid = '" + ds.Rid + "' LIMIT 100")

The SQL tables have their own columns, which differ from these classes’ properties. Telemetry tables (points_double, points_int, points_string, logs, channels) must filter on dataset_rid. Metadata tables (assets, runs, datasets, events) need not, and are capped at 10,000 rows.

Results are capped at 1 GiB. Use queryExportUrl for larger.

Options:

Workspace – Workspace RID to query. SQL always needs one: the client’s own is used unless this names another, and an unscoped client must give one.

Returns:

table – One variable per column. Timestamp columns come back as int64 nanoseconds. Pass them through nominal.fromNanos for a datetime.

queryExportUrl(sql, options)#

Run a query and get a download link for the CSV.

For results too large for query, which is capped at 1 GiB.

Exports queries on telemetry tables, as CSV. A query that reads assets, runs or datasets can’t be exported this way.

Options:

Workspace – Workspace RID to query. Defaults to the client’s own. A client with no workspace must give one.

Returns:

string – A time-limited download URL with no size cap.

static connect(name)#

Connect from a stored profile, else from NOMINAL_TOKEN.

c = nominal.Client.connect()          % the "default" profile
c = nominal.Client.connect("staging") % a named one

For code that runs both on a workstation (profile) and in CI (environment variable). Prefer fromProfile or fromToken when you know which you have.

The profile wins. NOMINAL_TOKEN carries no base URL or workspace, so falling back to it means Nominal production with no workspace scope, whatever the profile said. The fallback raises a nominal:profileFallback warning when it happens.

Raises nominal:noCredentials when neither is available. The message names the config file it looked in and the command that would fix it.

Parameters:

name

Profile name. Defaults to “default”.

Returns:

nominal.Client – The connection.

static fromProfile(name, options)#

Connect using credentials stored on disk.

c = nominal.Client.fromProfile()          % the "default" profile
c = nominal.Client.fromProfile("staging") % a named one

Reads ~/.config/nominal/config.yml, the file Nominal’s other clients also read. A profile holds the API key, the base URL, and optionally the workspace RID. To create one, follow API keys setup in the Nominal docs:

https://nominal-io.github.io/pub-docs/quickstart/quickstart/api-keys-setup/
Parameters:

name

Profile name. Defaults to “default”.

Options:

ConfigPath – Read this config file instead of the default.

Returns:

nominal.Client – The connection.

static fromToken(token, options)#

Connect with an API key you already hold.

c = nominal.Client.fromToken("<api-key>")
c = nominal.Client.fromToken(tok, BaseUrl="https://api.nominal.test")

Prefer fromProfile where you can. A key written into a script ends up in version control.

Parameters:

token

API key. Surrounding whitespace is trimmed.

Options:
  • Workspace – Workspace RID to scope the client to. Unset means unscoped.

  • BaseUrl – Base URL of your Nominal instance. Unset means Nominal production.

Returns:

nominal.Client – The connection.