Skip to content

Commit

Permalink
Merge pull request #219 from prabhuramachandran/fix-misc-bugs
Browse files Browse the repository at this point in the history
Fix many miscellaneous bugs
  • Loading branch information
prabhuramachandran committed Jun 5, 2019
2 parents f6d4bb4 + 92ffad3 commit c77cd10
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 38 deletions.
39 changes: 32 additions & 7 deletions pysph/solver/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,15 @@ def create_scheme(self):
"""

def __init__(self, fname=None, domain=None):
def __init__(self, fname=None, output_dir=None, domain=None):
""" Constructor
Parameters
----------
fname : str
file name to use for the output files.
output_dir : str
output directory name.
domain : pysph.base.nnps_base.DomainManager
A domain manager to use. This is used for periodic domains etc.
"""
Expand Down Expand Up @@ -218,11 +220,14 @@ def __init__(self, fname=None, domain=None):
'none': None
}

self.output_dir = abspath(self._get_output_dir_from_fname())
if output_dir is None:
self.output_dir = abspath(self._get_output_dir_from_fname())
else:
self.output_dir = output_dir
self.particles = []
self.inlet_outlet = []
# The default value that is overridden by the command line
# options passed or in initializee.
# options passed or in initialize.
self.cache_nnps = False
self.iom = None

Expand Down Expand Up @@ -419,7 +424,7 @@ def _setup_argparse(self):
"--directory",
action="store",
dest="output_dir",
default=self._get_output_dir_from_fname(),
default=self.output_dir,
help="Dump output in the specified directory.")

# --openmp
Expand Down Expand Up @@ -791,11 +796,20 @@ def _parse_command_line(self, force=False):

self.options = options

def _process_command_line(self):
"""Process the parsed command line arguments.
This method calls the scheme's ``consume_user_options`` and
:py:meth:`consume_user_options` as well as the
:py:meth:`configure_scheme`.
"""
options = self.options
# save the path where we want to dump output
self.output_dir = abspath(options.output_dir)
mkdir(self.output_dir)
if self.scheme is not None:
self.scheme.consume_user_options(self.options)
self.scheme.consume_user_options(options)
self.consume_user_options()
if self.scheme is not None:
self.configure_scheme()
Expand Down Expand Up @@ -824,6 +838,7 @@ def _setup_logging(self):
for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler)
lfn = os.path.join(self.output_dir, filename)
mkdir(self.output_dir)
format = '%(levelname)s|%(asctime)s|%(name)s|%(message)s'
logging.basicConfig(
level=level, format=format, filename=lfn, filemode='a')
Expand Down Expand Up @@ -1451,7 +1466,12 @@ def read_info(self, fname_or_dir):
info_dir = dirname(fname_or_dir)
with open(fname_or_dir, 'r') as f:
info = json.load(f)

self.args = info.get('args', self.args)
self._parse_command_line(force=True)

self.fname = info.get('fname', self.fname)

output_dir = info.get('output_dir', self.output_dir)
if realpath(info_dir) != realpath(output_dir):
# Happens if someone moved the directory!
Expand All @@ -1460,8 +1480,11 @@ def read_info(self, fname_or_dir):
else:
self.output_dir = output_dir

self.args = info.get('args', self.args)
self._parse_command_line(force=True)
# Set the output directory of the options so it is corrected as per the
# info file.
self.options.output_dir = self.output_dir
self._process_command_line()

return info

def run(self, argv=None):
Expand All @@ -1474,6 +1497,7 @@ def run(self, argv=None):
start_time = time.time()

self._parse_command_line(force=argv is not None)
self._process_command_line()
self._setup_logging()
self._configure_global_config()

Expand Down Expand Up @@ -1574,6 +1598,7 @@ def setup(self, solver, equations, nnps=None, inlet_outlet_factory=None,
self.equations = equations
solver.get_options(self.arg_parse)
self._parse_command_line()
self._process_command_line()
self._setup_logging()
self._configure_global_config()

Expand Down
51 changes: 45 additions & 6 deletions pysph/solver/tests/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
except ImportError:
import mock

import os
import shutil
import sys
from tempfile import mkdtemp

from pysph.solver.application import Application
from pysph.solver.solver import Solver

Expand Down Expand Up @@ -54,10 +59,22 @@ def create_nnps(self):

class TestApplication(TestCase):

# Test When testarg is notpassed
def test_user_options_false(self):
def setUp(self):
self.output_dir = mkdtemp()
self.app = MockApp(output_dir=self.output_dir)

def tearDown(self):
if sys.platform.startswith('win'):
try:
shutil.rmtree(self.output_dir)
except WindowsError:
pass
else:
shutil.rmtree(self.output_dir)

def test_user_options_when_args_are_not_passed(self):
# Given
app = MockApp()
app = self.app

# When
args = []
Expand All @@ -69,10 +86,9 @@ def test_user_options_false(self):
error_message = "Expected %f, got %f" % (expected, app.testarg)
self.assertEqual(expected, app.testarg, error_message)

# Test When testarg is passed
def test_user_options_true(self):
def test_user_options_when_args_are_passed(self):
# Given
app = MockApp()
app = self.app

# When
args = ['--testarg', '20']
Expand All @@ -82,3 +98,26 @@ def test_user_options_true(self):
expected = 20.0
error_message = "Expected %f, got %f" % (expected, app.testarg)
self.assertEqual(expected, app.testarg, error_message)

def test_output_dir_when_moved_and_read_info_called(self):
# Given
app = self.app

args = ['-d', app.output_dir]
app.run(args)

copy_root = mkdtemp()
copy_dir = os.path.join(copy_root, 'new')
shutil.copytree(app.output_dir, copy_dir)
self.addCleanup(shutil.rmtree, copy_root)
orig_fname = app.fname

# When
app = MockApp()
app.read_info(copy_dir)

# Then
realpath = os.path.realpath
assert realpath(app.output_dir) != realpath(self.output_dir)
assert realpath(app.output_dir) == realpath(copy_dir)
assert app.fname == orig_fname
71 changes: 46 additions & 25 deletions pysph/tools/mayavi_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,9 @@ def _update_plot(self):
plot = mlab.pipeline.surface(src, colormap='viridis')
self.plot = plot
scm = plot.module_manager.scalar_lut_manager
scm.set(show_legend=self.show_legend,
use_default_name=False,
data_name=self.scalar)
scm.trait_set(show_legend=self.show_legend,
use_default_name=False,
data_name=self.scalar)
self.sync_trait('show_legend', scm, mutual=True)
else:
self.plot.visible = True
Expand Down Expand Up @@ -467,9 +467,9 @@ def _particle_array_changed(self, old, pa):
)
p.actor.property.point_size = 6
scm = p.module_manager.scalar_lut_manager
scm.set(show_legend=self.show_legend,
use_default_name=False,
data_name=self.scalar)
scm.trait_set(show_legend=self.show_legend,
use_default_name=False,
data_name=self.scalar)
self.sync_trait('visible', p, mutual=True)
self.sync_trait('show_legend', scm, mutual=True)
self.sync_trait('point_size', p.actor.property, mutual=True)
Expand Down Expand Up @@ -508,6 +508,7 @@ def _range_changed(self, value):
scm = self.plot.module_manager.scalar_lut_manager
try:
rng = eval(value)
len(rng)
except Exception:
rng = None

Expand Down Expand Up @@ -566,36 +567,37 @@ def _show_time_changed(self, value):
txt.visible = False

def _get_vectors_for_plot(self, vectors):
comps = [x.strip() for x in vectors.split(',')]
comps = vectors.split(',')
namespace = self._eval_ns
if len(comps) == 3:
try:
vec = [eval(c, namespace) for c in comps]
vec = eval(vectors, namespace)
except Exception:
return None
else:
return vec

def _set_vector_plot_data(self, vectors):
vec = self._get_vectors_for_plot(vectors)
if vec is not None:
self.plot.mlab_source.vectors = numpy.column_stack(vec)

def _vectors_changed(self, value):
if self.plot_vectors is None:
return
vec = self._get_vectors_for_plot(value)
if vec is not None:
self.plot.mlab_source.set(
vectors=numpy.c_[vec[0], vec[1], vec[2]]
)
self._set_vector_plot_data(value)

def _show_vectors_changed(self, value):
pv = self.plot_vectors
if pv is not None:
pv.visible = value
elif self.plot is not None and value:
self._vectors_changed(self.vectors)
self._set_vector_plot_data(self.vectors)
pv = self.scene.mlab.pipeline.vectors(
self.plot.mlab_source.m_data,
mask_points=self.mask_on_ratio,
scale_factor=self.scale_factor,
colormap='viridis'
colormap='viridis', reset_zoom=False
)
self.plot_vectors = pv

Expand Down Expand Up @@ -851,7 +853,7 @@ def update_plot(self):
pa = controller.get_named_particle_array(name)
arrays.append(pa)
pah = self.particle_arrays[idx]
pah.set(particle_array=pa, time=t)
pah.trait_set(particle_array=pa, time=t)

self.interpolator.particle_arrays = arrays

Expand Down Expand Up @@ -984,7 +986,9 @@ def _client_changed(self, old, new):
else:
# Turn on the legend for the first particle array.
if len(self.particle_arrays) > 0:
self.particle_arrays[0].set(show_legend=True, show_time=True)
self.particle_arrays[0].trait_set(
show_legend=True, show_time=True
)

def _timer_event(self):
# catch all Exceptions else timer will stop
Expand Down Expand Up @@ -1021,11 +1025,12 @@ def _record_changed(self, value):

def _files_changed(self, value):
if len(value) == 0:
self._n_files = 0
return
else:
d = os.path.dirname(os.path.abspath(value[0]))
self.movie_directory = os.path.join(d, 'movie')
self.set(directory=d, trait_change_notify=False)
self.trait_set(directory=d, trait_change_notify=False)
self._n_files = len(value) - 1
self._frame_count = 0
self._count = 0
Expand All @@ -1047,8 +1052,14 @@ def _files_changed(self, value):
def _file_count_changed(self, value):
# Save out any updates for the previous file if needed.
self._handle_particle_array_updates()
if not self.files:
return
# Load the new file.
value = min(value, len(self.files))
fname = self.files[value]
if not os.path.exists(fname):
print("File %s is missing, ignoring!" % fname)
return
self._file_name = fname
self.current_file = os.path.basename(fname)
# Code to read the file, create particle array and setup the helper.
Expand All @@ -1070,14 +1081,14 @@ def _file_count_changed(self, value):
pa = arrays[name]
pah = self._make_particle_array_helper(self.scene, name)
# Must set this after setting the scene.
pah.set(particle_array=pa, time=t)
pah.trait_set(particle_array=pa, time=t)
pas.append(pah)
self.particle_arrays = pas
else:
for idx, name in enumerate(pa_names):
pa = arrays[name]
pah = self.particle_arrays[idx]
pah.set(particle_array=pa, time=t)
pah.trait_set(particle_array=pa, time=t)

self.interpolator.particle_arrays = list(arrays.values())

Expand Down Expand Up @@ -1125,12 +1136,17 @@ def _scalar_changed(self, value):

def _update_files_fired(self):
fc = self.file_count
files = glob_files(self.files[fc])
if len(self.files) == 0:
files = get_files_in_dir(self.directory)
else:
files = glob_files(self.files[fc])
sort_file_list(files)
self.files = files
self.file_count = fc
if self.play:
self._play_changed(self.play)
if len(files) > 0:
fc = min(len(files), fc)
self.file_count = fc
if self.play:
self._play_changed(self.play)

def _shell_fired(self):
ns = self._get_shell_namespace()
Expand Down Expand Up @@ -1282,6 +1298,7 @@ def main(args=None):
kw = {}
files = []
scripts = []
directory = None
for arg in args:
if '=' not in arg:
if arg.endswith('.py'):
Expand All @@ -1298,6 +1315,7 @@ def main(args=None):
files.extend(glob.glob(arg))
continue
elif os.path.isdir(arg):
directory = arg
_files = get_files_in_dir(arg)
files.extend(_files)
config_file = os.path.join(arg, 'mayavi_config.py')
Expand All @@ -1321,7 +1339,10 @@ def main(args=None):
# If we set the particle arrays before the scene is activated, the arrays
# are not displayed on screen so we use do_later to set the files.
m = MayaviViewer(live_mode=live_mode)
do_later(m.set, files=files, **kw)
if not directory and len(files) > 0:
directory = os.path.dirname(files[0])
m.trait_set(directory=directory, trait_change_notify=False)
do_later(m.trait_set, files=files, **kw)
for script in scripts:
do_later(m.run_script, script)
m.configure_traits()
Expand Down

0 comments on commit c77cd10

Please sign in to comment.