TDMS_to_UFF / app.py
MGC1991MF's picture
Update app.py
b9fe2b2 verified
Raw
History Blame Contribute Delete
4.12 kB
"""
Front-end en Gradio para convertir archivos TDMS (NI LabVIEW) a UFF
(Universal File Format, dataset 58). Listo para desplegar en Hugging
Face Spaces (SDK: gradio).
"""
import os
import tempfile
import gradio as gr
import pandas as pd
from converter import inspect_tdms, convert_tdms_to_uff
try:
import spaces
_gpu = spaces.GPU
except ImportError:
def _gpu(fn):
return fn
# ---------------------------------------------------------------- helpers
def _labels_from_summary(summary):
return [f'{row["grupo"]}/{row["canal"]}' for row in summary]
def cargar_tdms(file):
"""Al subir un archivo: inspecciona y muestra los canales disponibles."""
if file is None:
return (
gr.update(value=None),
gr.update(choices=[], value=[]),
"Sube un archivo .tdms para comenzar.",
)
try:
summary = inspect_tdms(file.name)
except Exception as e:
return (
gr.update(value=None),
gr.update(choices=[], value=[]),
f"❌ No se pudo leer el TDMS: {e}",
)
if not summary:
return (
gr.update(value=None),
gr.update(choices=[], value=[]),
"⚠️ El archivo no contiene canales.",
)
df = pd.DataFrame(summary)
labels = _labels_from_summary(summary)
msg = f"✅ {len(labels)} canal(es) detectado(s). Selecciona cuáles convertir."
return gr.update(value=df), gr.update(choices=labels, value=labels), msg
@_gpu
def convertir(file, seleccion, progress=gr.Progress()):
"""Convierte los canales seleccionados y devuelve el archivo .uff."""
if file is None:
return None, "❌ Primero sube un archivo .tdms."
if not seleccion:
return None, "❌ Selecciona al menos un canal."
base = os.path.splitext(os.path.basename(file.name))[0]
out_dir = tempfile.mkdtemp()
out_path = os.path.join(out_dir, f"{base}.uff")
def cb(frac, msg):
progress(frac, desc=msg)
try:
n, warns = convert_tdms_to_uff(
file.name, out_path, selected=list(seleccion), progress_cb=cb
)
except Exception as e:
return None, f"❌ Error durante la conversión: {e}"
msg = f"✅ Conversión completa: {n} canal(es) escritos como dataset 58."
if warns:
msg += "\n\n⚠️ Avisos:\n" + "\n".join(f"• {w}" for w in warns)
return out_path, msg
# ---------------------------------------------------------------- interfaz
with gr.Blocks(title="TDMS → UFF") as demo:
gr.Markdown(
"""
# Conversor TDMS → UFF
Convierte archivos **TDMS** (NI LabVIEW / DIAdem) a **UFF**
(Universal File Format, *dataset 58* — series de tiempo), compatible
con software de análisis modal y de vibraciones.
"""
)
with gr.Row():
with gr.Column(scale=1):
archivo = gr.File(
label="Archivo TDMS",
file_types=[".tdms"],
type="filepath",
)
canales = gr.CheckboxGroup(
label="Canales a convertir",
choices=[],
)
boton = gr.Button("Convertir a UFF", variant="primary")
with gr.Column(scale=2):
tabla = gr.Dataframe(
label="Contenido del TDMS",
interactive=False,
)
estado = gr.Markdown("Sube un archivo .tdms para comenzar.")
salida = gr.File(label="Archivo UFF generado")
archivo.change(cargar_tdms, inputs=archivo, outputs=[tabla, canales, estado])
boton.click(convertir, inputs=[archivo, canales], outputs=[salida, estado])
gr.Markdown(
"""
---
**Notas**
- Cada canal se escribe como un *dataset 58* con eje X en segundos
(usa `wf_increment` del TDMS; si no existe, asume dt = 1 s).
- La unidad del canal (`unit_string`) se conserva en el eje Y.
- Salida en UFF ASCII, legible por pyuff, ME'scope, Test.Lab, etc.
"""
)
if __name__ == "__main__":
demo.launch()