Skip to content

05_05_10 - Visualization System

📋 Descripción

Sistema de visualización para topologías DSP que genera diagramas en múltiples formatos (GraphViz DOT, SVG, ASCII art, Mermaid). Facilita debugging, documentación y comprensión de grafos complejos.

🎯 Objetivos

  1. Múltiples formatos: DOT, SVG, PNG, PDF, ASCII, Mermaid
  2. Customización: Colores, estilos, layouts, highlighting
  3. Visualización de análisis: Execution order, critical path, buffer plan
  4. Terminal-friendly: Renderizado ASCII para debugging rápido
  5. Integración: Compatible con GraphViz, Mermaid, documentación

🏗️ Arquitectura

Componentes Principales

topology_visualizer.hpp/cpp      # Sistema de visualización
├── DotExporter                 # GraphViz DOT format
├── SvgExporter                 # SVG con auto-layout
├── AsciiRenderer               # ASCII art (terminal)
├── MermaidExporter             # Mermaid diagrams
├── TopologyVisualizer          # Interfaz principal
├── ExecutionVisualizer         # Visualizar execution order
└── BufferVisualizer            # Visualizar buffer plan

Formatos Soportados

Formato Uso Herramienta
DOT Input para GraphViz → PNG/PDF/SVG
SVG Vector graphics Navegadores web
PNG Imágenes raster Docs, presentaciones
PDF Documentos Reportes, papers
ASCII Terminal/logs Debugging rápido
Mermaid Markdown docs GitHub, GitLab, etc.

🎨 GraphViz DOT Export

Exportar a DOT

#include "topology_visualizer.hpp"

using namespace audiolab::topology::visualization;

// Exportar a DOT string
std::string dot = DotExporter::export_to_dot(topology);
std::cout << dot;

// Exportar a archivo
DotExporter::export_to_file(topology, "topology.dot");

Ejemplo DOT Generado

digraph "biquad_filter" {
  rankdir=TB;
  node [fontname="Arial"];
  edge [fontname="Arial", fontsize=10];

  "input" [shape=ellipse, label="input\n(external_input)", fillcolor="lightblue", style=filled];
  "mul_b0" [shape=box, label="mul_b0\n(multiply_scalar)", fillcolor="lightyellow", style=filled];
  "output" [shape=ellipse, label="output\n(external_output)", fillcolor="lightgreen", style=filled];

  "input" -> "mul_b0" [label="out → in"];
  "mul_b0" -> "output" [label="out → in"];
}

Customización

VisualizationOptions options;

// Layout
options.direction = LayoutDirection::LeftToRight;
options.compact_layout = true;
options.node_spacing = 0.8f;

// Appearance
options.color_scheme = ColorScheme::Pastel;
options.show_port_names = true;
options.show_buffer_sizes = true;

// Highlighting
options.highlighted_nodes = {"filter", "gain"};
options.critical_path = {"input", "filter", "delay", "output"};

// Estilos por tipo de nodo
options.node_styles[NodeType::Source] = NodeStyle::Circle;
options.node_styles[NodeType::Processing] = NodeStyle::Box;
options.node_styles[NodeType::Sink] = NodeStyle::Circle;

// Colores por tipo
options.node_colors[NodeType::Source] = "lightgreen";
options.node_colors[NodeType::Processing] = "lightyellow";
options.node_colors[NodeType::Sink] = "lightcoral";

std::string dot = DotExporter::export_to_dot(topology, options);

🖼️ Generar Imágenes (PNG/PDF)

Usando GraphViz

// Requiere GraphViz instalado (comando 'dot')

// Generar PNG
bool success = TopologyVisualizer::generate_image(
    topology,
    "topology.png",
    OutputFormat::PNG
);

// Generar PDF
success = TopologyVisualizer::generate_image(
    topology,
    "topology.pdf",
    OutputFormat::PDF
);

if (success) {
    std::cout << "✅ Image generated successfully\n";
} else {
    std::cerr << "❌ GraphViz not found or error occurred\n";
}

Desde Línea de Comandos

# 1. Exportar DOT
./your_app --export-dot topology.dot

# 2. Generar imagen con GraphViz
dot -Tpng topology.dot -o topology.png
dot -Tpdf topology.dot -o topology.pdf
dot -Tsvg topology.dot -o topology.svg

📟 ASCII Art (Terminal)

Renderizado ASCII

// Renderizar a terminal
AsciiOptions ascii_opts;
ascii_opts.use_unicode = true;    // Unicode box chars (└─┘)
ascii_opts.compact = false;
ascii_opts.show_edge_labels = true;

TopologyVisualizer::render_to_terminal(topology, ascii_opts);

Salida ASCII

Topology: biquad_filter
──────────────────────────────────────────────────

┌────────────────────────────────┐
│ input (external_input)         │
└────────────────────────────────┘
  ↓ out → in

┌────────────────────────────────┐
│ mul_b0 (multiply_scalar)       │
└────────────────────────────────┘
  ↓ out → out

┌────────────────────────────────┐
│ output (external_output)       │
└────────────────────────────────┘

ASCII sin Unicode (ASCII puro)

ascii_opts.use_unicode = false;

// Output:
// +------------------------------+
// | input (external_input)       |
// +------------------------------+
//   > out -> in
//   |

Visualizar Execution Order

std::vector<NodeID> exec_order = {"input", "gain", "filter", "delay", "output"};

std::string ascii = AsciiRenderer::render_execution_order(exec_order);
std::cout << ascii;

Salida:

Execution Order:
  1. input
  2. gain
  3. filter
  4. delay
  5. output

🌐 SVG Export

Exportar SVG

// SVG con auto-layout
std::string svg = SvgExporter::export_to_svg(topology);

// Guardar a archivo
SvgExporter::export_to_file(topology, "topology.svg");

// Abrir en navegador
std::system("open topology.svg");  // macOS
std::system("xdg-open topology.svg");  // Linux
std::system("start topology.svg");  // Windows

Características SVG

  • Auto-layout: Posicionamiento automático de nodos
  • Interactivo: Compatible con navegadores web
  • Escalable: Vector graphics, sin pérdida de calidad
  • Embebible: Se puede insertar en HTML

🐟 Mermaid Export

Exportar Mermaid

// Mermaid para Markdown
std::string mermaid = MermaidExporter::export_to_mermaid(topology);
std::cout << mermaid;

// Guardar a archivo Markdown
MermaidExporter::export_to_file(topology, "topology.md");

Ejemplo Mermaid Generado

```mermaid
graph TB
  input["input\n(external_input)"]
  mul_b0["mul_b0\n(multiply_scalar)"]
  output["output\n(external_output)"]
  input --> mul_b0 |out→in|
  mul_b0 --> output |out→in|
```

Uso en Documentación

Mermaid se renderiza automáticamente en: - GitHub README.md - GitLab wikis - VS Code (con extensión) - Obsidian, Notion, etc.

🔍 Visualización de Análisis

Critical Path

// Resaltar critical path
std::vector<NodeID> critical_path = {"input", "filter", "delay", "output"};

VisualizationOptions options;
options.critical_path = critical_path;

std::string dot = ExecutionVisualizer::visualize_critical_path(
    topology,
    critical_path,
    OutputFormat::DOT
);

DotExporter::export_to_file(topology, "critical_path.dot", options);

Parallel Stages

std::vector<std::vector<NodeID>> stages = {
    {"input"},
    {"gain1", "gain2"},     // Parallel
    {"mixer"},
    {"output"}
};

std::string ascii = ExecutionVisualizer::visualize_stages(
    stages,
    OutputFormat::ASCII
);

std::cout << ascii;

Salida:

Parallel Execution Stages:

Stage 0 (1 nodes):
  ┌──
  │ input
  └──
Stage 1 (2 nodes):
  ┌──
  │ gain1
  │ gain2
  └──
Stage 2 (1 nodes):
  ┌──
  │ mixer
  └──
Stage 3 (1 nodes):
  ┌──
  │ output
  └──

Buffer Lifetimes (Gantt Chart)

std::vector<std::pair<size_t, size_t>> lifetimes = {
    {0, 3},  // Buffer 0: stages 0-3
    {1, 2},  // Buffer 1: stages 1-2
    {2, 4}   // Buffer 2: stages 2-4
};

