mirror of
https://github.com/gsi-upm/soil
synced 2024-11-14 15:32:29 +00:00
Map added
This commit is contained in:
parent
da1ce1ea30
commit
819c371292
@ -1,6 +1,6 @@
|
||||
name: TerroristNetworkModel_sim
|
||||
load_module: TerroristNetworkModel
|
||||
max_time: 100
|
||||
max_time: 150
|
||||
num_trials: 1
|
||||
network_params:
|
||||
generator: random_geometric_graph
|
||||
@ -30,7 +30,7 @@ environment_params:
|
||||
# TerroristSpreadModel
|
||||
information_spread_intensity: 0.7
|
||||
terrorist_additional_influence: 0.035
|
||||
max_vulnerability: 0.5
|
||||
max_vulnerability: 0.6
|
||||
prob_interaction: 0.5
|
||||
|
||||
# TrainingAreaModel and HavenModel
|
||||
@ -38,7 +38,7 @@ environment_params:
|
||||
haven_influence: 0.20
|
||||
|
||||
# TerroristNetworkModel
|
||||
vision_range: 0.50
|
||||
vision_range: 0.30
|
||||
sphere_influence: 2
|
||||
weight_social_distance: 0.035
|
||||
weight_link_distance: 0.035
|
||||
@ -49,10 +49,12 @@ visualization_params:
|
||||
shapes:
|
||||
TrainingAreaModel: target
|
||||
HavenModel: home
|
||||
TerroristNetworkModel: person
|
||||
colors:
|
||||
- attr_id: 0
|
||||
color: green
|
||||
color: '#40de40'
|
||||
- attr_id: 1
|
||||
color: red
|
||||
- attr_id: 2
|
||||
color: '#c16a6a'
|
||||
background_image: 'map.png'
|
||||
|
2
run.py
2
run.py
@ -14,7 +14,7 @@ if __name__ == "__main__":
|
||||
|
||||
parser = argparse.ArgumentParser(description='Visualization of a Graph Model')
|
||||
|
||||
parser.add_argument('--name', '-n', nargs=1, default='SOIL Model', help='name of the simulation')
|
||||
parser.add_argument('--name', '-n', nargs=1, default='SOIL', help='name of the simulation')
|
||||
parser.add_argument('--dump', '-d', help='dumping results in folder output', action='store_true')
|
||||
parser.add_argument('--verbose', '-v', help='verbose mode', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
12
server.py
12
server.py
@ -94,10 +94,11 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
|
||||
|
||||
settings = []
|
||||
for key in self.config['environment_params']:
|
||||
if type(self.config['environment_params'][key]) == float:
|
||||
setting_type = 'number'
|
||||
elif type(self.config['environment_params'][key]) == int:
|
||||
setting_type = 'number'
|
||||
if type(self.config['environment_params'][key]) == float or type(self.config['environment_params'][key]) == int:
|
||||
if self.config['environment_params'][key] <= 1:
|
||||
setting_type = 'number'
|
||||
else:
|
||||
setting_type = 'great_number'
|
||||
elif type(self.config['environment_params'][key]) == bool:
|
||||
setting_type = 'boolean'
|
||||
else:
|
||||
@ -122,7 +123,6 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
|
||||
elif msg['type'] == 'run_simulation':
|
||||
if self.application.verbose:
|
||||
logger.info('Running new simulation for {name}'.format(name=self.config['name']))
|
||||
print(msg['data'])
|
||||
self.send_log('INFO.soil', 'Running new simulation for {name}'.format(name=self.config['name']))
|
||||
self.config['environment_params'] = msg['data']
|
||||
self.run_simulation()
|
||||
@ -209,7 +209,7 @@ class ModularServer(tornado.web.Application):
|
||||
settings = {'debug': True,
|
||||
'template_path': os.path.dirname(__file__) + '/templates'}
|
||||
|
||||
def __init__(self, model, visualization_element, name='SOIL Model', verbose=True,
|
||||
def __init__(self, model, visualization_element, name='SOIL', verbose=True,
|
||||
*args, **kwargs):
|
||||
|
||||
self.verbose = verbose
|
||||
|
@ -33,6 +33,25 @@ html, body {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wrapper-heading {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.soil_logo {
|
||||
padding: 0 !important;
|
||||
border-left: none !important;
|
||||
border-right: none !important;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
background-color: rgb(88, 88, 88);
|
||||
}
|
||||
|
||||
.soil_logo > img {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.node {
|
||||
stroke: #fff;
|
||||
stroke-width: 1.5px;
|
||||
@ -292,7 +311,7 @@ table#link-distance .max {
|
||||
|
||||
/* Console */
|
||||
|
||||
#update, .console {
|
||||
#update, .console, .soil_logo {
|
||||
padding: 10px 15px;
|
||||
height: 135px;
|
||||
border: 1px solid #585858;
|
||||
@ -317,6 +336,7 @@ table#link-distance .max {
|
||||
overflow: auto;
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.console::-webkit-scrollbar {
|
||||
|
BIN
templates/img/background/map.png
Normal file
BIN
templates/img/background/map.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
BIN
templates/img/logo_soil.png
Normal file
BIN
templates/img/logo_soil.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 101 KiB |
@ -74,7 +74,7 @@
|
||||
);
|
||||
|
||||
if ( file['type'] !== "application/x-yaml" ) {
|
||||
console.log('File format not supported. Sorry for the inconvenience.');
|
||||
console.error('File format not supported. Sorry for the inconvenience.');
|
||||
_socket.error('File format not supported. Sorry for the inconvenience.');
|
||||
return;
|
||||
} else {
|
||||
@ -142,13 +142,21 @@
|
||||
|
||||
<div class="container-fluid fixed">
|
||||
|
||||
<!-- CONSOLE -->
|
||||
<div class="col-sm-9 console">
|
||||
Please, upload a YAML file that defines all the parameters of a simulation. <br/>
|
||||
If you don't know how to write the file, please visit this page:<br/>
|
||||
http://soilsim.readthedocs.io/en/latest/quickstart.html<br/>
|
||||
<div class="col-sm-9 wrapper-heading">
|
||||
<!-- CONSOLE -->
|
||||
<div class="console">
|
||||
Please, upload a YAML file that defines all the parameters of a simulation. <br/>
|
||||
If you don't know how to write the file, please visit this page:<br/>
|
||||
http://soilsim.readthedocs.io/en/latest/quickstart.html<br/>
|
||||
</div>
|
||||
<!-- //CONSOLE -->
|
||||
|
||||
<!-- SOIL Logo -->
|
||||
<div class="soil_logo" >
|
||||
<img src="img/logo_soil.png" />
|
||||
</div>
|
||||
<!-- //SOIL Logo -->
|
||||
</div>
|
||||
<!-- //CONSOLE -->
|
||||
|
||||
<div id="update" class="col-sm-3">
|
||||
<!-- Load File -->
|
||||
@ -210,7 +218,7 @@
|
||||
<div class="container-fluid">
|
||||
|
||||
<div id="graph_container">
|
||||
<svg id="graph" class="col-sm-9"></svg>
|
||||
<svg id="graph" class="col-sm-9" xmlns="http://www.w3.org/2000/svg"></svg>
|
||||
</div>
|
||||
|
||||
<div id="configuration" class="col-sm-3">
|
||||
|
@ -26,12 +26,12 @@ ws.onmessage = function(message) {
|
||||
self.GraphVisualization.import(convertJSON(msg['data']), function() {
|
||||
reset_configuration();
|
||||
set_configuration();
|
||||
$('#home_menu').click(function() {
|
||||
setTimeout(function() {
|
||||
reset_timeline();
|
||||
set_timeline(msg['data']);
|
||||
}, 1000);
|
||||
});
|
||||
// $('#home_menu').click(function() {
|
||||
// setTimeout(function() {
|
||||
// reset_timeline();
|
||||
// set_timeline(msg['data']);
|
||||
// }, 1000);
|
||||
// });
|
||||
reset_timeline();
|
||||
set_timeline(msg['data']);
|
||||
$('#load').hide();
|
||||
@ -52,7 +52,7 @@ ws.onmessage = function(message) {
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
console.log(msg['error']);
|
||||
console.error(msg['error']);
|
||||
_socket.error(msg['error']);
|
||||
$('#load').removeClass('loader');
|
||||
break;
|
||||
@ -65,10 +65,18 @@ ws.onmessage = function(message) {
|
||||
case 'visualization_params':
|
||||
console.log(msg['data']);
|
||||
self.GraphVisualization.set_params(msg['data']['shape_property'], msg['data']['shapes'], msg['data']['colors']);
|
||||
|
||||
if ( msg['data']['background_image'] ) {
|
||||
// $('svg#graph').css('background-image', 'linear-gradient(to bottom, rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%), url(img/background/' + msg['data']['background_image'])
|
||||
// .css('background-size', '130%').css('background-position', '5% 30%').css('background-repeat', 'no-repeat');
|
||||
$('<style>').text('svg line.link { stroke: white !important; stroke-width: 1.5px !important; }').appendTo($('html > head'));
|
||||
$('<style>').text('svg circle.node { stroke-width: 2.5px !important; }').appendTo($('html > head'));
|
||||
self.GraphVisualization.set_background('img/background/' + msg['data']['background_image']);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Unexpected message!')
|
||||
console.warn('Unexpected message!')
|
||||
}
|
||||
|
||||
}
|
||||
@ -111,8 +119,8 @@ var reset_trials = function() {
|
||||
var convertJSON = function(json) {
|
||||
// For NetworkX Geometric Graphs get positions
|
||||
json.nodes.forEach(function(node) {
|
||||
var scx = d3.scale.linear().domain([0, 1]).range([0, height]);
|
||||
var scy = d3.scale.linear().domain([0, 1]).range([height, 0]);
|
||||
var scx = d3.scale.linear().domain([0, 1]).range([0, width]);
|
||||
var scy = d3.scale.linear().domain([0, 1]).range([width, 0]);
|
||||
if ( node.pos ) {
|
||||
node.scx = scx(node.pos[0]);
|
||||
node.scy = scy(node.pos[1]);
|
||||
@ -227,8 +235,15 @@ var set_timeline = function(graph) {
|
||||
// Draw graph for the first time
|
||||
self.GraphVisualization.update_graph($('.config-item #properties').val(), maxUnix, function() {
|
||||
update_statistics_table();
|
||||
setTimeout(function() {
|
||||
self.GraphVisualization.fit();
|
||||
$('svg #root > image').attr('height', d3.select('#root').node().getBBox().height)
|
||||
setTimeout(function() {
|
||||
if ( $('svg #root > image').length !== 0 ) {
|
||||
$('svg #root > image').attr('height', d3.select('#root').node().getBBox().height * 1.2);
|
||||
var dx = d3.select('#graph-wrapper').node().getBBox().width - d3.select('svg #root > image').node().getBBox().width;
|
||||
var dy = d3.select('#graph-wrapper').node().getBBox().height - d3.select('svg #root > image').node().getBBox().height;
|
||||
$('svg #root > image').attr('transform', 'translate(' + (dx / 2) + ',' + (dy / 2) + ')');
|
||||
}
|
||||
self.GraphVisualization.fit();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
@ -397,7 +412,11 @@ var run_simulation = function() {
|
||||
case 'checkbox':
|
||||
environment_variables[this.id] = ($(this).is(':checked')) ? true : false;
|
||||
break;
|
||||
case 'number':
|
||||
environment_variables[this.id] = Number(this.value);
|
||||
break;
|
||||
default:
|
||||
console.warn(this.id + ' not defined when running simulation!');
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,13 @@ var initGUI = function(model_params) {
|
||||
});
|
||||
};
|
||||
|
||||
var addNumberInput = function(name, value) {
|
||||
var wrapper = $('<div>').attr('class', 'col-sm-6').height('110px');
|
||||
var label = $('<div>').width('100%').text(name).css('text-align', 'center').css('font-weight', 'bolder').appendTo(wrapper);
|
||||
var input = $('<input>').attr('id', name).attr('type', 'number').attr('class', 'form-control').attr('value', value).attr('min', 0).css('margin-top', '18px').appendTo(wrapper);
|
||||
$('#wrapper-settings').append(wrapper);
|
||||
}
|
||||
|
||||
var addTextBox = function(param, obj) {
|
||||
var well = $('<div class="well">' + obj.value + '</div>')[0];
|
||||
sidebar.append(well);
|
||||
@ -81,8 +88,11 @@ var initGUI = function(model_params) {
|
||||
case 'number':
|
||||
addSliderInput(model_params[option]['label'], model_params[option]['value']);
|
||||
break;
|
||||
case 'great_number':
|
||||
addNumberInput(model_params[option]['label'], model_params[option]['value']);
|
||||
break;
|
||||
default:
|
||||
console.log(model_params[option]['label'] + ' not defined!');
|
||||
console.warn(model_params[option]['label'] + ' not defined!');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
// Private constants
|
||||
var focus_opacity = 0.1,
|
||||
radius = 8,
|
||||
shape_size = 16,
|
||||
required_node = ['id', 'index', 'label', 'px', 'py', 'spells', 'weight', 'x', 'y', 'pos', 'scx', 'scy'];
|
||||
|
||||
// Private variables
|
||||
@ -29,8 +30,10 @@
|
||||
zoom, // Zoom
|
||||
|
||||
groot, // Append sections to svg to have nodes and edges separately
|
||||
graph_wrapper,
|
||||
glinks,
|
||||
gnodes,
|
||||
background_image,
|
||||
data_node, // Actual node data for the graph
|
||||
data_link, // Actual link data for the graph
|
||||
|
||||
@ -38,7 +41,8 @@
|
||||
node, // Circles for the nodes
|
||||
shape_property, // Property to whom the shape will be applied
|
||||
shapes, // Dictionary of shapes for nodes
|
||||
colors; // Dictionary of colors for nodes
|
||||
colors, // Dictionary of colors for nodes
|
||||
background; // Background of the graph
|
||||
|
||||
Number.prototype.between = function(min, max) {
|
||||
var min = (min || min === 0) ? min : Math.max(),
|
||||
@ -221,9 +225,18 @@
|
||||
.size([width, height]);
|
||||
|
||||
// Append sections to svg to have nodes and edges separately
|
||||
groot = svg.append('g') .attr('id', 'root');
|
||||
glinks = groot.append('g') .attr('id', 'links');
|
||||
gnodes = groot.append('g') .attr('id', 'nodes');
|
||||
groot = svg.append('g').attr('id', 'root');
|
||||
|
||||
// Set background
|
||||
if ( background !== undefined ) {
|
||||
background_image = groot.append('image').attr('href', background).style('opacity', '0.8');
|
||||
graph_wrapper = groot.append('g') .attr('id', 'graph-wrapper');
|
||||
glinks = graph_wrapper.append('g') .attr('id', 'links');
|
||||
gnodes = graph_wrapper.append('g') .attr('id', 'nodes');
|
||||
} else {
|
||||
glinks = groot.append('g') .attr('id', 'links');
|
||||
gnodes = groot.append('g') .attr('id', 'nodes');
|
||||
}
|
||||
|
||||
// Add patterns for shapes
|
||||
var defs = [];
|
||||
@ -245,8 +258,8 @@
|
||||
.attr('href', function(d) {
|
||||
return window.location.protocol + '//' + window.location.host + '/img/svg/' + d + '.svg';
|
||||
})
|
||||
.attr('width', 16)
|
||||
.attr('height', 16);
|
||||
.attr('width', shape_size)
|
||||
.attr('height', shape_size);
|
||||
|
||||
// Zoom
|
||||
zoom = d3.behavior
|
||||
@ -447,10 +460,25 @@
|
||||
radius = r(distance);
|
||||
node.attr('r', radius);
|
||||
|
||||
var s = d3.scale.linear().domain([30, 1000]).range([16, 48]);
|
||||
if ( shapes instanceof Object && shape_property ) {
|
||||
svg.selectAll('pattern image').attr('width', s(distance)).attr('height', s(distance));
|
||||
}
|
||||
|
||||
if (callback) { callback(radius); }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background image.
|
||||
* A function that set a background image.
|
||||
*
|
||||
* @param {object} image Path to image.
|
||||
*/
|
||||
function set_background(image) {
|
||||
background = image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set property and instant of time.
|
||||
* A function that draws the graph depends on the property and instant of time selected.
|
||||
@ -623,6 +651,7 @@
|
||||
update_graph: update_graph,
|
||||
set_params: set_params,
|
||||
set_link_distance: set_link_distance,
|
||||
set_background: set_background,
|
||||
fit: zoom_to_fit,
|
||||
reset: reset,
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user