Compute expressions and results#

This library hosts an experimental Python-internal DSL for expressing Nominal compute queries, with functions to execute and retrieve results.

Python-internal DSL#

The DSL is primarily backed by a method-chaining API which allows for clear composition and good language support inside your IDE.

Start an expression by selecting a channel with asset_channel, run_channel, or datasource_channel.

from nominal.experimental.compute.dsl.exprs import NumericExpr

chan = NumericExpr.asset_channel(asset_rid, data_scope_name, channel_name)

From there, you can rely on IDE hints to compose operations:

chan.⇥
    ┌─────────────────────────────┬───────────────────────────────────────────────┐
    │◇ abs                        │ def derivative(time_unit: TimeUnitLiteral)  x │
    │◇ acos                       │ ──────────────────────────────────────────    │
    │◇ asin                       │ Calculates the rate of change between         │
    │◇ atan2                      │ subsequent points.                            │
    │◇ channel                    │                                               │
    │◇ cos                        │                                               │
    │◇ cumulative_sum             │                                               │
    │◇ derivative               ▶ │                                               │
    ├─────────────────────────────┴───────────────────────────────────────────────┤
    │ Tab to accept • ↑/↓ to navigate • Esc to dismiss                            │
    └─────────────────────────────────────────────────────────────────────────────┘

The DSL exposes operator overloads where appropriate, and also includes explicit methods for the same operations:

assert (chan + chan) == chan.plus(chan)

Compute library#

After you have a compute query defined, you will want to test your compute logic. We expose a function to retrieve bucketed compute results, and will be expanding this library in the future with additional ways to retrieve compute results. For a full example:

from nominal.core import NominalClient
from nominal.experimental.compute.dsl import exprs
from nominal.experimental.compute import compute_buckets

client = NominalClient.from_profile("staging")
asset_rid = "ri.scout.gov-staging.asset.b51d64ef-e61e-490c-ba94-3988ec5b121f"
scope_name = "my_scope"
channel_name = "some_value"

asset = client.get_asset(asset_rid)
scope = asset.get_dataset(scope_name)
assert scope.bounds is not None

# Get channel by asset, data scope name, and channel name
channel = exprs.NumericExpr.asset_channel(asset_rid, scope_name, channel_name)

deriv = channel.derivative(time_unit="s")
integ = channel.integral(start_timestamp=scope.bounds.start, time_unit="s")
expr = (deriv + integ) / channel.abs()
for bucket in compute_buckets(client, expr, scope.bounds.start, scope.bounds.end):
    print(f"Timestamp: {bucket.timestamp}, Mean: {bucket.mean}")

When retrieving channels using the expressions library, you may also reference channels directly on datasources or runs:

# Reference a channel present on a run by data scope name
run_rid = "ri.catalog.gov-staging.dataset.b373ff5a-cd2b-4969-bf5b-772688a11249"
run_channel = exprs.NumericExpr.run_channel(run_rid, scope_name, channel_name)

# Reference a channel present in a dataset
dataset_rid = "ri.catalog.gov-staging.dataset.b373ff5a-cd2b-4969-bf5b-772688a11249"
datasource_channel = exprs.NumericExpr.datasource_channel(dataset_rid, channel_name)

When retrieving channels on an asset or a run, the default tag filters for a given data scope are applied to underlying expressions. However, it may still be useful to further filter data on tags that aren’t specified by the data scope definition– this is done using the additional_tags args (or just tags for datasource channels):

channel = exprs.NumericExpr.asset_channel(asset_rid, scope_name, channel_name, additional_tags={"color": "green"})
run_channel = exprs.NumericExpr.run_channel(run_rid, scope_name, channel_name, additional_tags={"color": "green"})
datasource_channel = exprs.NumericExpr.datasource_channel(dataset_rid, channel_name, tags={"platform": "electric-glider-mk1"})

API Reference#

Bucketed results#

Module: nominal.experimental.compute.

Classes

Bucket

Time-bucketed data for a numeric series within Nominal

Functions

batch_compute_buckets

Computed bucketed summaries for a batch of numeric expressions

compute_buckets

Compute a bucketed summary of the requested expression.

Expressions#

Module: nominal.experimental.compute.dsl.exprs.

Classes

ChannelExpr

Base interface for channel expressions scoped to a dataset, asset, or run.

EnumExpr

A compute expression for categorical channel data.

Expr

Base class for all compute expressions.

NumericExpr

A compute expression for numeric channel data and derived signals.

RangeExpr

A compute expression for time ranges that can be combined or inverted.