CSV upload#

Upload a CSV file of time-series data to a dataset. The timestamp column places each row in time, and every other column becomes a channel.

In code#

Each example uploads sample.csv, a minute of test data whose timestamp column holds ISO 8601 times, to an existing dataset:

from nominal.core import NominalClient

client = NominalClient.from_profile("default")
dataset = client.get_dataset("<ri.catalog.instance.dataset.identifier>")  # or client.create_dataset("My dataset")

file = dataset.add_tabular_data("sample.csv", timestamp_column="timestamp", timestamp_type="iso_8601")  # also Parquet
file.poll_until_ingestion_completed()  # raises NominalIngestError if the ingest fails
client = nominal.Client.fromProfile();
dataset = client.datasetByRid("<ri.catalog.instance.dataset.identifier>");

job = client.ingest("sample.csv", TimestampColumn="timestamp", Dataset=dataset);  % or NewDataset="My dataset"
job.wait();  % raises if the ingest fails

LabVIEW example that uploads a CSV file to a new dataset, with labels and properties

use nominal::core::{CsvIngest, Timestamp};

let client = nominal::NominalClient::from_profile("default")?;
client.ingest()
    .upload_csv("sample.csv", "<ri.catalog.instance.dataset.identifier>", CsvIngest::new(Timestamp::iso8601("timestamp")))
    .await?;
import (
	"bytes"
	"os"

	ingestapi "github.com/nominal-io/nominal-api-go/ingest/api"
	uploadapi "github.com/nominal-io/nominal-api-go/upload/api"
	"github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient"
	"github.com/palantir/pkg/rid"
	"github.com/palantir/pkg/safelong"
)

// httpClient is a conjure-go-runtime httpclient.Client for your Nominal REST API URL,
// and token is your API key as a bearertoken.Token
data, _ := os.ReadFile("sample.csv")
size := safelong.SafeLong(len(data))
path, _ := uploadapi.NewUploadServiceClient(httpClient).UploadFile(ctx, token, "sample.csv", &size, nil,
	httpclient.RequestBodyInMemory(bytes.NewReader(data)))
datasetRid, _ := rid.ParseRID("<ri.catalog.instance.dataset.identifier>")
ingestapi.NewIngestServiceClient(httpClient).Ingest(ctx, token, ingestapi.IngestRequest{
	Options: ingestapi.NewIngestOptionsFromCsv(ingestapi.CsvOpts{
		Source: ingestapi.NewIngestSourceFromS3(ingestapi.S3IngestSource{Path: string(path)}),
		Target: ingestapi.NewDatasetIngestTargetFromExisting(ingestapi.ExistingDatasetIngestDestination{DatasetRid: datasetRid}),
		TimestampMetadata: ingestapi.TimestampMetadata{
			SeriesName:    "timestamp",
			TimestampType: ingestapi.NewTimestampTypeFromAbsolute(ingestapi.NewAbsoluteTimestampFromIso8601(ingestapi.Iso8601Timestamp{})),
		},
	}),
})
nomctl ingest csv sample.csv --timestamp-column timestamp --timestamp-type iso8601 \
  --dataset <ri.catalog.instance.dataset.identifier>  # or --name "My dataset"

In the Nominal app#

  1. Open the dataset’s page and click UPLOAD DATA. To find the dataset, in the sidebar click Data, then Data sources.

  2. Drop the file onto Upload files, or click SELECT FILES and pick it.

  3. In the Settings panel, check the Timestamp column and Timestamp format. For sample.csv, they’re timestamp and Absolute (ISO 8601).

  4. Click CONFIRM & INGEST.