--- myst: html_meta: description: "Create runs on assets or from datasets, then find, update and annotate them." --- # Runs {.lead} A run names a span of time for one test or analysis, such as a flight or a test-stand firing. It references data rather than copying it. ```{include} /guides/_snippets/connect-the-client.md ``` ## Create a run on an asset When the data already belongs to an [asset](/guides/assets.md), create the run from the asset with the test's time window. The run sees the asset's datasets through their data scopes, so you don't attach them again. ```python from datetime import datetime, timezone asset = client.get_asset("") run = asset.create_run( "Flight acceptance test", start=datetime(2026, 9, 10, 14, 38, tzinfo=timezone.utc), end=datetime(2026, 9, 10, 14, 48, tzinfo=timezone.utc), ) ``` Start and end accept timezone-aware datetimes or epoch nanoseconds. Pass `end=None` for a test that's still running. For a run across several assets, use {py:meth}`~nominal.core.NominalClient.create_run` with `assets=[...]`. ## Create a run from datasets Without an asset, attach each dataset to the run under a ref name with {py:meth}`~nominal.core.Run.add_dataset`. This example sets the run's bounds from an uploaded file. ```{include} /guides/_snippets/sample-flight-csv.md ``` ```python dataset = client.create_dataset("Frosty flight") file = dataset.add_tabular_data("flight.csv", timestamp_column="time", timestamp_type="iso_8601") file.poll_until_ingestion_completed() assert file.bounds is not None # set once ingestion succeeds run = client.create_run("High precipitation flight", start=file.bounds.start, end=file.bounds.end) run.add_dataset("telemetry", dataset) ``` The ref name, here `"telemetry"`, is the dataset's name within the run. Use the same ref name for the same kind of data on every run, so workbook templates and checklists work across runs. `add_dataset` also takes `series_tags`, to select [tagged data](/guides/streaming/overview.md#add-tags-to-filter-data-in-a-run-or-asset), and a time `offset`. {py:meth}`~nominal.core.Run.get_dataset` and {py:meth}`~nominal.core.Run.list_datasets` return only datasets attached this way. For data on an associated asset, use {py:meth}`~nominal.core.Asset.get_dataset`. {py:meth}`~nominal.core.Run.remove_data_sources` detaches a dataset without deleting it: ```python run.remove_data_sources(ref_names=["telemetry"]) ``` ## Find runs Retrieve one run by the RID on its page in Nominal, or search with {py:meth}`~nominal.core.NominalClient.search_runs`: ```python run = client.get_run("") review_runs = client.search_runs(labels=["needs-review"], asset=asset) ``` `name_substring` matches names, descriptions, labels and properties, so results may not contain the text in their name. ## Update a run {py:meth}`~nominal.core.Run.update` replaces each field you pass and leaves the others unchanged. To add a property, merge it with the existing ones: ```python run.update(labels=["reviewed"], properties={**run.properties, "reviewer": "flight-test"}) ``` To close a run that's still going, set its end: ```python run.update(end=datetime.now(timezone.utc)) ``` Changing bounds changes the window the run shows, not the stored data. ## Attachments, workbooks and events Attach files about this test to the run, and files about the system to its [asset](/guides/assets.md#update-metadata-and-attachments): ```python run.add_attachments([client.create_attachment("flight_report.pdf")]) ``` Create a workbook for the run from a template whose inputs match the run's ref names or data scope names. See [Workbooks](/guides/workbooks.md). Mark moments inside the run with [events](/guides/events.md). ## Archive a run {py:meth}`~nominal.core.Run.archive` hides the run without deleting its data: ```python run.archive() ```