# Client

## class nominal.Client

An authenticated connection to Nominal.

Two ways to authenticate, matching the Python client:

```matlab
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:

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

delete(c) closes the connection.

> **See also**
>
> [`nominal.Asset`](https://dev.nominal.io/matlab/ref/Asset.md#nominal.Asset "nominal.Asset"), [`nominal.Dataset`](https://dev.nominal.io/matlab/ref/Dataset.md#nominal.Dataset "nominal.Dataset"), [`nominal.Run`](https://dev.nominal.io/matlab/ref/Run.md#nominal.Run "nominal.Run"), [`nominal.shutdown()`](https://dev.nominal.io/matlab/ref/functions.md#nominal.shutdown "nominal.shutdown")

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.

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.Client.datasets()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.datasets "nominal.Client.datasets")

    ### datasets(filter)

    Datasets you can see, as a table.

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.Client.assets()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.assets "nominal.Client.assets"), [`nominal.Dataset.channels()`](https://dev.nominal.io/matlab/ref/Dataset.md#nominal.Dataset.channels "nominal.Dataset.channels")

    ### runs(filter, options)

    Runs matching every filter given, as a table.

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.Client.runByRid()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.runByRid "nominal.Client.runByRid"), [`nominal.Client.assets()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.assets "nominal.Client.assets")

    ### 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.

    > **See also**
    >
    > [`nominal.Client.assetByRid()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.assetByRid "nominal.Client.assetByRid"), [`nominal.Client.assets()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.assets "nominal.Client.assets")

    ### 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.

    > **See also**
    >
    > [`nominal.Client.getOrCreateAsset()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.getOrCreateAsset "nominal.Client.getOrCreateAsset")

    ### createDataset(name)

    Create a dataset attached to no asset.

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.Asset.addDataset()`](https://dev.nominal.io/matlab/ref/Asset.md#nominal.Asset.addDataset "nominal.Asset.addDataset"), [`nominal.Asset.getOrCreateDataset()`](https://dev.nominal.io/matlab/ref/Asset.md#nominal.Asset.getOrCreateDataset "nominal.Asset.getOrCreateDataset")

    ### 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.

    ```matlab
    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.

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.Asset.run()`](https://dev.nominal.io/matlab/ref/Asset.md#nominal.Asset.run "nominal.Asset.run"), [`nominal.Asset.addDataset()`](https://dev.nominal.io/matlab/ref/Asset.md#nominal.Asset.addDataset "nominal.Asset.addDataset")

    ### ingest(path, options)

    Upload a CSV or Parquet file and start ingesting it.

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.IngestJob`](https://dev.nominal.io/matlab/ref/IngestJob.md#nominal.IngestJob "nominal.IngestJob"), [`nominal.Dataset.write()`](https://dev.nominal.io/matlab/ref/Dataset.md#nominal.Dataset.write "nominal.Dataset.write")

    ### query(sql, options)

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

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.Client.queryExportUrl()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.queryExportUrl "nominal.Client.queryExportUrl"), [`nominal.fromNanos()`](https://dev.nominal.io/matlab/ref/functions.md#nominal.fromNanos "nominal.fromNanos")

    ### 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.

    > **See also**
    >
    > [`nominal.Client.query()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.query "nominal.Client.query")

    ### static connect(name)

    Connect from a stored profile, else from NOMINAL_TOKEN.

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.Client.fromProfile()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.fromProfile "nominal.Client.fromProfile"), [`nominal.Client.fromToken()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.fromToken "nominal.Client.fromToken")

    ### static fromProfile(name, options)

    Connect using credentials stored on disk.

    ```matlab
    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:

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.Client.fromToken()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.fromToken "nominal.Client.fromToken")

    ### static fromToken(token, options)

    Connect with an API key you already hold.

    ```matlab
    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.

    > **See also**
    >
    > [`nominal.Client.fromProfile()`](https://dev.nominal.io/matlab/ref/Client.md#nominal.Client.fromProfile "nominal.Client.fromProfile")
