1
0
mirror of https://github.com/gsi-upm/soil synced 2024-11-22 19:22:29 +00:00

Map added

This commit is contained in:
Tasio Mendez 2018-04-11 19:40:59 +02:00
parent da1ce1ea30
commit 819c371292
10 changed files with 127 additions and 39 deletions

View File

@ -1,6 +1,6 @@
name: TerroristNetworkModel_sim name: TerroristNetworkModel_sim
load_module: TerroristNetworkModel load_module: TerroristNetworkModel
max_time: 100 max_time: 150
num_trials: 1 num_trials: 1
network_params: network_params:
generator: random_geometric_graph generator: random_geometric_graph
@ -30,7 +30,7 @@ environment_params:
# TerroristSpreadModel # TerroristSpreadModel
information_spread_intensity: 0.7 information_spread_intensity: 0.7
terrorist_additional_influence: 0.035 terrorist_additional_influence: 0.035
max_vulnerability: 0.5 max_vulnerability: 0.6
prob_interaction: 0.5 prob_interaction: 0.5
# TrainingAreaModel and HavenModel # TrainingAreaModel and HavenModel
@ -38,7 +38,7 @@ environment_params:
haven_influence: 0.20 haven_influence: 0.20
# TerroristNetworkModel # TerroristNetworkModel
vision_range: 0.50 vision_range: 0.30
sphere_influence: 2 sphere_influence: 2
weight_social_distance: 0.035 weight_social_distance: 0.035
weight_link_distance: 0.035 weight_link_distance: 0.035
@ -49,10 +49,12 @@ visualization_params:
shapes: shapes:
TrainingAreaModel: target TrainingAreaModel: target
HavenModel: home HavenModel: home
TerroristNetworkModel: person
colors: colors:
- attr_id: 0 - attr_id: 0
color: green color: '#40de40'
- attr_id: 1 - attr_id: 1
color: red color: red
- attr_id: 2 - attr_id: 2
color: '#c16a6a' color: '#c16a6a'
background_image: 'map.png'

2
run.py
View File

@ -14,7 +14,7 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Visualization of a Graph Model') 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('--dump', '-d', help='dumping results in folder output', action='store_true')
parser.add_argument('--verbose', '-v', help='verbose mode', action='store_true') parser.add_argument('--verbose', '-v', help='verbose mode', action='store_true')
args = parser.parse_args() args = parser.parse_args()

View File

