KGVisualizer, AnalyticsVisualizer, TemporalVisualizer, and OntologyVisualizer turn graph dicts, analytics results, and ontologies into interactive HTML dashboards or static images in a single method call. Use them to present centrality rankings, community clusters, event timelines, and before/after snapshot diffs to stakeholders without writing any rendering code.
All visualizers accept output="interactive" (Plotly/pyvis HTML, shown in Jupyter or saved to file) or output="static" (PNG/SVG via Matplotlib). Omit file_path to get the figure object back for further manipulation.

Rendering the Full Knowledge Graph

The first thing to put in front of stakeholders is the full network — nodes coloured by entity type, sized by degree centrality, with tooltips showing content on hover.
from semantica.context import AgentContext, ContextGraph
from semantica.vector_store import VectorStore
from semantica.visualization import KGVisualizer

graph = ContextGraph(advanced_analytics=True)
ctx   = AgentContext(
    vector_store=VectorStore(backend="faiss", dimension=768),
    knowledge_graph=graph,
    graph_expansion=True,
)
ctx.store([
    "APT29 exploited CVE-2024-3400 targeting NATO defense contractors.",
    "CVE-2024-3400 is a critical vulnerability in PAN-OS by Palo Alto Networks.",
    "HAMMERTOSS is APT29's C2 backdoor operating over Twitter and GitHub.",
    "APT29 conducted the SUNBURST supply chain attack against SolarWinds in 2020.",
], extract_entities=True, extract_relationships=True)

viz = KGVisualizer()

# Interactive network — saved to HTML, opens in any browser
viz.visualize_network(
    graph         = graph.to_dict(),
    output        = "interactive",
    file_path     = "reports/threat_graph.html",
    node_color_by = "type",      # colour each node by its entity type
    node_size_by  = "degree",    # larger nodes = more connections
    hover_data    = ["type", "content"],
)
The resulting HTML is fully self-contained — no server required. Share it as a file attachment and it renders in any browser with pan, zoom, and hover. For a static PNG suitable for a PDF report or a slide deck:
viz.visualize_network(
    graph     = graph.to_dict(),
    output    = "static",
    file_path = "reports/threat_graph.png",
    node_color_by = "type",
)
To highlight a specific attribution path through the graph — for example, the chain from APT29 through SUNBURST to SolarWinds — pass the node IDs as highlight_path:
viz.visualize_network(
    graph          = graph.to_dict(),
    output         = "static",
    file_path      = "reports/apt29_path.png",
    highlight_path = ["APT29", "SUNBURST", "SolarWinds"],
)

Showing Community Structure

After community detection, you have a dict mapping community labels to node ID lists. visualize_communities on KGVisualizer overlays those clusters on the network; AnalyticsVisualizer.visualize_community_structure forwards to that same community graph view.
from semantica.visualization import AnalyticsVisualizer

# The community dict you get from graph analytics
communities = {
    "node_assignments": {
        "apt29": 0,
        "hammertoss": 0,
        "nobelium": 0,
        "sunburst": 0,
        "cve-2024-3400": 1,
        "pan-os": 1,
        "globalprotect": 1,
        "solarwinds": 2,
        "orion-platform": 2,
        "cve-2020-10148": 2,
    },
    "num_communities": 3,
}

# Network view with community colouring
viz.visualize_communities(
    graph       = graph.to_dict(),
    communities = communities,
    output      = "interactive",
    file_path   = "reports/communities_network.html",
)

# Standalone breakdown chart — for a slide on "what are the 12 clusters?"
av = AnalyticsVisualizer()
av.visualize_community_structure(
    graph      = graph.to_dict(),
    communities = communities,
    output     = "interactive",
    file_path  = "reports/communities_breakdown.html",
)

Plotting Centrality Rankings

The centrality dict maps node IDs to scores. Two calls cover the two use cases: a network view where node size reflects centrality, and a standalone ranked bar chart for the “top 10 most connected nodes” slide.
centrality = {
    "centrality": {
        "apt29": 0.14,
        "cve-2024-3400": 0.11,
        "pan-os": 0.07,
        "hammertoss": 0.06,
        "nobelium": 0.05,
    }
}

# Network coloured and sized by centrality score
viz.visualize_centrality(
    graph          = graph.to_dict(),
    centrality     = centrality,
    centrality_type= "pagerank",
    output         = "interactive",
    file_path      = "reports/centrality_network.html",
)

# Standalone ranked bar chart — most impactful nodes at a glance
av.visualize_centrality_rankings(
    centrality      = centrality,
    centrality_type = "pagerank",
    output          = "interactive",
    file_path       = "reports/centrality_rankings.html",
)

Analytics Charts: Connectivity and Degree Distribution

After running graph analytics, two additional charts complete the picture. The connectivity chart shows how many disconnected components exist and how large each one is. The degree distribution shows the power-law shape of your graph — useful for confirming that your graph is scale-free (a few highly-connected hubs, many leaf nodes).
# Connectivity — pass the analysis result dict directly
# Keys the visualizer reads: "is_connected", "num_components", "component_sizes"
connectivity = {
    "is_connected":    False,
    "num_components":  3,
    "component_sizes": [42, 8, 2],
}

av.visualize_connectivity(
    connectivity = connectivity,
    output       = "interactive",
    file_path    = "reports/connectivity.html",
)

# Degree distribution — pass the graph dict directly
av.visualize_degree_distribution(
    graph     = graph.to_dict(),
    output    = "interactive",
    file_path = "reports/degree_distribution.html",
)
visualize_connectivity takes the connectivity analysis result dict — not graph.to_dict(). The dict must contain "is_connected", "num_components", and "component_sizes". Compute it from your graph analytics output and pass the result.

Drawing a Timeline of Events

When the story you are telling is temporal — a CVE lifecycle, an incident timeline, a campaign progression — TemporalVisualizer.visualize_timeline turns a list of timestamped events into a scrollable interactive chart.
from semantica.visualization import TemporalVisualizer

tv = TemporalVisualizer()

# Events are passed inside a dict under the "events" key
tv.visualize_timeline(
    temporal_data = {"events": [
        {"id": "pub",   "label": "CVE-2024-3400 published",      "timestamp": "2024-03-14T00:00:00"},
        {"id": "exp",   "label": "Zero-day exploitation begins",  "timestamp": "2024-03-26T00:00:00"},
        {"id": "patch", "label": "PAN-OS hotfix released",        "timestamp": "2024-04-14T00:00:00"},
        {"id": "rem",   "label": "Contractor remediation confirmed","timestamp": "2024-04-30T00:00:00"},
    ]},
    output    = "interactive",
    file_path = "reports/cve_timeline.html",
)

Comparing Two Graph Snapshots Side-by-Side

When the question is “what changed between March 14 and April 14?”, visualize_snapshot_comparison takes two named snapshots from TemporalVersionManager and renders a side-by-side diff view showing nodes and edges added or removed.
from semantica.change_management import TemporalVersionManager

vm    = TemporalVersionManager(storage_path="versions.db")
snap1 = vm.get_version("pre_patch_march_14")
snap2 = vm.get_version("post_patch_april_14")

# Pass snapshots as a dict mapping label → snapshot dict
tv.visualize_snapshot_comparison(
    snapshots = {
        "pre_patch_march_14":   snap1,
        "post_patch_april_14":  snap2,
    },
    output    = "interactive",
    file_path = "reports/snapshot_diff.html",
)

Tracking Graph Growth Over Time

The final chart for a stakeholder review is the growth curve — how many nodes and edges has the graph accumulated over the past year? visualize_metrics_evolution takes a history dict and a parallel timestamps list.
# Build from TemporalVersionManager snapshots
versions = vm.list_versions()
versions.sort(key=lambda v: v["timestamp"])

timestamps      = [v["timestamp"][:10] for v in versions]
metrics_history = {
    "node_count": [len(v.get("nodes", [])) for v in versions],
    "edge_count": [len(v.get("edges", [])) for v in versions],
}

