added basic controls
This commit is contained in:
parent
0b7f3f2be5
commit
a9b70d61a8
6
:w
Normal file
6
:w
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#mynetwork {
|
||||||
|
height: 500px;
|
||||||
|
width: 500px;
|
||||||
|
background-color: white;
|
||||||
|
border: 4px black;
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
#mynetwork {
|
#mynetwork {
|
||||||
height: 500px;
|
height: 500px;
|
||||||
width: 500px;
|
width: 500px;
|
||||||
background-color: black;
|
background-color: white;
|
||||||
|
border: 3px solid black;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 network;
|
||||||
var simulationData;
|
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){
|
function createGraphFromDot(dotString){
|
||||||
var parsedData = vis.parseDOTNetwork(dotString);
|
var parsedData = vis.parseDOTNetwork(dotString);
|
||||||
// create a network
|
// create a network
|
||||||
@ -42,6 +21,10 @@ function createGraphFromDot(dotString){
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
autoResize: true,
|
autoResize: true,
|
||||||
nodes:{
|
nodes:{
|
||||||
|
shape: 'dot',
|
||||||
|
size: 40,
|
||||||
|
borderWidth: 0,
|
||||||
|
chosen: false,
|
||||||
font:{
|
font:{
|
||||||
size:0
|
size:0
|
||||||
},
|
},
|
||||||
@ -50,18 +33,18 @@ function createGraphFromDot(dotString){
|
|||||||
randomSeed: undefined,
|
randomSeed: undefined,
|
||||||
improvedLayout:true,
|
improvedLayout:true,
|
||||||
clusterThreshold: 150,
|
clusterThreshold: 150,
|
||||||
//hierarchical: {
|
hierarchical: {
|
||||||
//enabled:false,
|
enabled:false,
|
||||||
//levelSeparation: 150,
|
levelSeparation: 150,
|
||||||
//nodeSpacing: 100,
|
nodeSpacing: 100,
|
||||||
//treeSpacing: 200,
|
treeSpacing: 200,
|
||||||
//blockShifting: true,
|
blockShifting: true,
|
||||||
//edgeMinimization: true,
|
edgeMinimization: true,
|
||||||
//parentCentralization: true,
|
parentCentralization: true,
|
||||||
//direction: 'UD', // UD, DU, LR, RL
|
direction: 'UD', // UD, DU, LR, RL
|
||||||
//sortMethod: 'hubsize', // hubsize, directed
|
sortMethod: 'hubsize', // hubsize, directed
|
||||||
//shakeTowards: 'leaves' // roots, leaves
|
shakeTowards: 'leaves' // roots, leaves
|
||||||
//}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
network = new vis.Network(container, data, options);
|
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){
|
function visualizeOneStep(step){
|
||||||
@ -102,6 +77,7 @@ function visualizeOneStep(step){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
network.redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -110,7 +86,9 @@ function getSimulation(){
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(response =>{
|
.then(response =>{
|
||||||
simulationData = response;
|
simulationData = response;
|
||||||
|
stepSlider.max = simulationData.steps - 1;
|
||||||
createGraphFromDot(simulationData.dotGraph);
|
createGraphFromDot(simulationData.dotGraph);
|
||||||
|
visualizeOneStep(simulationData.states[0]);
|
||||||
//kelvin to celsius
|
//kelvin to celsius
|
||||||
//let temp = Math.ceil(response.main.temp - 273.15);
|
//let temp = Math.ceil(response.main.temp - 273.15);
|
||||||
//document.getElementById("weather").innerHTML = temp + "ºC";
|
//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()
|
getSimulation()
|
||||||
|
|||||||
@ -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)
|
jump_time = np.random.exponential(rates)
|
||||||
change_n = np.argmin(jump_time)
|
change_n = np.argmin(jump_time)
|
||||||
states[change_n] = S if states[change_n] == I else I
|
states[change_n] = S if states[change_n] == I else I
|
||||||
statesList.append(states)
|
statesList.append(states.copy())
|
||||||
return states
|
return states
|
||||||
|
|
||||||
statesList = []
|
statesList = []
|
||||||
steps = 1000 + random.choice(range(1000))
|
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)
|
G = clean_shuffle_graph(G_grid10x10)
|
||||||
TS_data = gen_sis(G, steps=steps,statesList=statesList)
|
TS_data = gen_sis(G, steps=steps,statesList=statesList)
|
||||||
# print(G.number_of_nodes())
|
# print(G.number_of_nodes())
|
||||||
|
|||||||
@ -12,7 +12,12 @@
|
|||||||
<script src="{{ asset('js/main.js') }}"></script>
|
<script src="{{ asset('js/main.js') }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
<label for="step">Choose a step</label>
|
||||||
<h1>Hello {{ controller_name }}! ✅</h1>
|
<input type="range" id="stepRange" name="step">
|
||||||
<div id="mynetwork"></div>
|
<input type="number" id="stepField" for="step" min=0></output>
|
||||||
|
<label for="animationDuration">Choose animation duration</label>
|
||||||
|
<input type="range" id="animationDurationRange" name="animationDuration" min=10 max=30>
|
||||||
|
<input type="number" id="animationDurationField" for="animationDuration" min=10 max=30></output>
|
||||||
|
<button id="playAnimation" onclick="playAnimation()">Run</button>
|
||||||
|
<div id="mynetwork"></div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
68
ä
Normal file
68
ä
Normal file
@ -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)
|
||||||
Loading…
x
Reference in New Issue
Block a user