---
name: render_sigma_html
kind: function
lang: py
domain: datascience
version: "1.0.0"
purity: impure
signature: "def render_sigma_html(graph_data: dict, output_path: str, title: str = 'OSINT Graph') -> str"
description: "Genera un archivo HTML standalone con sigma.js v2.4 que visualiza un grafo OSINT. Aplica ForceAtlas2, dark theme, filtros por tipo de nodo y tooltip con metadata. Retorna el path absoluto del archivo escrito."
tags: [graph, sigma, osint, visualization, html, forceatlas2, network, dark-theme]
uses_functions: [ops_to_sigma_json_py_datascience]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [json, os]
params:
  - name: graph_data
    desc: "dict en formato sigma.js con {nodes: [...], edges: [...]} (ej: output de ops_to_sigma_json_py_datascience)"
  - name: output_path
    desc: "path absoluto donde guardar el HTML (ej: '/tmp/osint_graph.html'). Directorio debe existir."
  - name: title
    desc: "titulo del grafo que aparece en la visualizacion (defecto: 'OSINT Graph')"
output: "string con el path absoluto del archivo HTML escrito. Archivo es standalone y abre en cualquier navegador."
tested: false
tests: []
test_file_path: ""
file_path: "python/functions/datascience/render_sigma_html.py"
---

## Ejemplo

```python
from datascience.ops_to_sigma_json import ops_to_sigma_json
from datascience.render_sigma_html import render_sigma_html

graph = ops_to_sigma_json("apps/osint_analysis/operations.db")
path = render_sigma_html(graph, "/tmp/osint_graph.html", title="Red OSINT")
print(f"Abre en el browser: {path}")
```

## Notas

Funcion impura — escribe un archivo en disco.

El HTML es completamente standalone: no necesita servidor web ni backend. Todos los assets se cargan desde jsDelivr CDN:
- graphology 0.25.4
- graphology-layout-forceatlas2 0.10.1
- sigma 2.4.0

El JSON del grafo se embebe directamente en el `<script>` para evitar peticiones CORS al abrir desde `file://`.

ForceAtlas2 se ejecuta sincrono con 500 iteraciones antes de instanciar el renderer. Para grafos grandes (>500 nodos) considerar reducir iteraciones o usar `barnesHutOptimize: true` (que se activa automaticamente para grafos >300 nodos).

Panel lateral (fijo, top-right):
- Titulo del grafo
- Contador de nodos y aristas
- Checkboxes de filtro por tipo (con color dot)

Tooltip (hover sobre nodo):
- Label y tipo del nodo
- status, domain
- Todos los campos adicionales de metadata aplanados

Los caracteres especiales en labels y metadata se escapan correctamente para evitar XSS al abrir el HTML.
