Skip to content

Commit

Permalink
Merge pull request #197 from prabhuramachandran/misc-viewer-improvements
Browse files Browse the repository at this point in the history
Misc viewer improvements
  • Loading branch information
prabhuramachandran committed Mar 28, 2019
2 parents 82773de + 84a0705 commit b166e00
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 15 deletions.
20 changes: 14 additions & 6 deletions docs/source/tutorial/circular_patch_simple.rst
Original file line number Diff line number Diff line change
Expand Up @@ -370,22 +370,22 @@ interpreter with a few useful objects available. These are::
>>> dir()
['__builtins__', '__doc__', '__name__', 'interpolator', 'mlab',
'particle_arrays', 'scene', 'self', 'viewer']
>>> len(particle_arrays)
1
>>> particle_arrays[0].name
>>> particle_arrays['fluid'].name
'fluid'

The ``particle_arrays`` object is a list of **ParticleArrayHelpers** which is
available in :py:class:`pysph.tools.mayavi_viewer.ParticleArrayHelper`. The
The ``particle_arrays`` object is a dictionary of **ParticleArrayHelpers**
which is available in
:py:class:`pysph.tools.mayavi_viewer.ParticleArrayHelper`. The
``interpolator`` is an instance of
:py:class:`pysph.tools.mayavi_viewer.InterpolatorView` that is used by the
viewer. The other objects can be used to script the user interface if desired.
Note that the ``particle_arrays`` can be indexed by array name or index.

Here is an example of scripting the viewer. Let us say we have two particle
arrays, `'boundary'` and `'fluid'` in that order. Let us say, we wish to make
the boundary translucent, then we can write the following::

b = particle_arrays[0]
b = particle_arrays['boundary']
b.plot.actor.property.opacity = 0.2

This does require some knowledge of Mayavi_ and scripting with it. The `plot`
Expand All @@ -394,6 +394,14 @@ a `Glyph` instance from Mayavi_. It is useful to use the `record feature
<http://docs.enthought.com/mayavi/mayavi/mlab_changing_object_looks.html#changing-object-properties-interactively>`_
of Mayavi to learn more about how best to script the view.

The viewer will always look for a ``mayavi_config.py`` script inside the
output directory to setup the visualization parameters. This file can be
created by overriding the :py:class:`pysph.solver.application.Application`
object's ``customize_output`` method. See the `dam break 3d
<https://github.com/pypr/pysph/blob/master/pysph/examples/dam_break_3d.py>`_
example to see this being used. Of course, this file can also be created
manually.


Loading output data files
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
8 changes: 8 additions & 0 deletions pysph/examples/dam_break_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ def configure_scheme(self):
def create_particles(self):
return self.geom.create_particles()

def customize_output(self):
self._mayavi_config('''
viewer.scalar = 'u'
b = particle_arrays['boundary']
b.plot.actor.mapper.scalar_visibility = False
b.plot.actor.property.opacity = 0.1
''')


if __name__ == '__main__':
app = DamBreak3D()
Expand Down
10 changes: 9 additions & 1 deletion pysph/examples/sphysics/case5.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,15 @@ def create_particles(self):
self.scheme.setup_properties([f, b])
return [f, b]

def customize_output(self):
self._mayavi_config('''
viewer.scalar = 'vmag'
b = particle_arrays['boundary']
b.plot.actor.mapper.scalar_visibility = False
b.plot.actor.property.opacity = 0.1
''')


if __name__ == '__main__':
app = Case5()
app.run()
app.run()
10 changes: 9 additions & 1 deletion pysph/examples/sphysics/dam_break.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,15 @@ def create_particles(self):
self.scheme.setup_properties([f, b])
return [f, b]

def customize_output(self):
self._mayavi_config('''
viewer.scalar = 'vmag'
b = particle_arrays['boundary']
b.plot.actor.mapper.scalar_visibility = False
b.plot.actor.property.opacity = 0.15
''')


if __name__ == '__main__':
app = DamBreak()
app.run()
app.run()
32 changes: 30 additions & 2 deletions pysph/solver/application.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# Standard imports.
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
import glob
import inspect
import json
import logging
import os
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from os.path import (abspath, basename, dirname, isdir, join, realpath,
splitext)
import socket
import sys
from textwrap import dedent
import time
import numpy as np
import warnings
Expand Down Expand Up @@ -124,7 +125,9 @@ def create_scheme(self):
10. :py:meth:`create_tools()`: Add any ``pysph.solver.tools.Tool``
instances.
Additionally, as the appliction runs there are several convenient optional
11. :py:meth:`customize_output()`: Customize the output visualization.
Additionally, as the application runs there are several convenient optional
callbacks setup:
1. :py:meth:`pre_step`: Called before each time step.
Expand Down Expand Up @@ -1379,6 +1382,17 @@ def _log_solver_info(self, solver):
eqn_info = equations
logger.info('Using equations:\n%s\n%s\n%s', sep, eqn_info, sep)

