Skip to content

Instantly share code, notes, and snippets.

@balouf
Created December 2, 2020 07:33
Show Gist options
  • Save balouf/9e8fe1a87fccc401853ecc346d9b2e1e to your computer and use it in GitHub Desktop.
Save balouf/9e8fe1a87fccc401853ecc346d9b2e1e to your computer and use it in GitHub Desktop.
Vis network tutorial
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:30:08.141218Z",
"end_time": "2020-12-02T07:30:08.152278Z"
},
"hide_input": true,
"init_cell": true,
"slideshow": {
"slide_type": "slide"
},
"trusted": true
},
"cell_type": "code",
"source": "%%HTML\n<div id=\"mynetwork\"></div>",
"execution_count": 1,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<IPython.core.display.HTML object>",
"text/html": "<div id=\"mynetwork\"></div>\n"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Fabien Mathieu"
},
{
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"cell_type": "markdown",
"source": "# What is VisJS / Vis Network"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "- Vis JS is a set of javascript visualization library\n- Vis Network is the graph module\n- Simple, intuitive, and powerful (imho)\n- NB: D3 JS is more powerful, but learning curve is steeper\n- Vis Network powers the LINCS graph: https://www.lincs.fr/research/lincs-graph/\n- Doc: https://visjs.github.io/vis-network/docs/network/"
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Javascript in a nutshell: the language"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "- JS: interpreted language (like Python) designed to be embedded in HTML\n- JS does not rely on indentation but on parenthesis and semicolons\n- Like Python, JS can use modules to increase its possibilities\n - JQuery: JS if $\\TeX$, JQuery is $\\LaTeX$ (not necessary).\n - VisJS. "
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Javascript in a nutshell: I/O"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Typical inputs/outputs in JS are achieved within the webpage (network access is also possible).\n- Inputs: change in the page (events) trigger some actions (functions)\n - click (double-click, ...)\n - text in input form\n - ...\n- Outputs: modify the content of some element of the page (div, a, img, ...)"
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Javascript in a nutshell: JSON"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "- json (JavaScript Object Notation): the standard javascript format for data\n - Is made of lists, dicts, and immutables (numbers, strings, bools).\n - Top element is list or dict.\n - the Python json module allows immediate conversion!\n "
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Javascript in a nutshell: running code"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "How to execute a javascript?\n- In HTML:\n - Import packages in the preamble using ``<script src='https://myscriptprovider.com/myscript.js'></script>``\n - Put you code in ``<script>My code</script>`` somwhere\n - Good JQuery practice: ``<script>$(document).ready(function(){ my code });``"
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Javascript in a nutshell: running code"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "How to execute a javascript?\n\n- In Jupyter:\n - Pretty much the same, using IPython HTML/javascript functions or magics\n - Main caveat: the import is better handled with some ``require`` tricks\n - There are more possibilities (too much?)"
},
{
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"cell_type": "markdown",
"source": "# Example: the title page"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "Title page is adapted from https://www.codementor.io/@isaib.cicourel/visjs-visualization-in-jupyter-notebook-phgb3fjv0\n\nCode of the first cell of this notebook:\n\n``%%HTML``\n\n``<div id=\"mynetwork\"></div>``"
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Example: the title page - javascript"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:30:08.154218Z",
"end_time": "2020-12-02T07:30:08.160230Z"
},
"init_cell": true,
"slideshow": {
"slide_type": "-"
},
"trusted": true
},
"cell_type": "code",
"source": "%%javascript\nrequirejs.config({\n paths: {\n vis: '//unpkg.com/vis-network/standalone/umd/vis-network.min'\n }\n});\n\nrequire(['vis'], function(vis){\nvar nodes = [{id: 1, label: 'Using', group: 'action'}, {id: 2, label: 'JavaScript', group: 'tool'},\n {id: 3, label: 'Vis', group: 'tool'}, {id: 31, label: 'JS', group: 'tool'},\n {id: 32, label: 'Network', group: 'tool'}, {id: 4, label: 'to display', group: 'action'},\n {id: 5, label: 'graphs', group: 'data'}, {id: 6, label: 'networks', group: 'data'},\n {id: 7, label: 'in', group: 'action'}, {id: 8, label: 'web pages', group: 'location'},\n {id: 9, label: 'notebooks', group: 'location'},\n];\nvar edges = [{from: 1, to: 2}, {from: 1, to: 3}, {from: 3, to: 31},\n {from: 3, to: 32}, {from: 32, to: 4}, {from: 31, to: 4},\n {from: 2, to: 4}, {from: 6, to: 4}, {from: 5, to: 4},\n {from: 5, to: 7}, {from: 6, to: 7}, {from: 7, to: 8}, {from: 7, to: 9},\n];\n// create a network\nvar data= {\n nodes: nodes,\n edges: edges,\n};\nvar options = {\n width: '800px',\n height: '400px'\n};\nvar container = document.getElementById('mynetwork');\nvar network = new vis.Network(container, data, options);\n});",
"execution_count": 2,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<IPython.core.display.Javascript object>",
"application/javascript": "requirejs.config({\n paths: {\n vis: '//unpkg.com/vis-network/standalone/umd/vis-network.min'\n }\n});\n\nrequire(['vis'], function(vis){\nvar nodes = [{id: 1, label: 'Using', group: 'action'}, {id: 2, label: 'JavaScript', group: 'tool'},\n {id: 3, label: 'Vis', group: 'tool'}, {id: 31, label: 'JS', group: 'tool'},\n {id: 32, label: 'Network', group: 'tool'}, {id: 4, label: 'to display', group: 'action'},\n {id: 5, label: 'graphs', group: 'data'}, {id: 6, label: 'networks', group: 'data'},\n {id: 7, label: 'in', group: 'action'}, {id: 8, label: 'web pages', group: 'location'},\n {id: 9, label: 'notebooks', group: 'location'},\n];\nvar edges = [{from: 1, to: 2}, {from: 1, to: 3}, {from: 3, to: 31},\n {from: 3, to: 32}, {from: 32, to: 4}, {from: 31, to: 4},\n {from: 2, to: 4}, {from: 6, to: 4}, {from: 5, to: 4},\n {from: 5, to: 7}, {from: 6, to: 7}, {from: 7, to: 8}, {from: 7, to: 9},\n];\n// create a network\nvar data= {\n nodes: nodes,\n edges: edges,\n};\nvar options = {\n width: '800px',\n height: '400px'\n};\nvar container = document.getElementById('mynetwork');\nvar network = new vis.Network(container, data, options);\n});\n"
},
"metadata": {}
}
]
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Code description"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "A Vis network object boils down to three jsons:\n- A list of nodes\n- A list of edges\n- A dict of options\n\nThe code creates a graph object from these jsons and injects it in the html content."
},
{
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"cell_type": "markdown",
"source": "# It's Python Workshop, not JS workshop!"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "JSON is not far from Python objects, we can use that.\n\nBefore going into details, let's pythonize the code."
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# HTML Template"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:31:19.624317Z",
"end_time": "2020-12-02T07:31:19.628312Z"
},
"trusted": true
},
"cell_type": "code",
"source": "html_template = \"\"\"\n<div id=\"%(name)s\"></div>\n<script>\nrequire.config({\n paths: {\n vis: '//unpkg.com/vis-network/standalone/umd/vis-network.min'\n }\n});\nrequire(['vis'], function(vis){\nvar nodes = %(nodes)s;\nvar edges = %(edges)s;\nvar data= {\n nodes: nodes,\n edges: edges,\n};\nvar options = %(options)s;\nvar container = document.getElementById('%(name)s');\nvar network = new vis.Network(container, data, options);\n});\n</script>\n\"\"\"",
"execution_count": 3,
"outputs": []
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# HTML crafter"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:31:21.428173Z",
"end_time": "2020-12-02T07:31:21.435175Z"
},
"trusted": true
},
"cell_type": "code",
"source": "from IPython.display import HTML, display\nimport uuid, json\ndef vis_graph(nodes=None, edges=None, options=None, template=html_template):\n name = str(uuid.uuid4())\n if nodes is None:\n nodes = [{'id': 0}, {'id': 1}]\n if edges is None:\n edges = [{'from': 0, 'to': 1}]\n if options is None:\n options=dict()\n options.setdefault('width', '800px')\n options.setdefault('height', '600px')\n dic = {'name': name, 'nodes': json.dumps(nodes), 'edges': json.dumps(edges), 'options': json.dumps(options)}\n display(HTML(template % dic))",
"execution_count": 4,
"outputs": []
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Showtime!"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:31:23.289430Z",
"end_time": "2020-12-02T07:31:23.294430Z"
},
"trusted": true
},
"cell_type": "code",
"source": "vis_graph()",
"execution_count": 5,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<IPython.core.display.HTML object>",
"text/html": "\n<div id=\"320cec0c-fe28-42e5-a6e9-a5f13ad17cee\"></div>\n<script>\nrequire.config({\n paths: {\n vis: '//unpkg.com/vis-network/standalone/umd/vis-network.min'\n }\n});\nrequire(['vis'], function(vis){\nvar nodes = [{\"id\": 0}, {\"id\": 1}];\nvar edges = [{\"from\": 0, \"to\": 1}];\nvar data= {\n nodes: nodes,\n edges: edges,\n};\nvar options = {\"width\": \"800px\", \"height\": \"600px\"};\nvar container = document.getElementById('320cec0c-fe28-42e5-a6e9-a5f13ad17cee');\nvar network = new vis.Network(container, data, options);\n});\n</script>\n"
},
"metadata": {}
}
]
},
{
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"cell_type": "markdown",
"source": "# Nodes"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "- One mandatory key: `id`\n- A few reserved keys: `label`, `title`, `group`, `image`, ...\n- As many additional keys as you wish\n - Unexpected keys are not processed by default by VisJS\n - But they can be accessed in other parts of you JS code (not covered here)"
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Nodes"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:31:35.118059Z",
"end_time": "2020-12-02T07:31:35.122115Z"
},
"trusted": true
},
"cell_type": "code",
"source": "nodes = [{'id': 0, 'label': 'Cow', 'title': 'A mammal', \n 'image': 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/CH_cow_2_cropped.jpg/480px-CH_cow_2_cropped.jpg'},\n {'id': 1, 'label': 'Platypus', 'title': 'A platypus', \n 'image': 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Ornithorhynchus.jpg/220px-Ornithorhynchus.jpg'},\n {'id': 2, 'label': 'Duck', 'title': 'A bird', \n 'image': 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Male_mallard_standing.jpg/440px-Male_mallard_standing.jpg'}]",
"execution_count": 6,
"outputs": []
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Nodes"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:31:36.687270Z",
"end_time": "2020-12-02T07:31:36.692270Z"
},
"trusted": true
},
"cell_type": "code",
"source": "vis_graph(nodes=nodes)",
"execution_count": 7,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<IPython.core.display.HTML object>",
"text/html": "\n<div id=\"10859e9d-516b-4797-a129-1acb342b0538\"></div>\n<script>\nrequire.config({\n paths: {\n vis: '//unpkg.com/vis-network/standalone/umd/vis-network.min'\n }\n});\nrequire(['vis'], function(vis){\nvar nodes = [{\"id\": 0, \"label\": \"Cow\", \"title\": \"A mammal\", \"image\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/CH_cow_2_cropped.jpg/480px-CH_cow_2_cropped.jpg\"}, {\"id\": 1, \"label\": \"Platypus\", \"title\": \"A platypus\", \"image\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Ornithorhynchus.jpg/220px-Ornithorhynchus.jpg\"}, {\"id\": 2, \"label\": \"Duck\", \"title\": \"A bird\", \"image\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Male_mallard_standing.jpg/440px-Male_mallard_standing.jpg\"}];\nvar edges = [{\"from\": 0, \"to\": 1}];\nvar data= {\n nodes: nodes,\n edges: edges,\n};\nvar options = {\"width\": \"800px\", \"height\": \"600px\"};\nvar container = document.getElementById('10859e9d-516b-4797-a129-1acb342b0538');\nvar network = new vis.Network(container, data, options);\n});\n</script>\n"
},
"metadata": {}
}
]
},
{
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"cell_type": "markdown",
"source": "# Edges"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "- Two mandatory keys: `from` and `to`\n- A few reserved keys: `label`, `title`, ...\n- As many additional keys as you wish"
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Edges"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:31:51.548877Z",
"end_time": "2020-12-02T07:31:51.553877Z"
},
"trusted": true
},
"cell_type": "code",
"source": "edges = [{'from': 0, 'to': 1, 'label': 'mammals', 'title': 'this is an edge'},\n {'from': 1, 'to': 2, 'label': 'look alike', 'title': 'this is another edge'}]",
"execution_count": 8,
"outputs": []
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Edges"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:31:54.651167Z",
"end_time": "2020-12-02T07:31:54.656170Z"
},
"trusted": true
},
"cell_type": "code",
"source": "vis_graph(nodes=nodes, edges=edges)",
"execution_count": 9,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<IPython.core.display.HTML object>",
"text/html": "\n<div id=\"c8369774-4b8c-43be-aa11-488f7758514f\"></div>\n<script>\nrequire.config({\n paths: {\n vis: '//unpkg.com/vis-network/standalone/umd/vis-network.min'\n }\n});\nrequire(['vis'], function(vis){\nvar nodes = [{\"id\": 0, \"label\": \"Cow\", \"title\": \"A mammal\", \"image\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/CH_cow_2_cropped.jpg/480px-CH_cow_2_cropped.jpg\"}, {\"id\": 1, \"label\": \"Platypus\", \"title\": \"A platypus\", \"image\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Ornithorhynchus.jpg/220px-Ornithorhynchus.jpg\"}, {\"id\": 2, \"label\": \"Duck\", \"title\": \"A bird\", \"image\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Male_mallard_standing.jpg/440px-Male_mallard_standing.jpg\"}];\nvar edges = [{\"from\": 0, \"to\": 1, \"label\": \"mammals\", \"title\": \"this is an edge\"}, {\"from\": 1, \"to\": 2, \"label\": \"look alike\", \"title\": \"this is another edge\"}];\nvar data= {\n nodes: nodes,\n edges: edges,\n};\nvar options = {\"width\": \"800px\", \"height\": \"600px\"};\nvar container = document.getElementById('c8369774-4b8c-43be-aa11-488f7758514f');\nvar network = new vis.Network(container, data, options);\n});\n</script>\n"
},
"metadata": {}
}
]
},
{
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"cell_type": "markdown",
"source": "# Options"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "This is where most of the customization is made through keys\n- `width`, `height`,...\n- `groups`: parameters for the group key of nodes (e.g. specific shape)\n- `physics`: tweak the physics engine\n- `nodes`, `edges`: customize them\n- ... (see https://visjs.github.io/vis-network/docs/network/)"
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Options"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:32:23.939987Z",
"end_time": "2020-12-02T07:32:23.943791Z"
},
"trusted": true
},
"cell_type": "code",
"source": "options = {'nodes': {'shape': 'circularImage', 'size': 40, 'borderWidth': 10},\n 'physics': {'solver': \"repulsion\",\n 'repulsion': {'nodeDistance': 300}}}",
"execution_count": 10,
"outputs": []
},
{
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"cell_type": "markdown",
"source": "# Options"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2020-12-02T07:32:43.599597Z",
"end_time": "2020-12-02T07:32:43.604597Z"
},
"trusted": true
},
"cell_type": "code",
"source": "vis_graph(nodes, edges, options)",
"execution_count": 11,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<IPython.core.display.HTML object>",
"text/html": "\n<div id=\"67086e86-fc4c-4097-9e78-3e13052a58d9\"></div>\n<script>\nrequire.config({\n paths: {\n vis: '//unpkg.com/vis-network/standalone/umd/vis-network.min'\n }\n});\nrequire(['vis'], function(vis){\nvar nodes = [{\"id\": 0, \"label\": \"Cow\", \"title\": \"A mammal\", \"image\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/CH_cow_2_cropped.jpg/480px-CH_cow_2_cropped.jpg\"}, {\"id\": 1, \"label\": \"Platypus\", \"title\": \"A platypus\", \"image\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Ornithorhynchus.jpg/220px-Ornithorhynchus.jpg\"}, {\"id\": 2, \"label\": \"Duck\", \"title\": \"A bird\", \"image\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Male_mallard_standing.jpg/440px-Male_mallard_standing.jpg\"}];\nvar edges = [{\"from\": 0, \"to\": 1, \"label\": \"mammals\", \"title\": \"this is an edge\"}, {\"from\": 1, \"to\": 2, \"label\": \"look alike\", \"title\": \"this is another edge\"}];\nvar data= {\n nodes: nodes,\n edges: edges,\n};\nvar options = {\"nodes\": {\"shape\": \"circularImage\", \"size\": 40, \"borderWidth\": 10}, \"physics\": {\"solver\": \"repulsion\", \"repulsion\": {\"nodeDistance\": 300}}, \"width\": \"800px\", \"height\": \"600px\"};\nvar container = document.getElementById('67086e86-fc4c-4097-9e78-3e13052a58d9');\nvar network = new vis.Network(container, data, options);\n});\n</script>\n"
},
"metadata": {}
}
]
},
{
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"cell_type": "markdown",
"source": "# That's it!"
}
],
"metadata": {
"celltoolbar": "Initialization Cell",
"kernelspec": {
"name": "python3",
"display_name": "Python 3",
"language": "python"
},
"language_info": {
"name": "python",
"version": "3.7.7",
"mimetype": "text/x-python",
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"pygments_lexer": "ipython3",
"nbconvert_exporter": "python",
"file_extension": ".py"
},
"toc": {
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"base_numbering": 1,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
},
"gist": {
"id": "",
"data": {
"description": "Vis network tutorial",
"public": true
}
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment