Skip to Content
This documentation is provided with the HEAT environment and is relevant for this HEAT instance only.
RunnersSystem Utilssystem-tabular-to-dataservice

system-tabular-to-dataservice (platform, system-utils)

The system-tabular-to-dataservice node is a platform-only transform on system-utils. It reads every node output from a single parent input-node (CSV/TSV uploads or tabular JSON), builds canonical $heat-dataservice, and adds tabularUploadSummary for a Next CustomRenderer panel.

Configuration matches tabular-to-dataservice on core-utils, plus multi-upload behaviour.


Typical pipeline

input-node (tabular-upload) → system-tabular-to-dataservice → heat-system-next-dimension

Shipped reference session templates:

  • system-tabular-dashboard-next (explicit timeColumn): shipped template
  • system-tabular-dashboard-autodetect-next (autodetect + dynamic layout): shipped template

How realm and time are chosen

QuestionConfiguration
Time axistimeColumn (required). Values become each series point’s timeMs.
Realm splitOptional realmColumn: distinct cell values → realms[].name. If unset, rows use defaultRealm (default default).
Primary key / dedupetimeColumn plus optional primaryKeyColumns, with dedupePolicy: last or first.
Milliseconds vs ISOtimeColumnIsMs (default true) with baseCapturedAt, or timeColumnIsIso8601 (timeMs = ms since minimum ISO timestamp per realm).

Set time and realm explicitly in defaultConfiguration, or enable autoDetectTimeColumn (platform extension) to infer the time column from headers and sample rows. Pair with emitSuggestedLayout and heat-system-next-dimension layoutFromParentOutput for an upload-any-CSV dashboard (template system-tabular-dashboard-autodetect-next).


Multi-upload behaviour (platform extensions)

PropertyDefaultDescription
realmPerFilefalseWhen true and realmColumn is unset, each parent output (each upload) becomes its own realm (name = slug of filename).
whenNoOutputscompleteParent has no outputs yet: complete (empty payload + summary), suspend, or fail.
maxFiles50Maximum parent outputs processed per run.
maxRowsPerFile100000Row cap per file (memory guardrail).

When multiple files are uploaded and realmColumn is set, realm names are prefixed with the file slug to avoid collisions (for example metrics_pilot_a).

When multiple files share defaultRealm without realmColumn, channel id values are prefixed with the file slug.


Shared configuration (parity with tabular-to-dataservice)

PropertyRequiredDefaultDescription
inputFormatautoauto | csv | tsv | json
sourceTable✖*,tables key for JSON tabular-query shape
timeColumn✔*,Header for timeMs (*optional when autoDetectTimeColumn is true)
autoDetectTimeColumnfalseInfer timeColumn and ISO vs ms mode from CSV headers and sample rows
emitSuggestedLayoutfalseAdd suggestedLayoutConfiguration (v2 Next layout) to node output
maxAutodetectSampleRows200Rows sampled per file for autodetect
timeColumnIsMstrueMs offset from baseCapturedAt
timeColumnIsIso8601falseISO timestamps per realm
baseCapturedAt✖**,ISO8601 base when using ms mode
sortByTimetrueSort series by timeMs
defaultRealmdefaultFallback realm name
realmColumn,Column whose distinct values become realms
discardRowsWithEmptyRealmfalseDrop rows with empty realm cell
groups / defaultGroupIdmetricsChannel groups
excludeColumns / includeColumns,Column filters
channels[]Explicit channel definitions
treatEmptyAsNone / discardEmptyValues / discardEmptyRowssee core-utilsEmpty handling
primaryKeyColumns[]Extra dedupe keys
dedupePolicylastlast | first
dataserviceVersion1.0Payload version
dashboardUsers[]Optional ACL GUIDs

* Required when JSON has multiple tables.
** Required when timeColumnIsMs=true and timeColumnIsIso8601=false.


Auto-discovered channels

Numeric columns (excluding time, realm, primary keys, excluded) become shape: "series" channels. Channel id = slugified header (Speed (m/s)speed_m_s). Layout channels must use these ids.


Output

{ "$heat-dataservice": { "version": "1.0", "groups": [], "realms": [] }, "dashboard_users": [], "tabularUploadSummary": { "schemaVersion": 1, "processedAt": "2026-05-20T12:00:00.000Z", "files": [], "totals": { "fileCount": 0, "rowCount": 0, "errorCount": 0 } } }

CustomRenderer reads $session.payload.tabularUploadSummary on the session page (sandbox mode). See CustomRenderer.


Example configuration

{ "timeColumn": "time_ms", "timeColumnIsMs": true, "baseCapturedAt": "2025-01-01T00:00:00Z", "realmColumn": "pilot_id", "realmPerFile": false, "whenNoOutputs": "complete" }

See also