Source code for simphony_mayavi.plugins.run_and_animate
import logging
from mayavi.mlab import animate
logger = logging.getLogger(__name__)
[docs]class RunAndAnimate(object):
def __init__(self, engine, mayavi_engine):
""" Standalone non-GUI based controller for running a Simphony
Modeling Engine and animating the CUDS dataset in Mayavi.
Precondition: The required CUDS datasets are already visible
in the Mayavi scene(s)
Parameters
----------
engine : ABCModelingEngine
Simphony Modeling Engine
mayavi_engine : mayavi.api.Engine
for retrieving scenes and visible datasets
"""
self.engine = engine
self.mayavi_engine = mayavi_engine
self._animator = None
[docs] def animate(self, number_of_runs, delay=None, ui=False,
update_all_scenes=False):
""" Run the modeling engine, and animate the scene.
If there is no source in the scene or none of the sources
belongs to the selected Engine ``engine``, a RuntimeError
is raised.
Parameters
----------
number_of_runs : int
the number of times the engine.run() is called
delay : int
delay between each run.
If None, use previous setting or the Mayavi's default (500)
ui : bool
whether an UI is shown, default is False
update_all_scenes : bool
whether all scenes are updated, default is False: i.e. only
the current scene is updated
Raises
------
RuntimeError
if nothing in scene(s) belongs to ``engine``
"""
if self.mayavi_engine is None:
message = "Mayavi engine is not defined in the manager"
raise RuntimeError(message)
if (not hasattr(self.mayavi_engine, "scenes") or
len(self.mayavi_engine.scenes) == 0):
message = "No active scene. Engine is not run"
raise RuntimeError(message)
if update_all_scenes:
get_sources_func = self._get_all_sources
else:
get_sources_func = self._get_current_sources
sources = get_sources_func()
if len(sources) == 0:
message = ("Nothing in scene belongs to the Engine.\n"
"Engine is not run.")
raise RuntimeError(message)
# remember the last delay being set
if delay is None:
if self._animator:
delay = self._animator.delay
else:
delay = 500
# close the old window and start a new one
# FIXME: there should be a better way
if (self._animator and self._animator.ui and
not self._animator.ui.destroyed):
self._animator.close()
@animate(delay=delay, ui=ui)
def anim():
# keep a reference to the engine being run
# if the engine is changed during animation
# the animation would terminate
engine_on_start = self.engine
for _ in xrange(number_of_runs):
if self.engine is not engine_on_start:
message = "Engine changed while animating. Stop running"
logger.warning(message)
break
self.engine.run()
self._update_sources(sources)
self.mayavi_engine.current_scene.render()
yield
self._animator = anim()
# -------------------------------------------------
# Private methods
# -------------------------------------------------
def _update_sources(self, sources):
""" Update multiple sources in scene"""
for source in sources:
source.update()
def _get_current_sources(self):
""" Return the current scene's sources that belong
to this manager's modeling engine
Note that this is not a Trait Property getter
Returns
-------
sources : set of EngineSource
"""
sources = self.mayavi_engine.current_scene.children
return {source for source in sources
if (hasattr(source, "engine") and
source.engine == self.engine)}
def _get_all_sources(self):
""" Return sources from all the scenes and that the sources
belong to this manager's modeling engine
Returns
-------
sources : set of EngineSource
"""
sources = {source
for scene in self.mayavi_engine.scenes
for source in scene.children
if (hasattr(source, "engine") and
source.engine == self.engine)}
return sources