mirror of
https://github.com/gsi-upm/soil
synced 2024-11-22 19:22:29 +00:00
Running new simulations
This commit is contained in:
parent
c93f3fafc7
commit
05c1b5c003
305
server.py
305
server.py
@ -19,7 +19,7 @@ logger = logging.getLogger(__name__)
|
|||||||
logger.setLevel(logging.INFO)
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
class VisualizationElement:
|
class VisualizationElement:
|
||||||
"""
|
"""
|
||||||
Defines an element of the visualization.
|
Defines an element of the visualization.
|
||||||
Attributes:
|
Attributes:
|
||||||
package_includes: A list of external JavaScript files to include that
|
package_includes: A list of external JavaScript files to include that
|
||||||
@ -32,190 +32,197 @@ class VisualizationElement:
|
|||||||
to the client.
|
to the client.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
package_includes = []
|
package_includes = []
|
||||||
local_includes = []
|
local_includes = []
|
||||||
js_code = ''
|
js_code = ''
|
||||||
render_args = {}
|
render_args = {}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def render(self, model):
|
def render(self, model):
|
||||||
return '<b>VisualizationElement goes here</b>.'
|
return '<b>VisualizationElement goes here</b>.'
|
||||||
|
|
||||||
|
|
||||||
class PageHandler(tornado.web.RequestHandler):
|
class PageHandler(tornado.web.RequestHandler):
|
||||||
""" Handler for the HTML template which holds the visualization. """
|
""" Handler for the HTML template which holds the visualization. """
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
self.render('index.html', port=self.application.port,
|
self.render('index.html', port=self.application.port,
|
||||||
model_name=self.application.model_name,
|
model_name=self.application.model_name,
|
||||||
package_includes=self.application.package_includes,
|
package_includes=self.application.package_includes,
|
||||||
local_includes=self.application.local_includes,
|
local_includes=self.application.local_includes,
|
||||||
scripts=self.application.js_code)
|
scripts=self.application.js_code)
|
||||||
|
|
||||||
|
|
||||||
class SocketHandler(tornado.websocket.WebSocketHandler):
|
class SocketHandler(tornado.websocket.WebSocketHandler):
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
if self.application.verbose:
|
if self.application.verbose:
|
||||||
logger.info('Socket opened!')
|
logger.info('Socket opened!')
|
||||||
|
|
||||||
|
|
||||||
def check_origin(self, origin):
|
def check_origin(self, origin):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def on_message(self, message):
|
def on_message(self, message):
|
||||||
""" Receiving a message from the websocket, parse, and act accordingly. """
|
""" Receiving a message from the websocket, parse, and act accordingly. """
|
||||||
|
|
||||||
msg = tornado.escape.json_decode(message)
|
msg = tornado.escape.json_decode(message)
|
||||||
|
|
||||||
if msg['type'] == 'config_file':
|
if msg['type'] == 'config_file':
|
||||||
|
|
||||||
if self.application.verbose:
|
if self.application.verbose:
|
||||||
print(msg['data'])
|
print(msg['data'])
|
||||||
|
|
||||||
config = list(yaml.load_all(msg['data']))
|
self.config = list(yaml.load_all(msg['data']))
|
||||||
|
|
||||||
if len(config) > 1:
|
if len(self.config) > 1:
|
||||||
error = 'Please, provide only one configuration.'
|
error = 'Please, provide only one configuration.'
|
||||||
if self.application.verbose:
|
if self.application.verbose:
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
self.write_message({'type': 'error',
|
self.write_message({'type': 'error',
|
||||||
'error': error})
|
'error': error})
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
config = config[0]
|
self.config = self.config[0]
|
||||||
self.send_log('INFO.soil', 'Using config: {name}'.format(name=config['name']))
|
self.send_log('INFO.soil', 'Using config: {name}'.format(name=self.config['name']))
|
||||||
|
|
||||||
self.name = config['name']
|
self.name = self.config['name']
|
||||||
|
|
||||||
settings = []
|
self.run_simulation()
|
||||||
for key in config['environment_params']:
|
|
||||||
if type(config['environment_params'][key]) == float:
|
|
||||||
setting_type = 'number'
|
|
||||||
elif type(config['environment_params'][key]) == bool:
|
|
||||||
setting_type = 'boolean'
|
|
||||||
else:
|
|
||||||
setting_type = 'undefined'
|
|
||||||
|
|
||||||
settings.append({
|
settings = []
|
||||||
'label': key,
|
for key in self.config['environment_params']:
|
||||||
'type': setting_type,
|
if type(self.config['environment_params'][key]) == float:
|
||||||
'value': config['environment_params'][key]
|
setting_type = 'number'
|
||||||
})
|
elif type(self.config['environment_params'][key]) == bool:
|
||||||
|
setting_type = 'boolean'
|
||||||
|
else:
|
||||||
|
setting_type = 'undefined'
|
||||||
|
|
||||||
self.write_message({'type': 'settings',
|
settings.append({
|
||||||
'data': settings})
|
'label': key,
|
||||||
|
'type': setting_type,
|
||||||
# Run simulation and capture logs
|
'value': self.config['environment_params'][key]
|
||||||
with self.logging(self.application.model.name):
|
})
|
||||||
self.application.model.run(config)
|
|
||||||
|
|
||||||
trials = []
|
self.write_message({'type': 'settings',
|
||||||
for i in range(config['num_trials']):
|
'data': settings})
|
||||||
trials.append('{}_trial_{}'.format(self.name, i))
|
|
||||||
self.write_message({'type': 'trials',
|
|
||||||
'data': trials })
|
|
||||||
|
|
||||||
elif msg['type'] == 'get_trial':
|
elif msg['type'] == 'get_trial':
|
||||||
if self.application.verbose:
|
if self.application.verbose:
|
||||||
logger.info('Trial {} requested!'.format(msg['data']))
|
logger.info('Trial {} requested!'.format(msg['data']))
|
||||||
self.send_log('INFO.user', 'Trial {} requested!'.format(msg['data']))
|
self.send_log('INFO.user', 'Trial {} requested!'.format(msg['data']))
|
||||||
self.write_message({'type': 'get_trial',
|
self.write_message({'type': 'get_trial',
|
||||||
'data': self.application.model.get_trial(self.name, msg['data']) })
|
'data': self.application.model.get_trial(self.name, msg['data']) })
|
||||||
|
|
||||||
else:
|
elif msg['type'] == 'run_simulation':
|
||||||
if self.application.verbose:
|
self.send_log('INFO.soil', 'Running new simulation for {name}'.format(name=self.config['name']))
|
||||||
logger.info('Unexpected message!')
|
self.config['environment_params'] = msg['data']
|
||||||
|
self.run_simulation()
|
||||||
|
|
||||||
def update_logging(self):
|
else:
|
||||||
try:
|
if self.application.verbose:
|
||||||
if (not self.log_capture_string.closed and self.log_capture_string.getvalue()):
|
logger.info('Unexpected message!')
|
||||||
self.send_log('INFO.soil', self.log_capture_string.getvalue())
|
|
||||||
self.log_capture_string.truncate(0)
|
|
||||||
self.log_capture_string.seek(0)
|
|
||||||
finally:
|
|
||||||
if self.capture_logging:
|
|
||||||
thread = threading.Timer(0.001, self.update_logging)
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
def on_close(self):
|
def update_logging(self):
|
||||||
logger.info('Socket closed!')
|
try:
|
||||||
|
if (not self.log_capture_string.closed and self.log_capture_string.getvalue()):
|
||||||
|
self.send_log('INFO.soil', self.log_capture_string.getvalue())
|
||||||
|
self.log_capture_string.truncate(0)
|
||||||
|
self.log_capture_string.seek(0)
|
||||||
|
finally:
|
||||||
|
if self.capture_logging:
|
||||||
|
thread = threading.Timer(0.001, self.update_logging)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
def send_log(self, logger, logging):
|
def on_close(self):
|
||||||
self.write_message({'type': 'log',
|
logger.info('Socket closed!')
|
||||||
'logger': logger,
|
|
||||||
'logging': logging })
|
|
||||||
|
|
||||||
@contextmanager
|
def send_log(self, logger, logging):
|
||||||
def logging(self, logger):
|
self.write_message({'type': 'log',
|
||||||
self.capture_logging = True
|
'logger': logger,
|
||||||
self.logger_application = logging.getLogger(logger)
|
'logging': logging })
|
||||||
self.log_capture_string = io.StringIO()
|
|
||||||
ch = logging.StreamHandler(self.log_capture_string)
|
|
||||||
self.logger_application.addHandler(ch)
|
|
||||||
self.update_logging()
|
|
||||||
yield self.capture_logging
|
|
||||||
|
|
||||||
self.log_capture_string.close()
|
def run_simulation(self):
|
||||||
self.logger_application.removeHandler(ch)
|
# Run simulation and capture logs
|
||||||
self.capture_logging = False
|
with self.logging(self.application.model.name):
|
||||||
return self.capture_logging
|
self.application.model.run(self.config)
|
||||||
|
|
||||||
|
trials = []
|
||||||
|
for i in range(self.config['num_trials']):
|
||||||
|
trials.append('{}_trial_{}'.format(self.name, i))
|
||||||
|
self.write_message({'type': 'trials',
|
||||||
|
'data': trials })
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def logging(self, logger):
|
||||||
|
self.capture_logging = True
|
||||||
|
self.logger_application = logging.getLogger(logger)
|
||||||
|
self.log_capture_string = io.StringIO()
|
||||||
|
ch = logging.StreamHandler(self.log_capture_string)
|
||||||
|
self.logger_application.addHandler(ch)
|
||||||
|
self.update_logging()
|
||||||
|
yield self.capture_logging
|
||||||
|
|
||||||
|
self.log_capture_string.close()
|
||||||
|
self.logger_application.removeHandler(ch)
|
||||||
|
self.capture_logging = False
|
||||||
|
return self.capture_logging
|
||||||
|
|
||||||
|
|
||||||
class ModularServer(tornado.web.Application):
|
class ModularServer(tornado.web.Application):
|
||||||
""" Main visualization application. """
|
""" Main visualization application. """
|
||||||
|
|
||||||
portrayal_method = None
|
portrayal_method = None
|
||||||
port = 8001
|
port = 8001
|
||||||
model_args = ()
|
model_args = ()
|
||||||
model_kwargs = {}
|
model_kwargs = {}
|
||||||
page_handler = (r'/', PageHandler)
|
page_handler = (r'/', PageHandler)
|
||||||
socket_handler = (r'/ws', SocketHandler)
|
socket_handler = (r'/ws', SocketHandler)
|
||||||
static_handler = (r'/(.*)', tornado.web.StaticFileHandler,
|
static_handler = (r'/(.*)', tornado.web.StaticFileHandler,
|
||||||
{'path': 'templates'})
|
{'path': 'templates'})
|
||||||
local_handler = (r'/local/(.*)', tornado.web.StaticFileHandler,
|
local_handler = (r'/local/(.*)', tornado.web.StaticFileHandler,
|
||||||
{'path': ''})
|
{'path': ''})
|
||||||
|
|
||||||
handlers = [page_handler, socket_handler, static_handler, local_handler]
|
handlers = [page_handler, socket_handler, static_handler, local_handler]
|
||||||
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 Model', verbose=True,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
|
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
self.package_includes = set()
|
self.package_includes = set()
|
||||||
self.local_includes = set()
|
self.local_includes = set()
|
||||||
self.js_code = []
|
self.js_code = []
|
||||||
|
|
||||||
self.visualization_element = visualization_element
|
self.visualization_element = visualization_element
|
||||||
|
|
||||||
self.model_name = name
|
self.model_name = name
|
||||||
self.model = model
|
self.model = model
|
||||||
self.model_args = args
|
self.model_args = args
|
||||||
self.model_kwargs = kwargs
|
self.model_kwargs = kwargs
|
||||||
#self.reset_model()
|
#self.reset_model()
|
||||||
|
|
||||||
# Initializing the application itself:
|
# Initializing the application itself:
|
||||||
super().__init__(self.handlers, **self.settings)
|
super().__init__(self.handlers, **self.settings)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
def reset_model(self):
|
def reset_model(self):
|
||||||
self.model = self.model_cls(*self.model_args, **self.model_kwargs)
|
self.model = self.model_cls(*self.model_args, **self.model_kwargs)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def render_model(self):
|
def render_model(self):
|
||||||
return self.visualization_element.render(self.model)
|
return self.visualization_element.render(self.model)
|
||||||
|
|
||||||
def launch(self, port=None):
|
def launch(self, port=None):
|
||||||
""" Run the app. """
|
""" Run the app. """
|
||||||
|
|
||||||
if port is not None:
|
if port is not None:
|
||||||
self.port = port
|
self.port = port
|
||||||
url = 'http://127.0.0.1:{PORT}'.format(PORT=self.port)
|
url = 'http://127.0.0.1:{PORT}'.format(PORT=self.port)
|
||||||
print('Interface starting at {url}'.format(url=url))
|
print('Interface starting at {url}'.format(url=url))
|
||||||
self.listen(self.port)
|
self.listen(self.port)
|
||||||
# webbrowser.open(url)
|
# webbrowser.open(url)
|
||||||
tornado.ioloop.IOLoop.instance().start()
|
tornado.ioloop.IOLoop.instance().start()
|
||||||
|
@ -24,6 +24,10 @@ html, body {
|
|||||||
margin-right: 10px !important;
|
margin-right: 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav.navbar-right a {
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-menu > li > a:hover {
|
.dropdown-menu > li > a:hover {
|
||||||
background-color: #d4d3d3;
|
background-color: #d4d3d3;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -398,3 +402,9 @@ table#link-distance .max {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** MODAL **/
|
||||||
|
.modal-footer,
|
||||||
|
.modal-header {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
@ -97,40 +97,38 @@
|
|||||||
$('.config-item #properties').change(function() {
|
$('.config-item #properties').change(function() {
|
||||||
self.GraphVisualization.update_graph($(this).val(), slider.value(), function() {
|
self.GraphVisualization.update_graph($(this).val(), slider.value(), function() {
|
||||||
update_statistics_table();
|
update_statistics_table();
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
chart_nodes = c3.generate({
|
// Run simulation
|
||||||
size: {
|
$('#simulation_modal .btn-success').click(function() {
|
||||||
width: width_chart,
|
if ( !jQuery.isEmptyObject(run_simulation()) ) {
|
||||||
height: height_chart
|
self.GraphVisualization.reset();
|
||||||
},
|
$('#load').show().addClass('loader');;
|
||||||
data: {
|
_socket.send(run_simulation(), 'run_simulation');
|
||||||
columns: [],
|
$('.console').append('<br/>');
|
||||||
type: 'area-spline'
|
}
|
||||||
},
|
$('#simulation_modal').modal('hide')
|
||||||
axis: {
|
|
||||||
x: { label: 'Time' },
|
|
||||||
y: { label: 'Number of nodes' }
|
|
||||||
},
|
|
||||||
point: { show: false },
|
|
||||||
bindto: '#chart_nodes'
|
|
||||||
});
|
});
|
||||||
chart_attrs = c3.generate({
|
|
||||||
size: {
|
chart_nodes = create_chart(width_chart, height_chart, 'Time', 'Number of nodes', '#chart_nodes');
|
||||||
width: width_chart,
|
chart_attrs = create_chart(width_chart, height_chart, 'Time', 'Attributes', '#chart_attrs');
|
||||||
height: height_chart
|
|
||||||
},
|
// Fill modal window
|
||||||
data: {
|
$('#simulation_modal').on('show.bs.modal', function(e) {
|
||||||
columns: [],
|
var variables = run_simulation()
|
||||||
type: 'area-spline'
|
var x = 0,
|
||||||
},
|
row;
|
||||||
axis: {
|
for (var i in variables) {
|
||||||
x: { label: 'Time' },
|
if ( x % 2 === 0 ) row = $('<tr>').appendTo('#simulation_modal table tbody');
|
||||||
y: { label: 'Attributes' }
|
$('<td>').text(i).appendTo(row);
|
||||||
},
|
$('<td>').text(variables[i]).appendTo(row);
|
||||||
point: { show: false },
|
x++;
|
||||||
bindto: '#chart_attrs'
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#simulation_modal').on('hide.bs.modal', function(e) {
|
||||||
|
$('#simulation_modal table tbody').empty();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +188,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li><a href="#">Run simulation</a></li>
|
<li><a href="#" id="run_simulation" role="button">Run simulation</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
@ -319,6 +317,29 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" tabindex="-1" role="dialog" id="simulation_modal">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
<h4 class="modal-title">New simulation</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>You are going to run a new simulation, all charts and trials are going to be lost. A new ones will be available after the simulation.</p>
|
||||||
|
<p>Check your new environment variables for this simulation.</p>
|
||||||
|
<table class="table">
|
||||||
|
<thead><tr><th>Variable</th><th>Value</th><th>Variable</th><th>Value</th></tr></thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-success">Run</button>
|
||||||
|
</div>
|
||||||
|
</div><!-- /.modal-content -->
|
||||||
|
</div><!-- /.modal-dialog -->
|
||||||
|
</div><!-- /.modal -->
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -9,123 +9,128 @@ ws.onopen = function() {
|
|||||||
|
|
||||||
// Receive data from server
|
// Receive data from server
|
||||||
ws.onmessage = function(message) {
|
ws.onmessage = function(message) {
|
||||||
//console.log('Message received!');
|
//console.log('Message received!');
|
||||||
|
|
||||||
var msg = JSON.parse(message.data);
|
var msg = JSON.parse(message.data);
|
||||||
|
|
||||||
switch(msg['type']) {
|
switch(msg['type']) {
|
||||||
case 'trials':
|
case 'trials':
|
||||||
$('#load').removeClass('loader');
|
$('#load').removeClass('loader');
|
||||||
reset_trials();
|
reset_trials();
|
||||||
set_trials(msg['data']);
|
set_trials(msg['data']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'get_trial':
|
case 'get_trial':
|
||||||
console.log(msg['data']);
|
console.log(msg['data']);
|
||||||
GraphVisualization.import(convertJSON(msg['data']['graph']), msg['data']['models'], function() {
|
GraphVisualization.import(convertJSON(msg['data']['graph']), msg['data']['models'], function() {
|
||||||
$('#load').hide();
|
$('#load').hide();
|
||||||
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']['graph']);
|
set_timeline(msg['data']['graph']);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
reset_timeline();
|
reset_timeline();
|
||||||
set_timeline(msg['data']['graph']);
|
set_timeline(msg['data']['graph']);
|
||||||
});
|
});
|
||||||
$('#charts .chart').removeClass('no-data');
|
$('#charts .chart').removeClass('no-data');
|
||||||
set_chart_nodes(msg['data']['graph'], chart_nodes)
|
set_chart_nodes(msg['data']['graph'], chart_nodes)
|
||||||
set_chart_attrs(msg['data']['graph'], chart_attrs, $('.config-item #properties').val())
|
set_chart_attrs(msg['data']['graph'], chart_attrs, $('.config-item #properties').val())
|
||||||
break;
|
$('.config-item #properties').change(function() {
|
||||||
|
chart_attrs.destroy();
|
||||||
|
chart_attrs = create_chart(width_chart, height_chart, 'Time', 'Attributes', '#chart_attrs');
|
||||||
|
set_chart_attrs(msg['data']['graph'], chart_attrs, $('.config-item #properties').val())
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
case 'settings':
|
case 'settings':
|
||||||
$('#wrapper-settings').empty().removeClass('none');
|
$('#wrapper-settings').empty().removeClass('none');
|
||||||
initGUI(msg['data']);
|
initGUI(msg['data']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'error':
|
case 'error':
|
||||||
console.log(msg['error']);
|
console.log(msg['error']);
|
||||||
_socket.error(msg['error']);
|
_socket.error(msg['error']);
|
||||||
$('#load').removeClass('loader');
|
$('#load').removeClass('loader');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'log':
|
case 'log':
|
||||||
$('.console').append('$ ' + msg['logger'] + ': ' + msg['logging'] + '<br/>');
|
$('.console').append('$ ' + msg['logger'] + ': ' + msg['logging'] + '<br/>');
|
||||||
$('.console').animate({ scrollTop: $('.console')[0].scrollHeight }, 'slow');
|
$('.console').animate({ scrollTop: $('.console')[0].scrollHeight }, 'slow');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.log('Unexpected message!')
|
console.log('Unexpected message!')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _socket = {
|
var _socket = {
|
||||||
send: function(message, type) {
|
send: function(message, type) {
|
||||||
var json = {}
|
var json = {}
|
||||||
json['type'] = type
|
json['type'] = type
|
||||||
json['data'] = message
|
json['data'] = message
|
||||||
ws.send(JSON.stringify(json))
|
ws.send(JSON.stringify(json))
|
||||||
},
|
},
|
||||||
error: function(message) {
|
error: function(message) {
|
||||||
$('#error-message').text(message);
|
$('#error-message').text(message);
|
||||||
$('.alert.alert-danger').show();
|
$('.alert.alert-danger').show();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var set_trials = function(trials) {
|
var set_trials = function(trials) {
|
||||||
for ( i in trials ) {
|
for ( i in trials ) {
|
||||||
var list_item = $('<li>').appendTo('.dropdown#trials .dropdown-menu');
|
var list_item = $('<li>').appendTo('.dropdown#trials .dropdown-menu');
|
||||||
$('<a>').val(i).text(trials[i]).appendTo(list_item);
|
$('<a>').val(i).text(trials[i]).appendTo(list_item);
|
||||||
}
|
}
|
||||||
// Select 'trials'
|
// Select 'trials'
|
||||||
$('.dropdown#trials li a').click(function() {
|
$('.dropdown#trials li a').click(function() {
|
||||||
var a = $('.dropdown-toggle .caret');
|
var a = $('.dropdown-toggle .caret');
|
||||||
$('.dropdown-toggle').text($(this).text() + ' ').append(a);
|
$('.dropdown-toggle').text($(this).text() + ' ').append(a);
|
||||||
_socket.send($(this).val(), 'get_trial');
|
_socket.send($(this).val(), 'get_trial');
|
||||||
});
|
});
|
||||||
// Request first trial as default
|
// Request first trial as default
|
||||||
_socket.send(0, 'get_trial')
|
_socket.send(0, 'get_trial')
|
||||||
};
|
};
|
||||||
|
|
||||||
var reset_trials = function() {
|
var reset_trials = function() {
|
||||||
// 'Trials' selector
|
// 'Trials' selector
|
||||||
$('.dropdown-menu').empty();
|
$('.dropdown-menu').empty();
|
||||||
var a = $('.dropdown-toggle .caret');
|
var a = $('.dropdown-toggle .caret');
|
||||||
$('.dropdown-toggle').text('Trials ').append(a);
|
$('.dropdown-toggle').text('Trials ').append(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
var convertJSON = function(json) {
|
var convertJSON = function(json) {
|
||||||
json.links.forEach(function(link) {
|
json.links.forEach(function(link) {
|
||||||
link.source = json.nodes[link.source]
|
link.source = json.nodes[link.source]
|
||||||
link.target = json.nodes[link.target]
|
link.target = json.nodes[link.target]
|
||||||
});
|
});
|
||||||
// Fix spells for nodes
|
// Fix spells for nodes
|
||||||
json.nodes.forEach(function(node) {
|
json.nodes.forEach(function(node) {
|
||||||
for (i in node.spells) {
|
for (i in node.spells) {
|
||||||
if (node.spells[i][0] > node.spells[i][1]) {
|
if (node.spells[i][0] > node.spells[i][1]) {
|
||||||
aux = node.spells[i][0];
|
aux = node.spells[i][0];
|
||||||
node.spells[i][0] = node.spells[i][1];
|
node.spells[i][0] = node.spells[i][1];
|
||||||
node.spells[i][1] = aux;
|
node.spells[i][1] = aux;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
var update_statistics_table = function() {
|
var update_statistics_table = function() {
|
||||||
|
|
||||||
$('#percentTable tbody').empty()
|
$('#percentTable tbody').empty()
|
||||||
|
|
||||||
var statisticsSorted = Object.keys(self.GraphVisualization.statistics).sort(function(a,b) {
|
var statisticsSorted = Object.keys(self.GraphVisualization.statistics).sort(function(a,b) {
|
||||||
return self.GraphVisualization.statistics[b] - self.GraphVisualization.statistics[a];
|
return self.GraphVisualization.statistics[b] - self.GraphVisualization.statistics[a];
|
||||||
});
|
});
|
||||||
|
|
||||||
for ( var i in statisticsSorted ) {
|
for ( var i in statisticsSorted ) {
|
||||||
if ( i <= 5 ) {
|
if ( i <= 5 ) {
|
||||||
// Draw table
|
// Draw table
|
||||||
var appendTo = '#percentTable > tbody tr:nth-child(' + Number(parseInt(i) + 1) + ')';
|
var appendTo = '#percentTable > tbody tr:nth-child(' + Number(parseInt(i) + 1) + ')';
|
||||||
var propertyName = (statisticsSorted[i].includes('class')) ?
|
var propertyName = (statisticsSorted[i].includes('class')) ?
|
||||||
statisticsSorted[i].split('.').pop().split('\'')[0] : statisticsSorted[i];
|
statisticsSorted[i].split('.').pop().split('\'')[0] : statisticsSorted[i];
|
||||||
@ -134,12 +139,12 @@ var update_statistics_table = function() {
|
|||||||
$('<td>').css('background-color', self.GraphVisualization.color(statisticsSorted[i])).addClass('col-sm-1').appendTo(appendTo);
|
$('<td>').css('background-color', self.GraphVisualization.color(statisticsSorted[i])).addClass('col-sm-1').appendTo(appendTo);
|
||||||
$('<td>').addClass('text-left col-sm-4').text(self.GraphVisualization.statistics[statisticsSorted[i]] + ' %').appendTo(appendTo);
|
$('<td>').addClass('text-left col-sm-4').text(self.GraphVisualization.statistics[statisticsSorted[i]] + ' %').appendTo(appendTo);
|
||||||
$('<td>').addClass('text-right col-sm-6 property-name').text(propertyName).appendTo(appendTo);
|
$('<td>').addClass('text-right col-sm-6 property-name').text(propertyName).appendTo(appendTo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var set_configuration = function() {
|
var set_configuration = function() {
|
||||||
// Number of nodes and links info table
|
// Number of nodes and links info table
|
||||||
$('<tr>').appendTo('#info-graph > tbody');
|
$('<tr>').appendTo('#info-graph > tbody');
|
||||||
$('<th>').text('Nodes:').appendTo('#info-graph > tbody tr:nth-child(1)');
|
$('<th>').text('Nodes:').appendTo('#info-graph > tbody tr:nth-child(1)');
|
||||||
$('<th>').text(self.GraphVisualization.nodes).addClass('text-right').appendTo('#info-graph > tbody tr:nth-child(1)');
|
$('<th>').text(self.GraphVisualization.nodes).addClass('text-right').appendTo('#info-graph > tbody tr:nth-child(1)');
|
||||||
@ -151,31 +156,34 @@ var set_configuration = function() {
|
|||||||
// Options of 'Select'
|
// Options of 'Select'
|
||||||
for ( var i in self.GraphVisualization.model['dynamic'] ) {
|
for ( var i in self.GraphVisualization.model['dynamic'] ) {
|
||||||
$('<option>').val(self.GraphVisualization.model['dynamic'][i].title)
|
$('<option>').val(self.GraphVisualization.model['dynamic'][i].title)
|
||||||
.text(self.GraphVisualization.model['dynamic'][i].title).appendTo('#properties-dynamic');
|
.text(self.GraphVisualization.model['dynamic'][i].title).appendTo('#properties-dynamic');
|
||||||
}
|
}
|
||||||
for ( var i in self.GraphVisualization.model['static'] ) {
|
for ( var i in self.GraphVisualization.model['static'] ) {
|
||||||
$('<option>').val(self.GraphVisualization.model['static'][i].title)
|
$('<option>').val(self.GraphVisualization.model['static'][i].title)
|
||||||
.text(self.GraphVisualization.model['static'][i].title).appendTo('#properties-static');
|
.text(self.GraphVisualization.model['static'][i].title).appendTo('#properties-static');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide optgroups if they are empty
|
// Hide optgroups if they are empty
|
||||||
if ( $('#properties-dynamic').children().length === 0 ) $('#properties-dynamic').hide();
|
if ( $('#properties-dynamic').children().length === 0 ) $('#properties-dynamic').hide();
|
||||||
if ( $('#properties-static').children().length === 0 ) $('#properties-static').hide();
|
if ( $('#properties-static').children().length === 0 ) $('#properties-static').hide();
|
||||||
|
|
||||||
update_statistics_table();
|
update_statistics_table();
|
||||||
|
|
||||||
// Enable 'Link Distance' slider
|
// Enable 'Link Distance' slider
|
||||||
$('#link-distance-slider').slider('enable').on('change', function(value) {
|
$('#link-distance-slider').slider('enable').on('change', function(value) {
|
||||||
self.GraphVisualization.set_link_distance(value.value.newValue);
|
self.GraphVisualization.set_link_distance(value.value.newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Enable 'Run configuration' button
|
||||||
|
$('#run_simulation').attr('data-toggle', 'modal').attr('data-target', '#simulation_modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
var reset_configuration = function() {
|
var reset_configuration = function() {
|
||||||
// Information table about the graph
|
// Information table about the graph
|
||||||
$('#info-graph > tbody').empty();
|
$('#info-graph > tbody').empty();
|
||||||
|
|
||||||
// 'Select' for properties
|
// 'Select' for properties
|
||||||
$('#properties-dynamic').empty().show();
|
$('#properties-dynamic').empty().show();
|
||||||
$('#properties-static').empty().show();
|
$('#properties-static').empty().show();
|
||||||
|
|
||||||
// 'Link Distance' slider
|
// 'Link Distance' slider
|
||||||
@ -183,35 +191,35 @@ var reset_configuration = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var set_timeline = function(graph) {
|
var set_timeline = function(graph) {
|
||||||
// 'Timeline' slider
|
// 'Timeline' slider
|
||||||
var [min, max] = get_limits(graph);
|
var [min, max] = get_limits(graph);
|
||||||
|
|
||||||
var stepUnix = (max - min) / 200;
|
var stepUnix = (max - min) / 200;
|
||||||
var minUnix = (min !== Math.min()) ? min : 0;
|
var minUnix = (min !== Math.min()) ? min : 0;
|
||||||
var maxUnix = (max !== Math.max()) ? max : minUnix + 20;
|
var maxUnix = (max !== Math.max()) ? max : minUnix + 20;
|
||||||
|
|
||||||
slider = d3.slider();
|
slider = d3.slider();
|
||||||
d3.select('#slider3').attr('width', width).call(
|
d3.select('#slider3').attr('width', width).call(
|
||||||
slider.axis(true).min(minUnix).max(maxUnix).step(stepUnix).value(maxUnix)
|
slider.axis(true).min(minUnix).max(maxUnix).step(stepUnix).value(maxUnix)
|
||||||
.on('slide', function(evt, value) {
|
.on('slide', function(evt, value) {
|
||||||
self.GraphVisualization.update_graph($('.config-item #properties').val(), value, function() {
|
self.GraphVisualization.update_graph($('.config-item #properties').val(), value, function() {
|
||||||
update_statistics_table();
|
update_statistics_table();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 'Speed' slider
|
// 'Speed' slider
|
||||||
$('#speed-slider').slider('enable').on('change', function(value) {
|
$('#speed-slider').slider('enable').on('change', function(value) {
|
||||||
speed = value.value.newValue;
|
speed = value.value.newValue;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 'Play'
|
// Button 'Play'
|
||||||
$('button#button_play').on('click', function() {
|
$('button#button_play').on('click', function() {
|
||||||
|
|
||||||
$('button#button_play').addClass('pressed').prop("disabled", true);
|
$('button#button_play').addClass('pressed').prop("disabled", true);
|
||||||
$('#speed-slider').slider('disable');
|
$('#speed-slider').slider('disable');
|
||||||
@ -220,8 +228,8 @@ var set_timeline = function(graph) {
|
|||||||
if (slider.value() >= maxUnix) {
|
if (slider.value() >= maxUnix) {
|
||||||
slider.value(minUnix);
|
slider.value(minUnix);
|
||||||
self.GraphVisualization.update_graph($('.config-item #properties').val(), slider.value(), function() {
|
self.GraphVisualization.update_graph($('.config-item #properties').val(), slider.value(), function() {
|
||||||
update_statistics_table();
|
update_statistics_table();
|
||||||
});
|
});
|
||||||
setTimeout(player, 1000);
|
setTimeout(player, 1000);
|
||||||
} else {
|
} else {
|
||||||
player();
|
player();
|
||||||
@ -231,9 +239,9 @@ var set_timeline = function(graph) {
|
|||||||
function player() {
|
function player() {
|
||||||
clearInterval(play);
|
clearInterval(play);
|
||||||
play = setInterval(function() {
|
play = setInterval(function() {
|
||||||
self.GraphVisualization.update_graph($('.config-item #properties').val(), slider.value(), function() {
|
self.GraphVisualization.update_graph($('.config-item #properties').val(), slider.value(), function() {
|
||||||
update_statistics_table();
|
update_statistics_table();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (slider.value() + slider.step() >= maxUnix) {
|
if (slider.value() + slider.step() >= maxUnix) {
|
||||||
slider.value(maxUnix);
|
slider.value(maxUnix);
|
||||||
@ -250,93 +258,130 @@ var set_timeline = function(graph) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 'Pause'
|
// Button 'Pause'
|
||||||
$('button#button_pause').on('click', function() {
|
$('button#button_pause').on('click', function() {
|
||||||
clearInterval(play);
|
clearInterval(play);
|
||||||
slider.step(stepUnix);
|
slider.step(stepUnix);
|
||||||
$('button#button_play').removeClass('pressed').prop("disabled", false);
|
$('button#button_play').removeClass('pressed').prop("disabled", false);
|
||||||
$('#speed-slider').slider('enable');
|
$('#speed-slider').slider('enable');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Button 'Zoom to Fit'
|
// Button 'Zoom to Fit'
|
||||||
$('button#button_zoomFit').click(function() { self.GraphVisualization.fit(); });
|
$('button#button_zoomFit').click(function() { self.GraphVisualization.fit(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
var reset_timeline = function() {
|
var reset_timeline = function() {
|
||||||
// 'Timeline' slider
|
// 'Timeline' slider
|
||||||
$('#slider3').html('');
|
$('#slider3').html('');
|
||||||
|
|
||||||
// 'Speed' slider
|
// 'Speed' slider
|
||||||
$('#speed-slider').slider('disable').slider('setValue', 1000);
|
$('#speed-slider').slider('disable').slider('setValue', 1000);
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
clearInterval(play);
|
clearInterval(play);
|
||||||
$('button#button_play').off().removeClass('pressed').prop("disabled", false);
|
$('button#button_play').off().removeClass('pressed').prop("disabled", false);
|
||||||
$('button#button_pause').off();
|
$('button#button_pause').off();
|
||||||
$('button#button_zoomFit').off();
|
$('button#button_zoomFit').off();
|
||||||
}
|
}
|
||||||
|
|
||||||
var get_limits = function(graph) {
|
var get_limits = function(graph) {
|
||||||
var max = Math.max();
|
var max = Math.max();
|
||||||
var min = Math.min()
|
var min = Math.min()
|
||||||
graph.links.forEach(function(link) {
|
graph.links.forEach(function(link) {
|
||||||
if (link.end > max) max = link.end
|
if (link.end > max) max = link.end
|
||||||
if (link.start > max) max = link.start
|
if (link.start > max) max = link.start
|
||||||
if (link.end < min) min = link.end
|
if (link.end < min) min = link.end
|
||||||
if (link.start < min) min = link.start
|
if (link.start < min) min = link.start
|
||||||
});
|
});
|
||||||
graph.nodes.forEach(function(node) {
|
graph.nodes.forEach(function(node) {
|
||||||
for (property in node) {
|
for (property in node) {
|
||||||
if ( Array.isArray(node[property]) ) {
|
if ( Array.isArray(node[property]) ) {
|
||||||
|
|
||||||
for (i in node[property]) {
|
for (i in node[property]) {
|
||||||
for (j in node[property][i]) {
|
for (j in node[property][i]) {
|
||||||
if (node[property][i][j] > max) max = node[property][i][j];
|
if (node[property][i][j] > max) max = node[property][i][j];
|
||||||
if (node[property][i][j] < min) min = node[property][i][j];
|
if (node[property][i][j] < min) min = node[property][i][j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return [min, max];
|
return [min, max];
|
||||||
}
|
}
|
||||||
|
|
||||||
var set_chart_nodes = function(graph, chart) {
|
var set_chart_nodes = function(graph, chart) {
|
||||||
var [min, max] = get_limits(graph);
|
var [min, max] = get_limits(graph);
|
||||||
var data = ['nodes']
|
var data = ['nodes']
|
||||||
for (var i = min; i <= max; i++) {
|
for (var i = min; i <= max; i++) {
|
||||||
data.push(this.GraphVisualization.get_nodes(i));
|
data.push(this.GraphVisualization.get_nodes(i));
|
||||||
}
|
}
|
||||||
chart.load({
|
chart.load({
|
||||||
unload: true,
|
unload: true,
|
||||||
columns: [data]
|
columns: [data]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var set_chart_attrs = function(graph, chart, property) {
|
var set_chart_attrs = function(graph, chart, property) {
|
||||||
var [min, max] = get_limits(graph);
|
var [min, max] = get_limits(graph);
|
||||||
var data_tmp = {}
|
var data_tmp = {}
|
||||||
for (var i = min; i <= max; i++) {
|
for (var i = min; i <= max; i++) {
|
||||||
this.GraphVisualization.get_attributes(property, i, function(object) {
|
this.GraphVisualization.get_attributes(property, i, function(object) {
|
||||||
for (var value in object) {
|
for (var value in object) {
|
||||||
if (!data_tmp[value]) {
|
if (!data_tmp[value]) {
|
||||||
var time = 0
|
var time = 0
|
||||||
for (var done in data_tmp)
|
for (var done in data_tmp)
|
||||||
time = (data_tmp[done].length > time) ? data_tmp[done].length - 1 : time
|
time = (data_tmp[done].length > time) ? data_tmp[done].length - 1 : time
|
||||||
data_tmp[value] = Array(time).fill(0);
|
data_tmp[value] = Array(time).fill(0);
|
||||||
}
|
}
|
||||||
data_tmp[value].push(object[value]);
|
data_tmp[value].push(object[value]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var data = $.map(data_tmp, function(value, index) {
|
var data = $.map(data_tmp, function(value, index) {
|
||||||
value.splice(0,0,index);
|
value.splice(0,0,index);
|
||||||
return [value];
|
return [value];
|
||||||
});
|
});
|
||||||
chart.load({
|
chart.load({
|
||||||
unload: true,
|
unload: true,
|
||||||
columns: data
|
columns: data
|
||||||
});
|
});
|
||||||
chart.axis.labels({y: property});
|
chart.axis.labels({y: property});
|
||||||
|
}
|
||||||
|
|
||||||
|
var create_chart = function(width, height, label_x, label_y, bind_to) {
|
||||||
|
return c3.generate({
|
||||||
|
size: {
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
columns: [],
|
||||||
|
type: 'area-spline'
|
||||||
|
},
|
||||||
|
axis: {
|
||||||
|
x: { label: label_x },
|
||||||
|
y: { label: label_y }
|
||||||
|
},
|
||||||
|
point: { show: false },
|
||||||
|
bindto: bind_to
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var run_simulation = function() {
|
||||||
|
var environment_variables = {}
|
||||||
|
$('#wrapper-settings input').each(function() {
|
||||||
|
switch(this.type) {
|
||||||
|
case 'text':
|
||||||
|
environment_variables[this.id] = Number(this.value);
|
||||||
|
break;
|
||||||
|
case 'checkbox':
|
||||||
|
environment_variables[this.id] = ($(this).is(':checked')) ? true : false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
return environment_variables;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
// Add model parameters that can be edited prior to a model run
|
// Add model parameters that can be edited prior to a model run
|
||||||
var initGUI = function(model_params) {
|
var initGUI = function(model_params) {
|
||||||
|
|
||||||
var onSubmitCallback = function(param_name, value) {
|
|
||||||
// SEND SOCKET REQUEST
|
|
||||||
};
|
|
||||||
|
|
||||||
var addBooleanInput = function(name, value) {
|
var addBooleanInput = function(name, value) {
|
||||||
var checked = (value) ? 'checked' : 'value';
|
var checked = (value) ? 'checked' : 'value';
|
||||||
|
|
||||||
@ -79,14 +75,14 @@ var initGUI = function(model_params) {
|
|||||||
var param_str = String(option);
|
var param_str = String(option);
|
||||||
|
|
||||||
switch (model_params[option]['type']) {
|
switch (model_params[option]['type']) {
|
||||||
case "boolean":
|
case 'boolean':
|
||||||
addBooleanInput(model_params[option]['label'], model_params[option]['value']);
|
addBooleanInput(model_params[option]['label'], model_params[option]['value']);
|
||||||
break;
|
break;
|
||||||
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 "object":
|
default:
|
||||||
addParamInput(param_str, model_params[option]); // catch-all for params that use Option class
|
console.log('Input type not defined!');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,17 +294,17 @@
|
|||||||
function importJSON(json, attributes, callback) {
|
function importJSON(json, attributes, callback) {
|
||||||
reset()
|
reset()
|
||||||
graph = json;
|
graph = json;
|
||||||
model = attributes
|
model = attributes;
|
||||||
|
|
||||||
// Create the graph itself
|
// Create the graph itself
|
||||||
Graph();
|
Graph();
|
||||||
|
|
||||||
self.GraphVisualization.nodes = graph.nodes.length;
|
self.GraphVisualization.nodes = graph.nodes.length;
|
||||||
self.GraphVisualization.links = graph.links.length;
|
self.GraphVisualization.links = graph.links.length;
|
||||||
self.GraphVisualization.model = model
|
self.GraphVisualization.model = model;
|
||||||
|
|
||||||
// Draw graph with default property and time for the first time
|
// Draw graph with default property and time for the first time
|
||||||
update_data(model.dynamic[0].title, 0)
|
update_data(model.dynamic[0].title, 0);
|
||||||
|
|
||||||
if (callback) { callback(); }
|
if (callback) { callback(); }
|
||||||
}
|
}
|
||||||
|
@ -7,63 +7,63 @@ from xml.etree import ElementTree
|
|||||||
|
|
||||||
class Model():
|
class Model():
|
||||||
|
|
||||||
def __init__(self, dump=True, dir_path='output'):
|
def __init__(self, dump=True, dir_path='output'):
|
||||||
self.name = 'soil'
|
self.name = 'soil'
|
||||||
self.dump = dump
|
self.dump = dump
|
||||||
self.dir_path = dir_path
|
self.dir_path = dir_path
|
||||||
|
|
||||||
def run(self, config):
|
def run(self, config):
|
||||||
name = config['name']
|
name = config['name']
|
||||||
print('Using config(s): {name}'.format(name=name))
|
print('Using config(s): {name}'.format(name=name))
|
||||||
|
|
||||||
sim = SoilSimulation(**config)
|
sim = SoilSimulation(**config)
|
||||||
sim.dir_path = os.path.join(self.dir_path, name)
|
sim.dir_path = os.path.join(self.dir_path, name)
|
||||||
sim.dump = self.dump
|
sim.dump = self.dump
|
||||||
|
|
||||||
print('Dumping results to {} : {}'.format(sim.dir_path, sim.dump))
|
print('Dumping results to {} : {}'.format(sim.dir_path, sim.dump))
|
||||||
|
|
||||||
sim.run_simulation()
|
sim.run_simulation()
|
||||||
|
|
||||||
|
|
||||||
def get_trial(self, name, trial):
|
def get_trial(self, name, trial):
|
||||||
graph = nx.read_gexf(os.path.join(self.dir_path, name, '{}_trial_{}.gexf'.format(name, trial)))
|
graph = nx.read_gexf(os.path.join(self.dir_path, name, '{}_trial_{}.gexf'.format(name, trial)))
|
||||||
|
|
||||||
attributes = self.get_attributes(os.path.join(self.dir_path, name, '{}_trial_{}.gexf'.format(name, trial)))
|
attributes = self.get_attributes(os.path.join(self.dir_path, name, '{}_trial_{}.gexf'.format(name, trial)))
|
||||||
json = {}
|
json = {}
|
||||||
json['graph'] = nx.node_link_data(graph)
|
json['graph'] = nx.node_link_data(graph)
|
||||||
json['models'] = attributes
|
json['models'] = attributes
|
||||||
return json
|
return json
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_attributes(self, path_gexf):
|
def get_attributes(self, path_gexf):
|
||||||
attributes = {}
|
attributes = {}
|
||||||
tree = ElementTree.parse(path_gexf)
|
tree = ElementTree.parse(path_gexf)
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
|
|
||||||
ns = { 'gexf': 'http://www.gexf.net/1.2draft' }
|
ns = { 'gexf': 'http://www.gexf.net/1.2draft' }
|
||||||
|
|
||||||
for mode in root[0].findall('gexf:attributes', ns):
|
for mode in root[0].findall('gexf:attributes', ns):
|
||||||
attributes[mode.attrib['mode']] = []
|
attributes[mode.attrib['mode']] = []
|
||||||
for attribute in mode:
|
for attribute in mode:
|
||||||
values = {
|
values = {
|
||||||
'id' : attribute.attrib['id'],
|
'id' : attribute.attrib['id'],
|
||||||
'title' : attribute.attrib['title'],
|
'title' : attribute.attrib['title'],
|
||||||
'type' : attribute.attrib['type']
|
'type' : attribute.attrib['type']
|
||||||
}
|
}
|
||||||
attributes[mode.attrib['mode']].append(values)
|
attributes[mode.attrib['mode']].append(values)
|
||||||
|
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
|
|
||||||
class GraphVisualization(VisualizationElement):
|
class GraphVisualization(VisualizationElement):
|
||||||
package_includes = []
|
package_includes = []
|
||||||
|
|
||||||
# TODO: esta por definir todos los ajustes de simulacion
|
# TODO: esta por definir todos los ajustes de simulacion
|
||||||
def __init__(self, params=None):
|
def __init__(self, params=None):
|
||||||
new_element = ("new funcion()")
|
new_element = ("new funcion()")
|
||||||
self.js_code = "elements.push(" + new_element + ");"
|
self.js_code = "elements.push(" + new_element + ");"
|
||||||
|
|
||||||
def render(self, model):
|
def render(self, model):
|
||||||
pass
|
pass
|
||||||
|
Loading…
Reference in New Issue
Block a user