GuiasExportação de dados

Exportação de dados: o formato .h5dcnvs

Quando você exporta um conjunto de dados, chamado de observação, do DataCNVS, recebe um arquivo que pode realmente ser aberto em qualquer lugar, e não um bloco proprietário que só faz sentido dentro do nosso aplicativo. Esta página explica o que há no arquivo, como abri-lo e apresenta exemplos práticos em Python e MATLAB.

Nesta página

O que você recebe #

A exportação gera um único arquivo com a extensão .h5dcnvs. Por baixo, ele é um arquivo HDF5 totalmente padrão; qualquer ferramenta compatível com HDF5 pode abri-lo, mesmo sem saber nada sobre o DataCNVS. O que o torna um arquivo .h5dcnvs é uma estrutura de árvore específica e autodescritiva em seu interior: cada valor é rotulado com sua função, suas unidades físicas e a variável e o tipo de grandeza que representa. Assim, o próprio arquivo se explica, seja quando aberto em um navegador HDF5 genérico, seja ao escrever cinco linhas de Python.

Uma exportação contém uma observação, com:

  • seus campos escalares (de valor único), por exemplo, o ponto de ajuste de um forno ou o ID de uma amostra,
  • seus campos de série (com valores em matriz), por exemplo, uma série de temperaturas ou medições de tensão,
  • a amostra à qual ela pertence, se houver,
  • e um catálogo das variáveis e dos tipos de grandeza referenciados por esses campos.

Somente dados canônicos do DataCNVS são exportados: os mesmos valores processados e com unidades resolvidas que você vê nas telas do aplicativo. Os dados brutos, tais como foram enviados, nunca são incluídos.

Exportação pelo aplicativo #

Abra a página de uma observação e use o botão Baixar no canto superior direito. A exportação é executada como uma tarefa em segundo plano, portanto, a página exibe o progresso enquanto o arquivo é criado; quando terminar, o download começará automaticamente. No momento, HDF5 é o único formato de exportação disponível, e cada exportação corresponde a uma observação: há um arquivo por exportação, referente à observação que você está visualizando.

Como abrir o arquivo #

Como .h5dcnvs é HDF5 puro, você tem uma grande variedade de ferramentas à disposição:

FerramentaIdeal paraObservações
HDFViewNavegar pela árvore, pelos atributos e pelos valores sem escrever códigoInterface gráfica gratuita do The HDF Group; exibe cada atributo e conjunto de dados exatamente como descrito abaixo
h5dump / h5lsInspeção rápida pela linha de comandoIncluídos nas ferramentas de linha de comando padrão do HDF5; h5dump -A file.h5dcnvs exibe todos os atributos da árvore
Python (h5py, xarray, pandas)Análises com scripts e notebooksVeja abaixo
MATLAB (h5info/h5read/h5readatt integrados)Análises com scripts e geração de gráficosNão requer toolbox; veja abaixo
R (rhdf5)Análises com scriptsPacote do Bioconductor; aplica-se o mesmo modelo de atributos/conjuntos de dados

Se qualquer outra ferramenta que você usa tiver uma opção genérica de "abrir arquivo HDF5/NetCDF" e permitir navegar por grupos e atributos, ela funcionará; o DataCNVS não exige um plugin específico do DataCNVS em nenhuma situação. Aponte-a para qualquer conjunto de dados values/value e leia os atributos units/long_name junto com ele.

Estrutura do arquivo #

A regra principal #

Os atributos contêm todas as informações descritivas; os conjuntos de dados contêm somente os valores propriamente ditos.

Tudo o que for metadado sobre uma medição, incluindo suas unidades, seu rótulo, a variável à qual corresponde e a observação à qual pertence, é um atributo HDF5. Os únicos dois tipos de conjunto de dados HDF5 em todo o arquivo são a matriz values de uma série e o único value de um escalar. Depois que você entende isso, navegar pela árvore se torna previsível: os atributos informam o que algo é, e os conjuntos de dados fornecem os números.

Visão geral da estrutura #

/                                        (grupo raiz, atributos no nível do arquivo; veja abaixo)
├─ observations_summary                  (um espelho em JSON de toda a árvore, por conveniência)
├─ catalog/
│   ├─ quantity_kinds/
│   │   └─ temperature/                  (um grupo por tipo de grandeza, nomeado por sua chave)
│   └─ variables/
│       └─ temperature/                  (um grupo por variável, nomeado por sua chave)
└─ observations/
    └─ obs_000001/
        ├─ sample/                       (presente somente se a observação tiver uma amostra)
        ├─ scalars/
        │   └─ contextual_furnace_setpoint/
        │       └─ value                 (Conjunto de dados)
        ├─ series/
        │   ├─ index_time/
        │   │   └─ values                (Conjunto de dados)
        │   └─ dependent_temperature/
        │       └─ values                (Conjunto de dados)
        └─ series_groups/                (presente somente quando as séries compartilham um índice comum)
            └─ group_000001/