@ -94,10 +94,11 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
settings = [] settings = []
for key in self.config['environment_params']: for key in self.config['environment_params']:
if type(self.config['environment_params'][key]) == float: if type(self.config['environment_params'][key]) == float or type(self.config['environment_params'][key]) == int:
setting_type = 'number' if self.config['environment_params'][key] <= 1:
elif type(self.config['environment_params'][key]) == int: setting_type = 'number'
setting_type = 'number' else:
setting_type = 'great_number'
elif type(self.config['environment_params'][key]) == bool: elif type(self.config['environment_params'][key]) == bool:
setting_type = 'boolean' setting_type = 'boolean'
else: else:
@ -122,7 +123,6 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
elif msg['type'] == 'run_simulation': elif msg['type'] == 'run_simulation':
if self.application.verbose: if self.application.verbose:
logger.info('Running new simulation for {name}'.format(name=self.config['name'])) 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.send_log('INFO.soil', 'Running new simulation for {name}'.format(name=self.config['name']))
self.config['environment_params'] = msg['data'] self.config['environment_params'] = msg['data']
self.run_simulation() self.run_simulation()
@ -209,7 +209,7 @@ class ModularServer(tornado.web.Application):
settings = {'debug': True, settings = {'debug': True,
'template_path': os.path.dirname(__file__) + '/templates'} '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): *args, **kwargs):
self.verbose = verbose self.verbose = verbose

View File

@ -33,6 +33,25 @@ html, body {
cursor: pointer; 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 { .node {
stroke: #fff; stroke: #fff;
stroke-width: 1.5px; stroke-width: 1.5px;
@ -292,7 +311,7 @@ table#link-distance .max {
/* Console */ /* Console */
#update, .console { #update, .console, .soil_logo {
padding: 10px 15px; padding: 10px 15px;
height: 135px; height: 135px;
border: 1px solid #585858; border: 1px solid #585858;
@ -317,6 +336,7 @@ table#link-distance .max {
overflow: auto; overflow: auto;
border-top-left-radius: 5px; border-top-left-radius: 5px;
border-bottom-left-radius: 5px; border-bottom-left-radius: 5px;
width: 100%;
} }
.console::-webkit-scrollbar { .console::-webkit-scrollbar {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
templates/img/logo_soil.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@ -74,7 +74,7 @@
); );
if ( file['type'] !== "application/x-yaml" ) { 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.'); _socket.error('File format not supported. Sorry for the inconvenience.');
return; return;
} else { } else {
@ -142,13 +142,21 @@
<div class="container-fluid fixed"> <div class="container-fluid fixed">
<!-- CONSOLE --> <div class="col-sm-9 wrapper-heading">
<div class="col-sm-9 console"> <!-- CONSOLE -->
Please, upload a YAML file that defines all the parameters of a simulation. <br/> <div class="console">
If you don't know how to write the file, please visit this page:<br/> Please, upload a YAML file that defines all the parameters of a simulation. <br/>
http://soilsim.readthedocs.io/en/latest/quickstart.html<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> </div>
<!-- //CONSOLE -->
<div id="update" class="col-sm-3"> <div id="update" class="col-sm-3">
<!-- Load File --> <!-- Load File -->
@ -210,7 +218,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div id="graph_container"> <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>
<div id="configuration" class="col-sm-3"> <div id="configuration" class="col-sm-3">

View File

@ -26,12 +26,12 @@ ws.onmessage = function(message) {
self.GraphVisualization.import(convertJSON(msg['data']), function() { self.GraphVisualization.import(convertJSON(msg['data']), function() {
reset_configuration(); reset_configuration();
set_configuration(); set_configuration();
$('#home_menu').click(function() { // $('#home_menu').click(function() {
setTimeout(function() { // setTimeout(function() {
reset_timeline(); // reset_timeline();
set_timeline(msg['data']); // set_timeline(msg['data']);
}, 1000); // }, 1000);
}); // });
reset_timeline(); reset_timeline();
set_timeline(msg['data']); set_timeline(msg['data']);
$('#load').hide(); $('#load').hide();
@ -52,7 +52,7 @@ ws.onmessage = function(message) {
break; break;
case 'error': case 'error':
console.log(msg['error']); console.error(msg['error']);
_socket.error(msg['error']); _socket.error(msg['error']);
$('#load').removeClass('loader'); $('#load').removeClass('loader');
break; break;
@ -65,10 +65,18 @@ ws.onmessage = function(message) {
case 'visualization_params': case 'visualization_params':
console.log(msg['data']); console.log(msg['data']);
self.GraphVisualization.set_params(msg['data']['shape_property'], msg['data']['shapes'], msg['data']['colors']); 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; break;
default: default:
console.log('Unexpected message!') console.warn('Unexpected message!')
} }
} }
@ -111,8 +119,8 @@ var reset_trials = function() {
var convertJSON = function(json) { var convertJSON = function(json) {
// For NetworkX Geometric Graphs get positions // For NetworkX Geometric Graphs get positions
json.nodes.forEach(function(node) { json.nodes.forEach(function(node) {
var scx = d3.scale.linear().domain([0, 1]).range([0, height]); var scx = d3.scale.linear().domain([0, 1]).range([0, width]);
var scy = d3.scale.linear().domain([0, 1]).range([height, 0]); var scy = d3.scale.linear().domain([0, 1]).range([width, 0]);
if ( node.pos ) { if ( node.pos ) {
node.scx = scx(node.pos[0]); node.scx = scx(node.pos[0]);
node.scy = scy(node.pos[1]); node.scy = scy(node.pos[1]);
@ -227,8 +235,15 @@ var set_timeline = function(graph) {
// Draw graph for the first time // Draw graph for the first time
self.GraphVisualization.update_graph($('.config-item #properties').val(), maxUnix, function() { self.GraphVisualization.update_graph($('.config-item #properties').val(), maxUnix, function() {
update_statistics_table(); update_statistics_table();
setTimeout(function() { $('svg #root > image').attr('height', d3.select('#root').node().getBBox().height)
self.GraphVisualization.fit(); 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); }, 100);
}); });
@ -397,7 +412,11 @@ var run_simulation = function() {
case 'checkbox': case 'checkbox':
environment_variables[this.id] = ($(this).is(':checked')) ? true : false; environment_variables[this.id] = ($(this).is(':checked')) ? true : false;
break; break;
case 'number':
environment_variables[this.id] = Number(this.value);
break;
default: default:
console.warn(this.id + ' not defined when running simulation!');
break; break;
} }

View File

@ -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 addTextBox = function(param, obj) {
var well = $('<div class="well">' + obj.value + '</div>')[0]; var well = $('<div class="well">' + obj.value + '</div>')[0];
sidebar.append(well); sidebar.append(well);
@ -81,8 +88,11 @@ var initGUI = function(model_params) {
case 'number': case 'number':
addSliderInput(model_params[option]['label'], model_params[option]['value']); addSliderInput(model_params[option]['label'], model_params[option]['value']);
break; break;
case 'great_number':
addNumberInput(model_params[option]['label'], model_params[option]['value']);
break;
default: default:
console.log(model_params[option]['label'] + ' not defined!'); console.warn(model_params[option]['label'] + ' not defined!');
break; break;
} }
} }

View File

@ -14,6 +14,7 @@
// Private constants // Private constants
var focus_opacity = 0.1, var focus_opacity = 0.1,
radius = 8, radius = 8,
shape_size = 16,
required_node = ['id', 'index', 'label', 'px', 'py', 'spells', 'weight', 'x', 'y', 'pos', 'scx', 'scy']; required_node = ['id', 'index', 'label', 'px', 'py', 'spells', 'weight', 'x', 'y', 'pos', 'scx', 'scy'];
// Private variables // Private variables
@ -29,8 +30,10 @@
zoom, // Zoom zoom, // Zoom
groot, // Append sections to svg to have nodes and edges separately groot, // Append sections to svg to have nodes and edges separately
graph_wrapper,
glinks, glinks,
gnodes, gnodes,
background_image,
data_node, // Actual node data for the graph data_node, // Actual node data for the graph
data_link, // Actual link data for the graph data_link, // Actual link data for the graph
@ -38,7 +41,8 @@
node, // Circles for the nodes node, // Circles for the nodes
shape_property, // Property to whom the shape will be applied shape_property, // Property to whom the shape will be applied
shapes, // Dictionary of shapes for nodes 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) { Number.prototype.between = function(min, max) {
var min = (min || min === 0) ? min : Math.max(), var min = (min || min === 0) ? min : Math.max(),
@ -221,9 +225,18 @@
.size([width, height]); .size([width, height]);
// Append sections to svg to have nodes and edges separately // Append sections to svg to have nodes and edges separately
groot = svg.append('g') .attr('id', 'root'); groot = svg.append('g').attr('id', 'root');
glinks = groot.append('g') .attr('id', 'links');
gnodes = groot.append('g') .attr('id', 'nodes'); // 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 // Add patterns for shapes
var defs = []; var defs = [];
@ -245,8 +258,8 @@
.attr('href', function(d) { .attr('href', function(d) {
return window.location.protocol + '//' + window.location.host + '/img/svg/' + d + '.svg'; return window.location.protocol + '//' + window.location.host + '/img/svg/' + d + '.svg';
}) })
.attr('width', 16) .attr('width', shape_size)
.attr('height', 16); .attr('height', shape_size);
// Zoom // Zoom
zoom = d3.behavior zoom = d3.behavior
@ -447,10 +460,25 @@
radius = r(distance); radius = r(distance);
node.attr('r', radius); 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); } 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. * Set property and instant of time.
* A function that draws the graph depends on the property and instant of time selected. * A function that draws the graph depends on the property and instant of time selected.
@ -623,6 +651,7 @@
update_graph: update_graph, update_graph: update_graph,
set_params: set_params, set_params: set_params,
set_link_distance: set_link_distance, set_link_distance: set_link_distance,
set_background: set_background,
fit: zoom_to_fit, fit: zoom_to_fit,
reset: reset, reset: reset,