GuideEsportazione dei dati

Esportazione dei dati: il formato .h5dcnvs

Quando esporti da DataCNVS un set di dati, chiamato osservazione, ottieni un file che puoi davvero aprire ovunque, non un file proprietario utilizzabile solo all'interno della nostra app. Questa pagina illustra cosa contiene il file, come aprirlo ed esempi pratici in Python e MATLAB.

In questa pagina

Cosa ottieni #

L'esportazione produce un singolo file con estensione .h5dcnvs. In realtà, si tratta di un file HDF5 del tutto standard; qualsiasi strumento compatibile con HDF5 può aprirlo, anche senza conoscere DataCNVS. Ciò che lo rende un file .h5dcnvs è una specifica struttura ad albero autodescrittiva al suo interno: ogni valore è etichettato con il proprio ruolo, le unità fisiche e la variabile e il tipo di grandezza che rappresenta, così il file si descrive da sé, sia che venga aperto in un generico visualizzatore HDF5, sia scrivendo cinque righe di Python.

Un'esportazione contiene un'osservazione, con:

  • i relativi campi scalari (a valore singolo), ad esempio il setpoint di un forno o l'ID di un campione,
  • i relativi campi serie (con valori in forma di array), ad esempio una serie di temperature o di misure di sollecitazione,
  • il campione a cui appartiene, se presente,
  • e un catalogo delle variabili e dei tipi di grandezza a cui fanno riferimento tali campi.

Vengono esportati solo i dati canonici di DataCNVS: gli stessi valori elaborati e con unità risolte che vedi nei canvas dell'app. I dati grezzi, così come caricati, non vengono mai inclusi.

Esportazione dall'app #

Apri la pagina di un'osservazione e utilizza il pulsante Scarica nell'angolo in alto a destra. L'esportazione viene eseguita come processo in background, quindi la pagina mostra lo stato di avanzamento durante la creazione del file; al termine, il download si avvia automaticamente. HDF5 è attualmente l'unico formato di esportazione disponibile e l'esportazione avviene per singola osservazione: viene creato un file per ogni esportazione, relativo all'osservazione visualizzata.

Apertura del file #

Poiché .h5dcnvs è un normale file HDF5, puoi scegliere tra numerosi strumenti:

StrumentoIdeale perNote
HDFViewEsplorare l'albero, gli attributi e i valori senza scrivere codiceInterfaccia grafica gratuita di The HDF Group; mostra ogni attributo e dataset esattamente come descritto di seguito
h5dump / h5lsIspezione rapida dalla riga di comandoIncluso negli strumenti standard da riga di comando di HDF5; h5dump -A file.h5dcnvs stampa ogni attributo dell'albero
Python (h5py, xarray, pandas)Analisi tramite script, notebookVedi più avanti
MATLAB (h5info/h5read/h5readatt integrati)Analisi tramite script, creazione di graficiNon richiede toolbox; vedi più avanti
R (rhdf5)Analisi tramite scriptPacchetto Bioconductor; si applica lo stesso modello di attributi/dataset

Se qualsiasi altro strumento che utilizzi dispone di un'opzione generica "apri file HDF5/NetCDF" e consente di esplorare gruppi e attributi, funzionerà; DataCNVS non richiede mai un plugin specifico per DataCNVS. Seleziona un qualsiasi dataset values/value e leggi insieme a esso gli attributi units/long_name.

Struttura del file #

La regola fondamentale #

Gli attributi contengono ogni informazione descrittiva; i dataset contengono solo i valori effettivi.

Tutto ciò che costituisce un metadato relativo a una misura, incluse le unità, l'etichetta, la variabile a cui corrisponde e l'osservazione a cui appartiene, è un attributo HDF5. Gli unici due tipi di dataset HDF5 presenti nell'intero file sono l'array values di una serie e il singolo value di uno scalare. Una volta compreso questo principio, esplorare l'albero diventa prevedibile: gli attributi indicano che cos'è un elemento, mentre i dataset forniscono i numeri.

La struttura in sintesi #