tv.visualize_metrics_evolution(
    metrics_history = metrics_history,
    timestamps      = timestamps,
    output          = "interactive",
    file_path       = "reports/graph_growth.html",
)
Or populate the history dict directly from known quarterly milestones:
tv.visualize_metrics_evolution(
    metrics_history = {
        "node_count": [50, 142, 309, 481],
        "edge_count": [88, 387, 821, 1340],
    },
    timestamps = ["2025-01-01", "2025-04-01", "2025-07-01", "2025-10-01"],
    output     = "interactive",
    file_path  = "reports/graph_growth.html",
)

Domain Examples

A full analyst briefing package: interactive threat network, community breakdown, CVE timeline, and graph growth curve — all generated from a live CTI graph before the morning standup.
from semantica.context import AgentContext, ContextGraph
from semantica.vector_store import VectorStore
from semantica.visualization import KGVisualizer, AnalyticsVisualizer, TemporalVisualizer
import os

graph = ContextGraph(advanced_analytics=True)
ctx   = AgentContext(
    vector_store=VectorStore(backend="faiss", dimension=768),
    knowledge_graph=graph,
    graph_expansion=True,
)
ctx.store([
    "APT29 used HAMMERTOSS for C2 via Twitter and GitHub in 2020.",
    "APT29 infrastructure cluster: 185.220.101.0/24, AS200651.",
    "SolarWinds supply chain compromise attributed to APT29, campaign SUNBURST.",
    "APT29 leveraged OAuth token theft against cloud workloads in 2023.",
], extract_entities=True, extract_relationships=True)

os.makedirs("reports", exist_ok=True)

kg_viz = KGVisualizer()

# Full network — interactive for the analyst portal
kg_viz.visualize_network(
    graph         = graph.to_dict(),
    output        = "interactive",
    file_path     = "reports/cti_network.html",
    node_color_by = "type",
    node_size_by  = "degree",
    hover_data    = ["type", "content"],
)

# Attribution path PNG for the slide deck
kg_viz.visualize_network(
    graph          = graph.to_dict(),
    output         = "static",
    file_path      = "reports/apt29_sunburst_path.png",
    highlight_path = ["APT29", "SUNBURST", "SolarWinds"],
)

# Connectivity overview
av = AnalyticsVisualizer()
av.visualize_connectivity(
    connectivity = {"is_connected": True, "num_components": 1, "component_sizes": [24]},
    output       = "interactive",
    file_path    = "reports/connectivity.html",
)

# CVE-2024-3400 incident timeline
tv = TemporalVisualizer()
tv.visualize_timeline(
    temporal_data = {"events": [
        {"id": "pub",   "label": "CVE-2024-3400 published",     "timestamp": "2024-03-14"},
        {"id": "exp",   "label": "Zero-day exploitation",        "timestamp": "2024-03-26"},
        {"id": "patch", "label": "PAN-OS hotfix released",       "timestamp": "2024-04-14"},
        {"id": "rem",   "label": "Remediation confirmed",        "timestamp": "2024-04-30"},
    ]},
    output    = "interactive",
    file_path = "reports/cve_timeline.html",
)

Output Modes

Every visualizer method accepts the same two output modes:
output valueFormatBest for
"interactive"Self-contained HTML (Plotly / pyvis)Jupyter notebooks, analyst portals, email attachments
"static"PNG / SVG (Matplotlib)PDF reports, slide decks, regulatory submissions
To get the figure object instead of writing to disk, omit file_path:
fig = viz.visualize_network(graph.to_dict(), output="interactive")
fig.show()              # renders inline in Jupyter
fig.write_html("out.html")   # manual export
  • Context Graphsgraph.to_dict() is the primary input for KGVisualizer
  • Ontology ManagementOntologyVisualizer renders ontologies produced by OntologyGenerator
  • Change ManagementTemporalVersionManager snapshots feed visualize_metrics_evolution() and visualize_snapshot_comparison()
  • Graph Analytics — centrality scores, community dicts, and connectivity results that feed the AnalyticsVisualizer
  • Export & Serialization — export the same graph to GraphML, GEXF, or DOT for Gephi and Graphviz