Exportación de datos: el formato .h5dcnvs
Cuando exportas desde DataCNVS un conjunto de datos, denominado observación, obtienes un archivo que puedes abrir en cualquier lugar, no un bloque de datos propietario que solo tiene sentido dentro de nuestra aplicación. Esta página explica qué contiene el archivo, cómo abrirlo y ofrece ejemplos prácticos en Python y MATLAB.
En esta página
Qué obtienes #
La exportación genera un único archivo con la extensión .h5dcnvs. En realidad, es un archivo HDF5 completamente estándar; cualquier herramienta compatible con HDF5 puede abrirlo, incluso sin saber nada sobre DataCNVS. Lo que lo convierte en un archivo .h5dcnvs es una estructura de árbol específica y autodescriptiva en su interior: cada valor está etiquetado con su función, sus unidades físicas y la variable y el tipo de magnitud que representa, de modo que el archivo se explica por sí mismo tanto si lo abres en un visor HDF5 genérico como si escribes cinco líneas de Python.
Una exportación contiene una observación, con:
- sus campos escalares (de un solo valor), p. ej., el punto de consigna de un horno o el ID de una muestra,
- sus campos de serie (con valores en forma de matriz), p. ej., una serie de temperaturas o mediciones de tensión,
- la muestra a la que pertenece, si existe,
- y un catálogo de las variables y los tipos de magnitud a los que hacen referencia esos campos.
Solo se exportan datos canónicos de DataCNVS: los mismos valores procesados y con las unidades resueltas que ves en los lienzos de la aplicación. Nunca se incluyen los datos sin procesar tal como se cargaron.
Exportación desde la aplicación #
Abre la página de una observación y usa el botón Descargar de la esquina superior derecha. La exportación se ejecuta como una tarea en segundo plano, por lo que la página muestra el progreso mientras se genera el archivo; cuando termina, la descarga se inicia automáticamente. Actualmente, HDF5 es el único formato de exportación disponible y cada exportación corresponde a una observación: hay un archivo por exportación, para la observación que estás viendo.
Cómo abrir el archivo #
Como .h5dcnvs es HDF5 estándar, dispones de una amplia variedad de herramientas:
| Herramienta | Ideal para | Notas |
|---|---|---|
| HDFView | Explorar el árbol, los atributos y los valores sin escribir código | Interfaz gráfica gratuita de The HDF Group; muestra cada atributo y conjunto de datos exactamente como se describe a continuación |
h5dump / h5ls | Inspección rápida desde la línea de comandos | Se incluye con las herramientas estándar de línea de comandos de HDF5; h5dump -A file.h5dcnvs muestra todos los atributos del árbol |
| Python (h5py, xarray, pandas) | Análisis mediante scripts y cuadernos | Consulta más abajo |
| MATLAB (h5info/h5read/h5readatt integrados) | Análisis mediante scripts y representación gráfica | No requiere ninguna caja de herramientas; consulta más abajo |
| R (rhdf5) | Análisis mediante scripts | Paquete de Bioconductor; se aplica el mismo modelo de atributos/conjuntos de datos |
Si cualquier otra herramienta que utilices incluye una opción genérica para «abrir un archivo HDF5/NetCDF» y permite explorar grupos y atributos, funcionará; DataCNVS no requiere ningún complemento específico para DataCNVS. Dirígela a cualquier conjunto de datos values/value y lee junto a él los atributos units/long_name.
Estructura del archivo #
La regla fundamental #
Los atributos contienen toda la información descriptiva; los conjuntos de datos contienen únicamente los valores reales.
Todo lo que constituye metadatos sobre una medición, incluidas sus unidades, su etiqueta, la variable a la que corresponde y la observación a la que pertenece, es un atributo HDF5. Los dos únicos tipos de conjunto de datos HDF5 de todo el archivo son la matriz values de una serie y el único value de un escalar. Una vez entendido esto, explorar el árbol resulta predecible: los atributos indican qué es cada elemento y los conjuntos de datos proporcionan los números.
Estructura de un vistazo #
/ (grupo raíz, atributos a nivel de archivo; consulta más abajo)
├─ observations_summary (un reflejo en JSON de todo el árbol, para mayor comodidad)
├─ catalog/
│ ├─ quantity_kinds/
│ │ └─ temperature/ (un grupo por cada tipo de magnitud, denominado según su clave)
│ └─ variables/
│ └─ temperature/ (un grupo por cada variable, denominado según su clave)
└─ observations/
└─ obs_000001/
├─ sample/ (presente solo si la observación tiene una muestra)
├─ scalars/
│ └─ contextual_furnace_setpoint/
│ └─ value (Conjunto de datos)
├─ series/
│ ├─ index_time/
│ │ └─ values (Conjunto de datos)
│ └─ dependent_temperature/
│ └─ values (Conjunto de datos)
└─ series_groups/ (presente solo cuando varias series comparten un índice común)
└─ group_000001/Los nombres de grupos y campos son estables, deterministas y legibles. La misma observación exportada dos veces genera el mismo árbol, y la ruta HDF5 de un campo (p. ej., observations/obs_000001/series/dependent_temperature) también sirve como su ubicación en lenguaje natural.
Atributos raíz #
Un pequeño conjunto de atributos del grupo raíz del archivo describe la exportación en su totalidad:
| Atributo | Significado |
|---|---|
format | Siempre "datacnvs.interchange.hdf5", lo que identifica el archivo como una exportación de DataCNVS y no como cualquier archivo HDF5 |
format_version | Versión del formato del contenedor (entero) |
generated_at | Momento en el que se generó la exportación, en formato ISO-8601 UTC |
source_tenant_slug | El espacio de trabajo desde el que se exportaron los datos |
title, readme | Un título legible y un breve párrafo que explica el árbol; léelo primero si estás explorando un archivo por primera vez |
Catálogo: variables y tipos de magnitud #
catalog/quantity_kinds/<key>/ y catalog/variables/<key>/ contienen los metadatos compartidos a los que remiten los campos escalares y de serie, por lo que solo se escriben una vez aunque varios campos utilicen la misma variable. Un grupo de tipo de magnitud tiene este aspecto:
catalog/quantity_kinds/temperature/
├─ @key = "temperature"
├─ @label = "Temperature"
├─ @canonical_units = "K"
├─ @units = "K" (duplicado, al estilo CF; consulta más abajo)
├─ @symbol = "T"
└─ @common_units = ["degC", "degF", "K"]Un grupo de variables es similar y, además, contiene @quantity_kind_key, que es la cadena que se busca en catalog/quantity_kinds/ para resolver sus unidades y su definición.
La observación #
El grupo observations/obs_000001/ es la observación que exportaste, con obs_type, title, technique, notes, ingestion_status y created_at como atributos, además de un subgrupo sample/ si hay una muestra asociada.
En su interior, cada campo escalar y de serie tiene su propio grupo bajo scalars/ o series/, denominado mediante un identificador legible (p. ej., contextual_furnace_setpoint, dependent_temperature, index_time). Cada grupo de campos utiliza el mismo vocabulario de atributos, presentado en paralelo en dos estilos que se solapan:
| Atributo | Estilo | Significado |
|---|---|---|
units | Convención CF | Unidades físicas, resueltas a partir del tipo de magnitud (o de units_override si el campo las sobrescribe) |
long_name | Convención CF | Etiqueta legible: el alias del campo, si lo tiene; de lo contrario, el nombre de la variable |
standard_name | Campo de la convención CF | Reutilizado para contener la clave del tipo de magnitud de DataCNVS; no se valida con respecto al vocabulario CF real |
role | DataCNVS | Por qué existe este campo en la observación, p. ej., dependent, contextual, index |
dtype | DataCNVS | El tipo de datos de DataCNVS del valor; consulta la referencia de tipos más abajo |
variable_key, quantity_kind_key | DataCNVS | Claves de búsqueda para catalog/variables/ y catalog/quantity_kinds/ |
alias, units_override | DataCNVS | Presentes solo cuando el campo sobrescribe la etiqueta o las unidades predeterminadas de la variable |
Los nombres al estilo CF (units, long_name, standard_name) existen porque las herramientas científicas genéricas para HDF5/NetCDF los reconocen ampliamente, por lo que se obtienen unidades y etiquetas legibles sin ningún complemento específico para DataCNVS. Los nombres al estilo DataCNVS permiten realizar búsquedas inequívocas y fáciles de usar en el código. Ambos describen el mismo campo; usa el que mejor se adapte a tu herramienta.
Los campos de serie también contienen series_kind ("series" o "index"), length y, si la serie comparte un índice común con otras (p. ej., un eje temporal compartido por varias curvas dependientes), series_group_ref, que apunta a una entrada de series_groups/ (consulta la sección siguiente).
Grupos de series #
Cuando dos o más series de la observación comparten un índice común (lo más habitual: un eje temporal o de posición con varias mediciones dependientes respecto a él), se vinculan mediante observations/obs_000001/series_groups/group_NNNNNN/. Este grupo no duplica ningún dato; se limita a enumerar las rutas de los miembros y, solo para facilitar la exploración, proporciona enlaces simbólicos HDF5 a los conjuntos de datos values reales, de modo que un explorador de árboles muestra visualmente la relación. El código siempre debe resolver la relación a partir del atributo series_group_ref, no recorriendo los enlaces.
Una serie sin el atributo series_group_ref simplemente no tiene un índice compartido, por lo que sus valores deben tratarse como ordenados según la posición de la fila (punto 0, punto 1, punto 2, …).
observations_summary #
El conjunto de datos observations_summary del nivel raíz contiene la misma información que todo el árbol, expresada de nuevo como un único documento JSON que incluye la observación, sus campos y las entradas del catálogo con sus rutas HDF5. Es una comodidad para los scripts que prefieran analizar un bloque JSON en vez de recorrer el árbol de grupos, y se garantiza que es un reflejo estricto de lo que ya indican los atributos (nunca una fuente de información adicional).
Referencia de tipos de datos #
El atributo dtype de cada campo indica cómo se almacena físicamente su conjunto de datos value/values:
| DataCNVS dtype | Almacenado como | Notas |
|---|---|---|
string | Texto UTF-8 | |
boolean | booleano | |
integer | Entero de 64 bits | |
number / numeric(p,s) | Número de coma flotante de 64 bits | |
date | Texto de fecha ISO-8601, p. ej., "2026-06-01" | |
datetime / timestamp | Entero de 64 bits que representa los milisegundos transcurridos desde la época Unix (UTC) | También incluye un atributo time_units = "epoch_ms_utc" a modo de recordatorio |
json, list, struct, map, dictionary | Texto UTF-8 que contiene el valor codificado en JSON | También incluye encoding = "json"; analiza la cadena como JSON para recuperar el valor estructurado |
Las series numéricas grandes se comprimen con gzip y se dividen en bloques; los valores pequeños y el texto se almacenan sin comprimir. Esto es transparente para todos los lectores que se indican a continuación: h5py, xarray y MATLAB realizan la descompresión automáticamente.
Cómo trabajar con exportaciones en Python #
La vía más directa es h5py; no necesita código específico para DataCNVS, solo los nombres de atributos documentados anteriormente.
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 valor escalar, con sus unidades.
setpoint = obs["scalars/contextual_furnace_setpoint"]
print(setpoint["value"][()], setpoint.attrs["units"])
# Una serie y sus unidades/etiqueta.
temperature = obs["series/dependent_temperature"]
values = temperature["values"][:]
print(f"{len(values)} points, units={temperature.attrs['units']}")
# Una serie de índices de fecha y hora se decodifica a partir de milisegundos desde la é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
]
# Consulta el tipo de magnitud de un campo mediante el catálogo compartido.
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 se decodifica con json.loads.
# struct_field = obs["scalars/contextual_some_json_field"]
# value = json.loads(struct_field["value"][()])
# Todo el árbol, expresado de nuevo como JSON, si resulta más fácil trabajar así.
summary = json.loads(f["observations_summary"][()])Si prefieres trabajar con matrices etiquetadas en lugar de rutas HDF5 sin procesar, crea un xarray.Dataset a partir de los elementos anteriores (el archivo no incorpora escalas de dimensión, por lo que las etiquetas se ensamblan una vez durante la lectura):
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 trabajar con tablas, la matriz values de una serie se convierte directamente en una columna de pandas.Series o DataFrame: pandas.Series(temperature["values"][:]).
Cómo trabajar con exportaciones en MATLAB #
Las funciones HDF5 integradas de MATLAB (h5info, h5disp, h5read, h5readatt) no requieren ninguna caja de herramientas y funcionan directamente con archivos .h5dcnvs.
file = "furnace_run_14.h5dcnvs";
% Recorre todo el árbol, incluidos todos los atributos.
h5disp(file);
% Lee el título de la observación.
obsTitle = h5readatt(file, "/observations/obs_000001", "title");
% Lee una serie y sus unidades.
temperature = h5read(file, "/observations/obs_000001/series/dependent_temperature/values");
units = h5readatt(file, "/observations/obs_000001/series/dependent_temperature", "units");
% El índice temporal asociado se decodifica a partir de milisegundos desde la é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");
% Un valor escalar, con sus 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));Notas para quienes utilizan MATLAB:
- Los campos de texto de longitud variable (etiquetas, valores codificados en JSON y cadenas de fecha ISO) se devuelven desde
h5read/h5readattcomo una cadena de MATLAB o una matriz de celdas de vectores de caracteres, en función de si el conjunto de datos o atributo subyacente es escalar o tiene valores en forma de matriz; envuelve los valores individuales enstring(...)si necesitas que todos los campos tengan tipos coherentes. - Un valor
json/list/struct/map/dictionaryse lee como texto JSON; decodifícalo conjsondecode(...). h5info(file, "/observations/obs_000001")proporciona la misma lista de atributos y conjuntos de datos que muestrah5disp, pero como una estructura que puedes recorrer mediante código en lugar de leerla en la consola.
Límites y conservación #
- La exportación se realiza por observación: un archivo, una observación.
- Solo se exportan los datos canónicos (procesados), nunca los datos sin procesar tal como se cargaron.
- Los enlaces de descarga caducan 7 días después de que finalice la exportación; los datos de la observación subyacente no se modifican, por lo que puedes volver a exportarlos.
¿Necesitas otro formato? #
Actualmente, HDF5 es el único formato de exportación. Si tu flujo de trabajo necesita otra opción, como un archivo CSV plano, otro formato de intercambio o el formato nativo de una herramienta específica, háznoslo saber.
Habla con el equipo de DataCNVS