diff --git a/:w b/:w new file mode 100644 index 0000000..6b8a474 --- /dev/null +++ b/:w @@ -0,0 +1,6 @@ +#mynetwork { + height: 500px; + width: 500px; + background-color: white; + border: 4px black; +} diff --git a/visualizer/public/css/main.css b/visualizer/public/css/main.css index 8ae5e0e..d703d37 100644 --- a/visualizer/public/css/main.css +++ b/visualizer/public/css/main.css @@ -1,5 +1,6 @@ #mynetwork { height: 500px; width: 500px; - background-color: black; + background-color: white; + border: 3px solid black; } diff --git a/visualizer/public/js/main.js b/visualizer/public/js/main.js index 91de467..110a213 100644 --- a/visualizer/public/js/main.js +++ b/visualizer/public/js/main.js @@ -1,34 +1,13 @@ - // create an array with nodes - //var nodes = new vis.DataSet([ - //{ id: 1, label: "Node 1" }, - //{ id: 2, label: "Node 2" }, - //{ id: 3, label: "Node 3" }, - //{ id: 4, label: "Node 4" }, - //{ id: 5, label: "Node 5" } - //]); -// - //// create an array with edges - //var edges = new vis.DataSet([ - //{ from: 1, to: 3 }, - //{ from: 1, to: 2 }, - //{ from: 2, to: 4 }, - //{ from: 2, to: 5 }, - //{ from: 3, to: 3 } - //]); - - // create a network - //var container = document.getElementById("mynetwork"); - //var data = { - //nodes: nodes, - //edges: edges - //}; - //var options = { - //height: '100%', - //width: '100%', - //}; - //var network = new vis.Network(container, data, options); var network; var simulationData; +animationPlaying = false; +currentAnimationStep = 0; +var animationInterval; +var animationLen = 10; +const stepSlider = document.querySelector('#stepRange'); +const stepField = document.querySelector('#stepField'); +const animationDurationSlider = document.querySelector('#animationDurationRange'); +const animationDurationField = document.querySelector('#animationDurationField'); function createGraphFromDot(dotString){ var parsedData = vis.parseDOTNetwork(dotString); // create a network @@ -42,6 +21,10 @@ function createGraphFromDot(dotString){ width: '100%', autoResize: true, nodes:{ + shape: 'dot', + size: 40, + borderWidth: 0, + chosen: false, font:{ size:0 }, @@ -50,18 +33,18 @@ function createGraphFromDot(dotString){ randomSeed: undefined, improvedLayout:true, clusterThreshold: 150, - //hierarchical: { - //enabled:false, - //levelSeparation: 150, - //nodeSpacing: 100, - //treeSpacing: 200, - //blockShifting: true, - //edgeMinimization: true, - //parentCentralization: true, - //direction: 'UD', // UD, DU, LR, RL - //sortMethod: 'hubsize', // hubsize, directed - //shakeTowards: 'leaves' // roots, leaves - //} + hierarchical: { + enabled:false, + levelSeparation: 150, + nodeSpacing: 100, + treeSpacing: 200, + blockShifting: true, + edgeMinimization: true, + parentCentralization: true, + direction: 'UD', // UD, DU, LR, RL + sortMethod: 'hubsize', // hubsize, directed + shakeTowards: 'leaves' // roots, leaves + } }, }; network = new vis.Network(container, data, options); @@ -74,14 +57,6 @@ function createGraphFromDot(dotString){ //} //}); //}); - - //console.log(network.selectNodes([0])); - n = network.body.nodes[0]; - n.setOptions({ - color:{ - background: "#ffffff", - } - }) } function visualizeOneStep(step){ @@ -102,6 +77,7 @@ function visualizeOneStep(step){ }); } } + network.redraw(); } @@ -110,7 +86,9 @@ function getSimulation(){ .then(response => response.json()) .then(response =>{ simulationData = response; + stepSlider.max = simulationData.steps - 1; createGraphFromDot(simulationData.dotGraph); + visualizeOneStep(simulationData.states[0]); //kelvin to celsius //let temp = Math.ceil(response.main.temp - 273.15); //document.getElementById("weather").innerHTML = temp + "ºC"; @@ -118,4 +96,56 @@ function getSimulation(){ }); } +function playAnimation(){ + if(!animationPlaying){ + currentAnimationStep = 0; + //Play the animation + animationInterval = setInterval(function(){ + //This is the animation routine + if(currentAnimationStep == simulationData.steps){ + //At the end of animation + clearInterval(animationInterval); + animationPlaying = false; + return; + } + visualizeOneStep(simulationData.states[currentAnimationStep]); + currentAnimationStep ++; + stepSlider.value = currentAnimationStep; + stepField.value = currentAnimationStep; + }, animationLen * 1000 / simulationData.steps); + + }else{ + //stop the animation + clearInterval(animationInterval); + currentAnimationStep = 0; + } + //switch boolean + animationPlaying = !animationPlaying; +} + +stepField.value = 0; +stepSlider.min = 0; +stepSlider.max = 0; +stepSlider.addEventListener('input', function(){ + stepField.value = stepSlider.value; + visualizeOneStep(simulationData.states[stepSlider.value]); + //console.log(stepSlider.value); +}); +stepField.addEventListener('input', function(){ + stepSlider.value = stepField.value; + visualizeOneStep(simulationData.states[stepField.value]); + //console.log(stepSlider.value); +}); + +animationDurationField.value = 10; +animationDurationSlider.value = 10; +animationDurationSlider.addEventListener('input', function(){ + animationLen = animationDurationSlider.value; + animationDurationField.value = animationLen; +}); +animationDurationField.addEventListener('input', function(){ + animationLen = animationDurationField.value; + animationDurationSlider.value = animationLen; +}); + getSimulation() diff --git a/visualizer/public/python/simulation.py b/visualizer/public/python/simulation.py index 83e7abe..4cf4c21 100755 --- a/visualizer/public/python/simulation.py +++ b/visualizer/public/python/simulation.py @@ -34,12 +34,13 @@ def gen_sis(G, steps = 1000, inf_rate=1.0, rec_rate=2.0, noise=0.1, statesList = jump_time = np.random.exponential(rates) change_n = np.argmin(jump_time) states[change_n] = S if states[change_n] == I else I - statesList.append(states) + statesList.append(states.copy()) return states statesList = [] steps = 1000 + random.choice(range(1000)) -G_grid10x10 = nx.grid_2d_graph(10,10) +# G_grid10x10 = nx.grid_2d_graph(10,10) +G_grid10x10 = nx.newman_watts_strogatz_graph(120, 4, 0.15, seed=42) G = clean_shuffle_graph(G_grid10x10) TS_data = gen_sis(G, steps=steps,statesList=statesList) # print(G.number_of_nodes()) diff --git a/visualizer/templates/main/index.html.twig b/visualizer/templates/main/index.html.twig index a875be4..6ac7908 100755 --- a/visualizer/templates/main/index.html.twig +++ b/visualizer/templates/main/index.html.twig @@ -12,7 +12,12 @@ {% endblock %} {% block body %} - -

