# PARAPLOT, slex y el DAT compartido

## Cadena y responsabilidades

### Transporte y grupos actuales

La entrada documental es `.ds` textual, por archivo o stdin, con una o varias `TABLE` y PARAPLOT opcionales. Siru transmite `TABLE nombre_del_caso` y el pedido gráfico ya leído; las tablas externas también se incorporan. Los datos pasan por Slex y Tabular2, sin un segundo lector de números en Simplot. El protocolo JSON descrito más abajo es el receptor anterior, conservado por compatibilidad, no el usado ahora por Siru.

Cada `PARAPLOT NOMBRE` produce `GNUPLOT NOMBRE`; si falta nombre se usa su posición entre todos los PARAPLOT desde 1. No se permiten identificadores duplicados. Sin PARAPLOT se genera `GNUPLOT 1` automático. `GLOBAL.simplots` conserva los grupos con nombre, pedido y modelo; `GLOBAL.gnuplots` conserva nombre y texto de los programas recibidos. La gramática única y el detalle de numeración están en [§15.0 de Gramática .ds](../../slex/d2datdinc/doc/GRAMATICA.md#150-grupos-paraplot-y-resultado-gnuplot).

Simplot genera y ejecuta por defecto. `--no-generar` ejecuta los GNUPLOT existentes; `--no-ejecutar` genera sin invocar Gnuplot. La receta de terminal final de cada sección selecciona ese grupo y usa Bash; Simplot no la ejecuta por shell. `-noX` suprime ventanas y `-save` guarda el documento y los SVG ejecutados, respaldando versiones anteriores. La generación documental no cubre todavía todas las órdenes del recorrido histórico.

**Decisión del 11/10/2026:** `UNIDADES` y `RESULTADOS` se interpretan en Slex (`ds2dat/d2datdinc`), al pasar de `.ds` a `.dat`, antes de simular con Siru, incluso cuando no se dibuja. Se normalizan los datos de entrada y se dejan interpretados los pedidos que se aplicarán a los valores de salida. Simplot interpreta PARAPLOT para dibujar tablas con nombres, magnitudes y unidades ya resueltos. Si recibe directamente un `.ds`, debe usar ese mismo procesamiento previo. Tabular2 y Unidades siguen siendo las herramientas de cálculo y conversión; no se necesita ejecutar una simulación para preparar una tabla externa.

**Excepción prevista, no implementada y no prioritaria:** sólo un campo `RESULTADO GRAFICO` permitiría a Simplot intervenir en unidades, después de Siru y exclusivamente para la presentación del gráfico, sin modificar la tabla original ni el cálculo. Se deja documentado para una ampliación futura; no se agrega código. PARAPLOT por sí solo no autoriza reinterpretar unidades físicas. Los comportamientos históricos descritos más abajo siguen pendientes de migrar a este contrato.

La definición única está en [la gramática común, §3.9](../../slex/d2datdinc/doc/GRAMATICA.md#39-unidades-y-resultados-comunes-paraplot-para-el-dibujo): prioridad de unidades, `library.siru` como fuente de modelos y FORMAS como referencia al modelo, sin copiar sus unidades. La presencia actual de `resultados` y `unidades` dentro de `GLOBAL.simplot` es un contrato heredado que deberá adaptarse; las secciones siguientes documentan el transporte existente, no una migración ya terminada.

    .ds / .ds2 / .paraplot → d2datdinc (slex) → .dat
                                            ├─ siru: calcula el circuito
                                            └─ simplot: dibuja tablas existentes

Simplot usa el mismo lector de Siru para las descripciones; no mantiene otro parser de secciones DS. Un PARAPLOT suelto equivale a entrar en la sección PARAPLOT antes de leer sus órdenes. El DAT puede usarse sin conservar el DS. Las tablas numéricas siguen siendo entradas separadas: el DAT describe los gráficos, no contiene automáticamente todos los resultados de simulación.

La sección superior `TABLE` con datos textuales embebidos en `.d` o `.ds` ya se lee en el DAT común de Slex (`slex/d2datdinc/doc/GRAMATICA.md`); aún falta que Simplot consuma esas entradas de `GLOBAL.tablas`. Tabular2 ya acepta texto o bytes con formato explícito, aunque el adaptador desde el DAT falta. Un binario deberá viajar codificado y decodificarse antes de entregarlo a Tabular2. El actual `--stdin` de Simplot sigue aceptando una cabecera JSON y una tabla, no esa secuencia general de secciones ni varias tablas embebidas.

Siru lee el DAT completo y conserva `GLOBAL.simplot`; la sección no cambia sus ecuaciones ni la elección de integrador. Al terminar llama a Simplot por defecto y transmite descripción y tabla por pipe; `-nosimplot` anula esa llamada. Son procesos separados, no tareas que siempre deban iniciarse a mano. La prueba cruzada comprueba que Siru y Simplot recuperan la misma sección.

## Uso desde el árbol

    cd ~/svn/siru/slex/d2datdinc
    make -j2 d2datdinc

Trabajar sobre copias en un directorio de corrida. Para generar el dato:

    ~/svn/siru/slex/d2datdinc/d2datdinc \
      -c ~/svn/siru/slex/d2datdinc/d2datdinc.slex \
      -b ~/svn/siru/slex/d2datdinc/biblioteca caso.ds -o caso.dat

Con `caso.dat` y sus tablas presentes:

    perl -I"$HOME/svn/siru/simplot/lib" \
      "$HOME/svn/siru/simplot/scripts/simplot.pl" \
      -nokill -graf=4 caso.dat

También se puede dar directamente `caso.ds` o `caso.paraplot`: Simplot invoca d2datdinc sin shell y recibe JSON por su salida estándar. Desde el árbol localiza el lector hermano, su tabla y su biblioteca. Instalado busca `d2datdinc` en PATH.

## Entrada estándar: Siru → Simplot

`simplot --stdin -graf=4 -sinventana -outdir=graficos` recibe **una línea JSON UTF-8, un salto de línea y la tabla completa**, y termina la lectura con EOF. No se indican archivos de entrada en la orden. La descripción y los datos viajan por el mismo pipe; Simplot no abre el `.ds`, `.dat` ni `.simul` del productor. Los modos por archivos siguen disponibles, incluido `--simulado` para vincular explícitamente un documento a otra tabla.

| Campo de cabecera | Contenido |
|---|---|
| `protocolo`, `version` | `"simplot-stdin"`, `1` |
| `documento` | Ruta absoluta lógica del documento original; no tiene que existir. Fija la base de las referencias externas. |
| `global` | Objeto con `simplot` (contrato gráfico v1 o v2 completo) y, opcionalmente, `outs` (OUTPUTS). Puede ser `{}` para dibujar automáticamente las columnas. |
| `formato` | `"simul"` o `"csv"` |
| `bytes` | Cantidad exacta de octetos que siguen al salto de línea, entero positivo. |
| `tabla` | Nombre lógico del caso, sin ruta ni extensión: Siru envía `caso` para `caso.ds`, incluso si guarda `caso-1.simul`. Opcional para productores anteriores. Simplot lo conserva como `GLOBAL.tabla_resultado` cuando genera DAT y como `nombre_tabla` en el resultado del receptor. |

Ejemplo mínimo de productor Perl, sin ningún archivo de entrada compartido:

```perl
use JSON::PP qw(encode_json);
use File::Spec;
my $tabla = "0 10\n1 20\n";
open my $p, '|-', 'simplot', '--stdin', '-graf=4', '-sinventana' or die $!;
binmode $p;
print {$p} encode_json({protocolo=>'simplot-stdin', version=>1,
    documento=>File::Spec->rel2abs('ejemplo.ds'), global=>{},
    formato=>'simul', bytes=>length($tabla)}), "\n", $tabla or die $!;
close $p or die "Simplot fallo\n";
```

Siru transmite su descripción ya interpretada y copia la salida numérica al pipe por bloques de 64 KiB, sin redondearla ni cargar toda la tabla en memoria. En CSV envía el CSV original: la conversión del receptor se delega a Tabular2. La precisión textual, los encabezados, las unidades y los bloques de una tabla SIMUL se conservan en el transporte. Una entrada `.din` sin descripción gráfica usa la presentación automática; si sólo hay OUTPUTS, el receptor completa el modelo con el lector existente a partir del JSON recibido, sin releer el DS.

Simplot prepara un directorio propio `simplot-entrada-XXXXXX/` con la tabla recibida y, cuando corresponde, un DAT interno, porque los motores históricos y Tabular2 trabajan con archivos. Esos archivos son internos al receptor y quedan junto a los gráficos para reproducirlos: **no se requieren rutas de datos compartidas entre Siru y Simplot**. Las referencias a la tabla homónima del documento se vinculan a la tabla recibida; las otras fuentes declaradas en PARAPLOT siguen siendo archivos externos relativos al directorio original. No se transmiten automáticamente esas tablas externas.

Límites: un documento y una tabla por invocación, dibujo al terminar (no animación en vivo), sin diálogo interactivo en `--stdin`. Los bloques múltiples viajan completos pero conservan las reglas del motor: v2 exige seleccionar el bloque. Una cabecera inválida, longitud incorrecta, truncamiento o datos sobrantes se rechazan antes de graficar. No es un protocolo para entradas no confiables: siguen vigentes las capacidades del lenguaje gráfico y el acceso a fuentes externas.

## Descripción del contrato v1

Este contrato se conserva para las órdenes históricas todavía no traducidas. El [modelo estructurado](DAT-SIMPLOT-V2.md) ya tiene productor slex, validador y renderizador: se selecciona automáticamente para las órdenes compatibles. La consola acepta ambos formatos; no convierte automáticamente todas las órdenes históricas.

Solo se agrega `GLOBAL.simplot` cuando hay información gráfica. Los circuitos sin ella mantienen su dato anterior.

| Campo | Tipo | Significado |
|---|---|---|
| `version` | Número, 1 | Versión del contrato |
| `ordenes` | Lista ordenada de objetos | PARAPLOT, GRAFICOS o ACEPTAR_GRAFICOS |
| `adicionales` | Lista ordenada de objetos | GRAFICOS_ADICIONALES |
| `resultados` | Lista de textos | Pedidos RESULTADOS, separados por comas externas a paréntesis/comillas |
| `unidades` | Lista de textos | Sección UNIDADES |
| `agregar` | 0 o 1, opcional | Control ANADIR_GRAFICOS; por defecto 0 |

Una orden tiene `comando` (minúsculas), `objeto` (nombre simbólico, salvo nomostrar) y `valor` (texto). Por ejemplo:

    {"comando":"lineas","objeto":"GRAFICO","valor":"DATOS,1:2,3"}

No se convierte toda la gramática de columnas y unidades a objetos tipados en esta primera versión: esa semántica sigue en el motor de Simplot. El adaptador reconstruye órdenes PARAPLOT a partir de los objetos para aprovechar el motor existente. La lectura de secciones, comentarios, includes y sentencias se hace en slex; no es todavía una sustitución completa del intérprete gráfico.

GRAFICOS reemplaza los pedidos automáticos de RESULTADOS, conservando la definición implícita de SIMULADO cuando corresponde. GRAFICOS_ADICIONALES se agrega al final. `ANADIR_GRAFICOS=1`, `AÑADIR_GRAFICOS=1` y `AGREGAR_GRAFICOS=1` en RUN_CONTROLS piden sumar los gráficos explícitos a los automáticos; se acepta 0/1 o [0]/[1].

## Rutas, compatibilidad y errores

- Las rutas de tablas se interpretan relativas al documento gráfico. Para mover un DAT, trasladar también sus tablas conservando las rutas o declarar rutas adecuadas. No se copia automáticamente una tabla al generar el DAT.
- Los nombres reales conservan mayúsculas/minúsculas; los nombres simbólicos los normaliza Simplot. Las palabras clave gráficas se normalizan en slex.
- Un comando desconocido o incompleto hace fallar la lectura. No se ejecutan expresiones para armar el DAT ni se necesita Gnuplot en esa etapa.
- Al leer un DAT con `GLOBAL` pero sin `GLOBAL.simplot`, Simplot invoca automáticamente `d2datdinc --graficos`: puede generar la descripción gráfica a partir de OUTPUTS sin PARAPLOT, sin modificar el DAT original. Si el lector no puede producir una descripción válida, la lectura o la validación falla; no basta con tener cualquier DAT de cálculo. Versiones gráficas desconocidas se rechazan.
- El motor histórico interpreta funciones de Gnuplot: el DAT no constituye un entorno seguro para ejecutar archivos no confiables.
- La sintaxis v1 enumera las órdenes documentadas. Abreviaturas accidentales del parser Perl antiguo no forman parte del contrato.

## Corpus y límites

Decisión de ampliación: los pedidos de procesamiento numérico general que transporte el DAT se ejecutarán mediante Tabular2, no mediante un nuevo motor numérico de Simplot. El catálogo y las pruebas de cálculo se planifican en [Tabular2](../../tabular2/doc/PLAN-PROCESAMIENTO-NUMERICO.md); Simplot se ocupa de consumir las tablas/resultados y representarlos. El contrato v1 y el código actual no cambian por esta anotación.

`corpus/ds/graficos.ds` y su tabla prueban el recorrido nuevo. `tests/dato.t` genera el DAT, elimina el DS de la copia temporal y comprueba que se produce la imagen, que los adicionales no se pierden y que Siru conserva el contrato. El corpus histórico prueba además los PARAPLOT sueltos a través de slex.

Pendientes: AST tipado para series/transformaciones, rutas rebajadas automáticamente al escribir el DAT en otro directorio, identidad de bloques de rerun dentro de una misma tabla y pruebas de todas las abreviaturas históricas. No se agregan FFT, barras de error ni un motor web en esta etapa.
