// Package synthetic implements a DataSource that computes signals from // existing upstream signals by running them through configurable DSP pipelines. package synthetic // SignalDef describes one synthetic signal. type SignalDef struct { Name string `json:"name"` DS string `json:"ds"` // upstream data source name Signal string `json:"signal"` // upstream signal name (or "" for constant) Inputs []InputRef `json:"inputs"` // alternative multi-input format Pipeline []NodeDef `json:"pipeline"` // ordered list of DSP nodes Graph *Graph `json:"graph,omitempty"` // DAG form (preferred when present) Meta MetaOverride `json:"meta"` // optional metadata overrides // Visibility controls who sees this signal in the signal tree: // "global" — listed in every panel's edit mode // "user" — listed in every panel owned by Owner // "panel" — listed only when editing the bound Panel // An empty value is treated as "global" for backward compatibility with // definitions created before this field existed. Visibility string `json:"visibility,omitempty"` Owner string `json:"owner,omitempty"` // creator identity (stamped server-side) Panel string `json:"panel,omitempty"` // bound interface id for "panel" visibility } // InputRef names one upstream signal used as input to the pipeline. type InputRef struct { DS string `json:"ds"` Signal string `json:"signal"` } // NodeDef is a single node in the pipeline. type NodeDef struct { Type string `json:"type"` Params map[string]any `json:"params,omitempty"` } // Graph is the DAG form of a synthetic signal: a set of nodes (sources, ops and // one output) wired together by explicit per-node ordered input lists. It // supersedes the linear Inputs+Pipeline form: when SignalDef.Graph is set it is // authoritative; otherwise the legacy linear fields are converted into an // equivalent graph at load time (see toGraph). type Graph struct { Nodes []GraphNode `json:"nodes"` Output string `json:"output"` // id of the output node } // GraphNode is one node in a Graph. // // kind=="source": carries DS+Signal; has no Inputs (a graph root). // kind=="op": carries Op + Params; Inputs lists upstream node IDs in the // order the op receives them (input 0, 1, … e.g. a−b, a÷b). // kind=="output": Inputs has a single upstream node whose value is the result. // // X/Y are the editor layout coordinates, persisted so a reloaded graph keeps its // shape; they have no effect on evaluation. type GraphNode struct { ID string `json:"id"` Kind string `json:"kind"` Op string `json:"op,omitempty"` Params map[string]any `json:"params,omitempty"` DS string `json:"ds,omitempty"` Signal string `json:"signal,omitempty"` Inputs []string `json:"inputs,omitempty"` X float64 `json:"x,omitempty"` Y float64 `json:"y,omitempty"` } // MetaOverride allows the synthetic signal to override display metadata. type MetaOverride struct { Unit string `json:"unit,omitempty"` Description string `json:"description,omitempty"` DisplayLow float64 `json:"displayLow,omitempty"` DisplayHigh float64 `json:"displayHigh,omitempty"` Writable bool `json:"writable,omitempty"` }