Hello {{ controller_name }}! ✅

-
+ + + + + + + +
{% endblock %} diff --git a/ä b/ä new file mode 100644 index 0000000..ad7b49f --- /dev/null +++ b/ä @@ -0,0 +1,68 @@ +import math, random, os, time, sys, io +import json +import numpy as np +import networkx as nx +import scipy +import time +from networkx.drawing.nx_pydot import write_dot + +def clean_shuffle_graph(G): + random_seed_state = int(random.random()*100000) # quick hack to go back to random afterwards + random.seed(42) + node_mapping = dict(zip(sorted(G.nodes()), sorted(G.nodes(), key=lambda _: random.random()))) # maybe sorted not really deterministic + G = nx.relabel_nodes(G, node_mapping) + G = nx.convert_node_labels_to_integers(G) + if not nx.is_connected(G): + print('Graph is not connected, try a differnt one.') + assert(nx.is_connected(G)) + random.seed(random_seed_state) + return G + +def gen_sis(G, steps = 1000, inf_rate=1.0, rec_rate=2.0, noise=0.1, statesList = None): + S = [1., 0.] + I = [0., 1.] + states = [random.choice([S, I]) for i in range(G.number_of_nodes())] + for _ in range(steps): + rates = np.zeros(G.number_of_nodes()) + for n in range(G.number_of_nodes()): + rates[n] = noise + if states[n] == I: + rates[n] += rec_rate + if states[n] == S: + rates[n] += inf_rate * len([n_j for n_j in G.neighbors(n) if states[n_j] == I]) + rates[n] = 1.0/rates[n] # numpy uses mean as rate param + jump_time = np.random.exponential(rates) + change_n = np.argmin(jump_time) + states[change_n] = S if states[change_n] == I else I + statesList.append(states.copy()) + return states + +statesList = [] +steps = 1000 + random.choice(range(1000)) +G_grid10x10 = nx.grid_2d_graph(10,10) +G = clean_shuffle_graph(G_grid10x10) +TS_data = gen_sis(G, steps=steps,statesList=statesList) +# print(G.number_of_nodes()) +# f = open("graph.dot", "rw") +# nx.drawing.nx_pydot.write_dot(G,f) +# f.write("\n") +# f.close() +# Writing the json file to stdout +# f = StringIO("") +dotGraph = "" + +#Write dot file to string +with io.StringIO() as f: + write_dot(G, f) + f.seek(0) + dotGraph = f.read() + +output = { + "name" : "testGraph", + "dotGraph" : dotGraph, + "steps" : steps, + "states" : statesList, + } + +jsonOutput = json.dumps(output) +print(jsonOutput)