### Install Graphistry Package Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/playground.ipynb This command installs the Graphistry library, which is used for GPU-accelerated big graph analytics and visualization. ```bash !pip install graphistry ``` -------------------------------- ### Data Loading and Processing Examples Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/playground.ipynb Examples demonstrating how to load data using Pandas and Dask DataFrames. This includes reading Parquet files and basic data manipulation like resetting the index. ```Python # df = pd.read_parquet('maccdc2012_edges.parq').head(10) # df = dd.read_parquet('./data/maccdc2012_full_edges.parq').compute() # edges_df = edges_df.reset_index(drop=True) ``` -------------------------------- ### Install Xarray Package Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/playground.ipynb This command installs the Xarray library, a package that adds support for labeled multi-dimensional arrays to Python, often used in scientific computing. ```bash !pip install xarray ``` -------------------------------- ### Pyvis Network Visualization with Embedded JavaScript Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/playground.ipynb This example shows how to generate a Pyvis network graph and then manually inject custom JavaScript code into the HTML output. It adds a script to handle node clicks by displaying an alert. The graph is saved to an HTML file, modified with the new script, and then displayed. ```python import networkx as nx from pyvis.network import Network G = nx.karate_club_graph() nt = Network(height='400px', width='100%', directed=False) for node in G.nodes: nt.add_node(node) for edge in G.edges: nt.add_edge(edge[0], edge[1]) nt.set_options(""" var options = { "nodes": { "borderWidth": 2 }, "edges": { "color": { "inherit": true }, "smooth": { "type": "continuous" } }, "physics": { "minVelocity": 0.75 } } """) html_file = "graph.html" nt.write_html(html_file, notebook=False) # Add the JavaScript code to the generated HTML file with open(html_file, 'r') as file: html_code = file.read() js_code = """ """ html_code = html_code.replace("", f"{js_code}\n") with open(html_file, 'w') as file: file.write(html_code) nt.show(html_file) ``` -------------------------------- ### Custom Callback Function Example Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/playground.ipynb A simple Python function that serves as a callback, demonstrating how to receive and process a node ID when it's clicked in an interactive plot. ```Python def my_callback(node_id): print(f'Clicked {node_id}') ``` -------------------------------- ### Vis.js Graph Initialization and Data Loading Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/js/graph_select.html Initializes a Vis.js network graph with specified options and fetches graph data from 'graph_data.json'. It populates a dropdown menu with all available nodes and sets up event listeners for node selection and search functionality. ```javascript document.addEventListener('DOMContentLoaded', function() { var allNodes = new vis.DataSet([]); var allEdges = new vis.DataSet([]); var nodes = new vis.DataSet([]); var edges = new vis.DataSet([]); var container = document.getElementById('graph'); var options = { edges: { smooth: { enabled: false } }, interaction: { hover: true, dragNodes: true, zoomView: true }, layout: { improvedLayout: false }, physics: { enabled: true, solver: "forceAtlas2Based", forceAtlas2Based: { avoidOverlap: 0.5, centralGravity: 0.001 }, stabilization: { enabled: false, iterations: 100 } } }; var nodeSelectMenu = document.getElementById('node-select-menu'); window.graphInstance = new vis.Network(container, { nodes: nodes, edges: edges }, options); fetch('graph_data.json') .then(response => response.json()) .then(data => { allNodes.add(data.nodes); allEdges.add(data.edges); allNodes.forEach(function(node) { var option = document.createElement('a'); option.classList.add('dropdown-item'); option.href = '#'; option.dataset.nodeId = node.id; option.textContent = node.label; nodeSelectMenu.appendChild(option); }); }); function displaySelectedNodeAndNeighbors(nodeId) { var nodesToShow = new vis.DataSet([]); var edgesToShow = new vis.DataSet([]); nodesToShow.add(allNodes.get(nodeId)); var connectedEdges = allEdges.get({ filter: function(edge) { return edge.from === nodeId || edge.to === nodeId; } }); edgesToShow.add(connectedEdges); connectedEdges.forEach(edge => { nodesToShow.add(allNodes.get(edge.from)); nodesToShow.add(allNodes.get(edge.to)); }); window.graphInstance.setData({ nodes: nodesToShow, edges: edgesToShow }); } var searchInput = document.getElementById('search-input'); searchInput.addEventListener('input', function() { var searchValue = this.value.toLowerCase(); var options = nodeSelectMenu.querySelectorAll('.dropdown-item'); options.forEach(function(option) { if (option.textContent.toLowerCase().indexOf(searchValue) > -1) { option.style.display = ''; } else { option.style.display = 'none'; } }); }); nodeSelectMenu.addEventListener('click', function(e) { e.preventDefault(); var target = e.target; if (target.classList.contains('dropdown-item')) { var nodeId = target.dataset.nodeId; displaySelectedNodeAndNeighbors(nodeId); } }); }); ``` -------------------------------- ### HoloViews Initialization for Bokeh Backend Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/playground.ipynb This Python code initializes HoloViews with the Bokeh backend and sets default visualization options for graphs, nodes, and RGB elements. It configures background color, dimensions, and axis visibility for enhanced graph rendering. ```python import holoviews as hv from holoviews import opts, dim import networkx as nx import dask.dataframe as dd from holoviews.operation.datashader import ( datashade, dynspread, directly_connect_edges, bundle_graph, stack ) from holoviews.element.graphs import layout_nodes from datashader.layout import random_layout from colorcet import fire hv.extension('bokeh') keywords = dict(bgcolor='black', width=800, height=800, xaxis=None, yaxis=None) opts.defaults(opts.Graph(**keywords), opts.Nodes(**keywords), opts.RGB(**keywords)) ``` -------------------------------- ### Build and Visualize Graph Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/playground.ipynb This snippet demonstrates how to create a graph using NetworkX, calculate node positions using a spring layout, and draw the graph with Matplotlib. It prepares data for annotations and displays the graph. ```python import networkx as nx import matplotlib.pyplot as plt # Build your graph G = nx.karate_club_graph() pos = nx.spring_layout(G,k=0.1, iterations=20) # the layout gives us the nodes position x,y,annotes=[],[],[] x, y, annotes = [], [], [] for key in pos: d = pos[key] annotes.append(key) x.append(d[0]) y.append(d[1]) fig = plt.figure(figsize=(10,10)) ax = fig.add_subplot(111) nx.draw(G, pos, font_size=6, node_color='skyblue', edge_color='#BB0000', width=0.5, node_size=200, with_labels=True) # Assuming AnnoteFinder and connect are defined elsewhere # af = AnnoteFinder(x, y, annotes, my_callback) # connect('button_press_event', af) plt.show() ``` -------------------------------- ### Pyvis Network Visualization with Node Click Handling Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/playground.ipynb This snippet demonstrates how to create an interactive network graph using Pyvis. It configures node click events to display an alert with the clicked node's ID and sets various visualization options for the graph, including node borders and edge smoothing. The graph is then written to an HTML file and displayed. ```python import networkx as nx from pyvis.network import Network def on_node_click(node_id): print('CLICKED:', node_id) G = nx.karate_club_graph() nt = Network(height='400px', width='100%', directed=False) for node in G.nodes: nt.add_node(node, onclick=f"alert('CLICKED: {node}')") for edge in G.edges: nt.add_edge(edge[0], edge[1]) nt.set_options(""" var options = { "nodes": { "borderWidth": 2 }, "edges": { "color": { "inherit": true }, "smooth": { "type": "continuous" } }, "physics": { "minVelocity": 0.75 } } """) nt.write_html("graph.html", notebook=False) nt.show("graph.html") ``` -------------------------------- ### Draw Graph with vis.js Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/karate.html This function initializes and draws a graph using the vis.js library. It sets up node and edge data, configures various visual and interaction options, and enables physics stabilization for a dynamic layout. The function returns the created vis.js network instance. ```javascript function drawGraph() { var nodes = new vis.DataSet([ {"from": 0, "to": 7, "width": 1}, {"from": 3, "to": 12, "width": 1}, {"from": 3, "to": 13, "width": 1}, {"from": 4, "to": 6, "width": 1}, {"from": 4, "to": 10, "width": 1}, {"from": 5, "to": 6, "width": 1}, {"from": 5, "to": 10, "width": 1}, {"from": 5, "to": 16, "width": 1}, {"from": 6, "to": 16, "width": 1}, {"from": 8, "to": 30, "width": 1}, {"from": 8, "to": 32, "width": 1}, {"from": 8, "to": 33, "width": 1}, {"from": 9, "to": 33, "width": 1}, {"from": 13, "to": 33, "width": 1}, {"from": 14, "to": 32, "width": 1}, {"from": 14, "to": 33, "width": 1}, {"from": 15, "to": 32, "width": 1}, {"from": 15, "to": 33, "width": 1}, {"from": 18, "to": 32, "width": 1}, {"from": 18, "to": 33, "width": 1}, {"from": 19, "to": 33, "width": 1}, {"from": 20, "to": 32, "width": 1}, {"from": 20, "to": 33, "width": 1}, {"from": 22, "to": 32, "width": 1}, {"from": 22, "to": 33, "width": 1}, {"from": 23, "to": 25, "width": 1}, {"from": 23, "to": 27, "width": 1}, {"from": 23, "to": 29, "width": 1}, {"from": 23, "to": 32, "width": 1}, {"from": 23, "to": 33, "width": 1}, {"from": 24, "to": 25, "width": 1}, {"from": 24, "to": 27, "width": 1}, {"from": 24, "to": 31, "width": 1}, {"from": 25, "to": 31, "width": 1}, {"from": 26, "to": 29, "width": 1}, {"from": 26, "to": 33, "width": 1}, {"from": 27, "to": 33, "width": 1}, {"from": 28, "to": 31, "width": 1}, {"from": 28, "to": 33, "width": 1}, {"from": 29, "to": 32, "width": 1}, {"from": 29, "to": 33, "width": 1}, {"from": 30, "to": 32, "width": 1}, {"from": 30, "to": 33, "width": 1}, {"from": 31, "to": 32, "width": 1}, {"from": 31, "to": 33, "width": 1}, {"from": 32, "to": 33, "width": 1}]); nodeColors = {}; allNodes = nodes.get({ returnType: "Object" }); for (nodeId in allNodes) { nodeColors[nodeId] = allNodes[nodeId].color; } allEdges = edges.get({ returnType: "Object" }); data = { nodes: nodes, edges: edges }; var options = { "configure": { "enabled": true, "filter": [ "physics" ] }, "edges": { "color": { "inherit": true }, "smooth": { "enabled": true, "type": "dynamic" } }, "interaction": { "dragNodes": true, "hideEdgesOnDrag": false, "hideNodesOnDrag": false }, "physics": { "enabled": true, "stabilization": { "enabled": true, "fit": true, "iterations": 1000, "onlyDynamicEdges": false, "updateInterval": 50 } } }; // if this network requires displaying the configure window, // put it in its div options.configure["container"] = document.getElementById("config"); network = new vis.Network(container, data, options); return network; } drawGraph(); ``` -------------------------------- ### HTML Structure for Graph and Navigation Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/js/graph_select.html Defines the HTML structure for displaying the graph and navigation elements. Includes a placeholder for the graph container and a link for navigating to the graph section. ```html
* [Graph](#graphContainer) Select a node Stop simulation ``` -------------------------------- ### JavaScript Graph Visualization with vis.js Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/example.html Initializes global variables and draws a network graph using the vis.js library. It sets up nodes and edges from provided data, configures network options, and renders the graph in a container. ```javascript // initialize global variables. var edges; var nodes; var allNodes; var allEdges; var nodeColors; var originalNodes; var network; var container; var options, data; var filter = { item : '', property : '', value : [] }; // This method is responsible for drawing the graph, returns the drawn network function drawGraph() { var container = document.getElementById('mynetwork'); // parsing and collecting nodes and edges from the python nodes = new vis.DataSet([ {"color": "#97c2fc", "id": 1, "label": 1, "shape": "dot"}, {"color": "#97c2fc", "id": 2, "label": 2, "shape": "dot"}, {"color": "#97c2fc", "id": 3, "label": 3, "shape": "dot"} ]); edges = new vis.DataSet([ {"from": 1, "to": 2}, {"from": 2, "to": 3} ]); nodeColors = {}; allNodes = nodes.get({ returnType: "Object" }); for (nodeId in allNodes) { nodeColors[nodeId] = allNodes[nodeId].color; } allEdges = edges.get({ returnType: "Object" }); // adding nodes and edges to the graph data = {nodes: nodes, edges: edges}; var options = { "configure": { "enabled": false }, "edges": { "color": { "inherit": true }, "smooth": { "enabled": true, "type": "dynamic" } }, "interaction": { "dragNodes": true, "hideEdgesOnDrag": false, "hideNodesOnDrag": false }, "physics": { "enabled": true, "stabilization": { "enabled": true, "fit": true, "iterations": 1000, "onlyDynamicEdges": false, "updateInterval": 50 } } }; network = new vis.Network(container, data, options); return network; } drawGraph(); ``` -------------------------------- ### Initialize and Draw Zachary's Karate Club Graph Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/karate.html This JavaScript code initializes the vis.js network for the Zachary's Karate Club graph. It defines nodes and edges with their properties and then draws the network within a specified container. The code relies on the vis.js library. ```javascript var edges; var nodes; var allNodes; var allEdges; var nodeColors; var originalNodes; var network; var container; var options, data; var filter = { item : '', property : '', value : [] }; function drawGraph() { var container = document.getElementById('mynetwork'); nodes = new vis.DataSet([{"club": "Mr. Hi", "color": "#97c2fc", "id": 0, "label": 0, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 1, "label": 1, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 2, "label": 2, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 3, "label": 3, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 4, "label": 4, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 5, "label": 5, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 6, "label": 6, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 7, "label": 7, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 8, "label": 8, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 10, "label": 10, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 11, "label": 11, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 12, "label": 12, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 13, "label": 13, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 17, "label": 17, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 19, "label": 19, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 21, "label": 21, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 31, "label": 31, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 30, "label": 30, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 9, "label": 9, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 27, "label": 27, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 28, "label": 28, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 32, "label": 32, "shape": "dot", "size": 10}, {"club": "Mr. Hi", "color": "#97c2fc", "id": 16, "label": 16, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 33, "label": 33, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 14, "label": 14, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 15, "label": 15, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 18, "label": 18, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 20, "label": 20, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 22, "label": 22, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 23, "label": 23, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 25, "label": 25, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 29, "label": 29, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 24, "label": 24, "shape": "dot", "size": 10}, {"club": "Officer", "color": "#97c2fc", "id": 26, "label": 26, "shape": "dot", "size": 10}]); edges = new vis.DataSet([{"from": 0, "to": 1, "width": 1}, {"from": 0, "to": 2, "width": 1}, {"from": 0, "to": 3, "width": 1}, {"from": 0, "to": 4, "width": 1}, {"from": 0, "to": 5, "width": 1}, {"from": 0, "to": 6, "width": 1}, {"from": 0, "to": 7, "width": 1}, {"from": 0, "to": 8, "width": 1}, {"from": 0, "to": 10, "width": 1}, {"from": 0, "to": 11, "width": 1}, {"from": 0, "to": 12, "width": 1}, {"from": 0, "to": 13, "width": 1}, {"from": 0, "to": 17, "width": 1}, {"from": 0, "to": 19, "width": 1}, {"from": 0, "to": 21, "width": 1}, {"from": 0, "to": 31, "width": 1}, {"from": 1, "to": 2, "width": 1}, {"from": 1, "to": 3, "width": 1}, {"from": 1, "to": 7, "width": 1}, {"from": 1, "to": 13, "width": 1}, {"from": 1, "to": 17, "width": 1}, {"from": 1, "to": 19, "width": 1}, {"from": 1, "to": 21, "width": 1}, {"from": 1, "to": 30, "width": 1}, {"from": 2, "to": 3, "width": 1}, {"from": 2, "to": 7, "width": 1}, {"from": 2, "to": 8, "width": 1}, {"from": 2, "to": 9, "width": 1}, {"from": 2, "to": 13, "width": 1}, {"from": 2, "to": 27, "width": 1}, {"from": 2, "to": 28, "width": 1}, {"from": 2, "to": 32, "width": 1}, {"from": 3, "to": 4, "width": 1}, {"from": 3, "to": 7, "width": 1}, {"from": 3, "to": 8, "width": 1}, {"from": 3, "to": 9, "width": 1}, {"from": 3, "to": 13, "width": 1}, {"from": 3, "to": 27, "width": 1}, {"from": 3, "to": 28, "width": 1}, {"from": 3, "to": 32, "width": 1}, {"from": 4, "to": 5, "width": 1}, {"from": 4, "to": 7, "width": 1}, {"from": 4, "to": 8, "width": 1}, {"from": 4, "to": 9, "width": 1}, {"from": 4, "to": 13, "width": 1}, {"from": 4, "to": 27, "width": 1}, {"from": 4, "to": 28, "width": 1}, {"from": 4, "to": 32, "width": 1}, {"from": 5, "to": 6, "width": 1}, {"from": 5, "to": 7, "width": 1}, {"from": 5, "to": 8, "width": 1}, {"from": 5, "to": 9, "width": 1}, {"from": 5, "to": 13, "width": 1}, {"from": 5, "to": 27, "width": 1}, {"from": 5, "to": 28, "width": 1}, {"from": 5, "to": 32, "width": 1}, {"from": 6, "to": 7, "width": 1}, {"from": 6, "to": 8, "width": 1}, {"from": 6, "to": 9, "width": 1}, {"from": 6, "to": 13, "width": 1}, {"from": 6, "to": 27, "width": 1}, {"from": 6, "to": 28, "width": 1}, {"from": 6, "to": 32, "width": 1}, {"from": 7, "to": 8, "width": 1}, {"from": 7, "to": 9, "width": 1}, {"from": 7, "to": 13, "width": 1}, {"from": 7, "to": 27, "width": 1}, {"from": 7, "to": 28, "width": 1}, {"from": 7, "to": 32, "width": 1}, {"from": 8, "to": 9, "width": 1}, {"from": 8, "to": 13, "width": 1}, {"from": 8, "to": 27, "width": 1}, {"from": 8, "to": 28, "width": 1}, {"from": 8, "to": 32, "width": 1}, {"from": 9, "to": 13, "width": 1}, {"from": 9, "to": 27, "width": 1}, {"from": 9, "to": 28, "width": 1}, {"from": 9, "to": 32, "width": 1}, {"from": 10, "to": 13, "width": 1}, {"from": 10, "to": 17, "width": 1}, {"from": 10, "to": 19, "width": 1}, {"from": 10, "to": 21, "width": 1}, {"from": 10, "to": 30, "width": 1}, {"from": 11, "to": 13, "width": 1}, {"from": 11, "to": 17, "width": 1}, {"from": 11, "to": 19, "width": 1}, {"from": 11, "to": 21, "width": 1}, {"from": 11, "to": 30, "width": 1}, {"from": 12, "to": 13, "width": 1}, {"from": 12, "to": 17, "width": 1}, {"from": 12, "to": 19, "width": 1}, {"from": 12, "to": 21, "width": 1}, {"from": 12, "to": 30, "width": 1}, {"from": 13, "to": 17, "width": 1}, {"from": 13, "to": 19, "width": 1}, {"from": 13, "to": 21, "width": 1}, {"from": 13, "to": 30, "width": 1}, {"from": 17, "to": 19, "width": 1}, {"from": 17, "to": 21, "width": 1}, {"from": 17, "to": 30, "width": 1}, {"from": 19, "to": 21, "width": 1}, {"from": 19, "to": 30, "width": 1}, {"from": 21, "to": 30, "width": 1}, {"from": 21, "to": 31, "width": 1}, {"from": 21, "to": 32, "width": 1}, {"from": 21, "to": 33, "width": 1}, {"from": 30, "to": 32, "width": 1}, {"from": 30, "to": 33, "width": 1}, {"from": 31, "to": 32, "width": 1}, {"from": 31, "to": 33, "width": 1}, {"from": 32, "to": 33, "width": 1}]); data = {nodes: nodes, edges: edges}; network = new vis.Network(container, data, options); } ``` -------------------------------- ### Pyvis Network Visualization Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/playground.ipynb Generates an interactive HTML file for visualizing a graph using pyvis. It converts a NetworkX graph into a pyvis network and displays physics options. ```Python import networkx as nx from pyvis import network as net from IPython.core.display import display, HTML import networkx as nx G = nx.karate_club_graph() g4 = net.Network(height='400px', width='50%', notebook=True, heading='Zachary’s Karate Club graph') g4.from_nx(G) g4.show_buttons(filter_=['physics']) g4.show('karate.html') ``` -------------------------------- ### Graph Visualization with Tabs and Clustering Source: https://github.com/alekseishevkoplias/legendsgraph/blob/main/js/clust.html This JavaScript code initializes a graph visualization using the vis.js library. It fetches data from 'historical_events.json', creates nodes and edges, and applies clustering based on node degree. It also includes functionality to create tabs for selected nodes, display connected nodes, and center the graph on a specific node. Event listeners are set up for node clicks and a button to center the graph. ```javascript document.addEventListener('DOMContentLoaded', function() { // Fetch graph data from the JSON file fetch('historical_events.json') .then(response => response.json()) .then(data => { // Create a graph with the fetched data var nodes = new vis.DataSet(data.nodes); var edges = new vis.DataSet(data.edges); var container = document.getElementById('graph'); var data = { nodes: nodes, edges: edges }; var options = { interaction: { hover: true, dragNodes: true, zoomView: true }, layout: { improvedLayout: false, }, physics: { enabled: true, solver: "forceAtlas2Based", stabilization: { enabled: false, iterations: 1000, updateInterval: 50, onlyDynamicEdges: false, fit: true, damping: 0.9 } }, clusters: { clusterThreshold: 5, // Use the community algorithm to cluster nodes based on degree // See: https://github.com/visjs/vis-clustering algorithm: 'community', clusterEdgeProperties: { style: 'dashed', width: 2 }, clusterNodeProperties: { shape: 'dot', font: { size: 18, color: '#ffffff' }, borderWidth: 2, color: { background: '#ffffff', border: '#2B7CE9', highlight: { background: '#ffffff', border: '#2B7CE9' } } } } }; // Create a new dataset to hold the cluster data var clusterData = { nodes: [], edges: [] }; var clusterIndex = 0; // Define the join condition for clustering nodes var joinCondition = function(nodeOptions) { return nodeOptions.degree > options.clusters.clusterThreshold; }; // Use the vis-clustering library to create clusters var clusterer = new vis.Clustering({ joinCondition: joinCondition, clusterNodeProperties: options.clusters.clusterNodeProperties, clusterEdgeProperties: options.clusters.clusterEdgeProperties }); clusterer.cluster(data.nodes, clusterData); // Create a new dataset for the clustered graph data var clusteredNodes = new vis.DataSet(clusterData.nodes); var clusteredEdges = new vis.DataSet(clusterData.edges); var clusteredData = { nodes: clusteredNodes, edges: clusteredEdges }; // Create the graph using the clustered data var graph = new vis.Network(container, clusteredData, options); graph.on('click', function (params) { if (params.nodes.length > 0) { var nodeId = params.nodes[0]; window.alert(nodeId); var nodeLabel = clusteredNodes.get(nodeId).label; var connectedNodes = graph.getConnectedNodes(nodeId); createTab(nodeId, connectedNodes); } }); var button = document.getElementById('center-button'); button.onclick = function() { centerNode(graph, 1906); }; function centerNode(graph, nodeId) { var position = graph.getPositions([nodeId]); graph.moveTo({ position: position[nodeId], scale: 1, animation: true, easingFunction: 'easeInOutQuad' }); } // Print stabilization progress to console every 5 seconds var isStabilized = false; graph.on('stabilizationIterationsDone', function() { if (!isStabilized) { isStabilized = true; setInterval(function() { console.log(graph.stabilizationProgress.progress); }, 5000); } }); }); }); ```