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¶
- Múltiples formatos: DOT, SVG, PNG, PDF, ASCII, Mermaid
- Customización: Colores, estilos, layouts, highlighting
- Visualización de análisis: Execution order, critical path, buffer plan
- Terminal-friendly: Renderizado ASCII para debugging rápido
- 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 |
| 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:
🌐 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:
🎯 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¶
- GraphViz: https://graphviz.org/
- Mermaid: https://mermaid-js.github.io/
- SVG Spec: https://www.w3.org/TR/SVG2/
- 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