std::vector<EdgeID> edge_ids = {"in→gain", "gain→filter", "filter→out"};

std::string gantt = BufferVisualizer::visualize_lifetimes(lifetimes, edge_ids);
std::cout << gantt;

Salida:

Buffer Lifetimes (Gantt Chart):

in→gain:   ┌──────┐
gain→filter:  ┌────┐
filter→out:    ┌────────┐

🎯 Interfaz Unificada

TopologyVisualizer

// Uso simplificado con interfaz unificada

// String output
std::string output = TopologyVisualizer::visualize(
    topology,
    OutputFormat::DOT
);

// File output
TopologyVisualizer::visualize_to_file(
    topology,
    "output.dot",
    OutputFormat::DOT
);

// Terminal output
TopologyVisualizer::render_to_terminal(topology);

// Image generation
TopologyVisualizer::generate_image(
    topology,
    "topology.png",
    OutputFormat::PNG
);

Formatos Disponibles

enum class OutputFormat {
    DOT,        // GraphViz DOT → generate_image() → PNG/PDF
    SVG,        // Scalable Vector Graphics
    ASCII,      // ASCII art (terminal)
    Mermaid,    // Mermaid diagram
    PNG,        // PNG image (via GraphViz)
    PDF         // PDF document (via GraphViz)
};

📝 Ejemplo Completo

#include "topology_visualizer.hpp"
#include "../05_05_00_graph_representation/topology_builder.hpp"

using namespace audiolab::topology;
using namespace audiolab::topology::visualization;

int main() {
    // 1. Construir topología
    auto topology = TopologyBuilder()
        .setName("simple_filter")
        .addNode("input", "external_input", NodeType::Source)
        .addNode("gain", "multiply_scalar", NodeType::Processing)
        .addNode("lpf", "biquad_lowpass", NodeType::Processing)
        .addNode("output", "external_output", NodeType::Sink)
        .connect("input", "out", "gain", "in")
        .connect("gain", "out", "lpf", "in")
        .connect("lpf", "out", "output", "in")
        .setParameter("gain", "value", 0.8f)
        .setParameter("lpf", "fc", 1000.0f)
        .build();

    std::cout << "=== TOPOLOGY VISUALIZATION ===\n\n";

    // 2. ASCII (terminal)
    std::cout << "--- ASCII ---\n";
    TopologyVisualizer::render_to_terminal(topology);
    std::cout << "\n";

    // 3. DOT export
    std::cout << "--- DOT (GraphViz) ---\n";
    VisualizationOptions dot_opts;
    dot_opts.direction = LayoutDirection::LeftToRight;
    dot_opts.show_port_names = true;
    dot_opts.show_buffer_sizes = false;

    DotExporter::export_to_file(topology, "topology.dot", dot_opts);
    std::cout << "✅ Exported to topology.dot\n\n";

    // 4. SVG export
    std::cout << "--- SVG ---\n";
    SvgExporter::export_to_file(topology, "topology.svg");
    std::cout << "✅ Exported to topology.svg\n\n";

    // 5. Mermaid export
    std::cout << "--- Mermaid ---\n";
    MermaidExporter::export_to_file(topology, "topology.md");
    std::cout << "✅ Exported to topology.md\n\n";

    // 6. Generate PNG (requires GraphViz)
    std::cout << "--- PNG Generation ---\n";
    if (TopologyVisualizer::generate_image(topology, "topology.png", OutputFormat::PNG)) {
        std::cout << "✅ Generated topology.png\n";
    } else {
        std::cout << "⚠️  GraphViz not found, PNG not generated\n";
    }

    // 7. Highlight critical path
    std::cout << "\n--- Critical Path Visualization ---\n";
    VisualizationOptions critical_opts;
    critical_opts.critical_path = {"input", "gain", "lpf", "output"};
    critical_opts.direction = LayoutDirection::TopToBottom;

    DotExporter::export_to_file(topology, "critical_path.dot", critical_opts);
    std::cout << "✅ Exported critical path to critical_path.dot\n";

    return 0;
}