Os nomes de grupos e campos são estáveis, determinísticos e legíveis por pessoas. A mesma observação exportada duas vezes produz a mesma árvore, e o caminho HDF5 de um campo (por exemplo, observations/obs_000001/series/dependent_temperature) também serve como sua localização em linguagem simples.

Atributos da raiz #

Alguns atributos no grupo raiz do arquivo descrevem a exportação como um todo:

AtributoSignificado
formatSempre "datacnvs.interchange.hdf5", o que identifica este arquivo como uma exportação do DataCNVS, e não apenas como qualquer arquivo HDF5
format_versionVersão do formato do contêiner (número inteiro)
generated_atMomento em que a exportação foi gerada, no formato ISO-8601 UTC
source_tenant_slugO espaço de trabalho do qual os dados foram exportados
title, readmeUm título legível e um breve parágrafo explicando a árvore; leia isso primeiro se estiver explorando um arquivo pela primeira vez

Catálogo: variáveis e tipos de grandeza #

catalog/quantity_kinds/<key>/ e catalog/variables/<key>/ contêm os metadados compartilhados aos quais os campos escalares e de série fazem referência. Assim, eles são gravados apenas uma vez, mesmo que vários campos usem a mesma variável. Um grupo de tipo de grandeza tem esta aparência:

catalog/quantity_kinds/temperature/
├─ @key             = "temperature"
├─ @label           = "Temperature"
├─ @canonical_units = "K"
├─ @units           = "K"          (duplicado, no estilo CF; veja abaixo)
├─ @symbol          = "T"
└─ @common_units    = ["degC", "degF", "K"]

Um grupo de variáveis é semelhante e também contém @quantity_kind_key, que é a string a ser consultada em catalog/quantity_kinds/ para resolver suas unidades e sua definição.

A observação #

O grupo observations/obs_000001/ é a observação que você exportou, com obs_type, title, technique, notes, ingestion_status e created_at como atributos, além de um subgrupo sample/ caso haja uma amostra associada.

Em seu interior, cada campo escalar e de série recebe seu próprio grupo em scalars/ ou series/, nomeado com um slug legível (por exemplo, contextual_furnace_setpoint, dependent_temperature, index_time). Cada grupo de campos contém o mesmo vocabulário de atributos, apresentado lado a lado em dois estilos sobrepostos:

AtributoEstiloSignificado
unitsConvenção CFUnidades físicas, resolvidas a partir do tipo de grandeza (ou de units_override, se o campo as substituir)
long_nameConvenção CFRótulo legível: o alias do campo, se houver, ou o nome da variável
standard_nameCampo da convenção CFReutilizado para armazenar a chave de tipo de grandeza do DataCNVS; ele não é validado em relação ao vocabulário CF real
roleDataCNVSPor que esse campo existe na observação, por exemplo, dependent, contextual, index
dtypeDataCNVSO tipo de dados do valor no DataCNVS; veja a referência de tipos abaixo
variable_key, quantity_kind_keyDataCNVSChaves de consulta em catalog/variables/ e catalog/quantity_kinds/
alias, units_overrideDataCNVSPresentes somente quando o campo substitui o rótulo/as unidades padrão da variável

Os nomes no estilo CF (units, long_name, standard_name) existem porque são amplamente reconhecidos por ferramentas científicas genéricas para HDF5/NetCDF. Assim, você obtém unidades e rótulos legíveis sem nenhum plugin específico do DataCNVS. Os nomes no estilo DataCNVS existem para permitir consultas inequívocas e fáceis de usar em código. Ambos descrevem o mesmo campo; use o que melhor se adaptar à sua ferramenta.

Os campos de série também contêm series_kind ("series" ou "index"), length e, se a série compartilhar um índice comum com outras (por exemplo, um eixo de tempo compartilhado por várias curvas dependentes), series_group_ref, que aponta para uma entrada em series_groups/ (veja a próxima seção).

Grupos de séries #

Quando duas ou mais séries na observação compartilham um índice comum (na maioria das vezes, um eixo de tempo ou posição com várias medições dependentes relacionadas a ele), elas são vinculadas por meio de observations/obs_000001/series_groups/group_NNNNNN/. Esse grupo não duplica nenhum dado; ele apenas lista os caminhos dos membros e, somente para facilitar a navegação, fornece links simbólicos HDF5 para os conjuntos de dados values reais, de modo que um navegador de árvore mostre visualmente a relação. O código deve sempre resolver essa relação a partir do atributo series_group_ref, e não percorrendo os links.

Uma série sem o atributo series_group_ref simplesmente não tem um índice compartilhado; portanto, trate seus valores como ordenados pela posição da linha (ponto 0, ponto 1, ponto 2, …).

observations_summary #

O conjunto de dados observations_summary no nível da raiz contém as mesmas informações que a árvore inteira, reapresentadas como um único documento JSON com a observação, seus campos e as entradas do catálogo com seus caminhos HDF5. É uma conveniência para scripts que prefiram analisar um único bloco JSON em vez de percorrer a árvore de grupos, e há a garantia de que ele seja um espelho fiel do que os atributos já informam (nunca uma fonte de informações adicionais).

Referência de tipos de dados #

O atributo dtype de cada campo informa como seu conjunto de dados value/values é armazenado fisicamente:

