diff --git a/server.py b/server.py
index d649965..a8d0417 100644
--- a/server.py
+++ b/server.py
@@ -19,7 +19,7 @@ logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
class VisualizationElement:
- """
+ """
Defines an element of the visualization.
Attributes:
package_includes: A list of external JavaScript files to include that
@@ -32,190 +32,197 @@ class VisualizationElement:
to the client.
"""
- package_includes = []
- local_includes = []
- js_code = ''
- render_args = {}
+ package_includes = []
+ local_includes = []
+ js_code = ''
+ render_args = {}
- def __init__(self):
- pass
+ def __init__(self):
+ pass
- def render(self, model):
- return 'VisualizationElement goes here.'
+ def render(self, model):
+ return 'VisualizationElement goes here.'
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):
- self.render('index.html', port=self.application.port,
- model_name=self.application.model_name,
- package_includes=self.application.package_includes,
- local_includes=self.application.local_includes,
- scripts=self.application.js_code)
+ def get(self):
+ self.render('index.html', port=self.application.port,
+ model_name=self.application.model_name,
+ package_includes=self.application.package_includes,
+ local_includes=self.application.local_includes,
+ scripts=self.application.js_code)
class SocketHandler(tornado.websocket.WebSocketHandler):
- def open(self):
- if self.application.verbose:
- logger.info('Socket opened!')
-
+ def open(self):
+ if self.application.verbose:
+ logger.info('Socket opened!')
- def check_origin(self, origin):
- return True
+ def check_origin(self, origin):
+ return True
- def on_message(self, message):
- """ Receiving a message from the websocket, parse, and act accordingly. """
+ def on_message(self, message):
+ """ 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:
- print(msg['data'])
+ if self.application.verbose:
+ print(msg['data'])
- config = list(yaml.load_all(msg['data']))
+ self.config = list(yaml.load_all(msg['data']))
- if len(config) > 1:
- error = 'Please, provide only one configuration.'
- if self.application.verbose:
- logger.error(error)
- self.write_message({'type': 'error',
- 'error': error})
- return
- else:
- config = config[0]
- self.send_log('INFO.soil', 'Using config: {name}'.format(name=config['name']))
+ if len(self.config) > 1:
+ error = 'Please, provide only one configuration.'
+ if self.application.verbose:
+ logger.error(error)
+ self.write_message({'type': 'error',
+ 'error': error})
+ return
+ else:
+ self.config = self.config[0]
+ self.send_log('INFO.soil', 'Using config: {name}'.format(name=self.config['name']))
- self.name = config['name']
+ self.name = self.config['name']
- settings = []
- 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'
+ self.run_simulation()
- settings.append({
- 'label': key,
- 'type': setting_type,
- 'value': config['environment_params'][key]
- })
+ 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]) == bool:
+ setting_type = 'boolean'
+ else:
+ setting_type = 'undefined'
- self.write_message({'type': 'settings',
- 'data': settings})
-
- # Run simulation and capture logs
- with self.logging(self.application.model.name):
- self.application.model.run(config)
+ settings.append({
+ 'label': key,
+ 'type': setting_type,
+ 'value': self.config['environment_params'][key]
+ })
- trials = []
- for i in range(config['num_trials']):
- trials.append('{}_trial_{}'.format(self.name, i))
- self.write_message({'type': 'trials',
- 'data': trials })
+ self.write_message({'type': 'settings',
+ 'data': settings})
- elif msg['type'] == 'get_trial':
- if self.application.verbose:
- logger.info('Trial {} requested!'.format(msg['data']))
- self.send_log('INFO.user', 'Trial {} requested!'.format(msg['data']))
- self.write_message({'type': 'get_trial',
- 'data': self.application.model.get_trial(self.name, msg['data']) })
+ elif msg['type'] == 'get_trial':
+ if self.application.verbose:
+ logger.info('Trial {} requested!'.format(msg['data']))
+ self.send_log('INFO.user', 'Trial {} requested!'.format(msg['data']))
+ self.write_message({'type': 'get_trial',
+ 'data': self.application.model.get_trial(self.name, msg['data']) })
- else:
- if self.application.verbose:
- logger.info('Unexpected message!')
+ elif msg['type'] == 'run_simulation':
+ self.send_log('INFO.soil', 'Running new simulation for {name}'.format(name=self.config['name']))
+ self.config['environment_params'] = msg['data']
+ self.run_simulation()
- def update_logging(self):
- 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()
+ else:
+ if self.application.verbose:
+ logger.info('Unexpected message!')
- def on_close(self):
- logger.info('Socket closed!')
+ def update_logging(self):
+ 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):
- self.write_message({'type': 'log',
- 'logger': logger,
- 'logging': logging })
+ def on_close(self):
+ logger.info('Socket closed!')
- @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
+ def send_log(self, logger, logging):
+ self.write_message({'type': 'log',
+ 'logger': logger,
+ 'logging': logging })
- self.log_capture_string.close()
- self.logger_application.removeHandler(ch)
- self.capture_logging = False
- return self.capture_logging
-
+ def run_simulation(self):
+ # Run simulation and capture logs
+ with self.logging(self.application.model.name):
+ 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):
- """ Main visualization application. """
+ """ Main visualization application. """
- portrayal_method = None
- port = 8001
- model_args = ()
- model_kwargs = {}
- page_handler = (r'/', PageHandler)
- socket_handler = (r'/ws', SocketHandler)
- static_handler = (r'/(.*)', tornado.web.StaticFileHandler,
- {'path': 'templates'})
- local_handler = (r'/local/(.*)', tornado.web.StaticFileHandler,
- {'path': ''})
+ portrayal_method = None
+ port = 8001
+ model_args = ()
+ model_kwargs = {}
+ page_handler = (r'/', PageHandler)
+ socket_handler = (r'/ws', SocketHandler)
+ static_handler = (r'/(.*)', tornado.web.StaticFileHandler,
+ {'path': 'templates'})
+ local_handler = (r'/local/(.*)', tornado.web.StaticFileHandler,
+ {'path': ''})
- handlers = [page_handler, socket_handler, static_handler, local_handler]
- settings = {'debug': True,
- 'template_path': os.path.dirname(__file__) + '/templates'}
+ handlers = [page_handler, socket_handler, static_handler, local_handler]
+ settings = {'debug': True,
+ 'template_path': os.path.dirname(__file__) + '/templates'}
- def __init__(self, model, visualization_element, name='SOIL Model', verbose=True,
- *args, **kwargs):
-
- self.verbose = verbose
- self.package_includes = set()
- self.local_includes = set()
- self.js_code = []
-
- self.visualization_element = visualization_element
+ def __init__(self, model, visualization_element, name='SOIL Model', verbose=True,
+ *args, **kwargs):
+
+ self.verbose = verbose
+ self.package_includes = set()
+ self.local_includes = set()
+ self.js_code = []
+
+ self.visualization_element = visualization_element
- self.model_name = name
- self.model = model
- self.model_args = args
- self.model_kwargs = kwargs
- #self.reset_model()
+ self.model_name = name
+ self.model = model
+ self.model_args = args
+ self.model_kwargs = kwargs
+ #self.reset_model()
- # Initializing the application itself:
- super().__init__(self.handlers, **self.settings)
+ # Initializing the application itself:
+ super().__init__(self.handlers, **self.settings)
- '''
- def reset_model(self):
- self.model = self.model_cls(*self.model_args, **self.model_kwargs)
- '''
+ '''
+ def reset_model(self):
+ self.model = self.model_cls(*self.model_args, **self.model_kwargs)
+ '''
- def render_model(self):
- return self.visualization_element.render(self.model)
+ def render_model(self):
+ return self.visualization_element.render(self.model)
- def launch(self, port=None):
- """ Run the app. """
-
- if port is not None:
- self.port = port
- url = 'http://127.0.0.1:{PORT}'.format(PORT=self.port)
- print('Interface starting at {url}'.format(url=url))
- self.listen(self.port)
- # webbrowser.open(url)
- tornado.ioloop.IOLoop.instance().start()
+ def launch(self, port=None):
+ """ Run the app. """
+
+ if port is not None:
+ self.port = port
+ url = 'http://127.0.0.1:{PORT}'.format(PORT=self.port)
+ print('Interface starting at {url}'.format(url=url))
+ self.listen(self.port)
+ # webbrowser.open(url)
+ tornado.ioloop.IOLoop.instance().start()
diff --git a/templates/css/main.css b/templates/css/main.css
index e329697..6168a65 100644
--- a/templates/css/main.css
+++ b/templates/css/main.css
@@ -24,6 +24,10 @@ html, body {
margin-right: 10px !important;
}
+.nav.navbar-right a {
+ outline: none !important;
+}
+
.dropdown-menu > li > a:hover {
background-color: #d4d3d3;
cursor: pointer;
@@ -398,3 +402,9 @@ table#link-distance .max {
justify-content: center;
align-items: center;
}
+
+/** MODAL **/
+.modal-footer,
+.modal-header {
+ border: none !important;
+}
diff --git a/templates/index.html b/templates/index.html
index c81c55d..f51c8eb 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -97,40 +97,38 @@
$('.config-item #properties').change(function() {
self.GraphVisualization.update_graph($(this).val(), slider.value(), function() {
update_statistics_table();
- })
+ });
});
- chart_nodes = c3.generate({
- size: {
- width: width_chart,
- height: height_chart
- },
- data: {
- columns: [],
- type: 'area-spline'
- },
- axis: {
- x: { label: 'Time' },
- y: { label: 'Number of nodes' }
- },
- point: { show: false },
- bindto: '#chart_nodes'
+ // Run simulation
+ $('#simulation_modal .btn-success').click(function() {
+ if ( !jQuery.isEmptyObject(run_simulation()) ) {
+ self.GraphVisualization.reset();
+ $('#load').show().addClass('loader');;
+ _socket.send(run_simulation(), 'run_simulation');
+ $('.console').append('
');
+ }
+ $('#simulation_modal').modal('hide')
});
- chart_attrs = c3.generate({
- size: {
- width: width_chart,
- height: height_chart
- },
- data: {
- columns: [],
- type: 'area-spline'
- },
- axis: {
- x: { label: 'Time' },
- y: { label: 'Attributes' }
- },
- point: { show: false },
- bindto: '#chart_attrs'
+
+ chart_nodes = create_chart(width_chart, height_chart, 'Time', 'Number of nodes', '#chart_nodes');
+ chart_attrs = create_chart(width_chart, height_chart, 'Time', 'Attributes', '#chart_attrs');
+
+ // Fill modal window
+ $('#simulation_modal').on('show.bs.modal', function(e) {
+ var variables = run_simulation()
+ var x = 0,
+ row;
+ for (var i in variables) {
+ if ( x % 2 === 0 ) row = $('