Tabelle e database
Campi di dati, tabelle e database
Per le funzioni seguenti, le tabelle necessarie vengono passate alla funzione come risorsa. La tabella viene letta e preparata internamente.
Come campo di dati, a seconda del valore di ingresso si interpola tra i singoli elementi di dati.
Come tabella con nomi di campo è possibile cercare una voce corrispondente in determinati campi chiave e leggere diversi campi di tale voce.
È in programma l'implementazione di un'interfaccia sqlite per l'accesso a un'istanza di database locale con query di ricerca definibili.
Curva caratteristica, mappa caratteristica "lookup"
Con la funzione lookup() è possibile interpolare linearmente, da curve caratteristiche o mappe caratteristiche, dati relativi a una o tre grandezze di ingresso.
L1 = lookup(x, {...});
L2 = lookup(x, y, {...});
L3 = lookup(x, y, z, {...});
// Das Konfigurationsobjekt ist verpflichtend und muss
// auf eine Ressource verweisen:
Lx = lookup(..., {$ref:'myLookupData'});
L'oggetto di configurazione segue una propria sintassi e deve pertanto essere ottenuto con {$ref:'myLookupData'} dall'area delle risorse del modulo matematico. Sono supportati due formati: il classico formato di testo e una descrizione nel formato JSON semplificato1
Descrizione degli ingressi / assi
A ciascun segnale di ingresso viene assegnato un asse. Questo è definito dalla sua unità <unit>, da un valore iniziale <from>, dall'incremento <step> e dal numero di punti di appoggio <count>. Gli assi non devono necessariamente essere ordinati in sequenza numerica crescente.
Configurazione nel formato di testo (classico)
Per ciascun asse deve essere aggiunta all'inizio del blocco di testo la seguente descrizione, quindi almeno una e al massimo tre:
IN <unit> <from> <step> <count>
Configurazione nel formato JSON:
Nel formato JSON è inoltre possibile indicare un nome descrittivo, informale <name> e, in alternativa a uno dei parametri di valore citati in precedenza, il valore finale <to>. Devono quindi essere definite esattamente tre delle quattro proprietà <from>, <step>, <count> oppure <to>; la quarta viene calcolata.
{
axes: [
{ name: <str>, // optional description
unit: <str>, // recommended
// choose 3 as mandatory of the following 4:
from: <dbl>, // left-side value of input axis
step: <dbl>, // increment between interpolation points
count: <uint>, // number of interpolation points
to: <dbl> // right-side value of input axis
}, ...
], ...
}
Descrizione delle uscite
Il segnale di uscita è descritto da un'unità <unit>.
Configurazione nel formato di testo (classico)
La definizione seguente deve essere riportata una volta dopo la definizione degli ingressi:
OUT <unit>
Configurazione nel formato JSON:
Nel formato JSON è inoltre possibile indicare un nome descrittivo, informale <name>. Al posto dell'oggetto JSON per ciascuna uscita (raccomandato) è possibile indicare anche solo l'unità fisica come stringa.
{
outputs: [
{ name: <str>, // optional description
unit: <str> // recommended
}, ... // prepared to support vector output in future
<str>, ... // alternative to define output by unit
], ...
Campo di dati
Il campo di dati è costituito da valori <dbl>. L'ordine dei punti di appoggio risulta dal seguente pseudocodice:
foreach(z : axis3)
foreach(y : axis2)
foreach(x : axis1)
Value[x,y,z];
Configurazione nel formato di testo (classico)
I valori dei dati vengono semplicemente separati tra loro, in modo arbitrario, da spazi, tabulazioni o avanzamenti di riga e letti in sequenza nei punti di appoggio della curva caratteristica o della mappa caratteristica.
0 42.942 87.924 134.946
184.008 235.11 288.252
... continued up to 161 data points
Configurazione nel formato JSON:
Nel formato JSON tutti i valori dei dati vengono indicati in un array di numeri in virgola mobile.
{
data: [
<dbl>, ...
], ...
}
Riepilogo
Configurazione nel formato di testo (classico)
Curva caratteristica:
IN kPa 0.0 0.167751 161
OUT l
0
42.942
87.924
134.946
184.008
235.11
288.252
343.434
400.656
459.918
521.22
... continued up to 161 data points
Mappa caratteristica:
IN g/h 0 10000 22
IN 1/min 900 100 10
OUT kW
0.0 40.8 81.6 132.9 185.2 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0 200.0
0.0 40.0 80.0 131.3 184.3 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0 230.0
0.0 38.5 76.9 125.8 182.4 233.5 286.9 310.0 310.0 310.0 310.0 310.0 310.0 310.0 310.0 310.0 310.0 310.0 310.0 310.0 310.0 310.0
... 7 more rows with 22 data points each
Configurazione nel formato JSON semplificato
L'oggetto di configurazione può essere descritto anche nel formato JSON semplificato1.
{
axes: [
{ name: <str>, // optional description
unit: <str>, // recommended
from: <dbl>, // left-side value of input axis
step: <dbl>, // increment between interpolation points
count: <uint>, // number of interpolation points
to: <dbl> // right-side value of input axis
}, ...
],
outputs: [
{ name: <str>, // optional description
unit: <str> // recommended
}, ... // prepared to support vector output in future
<str>, ... // alternative to define output by unit
],
data: [
<dbl>, ...
]
}
Messa a disposizione come risorsa
Esistono molteplici possibilità per includere questa descrizione di curva caratteristica o di mappa caratteristica nelle risorse del modulo matematico.
Per piccole mappe caratteristiche o curve caratteristiche è adatta la formattazione come risorsa di testo:
"resources": {
"myLookupData": [
"IN kPa 0.0 0.167751 161"
, "OUT l"
, "0 42.942 87.924 134.946 184.008 235.11 288.252 343.434"
, "400.656 459.918 521.22 584.562 649.944 717.366 785.90745"
, "854.45145 ... and more"
], ...
In alternativa, la stessa mappa caratteristica nel formato JSON semplificato:
"resources": {
"myLookupData": {
axes: [{ name: "HydroStatPressure", unit: "kPa"
, from: 0.0, step: 0.167751, count: 161 }],
outputs: [{ name: "Volume", unit: "l" }],
data: [
0, 42.942, 87.924, 134.946, 184.008, 235.11, 288.252, 343.434
, 400.656, 459.918, 521.22, 584.562, 649.944, 717.366, 785.90745
, 854.45145, // ... and more
]
}, ...
Per mappe caratteristiche più grandi, o per quelle che non devono comparire né essere leggibili nella configurazione JSON di smartCORE, sarebbe opportuna una stringa elaborata.
Dapprima con un file di mappa caratteristica myLookupData.tab come sorgente di dati, che segua la sintassi indicata sopra (testo/JSON):
"resources": {
"myLookupData": {
"decoder": ["file"],
"value": "myLookupData.tab"
}, ...
oppure, se la mappa caratteristica è disponibile in forma compressa:
"resources": {
"myLookupData": {
"decoder": ["file", "unzip"],
"value": "myLookupData.gz"
}, ...
In alternativa i dati possono essere inseriti nella risorsa anche come stringa base64:
"resources": {
"myLookupData": {
"decoder": ["base64"],
"value": "Q09MCWcvaAkwCTEwMDAwCTIyDQpST1cJMS9taW4JOTAwCTEw..."
}, ...
... oppure il file compresso come stringa base64:
"resources": {
"myLookupData": {
"decoder": ["base64", "unzip"],
"value": "UEsDBBQAAgAIACt3cUoHOG6qmgEAAD4FAAAcAAAAUF9lZmZf..."
}
Query di ricerca "selectRow"
La funzione selectRow() cerca in modo sequenziale, in una tabella semplice, in tutte le righe una corrispondenza con le chiavi indicate e restituisce l'indice di riga trovato. Se non viene trovata alcuna corrispondenza, viene restituito -1. Una ricerca viene eseguita solo se cambia almeno uno dei valori chiave richiesti.
Questo indice di riga può essere utilizzato in getField() per leggere qualsiasi valore dai campi di dati della tabella.
m1 = selectRow(key1, ..., { table: <str> // mandatory
, colSep: <regex>
, anyKey: <var>
, key: <str> // mandatory (*)
, keys: [<str>] // mandatory (*)
});
// (*) exactly one of key or keys must be defined
| Proprietà | Valore | Descrizione |
|---|---|---|
| table | <str> | Obbligatorio: Nome di una risorsa di testo che definisce il contenuto della tabella. Gli elementi di dati vengono interpretati come Variant e forniscono quindi il miglior tipo di dati possibile. I numeri in virgola mobile devono essere scritti con il punto come separatore decimale. |
| colSep | <regex> | Espressione regolare che definisce i separatori di colonna. Default: "[,;|\t]", utilizzabile universalmente per un singolo carattere tra quelli indicati in []. |
| anyKey | <var> | Un elemento di dati con questo valore fornisce un risultato positivo per qualsiasi valore chiave, default: "*" |
| key | <str> | Obbligatorio (*, **): Un campo di dati della tabella in cui viene cercato il primo e unico valore chiave key1. |
| keys | [<str>] | Obbligatorio (*, **): Un vettore con più campi di dati, da applicare nell'ordine indicato ai valori chiave key1, key2, key3, ... |
(*) Per selezionare le colonne chiave deve essere utilizzata esattamente una delle proprietà key o keys.
(**) Per default viene sempre cercata una corrispondenza esatta del valore chiave con le voci nella colonna della tabella. Per modificare la query, all'identificatore del campo possono essere anteposti opzionalmente i seguenti operatori di confronto; tra operatore e identificatore possono essere inseriti spazi:
| Operatore | Significato | Esempio | Esecuzione come... |
|---|---|---|---|
KEY sia un identificatore di campo in keys:[..] | keyN sia il valore chiave passato come parametro | ||
== | Corrispondenza esatta (default) | 'KEY''==KEY' | keyN == Table[KEY] |
*= | per <str>: contiene | *=KEY | keyN contains Table[KEY] |
&= | per <uint>|<int>: tutti i bit della maschera impostati | '&=KEY' | bAnd(keyN, Table[KEY]) == Table[KEY] |
&> | per <uint>|<int>: almeno un bit della maschera impostato | '&>KEY' | bAnd(keyN, Table[KEY]) > 0 |
&0 | per <uint>|<int>:nessun bit della maschera impostato | '&0 KEY' | bAnd(keyN, Table[KEY]) == 0 |
<= | Minore o uguale | '<=KEY' | keyN <= Table[KEY] |
< | Minore di | '<KEY' | keyN < Table[KEY] |
>= | Maggiore o uguale | '>=KEY' | keyN >= Table[KEY] |
> | Maggiore di | '>KEY' | keyN > Table[KEY] |
Per il tipo di dati <str> i confronti si riferiscono all'ordine alfabetico.
Formattazione della tabella
-
La tabella viene caricata da una risorsa di testo (ASCII, UTF-8)
-
I separatori di colonna sono definiti tramite la proprietà colSep.
-
La stessa tabella può essere utilizzata in più funzioni
selectRow(). L'indicazione di colSep deve essere identica in tutte, poiché non è stabilito quale delle funzioni interpreti per prima la tabella (e quindi anche per tutte le altre istanze). -
La prima riga contiene i nomi dei campi, con i quali vengono poi definite anche le colonne chiave e i campi di risultato.
-
Le righe vuote vengono ignorate.
-
Le righe che iniziano con 3 caratteri uguali del gruppo
_ - = ~ *vengono interpretate come linea di separazione e ignorate. -
Ogni campo di dati viene letto ed elaborato individualmente come Variant. Non esistono quindi tipi di dati fissi per una colonna.
-
La ricerca avviene sempre in modo sequenziale attraverso tutte le righe.
Lettura di una voce di tabella "getField"
La funzione getField() legge da una tabella table interpretata con selectRow(), per l'indice di riga trovato rowIdx, l'elemento di dati corrispondente dal campo di dati field. Il tipo di dati è determinato dall'elemento di dati come Variant.
Se rowIdx è < 0 o al di fuori dell'intervallo valido, viene restituito il Variant definito con notFound.
v1 = getField(rowIdx, { table: <str> // mandatory
, field: <str> // mandatory
, notFound: <var>
});
| Proprietà | Valore | Descrizione |
|---|---|---|
| table | <str> | Obbligatorio: Nome di una risorsa di testo che definisce il contenuto della tabella. Questa deve essere stata interpretata e caricata in una funzione selectRow(). |
| field | <str> | Obbligatorio: Nome di un campo di dati da cui leggere il valore di risultato. |
| notFound | <var> | Questo Variant viene fornito come risultato se rowIdx non designa un risultato di ricerca valido. Default: false. |
Riproduzione di dati registrati "playback" 2
Questa funzione è in fase di implementazione e non è ancora destinata all'uso produttivo.
La funzione playback() apre un file "Tape" e ne estrae gli andamenti temporali di canali di dati selezionati "Tracks".
A seconda della struttura e della lunghezza delle sorgenti di dati utilizzate, possono ancora verificarsi violazioni di memoria e arresti anomali di smartCORE.
I track possono essere pubblicati con un prefisso aggiuntivo come variabili nel Math Module e quindi passati anche a smartCORE come variabile di output.
In modo analogo a un classico registratore a nastro, è possibile impostare marcatori per la riproduzione di un determinato intervallo di tempo e le funzioni di controllo (Stop, Play, Pause, Rewind) possono essere attivate anche tramite una logica estesa.

Attualmente è supportato il formato di file OSF non compresso. Altri formati come ad es. WAV, CSV, ... potrebbero seguire in versioni future.
Gli andamenti riprodotti nel sistema da un tape possono essere utilizzati come riferimento per segnali di misura, per seguire e monitorare il loro andamento dinamico dopo un evento di avvio.
Per testare nuove funzioni del Math Module, su un sistema di laboratorio stazionario è possibile riprodurre in tempo reale dati di misura provenienti dall'uso produttivo. optiCONTROL offre per la preparazione dei dati diverse possibilità di unione, taglio o selezione dei canali.
Per proteggere i file OSF sull'unità /sde dalla compressione automatica, è sufficiente utilizzare un'altra estensione di file, ad es. *.osf_pb o *.osf_tape.
t1 = playback(ctrl, {...});
t2 = playback(ctrl, tInfo, {...});
t3 = playback(ctrl, tInfo, source, {...});
// Configuration is mandatory for paths and keys
tx = playback(..., { directory: <str> // mandatory!
, source: <str> // mandatory! (or by parameter)
, varPrefix: <str>
, keys: [<str>] // mandatory!
, tBegin: <date>
, tRewind: <date>
, tEnd: <date>
, result: <enum>
, loop: <bool>
, tZoom: <dbl>
, endVar: <str>
});
Il parametro tInfo può contenere un valore scalare o un vettore con fino a 3 componenti. La descrizione è riportata anch'essa nella tabella seguente.
| Proprietà | Valore | Descrizione |
|---|---|---|
| directory | <str> | Percorso della directory con i tape |
| source | <str> | Tape iniziale, può essere sovrascritto tramite parametro. Ogni modifica carica dal tape indicato i canali selezionati con keys |
| varPrefix | <str> | Il prefisso viene anteposto ai canali selezionati per la pubblicazione come variabile, ad es. "Tape." |
| keys | [<str>] | Elenco di nomi di canali dal file tape che vengono caricati per la riproduzione. |
| tBegin | <date> | Istante di inizio sul tape selezionato |
| tRewind | <date> | Punto di destinazione per il riavvolgimento o l'avanzamento rapido |
| tEnd | <date> | Istante finale per la riproduzione o ritorno automatico |
| result | <enum> | Emissione della posizione del tape come abs: timestamp assoluto (default) relOrigin: timestamp relativo all'inizio del tape relBegin: timestamp relativo al marcatore tBeginrelInterval: posizione relativa nell'intervallo |
| loop | <bool> | Al raggiungimento del marcatore tEnd si torna a tRewind e la riproduzione prosegue. (def.: false) |
| tZoom | <dbl> | Fattore di zoom per l'asse del tempo durante la riproduzione (def: 1.0), : time-lapse : rallentatore |
| endVar | <str> | Variabile di uscita <bool>, viene impostata su 'true' quando il marcatore tEnd è raggiunto. |
| tInfo | <dbl> | |
| tInfo | [<dbl>, <dbl>] | |
| tInfo | [<dbl>, <dbl>, <dbl>] |