Salida

=== TOPOLOGY VISUALIZATION ===

--- ASCII ---
Topology: simple_filter
──────────────────────────────────────────────────

┌────────────────────────────────┐
│ input (external_input)         │
└────────────────────────────────┘
  ↓ out → in

┌────────────────────────────────┐
│ gain (multiply_scalar)         │
└────────────────────────────────┘
  ↓ out → in

┌────────────────────────────────┐
│ lpf (biquad_lowpass)           │
└────────────────────────────────┘
  ↓ out → in

┌────────────────────────────────┐
│ output (external_output)       │
└────────────────────────────────┘


--- DOT (GraphViz) ---
✅ Exported to topology.dot

--- SVG ---
✅ Exported to topology.svg

--- Mermaid ---
✅ Exported to topology.md

--- PNG Generation ---
✅ Generated topology.png

--- Critical Path Visualization ---
✅ Exported critical path to critical_path.dot

🔗 Integración

Con Documentation System

// Generar diagrams para docs
TopologyVisualizer::generate_image(topology, "docs/images/topology.png", OutputFormat::PNG);
MermaidExporter::export_to_file(topology, "docs/topology.md");

Con Testing Framework

// Visualizar topologías de test
TEST_CASE("Biquad Filter Topology") {
    auto topology = create_biquad_topology();

    // Debug: render ASCII
    TopologyVisualizer::render_to_terminal(topology);

    // Save for documentation
    TopologyVisualizer::visualize_to_file(
        topology,
        "tests/fixtures/biquad.dot",
        OutputFormat::DOT
    );
}

Con CI/CD Pipeline

# .github/workflows/docs.yml
- name: Generate Topology Diagrams
  run: |
    ./build/topology_tool --export-dot topology.dot
    dot -Tpng topology.dot -o docs/images/topology.png

📊 Métricas de Rendimiento

Operación Complejidad Tiempo Típico
DOT export O(V + E) <1ms para 100 nodos
SVG export O(V + E) ~2ms para 100 nodos
ASCII render O(V + E) <1ms
Mermaid export O(V + E) <1ms
PNG generation O(GraphViz) ~50-200ms (external)

🎨 Opciones de Estilo

Layout Directions

options.direction = LayoutDirection::TopToBottom;     // ↓ (default)
options.direction = LayoutDirection::LeftToRight;     // →
options.direction = LayoutDirection::BottomToTop;     // ↑
options.direction = LayoutDirection::RightToLeft;     // ←

Color Schemes

options.color_scheme = ColorScheme::Default;    // Standard colors
options.color_scheme = ColorScheme::Monochrome; // Black & white
options.color_scheme = ColorScheme::Pastel;     // Soft colors
options.color_scheme = ColorScheme::Vibrant;    // Bright colors
options.color_scheme = ColorScheme::Dark;       // Dark theme

Node Styles

options.node_styles[NodeType::Processing] = NodeStyle::Box;      // □
options.node_styles[NodeType::Processing] = NodeStyle::Circle;   // ○
options.node_styles[NodeType::Processing] = NodeStyle::Diamond;  // ◇
options.node_styles[NodeType::Processing] = NodeStyle::Hexagon;  // ⬡

🚀 Estado del Sistema

  • DotExporter: Export completo con customización
  • SvgExporter: SVG con auto-layout
  • AsciiRenderer: ASCII art con Unicode/ASCII puro
  • MermaidExporter: Mermaid diagrams para Markdown
  • TopologyVisualizer: Interfaz unificada
  • ExecutionVisualizer: Parallel stages y critical path
  • BufferVisualizer: Gantt chart de buffer lifetimes

📚 Referencias

  1. GraphViz: https://graphviz.org/
  2. Mermaid: https://mermaid-js.github.io/
  3. SVG Spec: https://www.w3.org/TR/SVG2/
  4. Graph Drawing: Di Battista et al. "Graph Drawing: Algorithms for the Visualization of Graphs"

Subsistema: 05_MODULES → 05_05_TOPOLOGY_DESIGN → 05_05_10_visualization Autor: AudioLab Development Team Versión: 1.0.0 Última actualización: 2025-10-10