/                                        (gruppo radice, attributi a livello di file, vedi sotto)
├─ observations_summary                  (una rappresentazione JSON dell'intero albero, per praticità)
├─ catalog/
│   ├─ quantity_kinds/
│   │   └─ temperature/                  (un gruppo per ogni tipo di grandezza, denominato in base alla relativa chiave)
│   └─ variables/
│       └─ temperature/                  (un gruppo per ogni variabile, denominato in base alla relativa chiave)
└─ observations/
    └─ obs_000001/
        ├─ sample/                       (presente solo se l'osservazione ha un campione)
        ├─ scalars/
        │   └─ contextual_furnace_setpoint/
        │       └─ value                 (Dataset)
        ├─ series/
        │   ├─ index_time/
        │   │   └─ values                (Dataset)
        │   └─ dependent_temperature/
        │       └─ values                (Dataset)
        └─ series_groups/                (presente solo quando le serie condividono un indice comune)
            └─ group_000001/

I nomi dei gruppi e dei campi sono stabili, deterministici e leggibili. Esportando due volte la stessa osservazione si ottiene lo stesso albero e il percorso HDF5 di un campo (ad esempio observations/obs_000001/series/dependent_temperature) ne costituisce anche la posizione in forma leggibile.

Attributi radice #

Alcuni attributi nel gruppo radice del file descrivono l'esportazione nel suo complesso:

AttributoSignificato
formatSempre "datacnvs.interchange.hdf5", che identifica il file come un'esportazione DataCNVS e non come un generico file HDF5
format_versionVersione del formato contenitore (numero intero)
generated_atData e ora di generazione dell'esportazione, in formato ISO-8601 UTC
source_tenant_slugL'area di lavoro da cui sono stati esportati i dati
title, readmeUn titolo leggibile e un breve paragrafo che spiega l'albero; leggilo per primo se stai esplorando un file per la prima volta

Catalogo: variabili e tipi di grandezza #

catalog/quantity_kinds/<key>/ e catalog/variables/<key>/ contengono i metadati condivisi a cui fanno riferimento i campi scalari e serie, così vengono scritti una sola volta anche se più campi utilizzano la stessa variabile. Un gruppo relativo a un tipo di grandezza ha questo aspetto:

catalog/quantity_kinds/temperature/
├─ @key             = "temperature"
├─ @label           = "Temperature"
├─ @canonical_units = "K"
├─ @units           = "K"          (duplicato, in stile CF, vedi sotto)
├─ @symbol          = "T"
└─ @common_units    = ["degC", "degF", "K"]

Un gruppo relativo a una variabile è simile e contiene inoltre @quantity_kind_key, ovvero la stringa da cercare in catalog/quantity_kinds/ per risolverne le unità e la definizione.

L'osservazione #

Il gruppo observations/obs_000001/ rappresenta l'osservazione esportata, con obs_type, title, technique, notes, ingestion_status e created_at come attributi, oltre a un sottogruppo sample/ se è associato un campione.

Al suo interno, ogni campo scalare e serie ha un proprio gruppo in scalars/ o series/, denominato mediante uno slug leggibile (ad esempio contextual_furnace_setpoint, dependent_temperature, index_time). Ogni gruppo di campi utilizza lo stesso vocabolario di attributi, presentato affiancato in due stili parzialmente sovrapposti:

AttributoStileSignificato
unitsConvenzione CFUnità fisiche, risolte dal tipo di grandezza (o da units_override se il campo le sostituisce)
long_nameConvenzione CFEtichetta leggibile: l'alias del campo, se presente, altrimenti il nome della variabile
standard_nameCampo della convenzione CFRiutilizzato per contenere la chiave del tipo di grandezza DataCNVS; non viene convalidato rispetto al vero vocabolario CF
roleDataCNVSIl motivo per cui questo campo è presente nell'osservazione, ad esempio dependent, contextual, index
dtypeDataCNVSIl tipo di dati DataCNVS del valore; vedi il riferimento dei tipi più avanti
variable_key, quantity_kind_keyDataCNVSChiavi di ricerca in catalog/variables/ e catalog/quantity_kinds/
alias, units_overrideDataCNVSPresenti solo quando il campo sostituisce l'etichetta o le unità predefinite della variabile

I nomi in stile CF (units, long_name, standard_name) esistono perché sono ampiamente riconosciuti dagli strumenti scientifici generici per HDF5/NetCDF, permettendo di ottenere unità ed etichette leggibili senza alcun plugin specifico per DataCNVS. I nomi in stile DataCNVS servono per ricerche univoche e facilmente gestibili dal codice. Entrambi descrivono lo stesso campo; usa quello più adatto al tuo strumento.

I campi serie contengono inoltre series_kind ("series" o "index"), length e, se la serie condivide un indice comune con altre (ad esempio un asse temporale condiviso da più curve dipendenti), series_group_ref, che punta a una voce in series_groups/ (vedi la sezione successiva).

Gruppi di serie #

Quando due o più serie dell'osservazione condividono un indice comune (nella maggior parte dei casi, un asse temporale o di posizione con diverse misure dipendenti rispetto a esso), vengono collegate tramite observations/obs_000001/series_groups/group_NNNNNN/. Questo gruppo non duplica alcun dato; elenca semplicemente i percorsi dei membri e, solo per agevolarne l'esplorazione, fornisce collegamenti simbolici HDF5 ai dataset values effettivi, in modo che un visualizzatore dell'albero mostri visivamente la relazione. Il codice deve sempre risolvere la relazione dall'attributo series_group_ref, non seguendo i collegamenti.

Una serie priva dell'attributo series_group_ref non ha semplicemente alcun indice condiviso, quindi considera i suoi valori ordinati in base alla posizione delle righe (punto 0, punto 1, punto 2, …).

observations_summary #

Il dataset observations_summary a livello radice contiene le stesse informazioni dell'intero albero, riformulate in un unico documento JSON che include l'osservazione, i relativi campi e le voci del catalogo con i rispettivi percorsi HDF5. È una soluzione pratica per gli script che preferiscono analizzare un unico blocco JSON anziché attraversare l'albero dei gruppi ed è garantito che sia una rappresentazione rigorosamente fedele di quanto già indicato dagli attributi (mai una fonte di informazioni aggiuntive).

Riferimento dei tipi di dati #

L'attributo dtype di ogni campo indica come viene memorizzato fisicamente il relativo dataset value/values:

dtype DataCNVSMemorizzato comeNote
stringTesto UTF-8
booleanValore booleano
integerNumero intero a 64 bit
number / numeric(p,s)Numero a virgola mobile a 64 bit
dateTesto di data ISO-8601, ad esempio "2026-06-01"
datetime / timestampNumero intero a 64 bit: millisecondi trascorsi dall'epoca Unix (UTC)Include anche un attributo time_units = "epoch_ms_utc" come promemoria
json, list, struct, map, dictionaryTesto UTF-8 contenente il valore codificato in JSONInclude anche encoding = "json"; analizza la stringa come JSON per recuperare il valore strutturato

Le serie numeriche di grandi dimensioni sono compresse con gzip e suddivise in blocchi; i valori piccoli e il testo vengono memorizzati senza compressione. Questo processo è trasparente per tutti i lettori descritti di seguito: h5py, xarray e MATLAB decomprimono tutto automaticamente.

Utilizzo delle esportazioni in Python #

Il metodo più diretto è h5py; non richiede codice specifico per DataCNVS, ma solo i nomi degli attributi documentati sopra.

python
import datetime as dt
import json

import h5py

with h5py.File("furnace_run_14.h5dcnvs", "r") as f:
    print(f.attrs["title"])
    print(f.attrs["readme"])

    obs = f["observations/obs_000001"]
    print(obs.attrs["title"], "-", obs.attrs["technique"])

    # Un valore scalare, con le relative unità.
    setpoint = obs["scalars/contextual_furnace_setpoint"]
    print(setpoint["value"][()], setpoint.attrs["units"])

    # Una serie e le relative unità/etichetta.
    temperature = obs["series/dependent_temperature"]
    values = temperature["values"][:]
    print(f"{len(values)} points, units={temperature.attrs['units']}")

    # Una serie indice datetime viene decodificata dai millisecondi trascorsi dall'epoca.
    index_time = obs["series/index_time"]
    epoch_ms = index_time["values"][:]
    timestamps = [
        dt.datetime(1970, 1, 1, tzinfo=dt.timezone.utc) + dt.timedelta(milliseconds=int(t))
        for t in epoch_ms
    ]

    # Cerca il tipo di grandezza di un campo tramite il catalogo condiviso.
    qk_key = temperature.attrs["quantity_kind_key"]
    qk = f[f"catalog/quantity_kinds/{qk_key}"]
    print(qk.attrs["label"], qk.attrs["canonical_units"])

    # Un campo json/list/struct/map viene decodificato con json.loads.
    # struct_field = obs["scalars/contextual_some_json_field"]
    # value = json.loads(struct_field["value"][()])

    # L'intero albero, riformulato come JSON, se è più facile da utilizzare.
    summary = json.loads(f["observations_summary"][()])

Se preferisci lavorare con array etichettati anziché con percorsi HDF5 non elaborati, crea un xarray.Dataset dagli elementi descritti sopra (il file non associa direttamente le scale delle dimensioni, quindi le etichette vengono assemblate una sola volta, durante la lettura):

python
import h5py
import xarray as xr

with h5py.File("furnace_run_14.h5dcnvs", "r") as f:
    obs = f["observations/obs_000001"]
    time = obs["series/index_time/values"][:]
    temp_grp = obs["series/dependent_temperature"]
    temp = temp_grp["values"][:]
    units = temp_grp.attrs["units"]

ds = xr.Dataset(
    {"temperature": ("time", temp, {"units": units})},
    coords={"time": ("time", time, {"units": "epoch_ms_utc"})},
)
ds.temperature.plot()

Per lavorare con dati tabulari, l'array values di una serie si converte direttamente in una colonna pandas.Series o DataFrame: pandas.Series(temperature["values"][:]).

Utilizzo delle esportazioni in MATLAB #

Le funzioni HDF5 integrate di MATLAB (h5info, h5disp, h5read, h5readatt) non richiedono alcun toolbox e funzionano direttamente con i file .h5dcnvs.

matlab
file = "furnace_run_14.h5dcnvs";

% Esplora l'intero albero, inclusi tutti gli attributi.
h5disp(file);

% Leggi il titolo dell'osservazione.
obsTitle = h5readatt(file, "/observations/obs_000001", "title");

% Leggi una serie e le relative unità.
temperature = h5read(file, "/observations/obs_000001/series/dependent_temperature/values");
units = h5readatt(file, "/observations/obs_000001/series/dependent_temperature", "units");

% L'indice temporale associato viene decodificato dai millisecondi trascorsi dall'epoca (UTC).
epochMs = h5read(file, "/observations/obs_000001/series/index_time/values");
t = datetime(epochMs, "ConvertFrom", "epochtime", ...
    "TicksPerSecond", 1000, "Epoch", "1970-01-01", "TimeZone", "UTC");

% Un valore scalare, con le relative unità.
setpoint = h5read(file, "/observations/obs_000001/scalars/contextual_furnace_setpoint/value");
setpointUnits = h5readatt(file, "/observations/obs_000001/scalars/contextual_furnace_setpoint", "units");

plot(t, temperature);
xlabel("Time");
ylabel(sprintf("Temperature (%s)", units));
title(sprintf("%s — setpoint %.1f %s", obsTitle, setpoint, setpointUnits));

Note per gli utenti MATLAB:

  • I campi di testo a lunghezza variabile (etichette, valori codificati in JSON, stringhe di date ISO) vengono restituiti da h5read/h5readatt come stringa MATLAB o come array di celle di vettori di caratteri, a seconda che il dataset/attributo sottostante sia scalare o in forma di array; racchiudi i singoli valori in string(...) se hai bisogno di una tipizzazione coerente tra i campi.
  • Un valore json/list/struct/map/dictionary viene letto come testo JSON; decodificalo con jsondecode(...).
  • h5info(file, "/observations/obs_000001") restituisce lo stesso elenco di attributi/dataset stampato da h5disp, ma sotto forma di struttura che puoi attraversare programmaticamente anziché leggerla dalla console.

Limiti e conservazione #

  • L'esportazione avviene per singola osservazione: un file, un'osservazione.
  • Vengono esportati solo i dati canonici (elaborati), mai i dati grezzi così come caricati.
  • I link per il download scadono 7 giorni dopo il completamento dell'esportazione; i dati dell'osservazione sottostante restano invariati, quindi puoi semplicemente eseguire una nuova esportazione.

Vuoi un formato diverso? #

Attualmente HDF5 è l'unico formato di esportazione. Se il tuo flusso di lavoro richiede altro, ad esempio un CSV in formato piatto, un diverso formato di interscambio o il formato nativo di uno strumento specifico, faccelo sapere.

Contatta il team DataCNVS