def _mayavi_config(self, code):
"""Write out the given code to a `mayavi_config.py` in the output
directory.
Note that this will call `textwrap.dedent` on the code.
"""
cfg = os.path.join(self.output_dir, 'mayavi_config.py')
if not os.path.exists(cfg):
with open(cfg, 'w') as fp:
fp.write(dedent(code))

######################################################################
# Public interface.
######################################################################
Expand Down Expand Up @@ -1471,6 +1485,8 @@ def run(self, argv=None):
self._message("Setup took: %.5f secs" % (setup_duration))
self._write_info(self.info_filename, completed=False, cpu_time=0)

self.customize_output()

start_time = time.time()
self.solver.solve(not self.options.quiet)
end_time = time.time()
Expand Down Expand Up @@ -1652,6 +1668,18 @@ def create_tools(self):
"""
return []

def customize_output(self):
"""Customize the output file visualization by adding any files.
For example, the pysph view command will look for a
``mayavi_config.py`` file that can be used to script the viewer. You
can use self._mayavi_config('code') to add a default customization
here.
Note that this is executed before the simulation starts.
"""
pass

def pre_step(self, solver):
"""If overloaded, this is called automatically before each integrator
step. The method is passed the solver instance.
Expand Down
25 changes: 20 additions & 5 deletions pysph/tools/mayavi_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,11 @@ def _update_plot(self):

if self.plot is None:
if interp.dim == 3:
plot = mlab.pipeline.scalar_cut_plane(src)
plot = mlab.pipeline.scalar_cut_plane(
src, colormap='viridis'
)
else:
plot = mlab.pipeline.surface(src)
plot = mlab.pipeline.surface(src, colormap='viridis')
self.plot = plot
scm = plot.module_manager.scalar_lut_manager
scm.set(show_legend=self.show_legend,
Expand Down Expand Up @@ -399,7 +401,9 @@ def _particle_array_changed(self, old, pa):
old_empty = len(old_x) == 0
if p is None and not empty:
src = mlab.pipeline.scalar_scatter(x, y, z, s)
p = mlab.pipeline.glyph(src, mode='point', scale_mode='none')
p = mlab.pipeline.glyph(
src, mode='point', scale_mode='none', colormap='viridis'
)
p.actor.property.point_size = 6
scm = p.module_manager.scalar_lut_manager
scm.set(show_legend=self.show_legend,
Expand Down Expand Up @@ -505,7 +509,8 @@ def _show_vectors_changed(self, value):
pv = self.scene.mlab.pipeline.vectors(
self.plot.mlab_source.m_data,
mask_points=self.mask_on_ratio,
scale_factor=self.scale_factor
scale_factor=self.scale_factor,
colormap='viridis'
)
self.plot_vectors = pv

Expand Down Expand Up @@ -1010,7 +1015,11 @@ def _shell_fired(self):
obj.edit_traits()

def _get_shell_namespace(self):
return dict(viewer=self, particle_arrays=self.particle_arrays,
pas = {}
for i, x in enumerate(self.particle_arrays):
pas[i] = x
pas[x.name] = x
return dict(viewer=self, particle_arrays=pas,
interpolator=self.interpolator, scene=self.scene,
mlab=self.scene.mlab)

Expand All @@ -1024,6 +1033,9 @@ def _directory_changed(self, d):
self.file_count = min(self.file_count, len(files))
else:
pass
config_file = os.path.join(d, 'mayavi_config.py')
if os.path.exists(config_file):
self.run_script(config_file)

def _live_mode_changed(self, value):
if value:
Expand Down Expand Up @@ -1168,6 +1180,9 @@ def main(args=None):
if len(_files) == 0:
_files = glob.glob(os.path.join(arg, '*.npz'))
files.extend(_files)
config_file = os.path.join(arg, 'mayavi_config.py')
if os.path.exists(config_file):
scripts.append(config_file)
continue
else:
usage()
Expand Down

0 comments on commit b166e00

Please sign in to comment.