dtype do DataCNVSArmazenado comoObservações
stringTexto UTF-8
booleanboolean
integerNúmero inteiro de 64 bits
number / numeric(p,s)Número de ponto flutuante de 64 bits
dateTexto de data ISO-8601, por exemplo, "2026-06-01"
datetime / timestampNúmero inteiro de 64 bits em milissegundos desde a época Unix (UTC)Também contém um atributo time_units = "epoch_ms_utc" como lembrete
json, list, struct, map, dictionaryTexto UTF-8 contendo o valor codificado em JSONTambém contém encoding = "json"; analise a string como JSON para recuperar o valor estruturado

Séries numéricas grandes são compactadas com gzip e divididas em blocos; valores pequenos e textos são armazenados sem compactação. Isso é transparente para todos os leitores abaixo: h5py, xarray e MATLAB fazem a descompactação automaticamente.

Como trabalhar com exportações em Python #

O caminho mais direto é usar h5py; ele não exige nenhum código específico do DataCNVS, apenas os nomes de atributos documentados acima.

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"])

    # Um valor escalar, com suas unidades.
    setpoint = obs["scalars/contextual_furnace_setpoint"]
    print(setpoint["value"][()], setpoint.attrs["units"])

    # Uma série e suas unidades/seu rótulo.
    temperature = obs["series/dependent_temperature"]
    values = temperature["values"][:]
    print(f"{len(values)} points, units={temperature.attrs['units']}")

    # Uma série de índice de data e hora é decodificada a partir de milissegundos desde a época.
    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
    ]

    # Consulte o tipo de grandeza de um campo por meio do catálogo compartilhado.
    qk_key = temperature.attrs["quantity_kind_key"]
    qk = f[f"catalog/quantity_kinds/{qk_key}"]
    print(qk.attrs["label"], qk.attrs["canonical_units"])

    # Um campo json/list/struct/map é decodificado com json.loads.
    # struct_field = obs["scalars/contextual_some_json_field"]
    # value = json.loads(struct_field["value"][()])

    # A árvore inteira, reapresentada como JSON, caso seja mais fácil trabalhar assim.
    summary = json.loads(f["observations_summary"][()])

Se você preferir trabalhar com matrizes rotuladas em vez de caminhos HDF5 brutos, crie um xarray.Dataset a partir das partes acima (o arquivo não associa escalas de dimensão por conta própria; portanto, você monta os rótulos uma vez durante a leitura):

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()

Para trabalhos tabulares, a matriz values de uma série é convertida diretamente em uma pandas.Series ou em uma coluna de DataFrame: pandas.Series(temperature["values"][:]).

Como trabalhar com exportações no MATLAB #

As funções HDF5 integradas do MATLAB (h5info, h5disp, h5read, h5readatt) não exigem toolbox e funcionam diretamente com arquivos .h5dcnvs.

matlab
file = "furnace_run_14.h5dcnvs";

% Navegue por toda a árvore, incluindo todos os atributos.
h5disp(file);

% Leia o título da observação.
obsTitle = h5readatt(file, "/observations/obs_000001", "title");

% Leia uma série e suas unidades.
temperature = h5read(file, "/observations/obs_000001/series/dependent_temperature/values");
units = h5readatt(file, "/observations/obs_000001/series/dependent_temperature", "units");

% O índice de tempo correspondente é decodificado a partir de milissegundos desde a época (UTC).
epochMs = h5read(file, "/observations/obs_000001/series/index_time/values");
t = datetime(epochMs, "ConvertFrom", "epochtime", ...
    "TicksPerSecond", 1000, "Epoch", "1970-01-01", "TimeZone", "UTC");

% Um valor escalar, com suas unidades.
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));

Observações para usuários do MATLAB:

  • Campos de texto de tamanho variável (rótulos, valores codificados em JSON, strings de data ISO) são retornados por h5read/h5readatt como uma string do MATLAB ou uma matriz de células de vetores de caracteres, dependendo de o conjunto de dados/atributo subjacente ser escalar ou ter valores em matriz; envolva valores únicos em string(...) se precisar de tipagem consistente entre os campos.
  • Um valor json/list/struct/map/dictionary é lido como texto JSON; decodifique-o com jsondecode(...).
  • h5info(file, "/observations/obs_000001") fornece a mesma lista de atributos/conjuntos de dados exibida por h5disp, mas como uma struct que você pode percorrer programaticamente em vez de lê-la no console.

Limites e retenção #

  • A exportação é feita por observação: um arquivo, uma observação.
  • Somente dados canônicos (processados) são exportados; os dados brutos, tais como foram enviados, nunca são incluídos.
  • Os links para download expiram sete dias após a conclusão da exportação; os dados da observação subjacente não são alterados, portanto, basta exportar novamente.

Quer outro formato? #

Atualmente, HDF5 é o único formato de exportação. Se o seu fluxo de trabalho precisar de outra opção, como um CSV simples, outro formato de intercâmbio ou o formato nativo de uma ferramenta específica, fale conosco.

Fale com a equipe do DataCNVS