Skip to content

Instantly share code, notes, and snippets.

@RobinL
Created September 22, 2025 06:07
Show Gist options
  • Select an option

  • Save RobinL/3a08784cf81291825887db7c4f12643c to your computer and use it in GitHub Desktop.

Select an option

Save RobinL/3a08784cf81291825887db7c4f12643c to your computer and use it in GitHub Desktop.
import json
import os
from IPython.display import display
# path = "./spec_no_lookup_force_in_data_section.json"
# path = "./spec_no_lookup_force_in_mark_section.json"
# path = "./spec_with_lookup.json"
path = "./spec_data_hardcoded.json"
with open(path, "r") as file:
spec = json.load(file)
spec
display({"application/vnd.vega.v5+json": spec}, raw=True)
def save_vega_html(
spec: dict, out_html: str = "vega_view.html", title: str = "Vega View", actions=True
) -> str:
html = f"""<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>{title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
<style>body {{ margin: 0; padding: 1rem; font-family: system-ui, sans-serif; }}</style>
</head>
<body>
<div id="vis"></div>
<script>
const spec = {json.dumps(spec)};
vegaEmbed("#vis", spec, {{ mode: "vega", actions: {str(actions).lower()} }}).catch(console.error);
</script>
</body>
</html>"""
with open(out_html, "w", encoding="utf-8") as f:
f.write(html)
return os.path.abspath(out_html)
out_path = save_vega_html(spec)
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 500,
"height": 500,
"signals": [
{
"name": "$cx",
"update": "width / 2"
},
{
"name": "$cy",
"update": "height / 2"
},
{
"name": "$nodeRadius",
"value": 8
},
{
"name": "$nodeCharge",
"value": -15
},
{
"name": "$linkDistance",
"value": 90
},
{
"name": "$static",
"value": true
}
],
"data": [
{
"name": "node-data",
"values": [
{
"group": 1,
"match_id": "31c32969-31fb-4bd1-9e65-861e41bfbb1e"
},
{
"group": 1,
"match_id": "63eb8ba5-6cad-4e2c-99a7-546dca9ff6c9"
}
]
},
{
"name": "link-data",
"values": [
{
"source": 0,
"target": 1,
"weight": 50.784104988004216
}
]
}
],
"scales": [
{
"name": "color",
"type": "ordinal",
"domain": {
"data": "node-data",
"field": "group"
},
"range": {
"scheme": "category20"
}
}
],
"marks": [
{
"name": "nodes",
"type": "symbol",
"zindex": 1,
"from": {
"data": "node-data"
},
"encode": {
"enter": {
"fill": {
"scale": "color",
"field": "group"
},
"stroke": {
"value": "white"
}
},
"update": {
"size": {
"signal": "2 * $nodeRadius * $nodeRadius"
},
"cursor": {
"value": "pointer"
}
}
},
"transform": [
{
"type": "force",
"iterations": 300,
"static": {
"signal": "$static"
},
"signal": "force",
"forces": [
{
"force": "center",
"x": {
"signal": "$cx"
},
"y": {
"signal": "$cy"
}
},
{
"force": "collide",
"radius": {
"signal": "$nodeRadius"
}
},
{
"force": "nbody",
"strength": {
"signal": "$nodeCharge"
}
},
{
"force": "link",
"links": "link-data",
"distance": {
"signal": "$linkDistance"
}
}
]
}
]
},
{
"type": "path",
"from": {
"data": "link-data"
},
"interactive": false,
"encode": {
"update": {
"stroke": {
"value": "#ccc"
},
"strokeWidth": {
"value": 2
}
}
},
"transform": [
{
"type": "linkpath",
"require": {
"signal": "force"
},
"shape": "line",
"sourceX": "datum.source.x",
"sourceY": "datum.source.y",
"targetX": "datum.target.x",
"targetY": "datum.target.y"
}
]
}
]
}
{
"$schema": "https://vega.github.io/schema/vega/v6.json",
"width": 500,
"height": 500,
"signals": [
{
"name": "$cx",
"update": "width / 2"
},
{
"name": "$cy",
"update": "height / 2"
},
{
"name": "$nodeRadius",
"value": 8
},
{
"name": "$nodeCharge",
"value": -15
},
{
"name": "$linkDistance",
"value": 90
},
{
"name": "$static",
"value": false
}
],
"data": [
{
"name": "link-data",
"values": [
{
"source": "a",
"target": "b",
"weight": 50.784104988004216
}
]
},
{
"name": "node-data",
"values": [
{
"group": 1,
"match_id": "a"
},
{
"group": 1,
"match_id": "b"
}
],
"transform": [
{
"type": "force",
"iterations": 300,
"static": {
"signal": "$static"
},
"signal": "force",
"forces": [
{
"force": "center",
"x": {
"signal": "$cx"
},
"y": {
"signal": "$cy"
}
},
{
"force": "collide",
"radius": {
"signal": "$nodeRadius"
}
},
{
"force": "nbody",
"strength": {
"signal": "$nodeCharge"
}
},
{
"force": "link",
"id": "match_id",
"links": "link-data",
"distance": {
"signal": "$linkDistance"
}
}
]
}
]
}
],
"scales": [
{
"name": "color",
"type": "ordinal",
"domain": {
"data": "node-data",
"field": "group"
},
"range": {
"scheme": "category20"
}
}
],
"marks": [
{
"name": "nodes",
"type": "symbol",
"zindex": 1,
"from": {
"data": "node-data"
},
"encode": {
"enter": {
"fill": {
"scale": "color",
"field": "group"
},
"stroke": {
"value": "white"
}
},
"update": {
"size": {
"signal": "2 * $nodeRadius * $nodeRadius"
},
"cursor": {
"value": "pointer"
},
"x": {
"field": "x"
},
"y": {
"field": "y"
}
}
},
"transform": []
},
{
"type": "path",
"from": {
"data": "link-data"
},
"interactive": false,
"encode": {
"update": {
"stroke": {
"value": "#ccc"
},
"strokeWidth": {
"value": 2
}
}
},
"transform": [
{
"type": "linkpath",
"require": {
"signal": "force"
},
"shape": "line",
"sourceX": "datum.source.x",
"sourceY": "datum.source.y",
"targetX": "datum.target.x",
"targetY": "datum.target.y"
}
]
}
]
}
{
"$schema": "https://vega.github.io/schema/vega/v6.json",
"width": 500,
"height": 500,
"signals": [
{
"name": "$cx",
"update": "width / 2"
},
{
"name": "$cy",
"update": "height / 2"
},
{
"name": "$nodeRadius",
"value": 8
},
{
"name": "$nodeCharge",
"value": -15
},
{
"name": "$linkDistance",
"value": 90
},
{
"name": "$static",
"value": false
}
],
"data": [
{
"name": "node-data",
"values": [
{
"group": 1,
"match_id": "a"
},
{
"group": 1,
"match_id": "b"
}
]
},
{
"name": "link-data",
"values": [
{
"source": "a",
"target": "b",
"weight": 50.784104988004216
}
]
}
],
"scales": [
{
"name": "color",
"type": "ordinal",
"domain": {
"data": "node-data",
"field": "group"
},
"range": {
"scheme": "category20"
}
}
],
"marks": [
{
"name": "nodes",
"type": "symbol",
"zindex": 1,
"from": {
"data": "node-data"
},
"encode": {
"enter": {
"fill": {
"scale": "color",
"field": "group"
},
"stroke": {
"value": "white"
}
},
"update": {
"size": {
"signal": "2 * $nodeRadius * $nodeRadius"
},
"cursor": {
"value": "pointer"
}
}
},
"transform": [
{
"type": "force",
"iterations": 300,
"static": {
"signal": "$static"
},
"signal": "force",
"forces": [
{
"force": "center",
"x": {
"signal": "$cx"
},
"y": {
"signal": "$cy"
}
},
{
"force": "collide",
"radius": {
"signal": "$nodeRadius"
}
},
{
"force": "nbody",
"strength": {
"signal": "$nodeCharge"
}
},
{
"force": "link",
"id": "datum.match_id",
"links": "link-data",
"distance": {
"signal": "$linkDistance"
}
}
]
}
]
},
{
"type": "path",
"from": {
"data": "link-data"
},
"interactive": false,
"encode": {
"update": {
"stroke": {
"value": "#ccc"
},
"strokeWidth": {
"value": 2
}
}
},
"transform": [
{
"type": "linkpath",
"require": {
"signal": "force"
},
"shape": "line",
"sourceX": "datum.source.x",
"sourceY": "datum.source.y",
"targetX": "datum.target.x",
"targetY": "datum.target.y"
}
]
}
]
}
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 500,
"height": 500,
"signals": [
{
"name": "$cx",
"update": "width / 2"
},
{
"name": "$cy",
"update": "height / 2"
},
{
"name": "$nodeRadius",
"value": 8
},
{
"name": "$nodeCharge",
"value": -15
},
{
"name": "$linkDistance",
"value": 90
},
{
"name": "$static",
"value": true
}
],
"data": [
{
"name": "node-data",
"values": [
{
"group": 1,
"match_id": "31c32969-31fb-4bd1-9e65-861e41bfbb1e"
},
{
"group": 1,
"match_id": "63eb8ba5-6cad-4e2c-99a7-546dca9ff6c9"
}
],
"transform": [
{
"type": "identifier",
"as": "index"
},
{
"type": "formula",
"as": "index",
"expr": "datum['index'] - 1"
}
]
},
{
"name": "link-data",
"values": [
{
"match_id_l": "63eb8ba5-6cad-4e2c-99a7-546dca9ff6c9",
"match_id_r": "31c32969-31fb-4bd1-9e65-861e41bfbb1e",
"weight": 50.784104988004216
}
],
"transform": [
{
"type": "lookup",
"from": "node-data",
"key": "match_id",
"fields": [
"match_id_l",
"match_id_r"
],
"as": [
"source",
"target"
]
},
{
"type": "formula",
"as": "source",
"expr": "datum['source']['index']"
},
{
"type": "formula",
"as": "target",
"expr": "datum['target']['index']"
},
{
"type": "project",
"fields": [
"source",
"target",
"weight"
]
}
]
}
],
"scales": [
{
"name": "color",
"type": "ordinal",
"domain": {
"data": "node-data",
"field": "group"
},
"range": {
"scheme": "category20"
}
}
],
"marks": [
{
"name": "nodes",
"type": "symbol",
"zindex": 1,
"from": {
"data": "node-data"
},
"encode": {
"enter": {
"fill": {
"scale": "color",
"field": "group"
},
"stroke": {
"value": "white"
}
},
"update": {
"size": {
"signal": "2 * $nodeRadius * $nodeRadius"
},
"cursor": {
"value": "pointer"
}
}
},
"transform": [
{
"type": "force",
"iterations": 300,
"static": {
"signal": "$static"
},
"signal": "force",
"forces": [
{
"force": "center",
"x": {
"signal": "$cx"
},
"y": {
"signal": "$cy"
}
},
{
"force": "collide",
"radius": {
"signal": "$nodeRadius"
}
},
{
"force": "nbody",
"strength": {
"signal": "$nodeCharge"
}
},
{
"force": "link",
"links": "link-data",
"distance": {
"signal": "$linkDistance"
}
}
]
}
]
},
{
"type": "path",
"from": {
"data": "link-data"
},
"interactive": false,
"encode": {
"update": {
"stroke": {
"value": "#ccc"
},
"strokeWidth": {
"value": 2
}
}
},
"transform": [
{
"type": "linkpath",
"require": {
"signal": "force"
},
"shape": "line",
"sourceX": "datum.source.x",
"sourceY": "datum.source.y",
"targetX": "datum.target.x",
"targetY": "datum.target.y"
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment