From 7f5c884c511c32a6e20c7b9a8ffde396571eefdc Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Tue, 15 Mar 2016 17:11:05 +0000 Subject: [PATCH 01/32] call SetSize for the vtkRenderWindow when wx.scene.set_size is called --- tvtk/pyface/ui/wx/scene.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tvtk/pyface/ui/wx/scene.py b/tvtk/pyface/ui/wx/scene.py index 92543e9e5..58be0c237 100644 --- a/tvtk/pyface/ui/wx/scene.py +++ b/tvtk/pyface/ui/wx/scene.py @@ -329,6 +329,9 @@ def get_size(self): def set_size(self, size): """Set the size of the window.""" + # the OpenGLRenderWindow needs resizing too; otherwise snapshots + # with off_screen_rendering would have the wrong size + self._vtk_control._Iren.GetRenderWindow().SetSize(size) self._vtk_control.SetSize(size) def hide_cursor(self): From b8694c1cc6366629909270075c76d01a322706b5 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Tue, 15 Mar 2016 17:54:49 +0000 Subject: [PATCH 02/32] add pillow to travis-requirement --- travis-requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/travis-requirements.txt b/travis-requirements.txt index e427cead8..2476a5b9b 100644 --- a/travis-requirements.txt +++ b/travis-requirements.txt @@ -1,3 +1,4 @@ +pillow mock Sphinx coverage From 80f13f0a6cccccd11ecbb041a4428397fd65700b Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Tue, 15 Mar 2016 17:55:56 +0000 Subject: [PATCH 03/32] added test for mlab.savefig --- integrationtests/mayavi/test_mlab_savefig.py | 121 +++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 integrationtests/mayavi/test_mlab_savefig.py diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py new file mode 100644 index 000000000..10e68045e --- /dev/null +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -0,0 +1,121 @@ +import os +import shutil +import unittest +import tempfile +from contextlib import contextmanager + +import numpy +from PIL import Image + +from mayavi import mlab +from mayavi.tools.figure import savefig + +from common import TestCase + + +@contextmanager +def get_figure_finally_close(): + try: + yield mlab.figure() + finally: + mlab.clf() + mlab.close() + + +class TestMlabSavefigUnitTest(unittest.TestCase): + + def setUp(self, figure=None): + # Make a temporary directory for saved figures + self.temp_dir = tempfile.mkdtemp() + self.filename = os.path.join(self.temp_dir, "saved_figure.png") + + # this ensures that the temporary directory is removed + self.addCleanup(self.cleanup) + + def cleanup(self): + shutil.rmtree(self.temp_dir) + + def test_savefig_with_size(self): + with get_figure_finally_close(): + # Set up the scene + X, Y = numpy.ogrid[-10:10, -10:10] + Z = X**2 + Y**2 + mlab.surf(X, Y, Z) + + # save the figure + savefig(self.filename, size=(131, 217)) + + # check + self.check_image((217, 131)) + + def test_savefig_with_size_offscreen(self): + with get_figure_finally_close() as fig: + # Use off-screen rendering + fig.scene.off_screen_rendering = True + + # Set up the scene + X, Y = numpy.ogrid[-10:10, -10:10] + Z = X**2 + Y**2 + mlab.surf(X, Y, Z) + + # save the figure + savefig(self.filename, size=(131, 217)) + + # check + self.check_image((217, 131)) + + def test_savefig_with_size_and_magnification(self): + with get_figure_finally_close(): + # Set up the scene + X, Y = numpy.ogrid[-10:10, -10:10] + Z = X**2 + Y**2 + mlab.surf(X, Y, Z) + + # save the figure + savefig(self.filename, size=(131, 217), magnification=2) + + # check if the image size is twice as big + self.check_image((434, 262)) + + def test_savefig_with_size_and_magnification_offscreen(self): + with get_figure_finally_close() as fig: + # Use off-screen rendering + fig.scene.off_screen_rendering = True + + # Set up the scene + X, Y = numpy.ogrid[-10:10, -10:10] + Z = X**2 + Y**2 + mlab.surf(X, Y, Z) + + # save the figure + savefig(self.filename, size=(131, 217), magnification=2) + + # check if the image size is twice as big + self.check_image((434, 262)) + + def check_image(self, size): + image = numpy.array(Image.open(self.filename))[:, :, :3] + + # check the size is correct + self.assertEqual(image.shape[:2], size) + + # check that there is no black spot + if (numpy.sum(image == [0, 0, 0], axis=2) == 3).any(): + self.fail("The saved image has black spots") + + +class TestMlabSavefig(TestCase): + + def test(self): + self.main() + + def do(self): + suite = unittest.TestLoader().loadTestsFromTestCase( + TestMlabSavefigUnitTest) + for test in suite: + test.run() + + +if __name__ == "__main__": + t = TestMlabSavefig() + t.test() From d7cdb87768764da581326bcf909d3b10348a9bbc Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 17 Mar 2016 10:34:53 +0000 Subject: [PATCH 04/32] use cleanUp to close all figure instead of using contextmanager less indentation --- integrationtests/mayavi/test_mlab_savefig.py | 74 +++++++++----------- 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py index 10e68045e..4cfac1fae 100644 --- a/integrationtests/mayavi/test_mlab_savefig.py +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -2,7 +2,6 @@ import shutil import unittest import tempfile -from contextlib import contextmanager import numpy from PIL import Image @@ -13,15 +12,6 @@ from common import TestCase -@contextmanager -def get_figure_finally_close(): - try: - yield mlab.figure() - finally: - mlab.clf() - mlab.close() - - class TestMlabSavefigUnitTest(unittest.TestCase): def setUp(self, figure=None): @@ -29,66 +19,66 @@ def setUp(self, figure=None): self.temp_dir = tempfile.mkdtemp() self.filename = os.path.join(self.temp_dir, "saved_figure.png") + self.figure = mlab.figure() + # this ensures that the temporary directory is removed + # and all scene is closed self.addCleanup(self.cleanup) def cleanup(self): shutil.rmtree(self.temp_dir) + mlab.close(all=True) def test_savefig_with_size(self): - with get_figure_finally_close(): - # Set up the scene - X, Y = numpy.ogrid[-10:10, -10:10] - Z = X**2 + Y**2 - mlab.surf(X, Y, Z) + # Set up the scene + X, Y = numpy.ogrid[-10:10, -10:10] + Z = X**2 + Y**2 + mlab.surf(X, Y, Z) - # save the figure - savefig(self.filename, size=(131, 217)) + # save the figure + savefig(self.filename, size=(131, 217)) # check self.check_image((217, 131)) def test_savefig_with_size_offscreen(self): - with get_figure_finally_close() as fig: - # Use off-screen rendering - fig.scene.off_screen_rendering = True + # Use off-screen rendering + self.figure.scene.off_screen_rendering = True - # Set up the scene - X, Y = numpy.ogrid[-10:10, -10:10] - Z = X**2 + Y**2 - mlab.surf(X, Y, Z) + # Set up the scene + X, Y = numpy.ogrid[-10:10, -10:10] + Z = X**2 + Y**2 + mlab.surf(X, Y, Z) - # save the figure - savefig(self.filename, size=(131, 217)) + # save the figure + savefig(self.filename, size=(131, 217)) # check self.check_image((217, 131)) def test_savefig_with_size_and_magnification(self): - with get_figure_finally_close(): - # Set up the scene - X, Y = numpy.ogrid[-10:10, -10:10] - Z = X**2 + Y**2 - mlab.surf(X, Y, Z) + # Set up the scene + X, Y = numpy.ogrid[-10:10, -10:10] + Z = X**2 + Y**2 + mlab.surf(X, Y, Z) - # save the figure - savefig(self.filename, size=(131, 217), magnification=2) + # save the figure + savefig(self.filename, size=(131, 217), magnification=2) # check if the image size is twice as big self.check_image((434, 262)) def test_savefig_with_size_and_magnification_offscreen(self): - with get_figure_finally_close() as fig: - # Use off-screen rendering - fig.scene.off_screen_rendering = True + # Use off-screen rendering + self.figure.scene.off_screen_rendering = True - # Set up the scene - X, Y = numpy.ogrid[-10:10, -10:10] - Z = X**2 + Y**2 - mlab.surf(X, Y, Z) + # Set up the scene + X, Y = numpy.ogrid[-10:10, -10:10] + Z = X**2 + Y**2 + mlab.surf(X, Y, Z) - # save the figure - savefig(self.filename, size=(131, 217), magnification=2) + # save the figure + savefig(self.filename, size=(131, 217), magnification=2) # check if the image size is twice as big self.check_image((434, 262)) From ac061bccb46dd1420e93160b68e31ccd425c5936 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 17 Mar 2016 11:21:46 +0000 Subject: [PATCH 05/32] only the test using Engine + off_screen_rendering fails on master but fixed on this branch --- integrationtests/mayavi/test_mlab_savefig.py | 74 +++++++++++++++----- 1 file changed, 57 insertions(+), 17 deletions(-) diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py index 4cfac1fae..3293fa540 100644 --- a/integrationtests/mayavi/test_mlab_savefig.py +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -7,6 +7,8 @@ from PIL import Image from mayavi import mlab +from mayavi.core.engine import Engine +from mayavi.core.off_screen_engine import OffScreenEngine from mayavi.tools.figure import savefig from common import TestCase @@ -14,71 +16,109 @@ class TestMlabSavefigUnitTest(unittest.TestCase): - def setUp(self, figure=None): + def setUp(self): # Make a temporary directory for saved figures self.temp_dir = tempfile.mkdtemp() self.filename = os.path.join(self.temp_dir, "saved_figure.png") - self.figure = mlab.figure() - # this ensures that the temporary directory is removed - # and all scene is closed - self.addCleanup(self.cleanup) + self.addCleanup(self.remove_tempdir) + + def setup_engine_and_figure(self, engine): + self.engine = engine + + if not engine.running: + engine.start() + + engine.new_scene() + self.figure = engine.current_scene + + self.addCleanup(self.cleanup_engine, self.engine) + + def cleanup_engine(self, engine): + scenes = [scene for scene in engine.scenes] + for scene in scenes: + engine.close_scene(scene) + engine.stop() - def cleanup(self): + def remove_tempdir(self): shutil.rmtree(self.temp_dir) - mlab.close(all=True) def test_savefig_with_size(self): + self.setup_engine_and_figure(Engine()) + # Set up the scene X, Y = numpy.ogrid[-10:10, -10:10] Z = X**2 + Y**2 - mlab.surf(X, Y, Z) + mlab.surf(X, Y, Z, figure=self.figure) # save the figure - savefig(self.filename, size=(131, 217)) + savefig(self.filename, size=(131, 217), figure=self.figure) # check self.check_image((217, 131)) def test_savefig_with_size_offscreen(self): - # Use off-screen rendering - self.figure.scene.off_screen_rendering = True + self.setup_engine_and_figure(OffScreenEngine()) # Set up the scene X, Y = numpy.ogrid[-10:10, -10:10] Z = X**2 + Y**2 - mlab.surf(X, Y, Z) + mlab.surf(X, Y, Z, figure=self.figure) # save the figure - savefig(self.filename, size=(131, 217)) + savefig(self.filename, size=(131, 217), figure=self.figure) # check self.check_image((217, 131)) def test_savefig_with_size_and_magnification(self): + self.setup_engine_and_figure(Engine()) + # Set up the scene X, Y = numpy.ogrid[-10:10, -10:10] Z = X**2 + Y**2 - mlab.surf(X, Y, Z) + mlab.surf(X, Y, Z, figure=self.figure) # save the figure - savefig(self.filename, size=(131, 217), magnification=2) + savefig(self.filename, size=(131, 217), magnification=2, + figure=self.figure) # check if the image size is twice as big self.check_image((434, 262)) def test_savefig_with_size_and_magnification_offscreen(self): + self.setup_engine_and_figure(OffScreenEngine()) + + # Use off-screen rendering + self.figure.scene.off_screen_rendering = True + + # Set up the scene + X, Y = numpy.ogrid[-10:10, -10:10] + Z = X**2 + Y**2 + mlab.surf(X, Y, Z, figure=self.figure) + + # save the figure + savefig(self.filename, size=(131, 217), magnification=2, + figure=self.figure) + + # check if the image size is twice as big + self.check_image((434, 262)) + + def test_savefig_with_size_and_magnification_offscreen_with_engine(self): + self.setup_engine_and_figure(Engine()) + # Use off-screen rendering self.figure.scene.off_screen_rendering = True # Set up the scene X, Y = numpy.ogrid[-10:10, -10:10] Z = X**2 + Y**2 - mlab.surf(X, Y, Z) + mlab.surf(X, Y, Z, figure=self.figure) # save the figure - savefig(self.filename, size=(131, 217), magnification=2) + savefig(self.filename, size=(131, 217), magnification=2, + figure=self.figure) # check if the image size is twice as big self.check_image((434, 262)) From ae1f11c2a7c54e67044f81bccf56c7679fd96fd2 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 17 Mar 2016 11:31:07 +0000 Subject: [PATCH 06/32] let's only test against the image size and forget about black spots which are hardware problems --- integrationtests/mayavi/test_mlab_savefig.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py index 3293fa540..d800f7157 100644 --- a/integrationtests/mayavi/test_mlab_savefig.py +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -129,10 +129,6 @@ def check_image(self, size): # check the size is correct self.assertEqual(image.shape[:2], size) - # check that there is no black spot - if (numpy.sum(image == [0, 0, 0], axis=2) == 3).any(): - self.fail("The saved image has black spots") - class TestMlabSavefig(TestCase): From 842d05227baf75a3790ac1e0d9b8f552b2b8b2f4 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 17 Mar 2016 14:44:06 +0000 Subject: [PATCH 07/32] set_size was doing the right thing, instead it was because the window is not lifted when saving an image + off_screen_rendering + wx --- tvtk/pyface/ui/wx/scene.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tvtk/pyface/ui/wx/scene.py b/tvtk/pyface/ui/wx/scene.py index 58be0c237..01efd64d0 100644 --- a/tvtk/pyface/ui/wx/scene.py +++ b/tvtk/pyface/ui/wx/scene.py @@ -329,9 +329,6 @@ def get_size(self): def set_size(self, size): """Set the size of the window.""" - # the OpenGLRenderWindow needs resizing too; otherwise snapshots - # with off_screen_rendering would have the wrong size - self._vtk_control._Iren.GetRenderWindow().SetSize(size) self._vtk_control.SetSize(size) def hide_cursor(self): @@ -684,9 +681,12 @@ def _do_idle(event, window=window): def _lift(self): """Lift the window to the top. Useful when saving screen to an image.""" - if self.render_window.off_screen_rendering: - # Do nothing if off screen rendering is being used. - return + ## The image size would be wrong if we don't lift the + ## the window even when off_screen_rendering is On + ## because the OnSize event is not being called anymore + # if self.render_window.off_screen_rendering: + # # Do nothing if off screen rendering is being used. + # return w = self._vtk_control while w and not w.IsTopLevel(): From 3a3761fe5869d702cda5a5569e7dcdc929e2f759 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 17 Mar 2016 16:40:43 +0000 Subject: [PATCH 08/32] size should be strictly respected. int(target_size // mag) gives wrong size --- integrationtests/mayavi/test_mlab_savefig.py | 74 ++++++++++++++------ mayavi/tools/figure.py | 14 ++-- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py index d800f7157..30fd8a7f0 100644 --- a/integrationtests/mayavi/test_mlab_savefig.py +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -14,6 +14,17 @@ from common import TestCase +def create_quiver3d(): + x, y, z = numpy.mgrid[1:10, 1:10, 1:10] + u, v, w = numpy.mgrid[1:10, 1:10, 1:10] + s = numpy.sqrt(u**2 + v**2) + mlab.quiver3d(x, y, z, u, v, w, scalars=s) + + +# Note: the figure size is delibrately set to be smaller than +# the required size during `savefig`, this forces the re-rendering +# to occur and catch any potential ill rendering + class TestMlabSavefigUnitTest(unittest.TestCase): def setUp(self): @@ -25,17 +36,21 @@ def setUp(self): self.addCleanup(self.remove_tempdir) def setup_engine_and_figure(self, engine): + # Set up a Engine/OffScreenEngine/... for the test case self.engine = engine if not engine.running: engine.start() - engine.new_scene() + # figure size is set to be small to force re-rendering + engine.new_scene(size=(90, 100)) self.figure = engine.current_scene + # the clean up function will close all figures and stop the engine self.addCleanup(self.cleanup_engine, self.engine) def cleanup_engine(self, engine): + """ Close all scenes in the engine and stop it """ scenes = [scene for scene in engine.scenes] for scene in scenes: engine.close_scene(scene) @@ -44,27 +59,41 @@ def cleanup_engine(self, engine): def remove_tempdir(self): shutil.rmtree(self.temp_dir) + def test_savefig(self): + """Test if savefig works with auto size, mag and a normal Engine""" + self.setup_engine_and_figure(Engine()) + + # Set up the scene + create_quiver3d() + + # save the figure (magnification is default "auto") + savefig(self.filename, figure=self.figure) + + # check + self.check_image() + def test_savefig_with_size(self): + """Test if savefig works with given size and a normal Engine""" self.setup_engine_and_figure(Engine()) # Set up the scene - X, Y = numpy.ogrid[-10:10, -10:10] - Z = X**2 + Y**2 - mlab.surf(X, Y, Z, figure=self.figure) + create_quiver3d() - # save the figure + # save the figure (magnification is default "auto") savefig(self.filename, size=(131, 217), figure=self.figure) # check self.check_image((217, 131)) + @unittest.skipIf(os.environ.get("TRAVIS", False), + ("Offscreen rendering is not tested on Travis " + "due to lack of GLX support")) def test_savefig_with_size_offscreen(self): + """Test if savefig works with given size on an OffScreenEngine""" self.setup_engine_and_figure(OffScreenEngine()) # Set up the scene - X, Y = numpy.ogrid[-10:10, -10:10] - Z = X**2 + Y**2 - mlab.surf(X, Y, Z, figure=self.figure) + create_quiver3d() # save the figure savefig(self.filename, size=(131, 217), figure=self.figure) @@ -73,12 +102,11 @@ def test_savefig_with_size_offscreen(self): self.check_image((217, 131)) def test_savefig_with_size_and_magnification(self): + """Test if savefig works with given size and magnification""" self.setup_engine_and_figure(Engine()) # Set up the scene - X, Y = numpy.ogrid[-10:10, -10:10] - Z = X**2 + Y**2 - mlab.surf(X, Y, Z, figure=self.figure) + create_quiver3d() # save the figure savefig(self.filename, size=(131, 217), magnification=2, @@ -87,16 +115,18 @@ def test_savefig_with_size_and_magnification(self): # check if the image size is twice as big self.check_image((434, 262)) + @unittest.skipIf(os.environ.get("TRAVIS", False), + ("Offscreen rendering is not tested on Travis " + "due to lack of GLX support")) def test_savefig_with_size_and_magnification_offscreen(self): + """Test savefig with off_screen_rendering and OffScreenEngine""" self.setup_engine_and_figure(OffScreenEngine()) # Use off-screen rendering self.figure.scene.off_screen_rendering = True # Set up the scene - X, Y = numpy.ogrid[-10:10, -10:10] - Z = X**2 + Y**2 - mlab.surf(X, Y, Z, figure=self.figure) + create_quiver3d() # save the figure savefig(self.filename, size=(131, 217), magnification=2, @@ -105,16 +135,18 @@ def test_savefig_with_size_and_magnification_offscreen(self): # check if the image size is twice as big self.check_image((434, 262)) + @unittest.skipIf(os.environ.get("TRAVIS", False), + ("Offscreen rendering is not tested on Travis " + "due to lack of GLX support")) def test_savefig_with_size_and_magnification_offscreen_with_engine(self): + """Test if savefig works with off_screen_rendering and Engine""" self.setup_engine_and_figure(Engine()) # Use off-screen rendering self.figure.scene.off_screen_rendering = True # Set up the scene - X, Y = numpy.ogrid[-10:10, -10:10] - Z = X**2 + Y**2 - mlab.surf(X, Y, Z, figure=self.figure) + create_quiver3d() # save the figure savefig(self.filename, size=(131, 217), magnification=2, @@ -123,11 +155,12 @@ def test_savefig_with_size_and_magnification_offscreen_with_engine(self): # check if the image size is twice as big self.check_image((434, 262)) - def check_image(self, size): + def check_image(self, size=None): image = numpy.array(Image.open(self.filename))[:, :, :3] # check the size is correct - self.assertEqual(image.shape[:2], size) + if size: + self.assertEqual(image.shape[:2], size) class TestMlabSavefig(TestCase): @@ -138,8 +171,7 @@ def test(self): def do(self): suite = unittest.TestLoader().loadTestsFromTestCase( TestMlabSavefigUnitTest) - for test in suite: - test.run() + unittest.TextTestRunner().run(suite) if __name__ == "__main__": diff --git a/mayavi/tools/figure.py b/mayavi/tools/figure.py index 28ff38306..54159af31 100644 --- a/mayavi/tools/figure.py +++ b/mayavi/tools/figure.py @@ -229,20 +229,14 @@ def savefig(filename, size=None, figure=None, magnification='auto', """ if figure is None: figure = gcf() + current_mag = figure.scene.magnification try: - if size is not None: - current_x, current_y = tuple(figure.scene.get_size()) - target_x, target_y = size - if magnification is 'auto': - magnification = max(target_x // current_x, - target_y // current_y) + 1 - target_x = int(target_x / magnification) - target_y = int(target_y / magnification) - size = target_x, target_y - elif magnification is 'auto': + if magnification is "auto": magnification = 1 + figure.scene.magnification = int(magnification) + figure.scene.save(filename, size=size, **kwargs) From 4d85baf0265da315aed1bef09ce2400e1753bafb Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 17 Mar 2016 16:42:14 +0000 Subject: [PATCH 09/32] mend --- .../mayavi/auto/mlab_helper_functions.rst | 90 ++++++++++--------- .../auto/mlab_pipeline_other_functions.rst | 24 ++--- .../mayavi/auto/mlab_pipeline_sources.rst | 12 +-- 3 files changed, 65 insertions(+), 61 deletions(-) diff --git a/docs/source/mayavi/auto/mlab_helper_functions.rst b/docs/source/mayavi/auto/mlab_helper_functions.rst index c6d5efe87..7af19c008 100644 --- a/docs/source/mayavi/auto/mlab_helper_functions.rst +++ b/docs/source/mayavi/auto/mlab_helper_functions.rst @@ -78,8 +78,8 @@ barchart :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer or - None. + points displayed on large datasets Must be an integer + (int or long) or None. :mode: The glyph used to represent the bars. Must be '2dcircle' or '2dcross' or '2ddiamond' or '2dsquare' or '2dthick_cross' or @@ -95,7 +95,7 @@ barchart :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer. Default: 8 + phi. Must be an integer (int or long). Default: 8 :scale_factor: the scaling applied to the glyphs. The size of the glyph is by default in drawing @@ -115,8 +115,7 @@ barchart -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -203,8 +202,7 @@ contour3d -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -300,8 +298,7 @@ contour_surf -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -393,7 +390,8 @@ flow :scalars: optional scalar data. :seed_resolution: The resolution of the seed. Determines the number of - seed points Must be an integer or None. + seed points Must be an integer (int or long) or + None. :seed_scale: Scales the seed around its default center Must be a float. Default: 1.0 @@ -415,8 +413,7 @@ flow -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -424,11 +421,11 @@ see :ref:`running-mlab-scripts` for more info):: from mayavi.mlab import * def test_flow(): - x, y, z = numpy.mgrid[0:5, 0:5, 0:5] - r = numpy.sqrt(x ** 2 + y ** 2 + z ** 4) + x, y, z = numpy.mgrid[-4:4:40j, -4:4:40j, 0:4:20j] + r = numpy.sqrt(x ** 2 + y ** 2 + z ** 2 + 0.1) u = y * numpy.sin(r) / r v = -x * numpy.sin(r) / r - w = numpy.zeros_like(z) + w = numpy.ones_like(z)*0.05 obj = flow(u, v, w) return obj @@ -492,8 +489,7 @@ imshow -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -552,11 +548,14 @@ mesh Default: 2.0 :mask: boolean mask array to suppress some data points. + Note: this works based on colormapping of scalars and will + not work if you specify a solid color using the + `color` keyword. :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer or - None. + points displayed on large datasets Must be an integer + (int or long) or None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -578,7 +577,7 @@ mesh :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer. Default: 8 + phi. Must be an integer (int or long). Default: 8 :scalars: optional scalar data. @@ -596,7 +595,8 @@ mesh lines, in mesh mode. If None, simple lines are used. :tube_sides: number of sides of the tubes used to - represent the lines. Must be an integer. Default: 6 + represent the lines. Must be an integer (int or long). + Default: 6 :vmax: vmax is used to scale the colormap. If None, the max of the data will be used @@ -606,8 +606,7 @@ mesh -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -698,7 +697,8 @@ plot3d lines, If None, simple lines are used. :tube_sides: number of sides of the tubes used to - represent the lines. Must be an integer. Default: 6 + represent the lines. Must be an integer (int or long). + Default: 6 :vmax: vmax is used to scale the colormap. If None, the max of the data will be used @@ -708,8 +708,7 @@ plot3d -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -781,8 +780,8 @@ points3d :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer or - None. + points displayed on large datasets Must be an integer + (int or long) or None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -800,7 +799,7 @@ points3d :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer. Default: 8 + phi. Must be an integer (int or long). Default: 8 :scale_factor: The scaling applied to the glyphs. the size of the glyph is by default calculated from the inter-glyph @@ -821,8 +820,7 @@ points3d -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -895,8 +893,8 @@ quiver3d :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer or - None. + points displayed on large datasets Must be an integer + (int or long) or None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -914,7 +912,7 @@ quiver3d :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer. Default: 8 + phi. Must be an integer (int or long). Default: 8 :scalars: optional scalar data. @@ -937,8 +935,7 @@ quiver3d -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -1014,6 +1011,9 @@ surf Default: 2.0 :mask: boolean mask array to suppress some data points. + Note: this works based on colormapping of scalars and will + not work if you specify a solid color using the + `color` keyword. :name: the name of the vtk object created. @@ -1055,8 +1055,7 @@ surf -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -1120,11 +1119,14 @@ triangular_mesh Default: 2.0 :mask: boolean mask array to suppress some data points. + Note: this works based on colormapping of scalars and will + not work if you specify a solid color using the + `color` keyword. :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer or - None. + points displayed on large datasets Must be an integer + (int or long) or None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -1146,7 +1148,7 @@ triangular_mesh :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer. Default: 8 + phi. Must be an integer (int or long). Default: 8 :scalars: optional scalar data. @@ -1164,7 +1166,8 @@ triangular_mesh lines, in mesh mode. If None, simple lines are used. :tube_sides: number of sides of the tubes used to - represent the lines. Must be an integer. Default: 6 + represent the lines. Must be an integer (int or long). + Default: 6 :vmax: vmax is used to scale the colormap. If None, the max of the data will be used @@ -1174,8 +1177,7 @@ triangular_mesh -**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent -IPython versions, or in the mayavi2 interactive shell, +**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: diff --git a/docs/source/mayavi/auto/mlab_pipeline_other_functions.rst b/docs/source/mayavi/auto/mlab_pipeline_other_functions.rst index 83348d9a7..e4d7203da 100644 --- a/docs/source/mayavi/auto/mlab_pipeline_other_functions.rst +++ b/docs/source/mayavi/auto/mlab_pipeline_other_functions.rst @@ -497,8 +497,8 @@ glyph :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer or - None. + points displayed on large datasets Must be an integer + (int or long) or None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -516,7 +516,7 @@ glyph :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer. Default: 8 + phi. Must be an integer (int or long). Default: 8 :scale_factor: the scaling applied to the glyphs. The size of the glyph is by default in drawing @@ -1201,7 +1201,8 @@ streamline added to the scene. Defaults to True. :seed_resolution: The resolution of the seed. Determines the number of - seed points Must be an integer or None. + seed points Must be an integer (int or long) or + None. :seed_scale: Scales the seed around its default center Must be a float. Default: 1.0 @@ -1509,7 +1510,8 @@ tube lines. Must be a float. Default: 0.05 :tube_sides: number of sides of the tubes used to - represent the lines. Must be an integer. Default: 6 + represent the lines. Must be an integer (int or long). + Default: 6 @@ -1566,8 +1568,8 @@ vector_cut_plane :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer or - None. + points displayed on large datasets Must be an integer + (int or long) or None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -1588,7 +1590,7 @@ vector_cut_plane :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer. Default: 8 + phi. Must be an integer (int or long). Default: 8 :scale_factor: the scaling applied to the glyphs. The size of the glyph is by default in drawing @@ -1642,8 +1644,8 @@ vectors :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer or - None. + points displayed on large datasets Must be an integer + (int or long) or None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -1661,7 +1663,7 @@ vectors :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer. Default: 8 + phi. Must be an integer (int or long). Default: 8 :scale_factor: the scaling applied to the glyphs. The size of the glyph is by default in drawing diff --git a/docs/source/mayavi/auto/mlab_pipeline_sources.rst b/docs/source/mayavi/auto/mlab_pipeline_sources.rst index 3a492ce00..83369046d 100644 --- a/docs/source/mayavi/auto/mlab_pipeline_sources.rst +++ b/docs/source/mayavi/auto/mlab_pipeline_sources.rst @@ -62,7 +62,7 @@ array2d_source builtin_image ~~~~~~~~~~~~~ -.. function:: builtin_image(metadata=) +.. function:: builtin_image(metadata=) Create a vtk image data source @@ -73,7 +73,7 @@ builtin_image builtin_surface ~~~~~~~~~~~~~~~ -.. function:: builtin_surface(metadata=) +.. function:: builtin_surface(metadata=) Create a vtk poly data source @@ -84,7 +84,7 @@ builtin_surface chaco_file ~~~~~~~~~~ -.. function:: chaco_file(metadata=) +.. function:: chaco_file(metadata=) Open a Chaco file @@ -178,7 +178,7 @@ open parametric_surface ~~~~~~~~~~~~~~~~~~ -.. function:: parametric_surface(metadata=) +.. function:: parametric_surface(metadata=) Create a parametric surface source @@ -189,7 +189,7 @@ parametric_surface point_load ~~~~~~~~~~ -.. function:: point_load(metadata=) +.. function:: point_load(metadata=) Simulates a point load on a cube of data (for tensors) @@ -429,7 +429,7 @@ vertical_vectors_source volume_file ~~~~~~~~~~~ -.. function:: volume_file(metadata=) +.. function:: volume_file(metadata=) Open a Volume file From c5e2fb346752c01f4e20eb3b1aa76a1b86fb068b Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 17 Mar 2016 16:45:39 +0000 Subject: [PATCH 10/32] Revert "mend" This reverts commit 4d85baf0265da315aed1bef09ce2400e1753bafb. --- .../mayavi/auto/mlab_helper_functions.rst | 90 +++++++++---------- .../auto/mlab_pipeline_other_functions.rst | 24 +++-- .../mayavi/auto/mlab_pipeline_sources.rst | 12 +-- 3 files changed, 61 insertions(+), 65 deletions(-) diff --git a/docs/source/mayavi/auto/mlab_helper_functions.rst b/docs/source/mayavi/auto/mlab_helper_functions.rst index 7af19c008..c6d5efe87 100644 --- a/docs/source/mayavi/auto/mlab_helper_functions.rst +++ b/docs/source/mayavi/auto/mlab_helper_functions.rst @@ -78,8 +78,8 @@ barchart :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer - (int or long) or None. + points displayed on large datasets Must be an integer or + None. :mode: The glyph used to represent the bars. Must be '2dcircle' or '2dcross' or '2ddiamond' or '2dsquare' or '2dthick_cross' or @@ -95,7 +95,7 @@ barchart :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer (int or long). Default: 8 + phi. Must be an integer. Default: 8 :scale_factor: the scaling applied to the glyphs. The size of the glyph is by default in drawing @@ -115,7 +115,8 @@ barchart -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -202,7 +203,8 @@ contour3d -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -298,7 +300,8 @@ contour_surf -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -390,8 +393,7 @@ flow :scalars: optional scalar data. :seed_resolution: The resolution of the seed. Determines the number of - seed points Must be an integer (int or long) or - None. + seed points Must be an integer or None. :seed_scale: Scales the seed around its default center Must be a float. Default: 1.0 @@ -413,7 +415,8 @@ flow -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -421,11 +424,11 @@ see :ref:`running-mlab-scripts` for more info):: from mayavi.mlab import * def test_flow(): - x, y, z = numpy.mgrid[-4:4:40j, -4:4:40j, 0:4:20j] - r = numpy.sqrt(x ** 2 + y ** 2 + z ** 2 + 0.1) + x, y, z = numpy.mgrid[0:5, 0:5, 0:5] + r = numpy.sqrt(x ** 2 + y ** 2 + z ** 4) u = y * numpy.sin(r) / r v = -x * numpy.sin(r) / r - w = numpy.ones_like(z)*0.05 + w = numpy.zeros_like(z) obj = flow(u, v, w) return obj @@ -489,7 +492,8 @@ imshow -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -548,14 +552,11 @@ mesh Default: 2.0 :mask: boolean mask array to suppress some data points. - Note: this works based on colormapping of scalars and will - not work if you specify a solid color using the - `color` keyword. :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer - (int or long) or None. + points displayed on large datasets Must be an integer or + None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -577,7 +578,7 @@ mesh :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer (int or long). Default: 8 + phi. Must be an integer. Default: 8 :scalars: optional scalar data. @@ -595,8 +596,7 @@ mesh lines, in mesh mode. If None, simple lines are used. :tube_sides: number of sides of the tubes used to - represent the lines. Must be an integer (int or long). - Default: 6 + represent the lines. Must be an integer. Default: 6 :vmax: vmax is used to scale the colormap. If None, the max of the data will be used @@ -606,7 +606,8 @@ mesh -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -697,8 +698,7 @@ plot3d lines, If None, simple lines are used. :tube_sides: number of sides of the tubes used to - represent the lines. Must be an integer (int or long). - Default: 6 + represent the lines. Must be an integer. Default: 6 :vmax: vmax is used to scale the colormap. If None, the max of the data will be used @@ -708,7 +708,8 @@ plot3d -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -780,8 +781,8 @@ points3d :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer - (int or long) or None. + points displayed on large datasets Must be an integer or + None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -799,7 +800,7 @@ points3d :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer (int or long). Default: 8 + phi. Must be an integer. Default: 8 :scale_factor: The scaling applied to the glyphs. the size of the glyph is by default calculated from the inter-glyph @@ -820,7 +821,8 @@ points3d -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -893,8 +895,8 @@ quiver3d :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer - (int or long) or None. + points displayed on large datasets Must be an integer or + None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -912,7 +914,7 @@ quiver3d :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer (int or long). Default: 8 + phi. Must be an integer. Default: 8 :scalars: optional scalar data. @@ -935,7 +937,8 @@ quiver3d -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -1011,9 +1014,6 @@ surf Default: 2.0 :mask: boolean mask array to suppress some data points. - Note: this works based on colormapping of scalars and will - not work if you specify a solid color using the - `color` keyword. :name: the name of the vtk object created. @@ -1055,7 +1055,8 @@ surf -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: @@ -1119,14 +1120,11 @@ triangular_mesh Default: 2.0 :mask: boolean mask array to suppress some data points. - Note: this works based on colormapping of scalars and will - not work if you specify a solid color using the - `color` keyword. :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer - (int or long) or None. + points displayed on large datasets Must be an integer or + None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -1148,7 +1146,7 @@ triangular_mesh :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer (int or long). Default: 8 + phi. Must be an integer. Default: 8 :scalars: optional scalar data. @@ -1166,8 +1164,7 @@ triangular_mesh lines, in mesh mode. If None, simple lines are used. :tube_sides: number of sides of the tubes used to - represent the lines. Must be an integer (int or long). - Default: 6 + represent the lines. Must be an integer. Default: 6 :vmax: vmax is used to scale the colormap. If None, the max of the data will be used @@ -1177,7 +1174,8 @@ triangular_mesh -**Example** (run in ``ipython --gui=qt``, or in the mayavi2 interactive shell, +**Example** (run in ``ipython -wthread``, ``ipython --gui=wx`` for recent +IPython versions, or in the mayavi2 interactive shell, see :ref:`running-mlab-scripts` for more info):: diff --git a/docs/source/mayavi/auto/mlab_pipeline_other_functions.rst b/docs/source/mayavi/auto/mlab_pipeline_other_functions.rst index e4d7203da..83348d9a7 100644 --- a/docs/source/mayavi/auto/mlab_pipeline_other_functions.rst +++ b/docs/source/mayavi/auto/mlab_pipeline_other_functions.rst @@ -497,8 +497,8 @@ glyph :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer - (int or long) or None. + points displayed on large datasets Must be an integer or + None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -516,7 +516,7 @@ glyph :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer (int or long). Default: 8 + phi. Must be an integer. Default: 8 :scale_factor: the scaling applied to the glyphs. The size of the glyph is by default in drawing @@ -1201,8 +1201,7 @@ streamline added to the scene. Defaults to True. :seed_resolution: The resolution of the seed. Determines the number of - seed points Must be an integer (int or long) or - None. + seed points Must be an integer or None. :seed_scale: Scales the seed around its default center Must be a float. Default: 1.0 @@ -1510,8 +1509,7 @@ tube lines. Must be a float. Default: 0.05 :tube_sides: number of sides of the tubes used to - represent the lines. Must be an integer (int or long). - Default: 6 + represent the lines. Must be an integer. Default: 6 @@ -1568,8 +1566,8 @@ vector_cut_plane :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer - (int or long) or None. + points displayed on large datasets Must be an integer or + None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -1590,7 +1588,7 @@ vector_cut_plane :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer (int or long). Default: 8 + phi. Must be an integer. Default: 8 :scale_factor: the scaling applied to the glyphs. The size of the glyph is by default in drawing @@ -1644,8 +1642,8 @@ vectors :mask_points: If supplied, only one out of 'mask_points' data point is displayed. This option is useful to reduce the number of - points displayed on large datasets Must be an integer - (int or long) or None. + points displayed on large datasets Must be an integer or + None. :mode: the mode of the glyphs. Must be '2darrow' or '2dcircle' or '2dcross' or '2ddash' or '2ddiamond' or '2dhooked_arrow' or @@ -1663,7 +1661,7 @@ vectors :resolution: The resolution of the glyph created. For spheres, for instance, this is the number of divisions along theta and - phi. Must be an integer (int or long). Default: 8 + phi. Must be an integer. Default: 8 :scale_factor: the scaling applied to the glyphs. The size of the glyph is by default in drawing diff --git a/docs/source/mayavi/auto/mlab_pipeline_sources.rst b/docs/source/mayavi/auto/mlab_pipeline_sources.rst index 83369046d..3a492ce00 100644 --- a/docs/source/mayavi/auto/mlab_pipeline_sources.rst +++ b/docs/source/mayavi/auto/mlab_pipeline_sources.rst @@ -62,7 +62,7 @@ array2d_source builtin_image ~~~~~~~~~~~~~ -.. function:: builtin_image(metadata=) +.. function:: builtin_image(metadata=) Create a vtk image data source @@ -73,7 +73,7 @@ builtin_image builtin_surface ~~~~~~~~~~~~~~~ -.. function:: builtin_surface(metadata=) +.. function:: builtin_surface(metadata=) Create a vtk poly data source @@ -84,7 +84,7 @@ builtin_surface chaco_file ~~~~~~~~~~ -.. function:: chaco_file(metadata=) +.. function:: chaco_file(metadata=) Open a Chaco file @@ -178,7 +178,7 @@ open parametric_surface ~~~~~~~~~~~~~~~~~~ -.. function:: parametric_surface(metadata=) +.. function:: parametric_surface(metadata=) Create a parametric surface source @@ -189,7 +189,7 @@ parametric_surface point_load ~~~~~~~~~~ -.. function:: point_load(metadata=) +.. function:: point_load(metadata=) Simulates a point load on a cube of data (for tensors) @@ -429,7 +429,7 @@ vertical_vectors_source volume_file ~~~~~~~~~~~ -.. function:: volume_file(metadata=) +.. function:: volume_file(metadata=) Open a Volume file From bd68dd67ee3d2156b27b5a6be1178dda146e27b8 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 17 Mar 2016 16:57:08 +0000 Subject: [PATCH 11/32] improve comment and function's order --- integrationtests/mayavi/test_mlab_savefig.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py index 30fd8a7f0..9e23f72b5 100644 --- a/integrationtests/mayavi/test_mlab_savefig.py +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -21,9 +21,9 @@ def create_quiver3d(): mlab.quiver3d(x, y, z, u, v, w, scalars=s) -# Note: the figure size is delibrately set to be smaller than -# the required size during `savefig`, this forces the re-rendering -# to occur and catch any potential ill rendering +# Note: the figure(window) size is delibrately set to be smaller than +# the required size in `savefig`, this forces the re-rendering to +# occur and catch any potential ill rendering class TestMlabSavefigUnitTest(unittest.TestCase): @@ -35,6 +35,9 @@ def setUp(self): # this ensures that the temporary directory is removed self.addCleanup(self.remove_tempdir) + def remove_tempdir(self): + shutil.rmtree(self.temp_dir) + def setup_engine_and_figure(self, engine): # Set up a Engine/OffScreenEngine/... for the test case self.engine = engine @@ -56,9 +59,6 @@ def cleanup_engine(self, engine): engine.close_scene(scene) engine.stop() - def remove_tempdir(self): - shutil.rmtree(self.temp_dir) - def test_savefig(self): """Test if savefig works with auto size, mag and a normal Engine""" self.setup_engine_and_figure(Engine()) From b0351698743057b1f105ee8032e45776c7deff71 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 17 Mar 2016 17:25:56 +0000 Subject: [PATCH 12/32] fix lanaguage in the comment [ci skip] --- tvtk/pyface/ui/wx/scene.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tvtk/pyface/ui/wx/scene.py b/tvtk/pyface/ui/wx/scene.py index 01efd64d0..e5c0751e9 100644 --- a/tvtk/pyface/ui/wx/scene.py +++ b/tvtk/pyface/ui/wx/scene.py @@ -681,9 +681,9 @@ def _do_idle(event, window=window): def _lift(self): """Lift the window to the top. Useful when saving screen to an image.""" - ## The image size would be wrong if we don't lift the - ## the window even when off_screen_rendering is On - ## because the OnSize event is not being called anymore + ## Even when off_screen_rendering is On, the image size would + ## be wrong if we don't lift the window because the OnSize + ## event would not be called anymore # if self.render_window.off_screen_rendering: # # Do nothing if off screen rendering is being used. # return From a09a1a380267ef4db0cf215fc50bc68c932295d8 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 24 Mar 2016 14:06:36 +0000 Subject: [PATCH 13/32] figure should be passed mlab.quiver3d in the test cases --- integrationtests/mayavi/test_mlab_savefig.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py index 9e23f72b5..8fef164b3 100644 --- a/integrationtests/mayavi/test_mlab_savefig.py +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -14,11 +14,11 @@ from common import TestCase -def create_quiver3d(): +def create_quiver3d(figure): x, y, z = numpy.mgrid[1:10, 1:10, 1:10] u, v, w = numpy.mgrid[1:10, 1:10, 1:10] s = numpy.sqrt(u**2 + v**2) - mlab.quiver3d(x, y, z, u, v, w, scalars=s) + mlab.quiver3d(x, y, z, u, v, w, scalars=s, figure=figure) # Note: the figure(window) size is delibrately set to be smaller than @@ -64,7 +64,7 @@ def test_savefig(self): self.setup_engine_and_figure(Engine()) # Set up the scene - create_quiver3d() + create_quiver3d(figure=self.figure) # save the figure (magnification is default "auto") savefig(self.filename, figure=self.figure) @@ -77,7 +77,7 @@ def test_savefig_with_size(self): self.setup_engine_and_figure(Engine()) # Set up the scene - create_quiver3d() + create_quiver3d(figure=self.figure) # save the figure (magnification is default "auto") savefig(self.filename, size=(131, 217), figure=self.figure) @@ -93,7 +93,7 @@ def test_savefig_with_size_offscreen(self): self.setup_engine_and_figure(OffScreenEngine()) # Set up the scene - create_quiver3d() + create_quiver3d(figure=self.figure) # save the figure savefig(self.filename, size=(131, 217), figure=self.figure) @@ -106,7 +106,7 @@ def test_savefig_with_size_and_magnification(self): self.setup_engine_and_figure(Engine()) # Set up the scene - create_quiver3d() + create_quiver3d(figure=self.figure) # save the figure savefig(self.filename, size=(131, 217), magnification=2, @@ -126,7 +126,7 @@ def test_savefig_with_size_and_magnification_offscreen(self): self.figure.scene.off_screen_rendering = True # Set up the scene - create_quiver3d() + create_quiver3d(figure=self.figure) # save the figure savefig(self.filename, size=(131, 217), magnification=2, @@ -146,7 +146,7 @@ def test_savefig_with_size_and_magnification_offscreen_with_engine(self): self.figure.scene.off_screen_rendering = True # Set up the scene - create_quiver3d() + create_quiver3d(figure=self.figure) # save the figure savefig(self.filename, size=(131, 217), magnification=2, From 19529f8078748ae2e3ccc870602d4fb71f0ee105 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 24 Mar 2016 14:07:17 +0000 Subject: [PATCH 14/32] calling the resize functions for two IdleEvent causes size to be wrong on MacOS --- tvtk/pyface/ui/wx/scene.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tvtk/pyface/ui/wx/scene.py b/tvtk/pyface/ui/wx/scene.py index e5c0751e9..e0bc90abb 100644 --- a/tvtk/pyface/ui/wx/scene.py +++ b/tvtk/pyface/ui/wx/scene.py @@ -658,21 +658,23 @@ def _show_parent_hack(window, parent): # messed up when the application window is shown. To work # around this a dynamic IDLE event handler is added and # immediately removed once it executes. This event handler - # simply forces a resize to occur. The _idle_count allows us - # to execute the idle function a few times (this seems to work - # better). + # simply forces a resize to occur. Previously this event + # handler is excecuted for the first two idle events. + # However this has caused scene.save to effectively ignore + # the `size` attribute on Mac OS (i.e. scene.save resizes the + # render window to the target size but then the idle handler + # resize it back to the old size before an image is saved. + # Since resizing once seems to be efficient, the idle handler + # is only called for the first idle event. def _do_idle(event, window=window): w = wx.GetTopLevelParent(window) # Force a resize sz = w.GetSize() w.SetSize((sz[0]-1, sz[1]-1)) w.SetSize(sz) - window._idle_count -= 1 - if window._idle_count < 1: - wx.EVT_IDLE(window, None) - del window._idle_count + # Remove the handler + wx.EVT_IDLE(window, None) - window._idle_count = 2 wx.EVT_IDLE(window, _do_idle) self._interactor = tvtk.to_tvtk(window._Iren) From 2b218a8cf32cf9c710b0a075499bec6cdf7ec613 Mon Sep 17 00:00:00 2001 From: Kit Date: Tue, 29 Mar 2016 11:35:06 +0100 Subject: [PATCH 15/32] modified docstring for savefig --- mayavi/tools/figure.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mayavi/tools/figure.py b/mayavi/tools/figure.py index 54159af31..f25374555 100644 --- a/mayavi/tools/figure.py +++ b/mayavi/tools/figure.py @@ -217,9 +217,6 @@ def savefig(filename, size=None, figure=None, magnification='auto', **Notes** - If the size specified is larger than the window size, and no - magnification parameter is passed, the magnification of the scene - is changed so that the image created has the requested size. Please note that if you are trying to save images with sizes larger than the window size, there will be additional computation cost. @@ -238,8 +235,8 @@ def savefig(filename, size=None, figure=None, magnification='auto', figure.scene.magnification = int(magnification) figure.scene.save(filename, - size=size, - **kwargs) + size=size, + **kwargs) finally: figure.scene.magnification = int(current_mag) From af88c5acb23efc5b64f5074309649d809c0d0072 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Tue, 29 Mar 2016 15:00:34 +0100 Subject: [PATCH 16/32] remove OnPaint handler after the scene is closed --- tvtk/pyface/ui/wx/scene.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tvtk/pyface/ui/wx/scene.py b/tvtk/pyface/ui/wx/scene.py index e0bc90abb..09e940888 100644 --- a/tvtk/pyface/ui/wx/scene.py +++ b/tvtk/pyface/ui/wx/scene.py @@ -571,6 +571,10 @@ def OnButtonUp(self, event): def _closed_fired(self): super(Scene, self)._closed_fired() self.picker = None + # Remove OnPaint handler for PaintEvent, otherwise + # OnPaint tries to reset the size of the nonexisting + # renderwindow + wx.EVT_PAINT(self._vtk_control, None) self._vtk_control = None ########################################################################### From c00b284f69a07a8fdb5429d22dbd77165ca5f5e4 Mon Sep 17 00:00:00 2001 From: Kit Date: Thu, 31 Mar 2016 13:51:47 +0100 Subject: [PATCH 17/32] create a new render window for snapshot --- tvtk/pyface/tvtk_scene.py | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index 9781277be..0e39e105e 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -403,10 +403,37 @@ def save(self, file_name, size=None, **kw_args): ) meth = getattr(self, 'save_' + meth_map[ext]) if size is not None: - orig_size = self.get_size() - self.set_size(size) + # We create a RenderWindow of the requested size + # instead of resizing the existing one + orig_renwin = self.render_window + renderer = self.renderer + + # temporarily remove the render from the render window + orig_renwin.remove_renderer(renderer) + + # new render window only used here for saving the image + temp_renwin = tvtk.RenderWindow( + size=size, + off_screen_rendering=orig_renwin.off_screen_rendering, + stereo_capable_window=orig_renwin.stereo_capable_window, + stereo_type=orig_renwin.stereo_type, + stereo_render=orig_renwin.stereo_render + ) + temp_renwin.add_renderer(renderer) + temp_renwin.render() + + self._renwin = temp_renwin meth(file_name, **kw_args) - self.set_size(orig_size) + self._renwin = orig_renwin + + # dispose of the render window for saving image + temp_renwin.remove_renderer(renderer) + del temp_renwin + + # Give the renderer back to the original render window + orig_renwin.add_renderer(renderer) + orig_renwin.render() + self._record_methods('save(%r, %r)'%(file_name, size)) else: meth(file_name, **kw_args) From 0597d502f3be586a6412969e02f542ad71b519b0 Mon Sep 17 00:00:00 2001 From: Kit Date: Thu, 31 Mar 2016 13:55:49 +0100 Subject: [PATCH 18/32] revert lifting the window for offscreen rendering in wx --- tvtk/pyface/ui/wx/scene.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tvtk/pyface/ui/wx/scene.py b/tvtk/pyface/ui/wx/scene.py index 09e940888..26e11e5ae 100644 --- a/tvtk/pyface/ui/wx/scene.py +++ b/tvtk/pyface/ui/wx/scene.py @@ -687,12 +687,9 @@ def _do_idle(event, window=window): def _lift(self): """Lift the window to the top. Useful when saving screen to an image.""" - ## Even when off_screen_rendering is On, the image size would - ## be wrong if we don't lift the window because the OnSize - ## event would not be called anymore - # if self.render_window.off_screen_rendering: - # # Do nothing if off screen rendering is being used. - # return + if self.render_window.off_screen_rendering: + # Do nothing if off screen rendering is being used. + return w = self._vtk_control while w and not w.IsTopLevel(): From 233d9931245a848b9f0ed2f19b445c28463729d8 Mon Sep 17 00:00:00 2001 From: Kit Date: Thu, 31 Mar 2016 13:58:37 +0100 Subject: [PATCH 19/32] added test for magnification and check for black spot --- integrationtests/mayavi/test_mlab_savefig.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py index 8fef164b3..b466b2dd4 100644 --- a/integrationtests/mayavi/test_mlab_savefig.py +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -85,6 +85,19 @@ def test_savefig_with_size(self): # check self.check_image((217, 131)) + def test_savefig_with_magnification(self): + """Test savefig with given magnification and a normal Engine""" + self.setup_engine_and_figure(Engine()) + + # Set up the scene + create_quiver3d(figure=self.figure) + + # save the figure with a magnification + savefig(self.filename, magnification=2, figure=self.figure) + + # check + self.check_image() + @unittest.skipIf(os.environ.get("TRAVIS", False), ("Offscreen rendering is not tested on Travis " "due to lack of GLX support")) @@ -162,6 +175,11 @@ def check_image(self, size=None): if size: self.assertEqual(image.shape[:2], size) + # check if the image has black spots + if (numpy.sum(image == [0, 0, 0], axis=2) == 3).any(): + message = "The image has black spots" + self.fail(message) + class TestMlabSavefig(TestCase): From e3e0c8d0336521d81474865c88cb9b46fea245df Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 15:12:07 +0100 Subject: [PATCH 20/32] check stereo/off_screen_rendering for older version of VTK --- tvtk/pyface/tvtk_scene.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index 0e39e105e..9593b1107 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -412,28 +412,31 @@ def save(self, file_name, size=None, **kw_args): orig_renwin.remove_renderer(renderer) # new render window only used here for saving the image - temp_renwin = tvtk.RenderWindow( - size=size, - off_screen_rendering=orig_renwin.off_screen_rendering, - stereo_capable_window=orig_renwin.stereo_capable_window, - stereo_type=orig_renwin.stereo_type, - stereo_render=orig_renwin.stereo_render - ) + temp_renwin = tvtk.RenderWindow(size=size) + + # older VTK may not support offscreen rendering + if orig_renwin.off_screen_rendering: + temp_renwin.off_screen_rendering = orig_renwin.off_screen_rendering + + # older VTK may not support stereo rendering + if orig_renwin.stereo_render: + temp_renwin.set( + stereo_capable_window=orig_renwin.stereo_capable_window, + stereo_type=orig_renwin.stereo_type, + stereo_render=True) + temp_renwin.add_renderer(renderer) temp_renwin.render() self._renwin = temp_renwin meth(file_name, **kw_args) - self._renwin = orig_renwin - - # dispose of the render window for saving image - temp_renwin.remove_renderer(renderer) - del temp_renwin # Give the renderer back to the original render window + temp_renwin.remove_renderer(renderer) orig_renwin.add_renderer(renderer) orig_renwin.render() + self._renwin = orig_renwin self._record_methods('save(%r, %r)'%(file_name, size)) else: meth(file_name, **kw_args) From 7ce1d5b5c8a72ade3a88bb531996c8ba55b0591c Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 15:12:40 +0100 Subject: [PATCH 21/32] read_front_buffer = False --- tvtk/pyface/tvtk_scene.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index 9593b1107..3fa26dc63 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -446,8 +446,7 @@ def save_ps(self, file_name): """Saves the rendered scene to a rasterized PostScript image. For vector graphics use the save_gl2ps method.""" if len(file_name) != 0: - w2if = tvtk.WindowToImageFilter(read_front_buffer= - not self.off_screen_rendering) + w2if = tvtk.WindowToImageFilter(read_front_buffer=False) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin @@ -459,8 +458,7 @@ def save_ps(self, file_name): def save_bmp(self, file_name): """Save to a BMP image file.""" if len(file_name) != 0: - w2if = tvtk.WindowToImageFilter(read_front_buffer= - not self.off_screen_rendering) + w2if = tvtk.WindowToImageFilter(read_front_buffer=False) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin @@ -472,8 +470,7 @@ def save_bmp(self, file_name): def save_tiff(self, file_name): """Save to a TIFF image file.""" if len(file_name) != 0: - w2if = tvtk.WindowToImageFilter(read_front_buffer= - not self.off_screen_rendering) + w2if = tvtk.WindowToImageFilter(read_front_buffer=False) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin @@ -485,8 +482,7 @@ def save_tiff(self, file_name): def save_png(self, file_name): """Save to a PNG image file.""" if len(file_name) != 0: - w2if = tvtk.WindowToImageFilter(read_front_buffer= - not self.off_screen_rendering) + w2if = tvtk.WindowToImageFilter(read_front_buffer=False) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin @@ -502,8 +498,7 @@ def save_jpg(self, file_name, quality=None, progressive=None): if len(file_name) != 0: if not quality and not progressive: quality, progressive = self.jpeg_quality, self.jpeg_progressive - w2if = tvtk.WindowToImageFilter(read_front_buffer= - not self.off_screen_rendering) + w2if = tvtk.WindowToImageFilter(read_front_buffer=False) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin From af81647fe36932bfcc178c4e0266dbf7434216f7 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 15:16:49 +0100 Subject: [PATCH 22/32] finalize temporary render window --- tvtk/pyface/tvtk_scene.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index 3fa26dc63..98853bc70 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -433,6 +433,7 @@ def save(self, file_name, size=None, **kw_args): # Give the renderer back to the original render window temp_renwin.remove_renderer(renderer) + temp_renwin.finalize() orig_renwin.add_renderer(renderer) orig_renwin.render() From 194e89d9759034783c744815b559f5aa77657f3c Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 16:40:06 +0100 Subject: [PATCH 23/32] use interactor if not on Mac --- tvtk/pyface/tvtk_scene.py | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index 98853bc70..d2b057a11 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -13,6 +13,7 @@ from __future__ import print_function +import sys import os.path from apptools.persistence import state_pickler @@ -405,6 +406,8 @@ def save(self, file_name, size=None, **kw_args): if size is not None: # We create a RenderWindow of the requested size # instead of resizing the existing one + + # Original render window and renderer orig_renwin = self.render_window renderer = self.renderer @@ -412,11 +415,12 @@ def save(self, file_name, size=None, **kw_args): orig_renwin.remove_renderer(renderer) # new render window only used here for saving the image - temp_renwin = tvtk.RenderWindow(size=size) + # set the size to (1, 1) in case of offscreen rendering + temp_renwin = tvtk.RenderWindow(size=(1, 1)) # older VTK may not support offscreen rendering if orig_renwin.off_screen_rendering: - temp_renwin.off_screen_rendering = orig_renwin.off_screen_rendering + temp_renwin.off_screen_rendering = True # older VTK may not support stereo rendering if orig_renwin.stereo_render: @@ -425,10 +429,26 @@ def save(self, file_name, size=None, **kw_args): stereo_type=orig_renwin.stereo_type, stereo_render=True) - temp_renwin.add_renderer(renderer) - temp_renwin.render() + # We need an interactor to contain the RenderWindow so that + # upon resizing an offscreen window, the window does not pop up + # Mar 30, 2016: On Mac OSX with vtkCocoaRenderWindow, this + # causes the rendering to fail upon resizing + if sys.platform != "darwin": + interactor = tvtk.RenderWindowInteractor(render_window=temp_renwin) + interactor.initialize() + temp_renwin.add_renderer(renderer) + + # resize to the requested size + interactor.size = size + temp_renwin.size = size + interactor.render() + else: + temp_renwin.add_renderer(renderer) + temp_renwin.size = size self._renwin = temp_renwin + + # More rendering occurs in the save method meth(file_name, **kw_args) # Give the renderer back to the original render window @@ -437,7 +457,9 @@ def save(self, file_name, size=None, **kw_args): orig_renwin.add_renderer(renderer) orig_renwin.render() + # Restore the render window self._renwin = orig_renwin + self._record_methods('save(%r, %r)'%(file_name, size)) else: meth(file_name, **kw_args) From e83050f174bc5e9a9841a7cc81b9e84ccd677b78 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 16:50:08 +0100 Subject: [PATCH 24/32] force offscreen for the temporary renderwindow for better user experience --- tvtk/pyface/tvtk_scene.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index d2b057a11..d7d9e16e7 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -415,12 +415,10 @@ def save(self, file_name, size=None, **kw_args): orig_renwin.remove_renderer(renderer) # new render window only used here for saving the image - # set the size to (1, 1) in case of offscreen rendering - temp_renwin = tvtk.RenderWindow(size=(1, 1)) - - # older VTK may not support offscreen rendering - if orig_renwin.off_screen_rendering: - temp_renwin.off_screen_rendering = True + # set the size to (1, 1) and off_screen_rendering + # to prevent this window from showing + temp_renwin = tvtk.RenderWindow( + size=(1, 1), off_screen_rendering=True) # older VTK may not support stereo rendering if orig_renwin.stereo_render: From e6563e7b538e4d616d0b84f1b90b3a6e8163c498 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 17:07:41 +0100 Subject: [PATCH 25/32] safer to use offscreen rendering only when directed --- tvtk/pyface/tvtk_scene.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index d7d9e16e7..0c919126d 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -415,10 +415,10 @@ def save(self, file_name, size=None, **kw_args): orig_renwin.remove_renderer(renderer) # new render window only used here for saving the image - # set the size to (1, 1) and off_screen_rendering - # to prevent this window from showing + # set the size to (1, 1) in case of off_screen_rendering + # this window would not be shown temp_renwin = tvtk.RenderWindow( - size=(1, 1), off_screen_rendering=True) + size=(1, 1), off_screen_rendering=self.off_screen_rendering) # older VTK may not support stereo rendering if orig_renwin.stereo_render: From 30e6e2b9f758bbf56e19acc31c3d592afb62c04e Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 17:31:56 +0100 Subject: [PATCH 26/32] use interactor to hold the render window when offscreen is true and not on Mac --- tvtk/pyface/tvtk_scene.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index 0c919126d..8a1a9063a 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -431,7 +431,7 @@ def save(self, file_name, size=None, **kw_args): # upon resizing an offscreen window, the window does not pop up # Mar 30, 2016: On Mac OSX with vtkCocoaRenderWindow, this # causes the rendering to fail upon resizing - if sys.platform != "darwin": + if sys.platform != "darwin" and self.off_screen_rendering: interactor = tvtk.RenderWindowInteractor(render_window=temp_renwin) interactor.initialize() temp_renwin.add_renderer(renderer) From 9b91e6dd138714d1a7ed3596267a75f0238f6538 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 17:43:40 +0100 Subject: [PATCH 27/32] clean code --- tvtk/pyface/tvtk_scene.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index 8a1a9063a..51d0a2dab 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -420,6 +420,8 @@ def save(self, file_name, size=None, **kw_args): temp_renwin = tvtk.RenderWindow( size=(1, 1), off_screen_rendering=self.off_screen_rendering) + self._renwin = temp_renwin + # older VTK may not support stereo rendering if orig_renwin.stereo_render: temp_renwin.set( @@ -434,17 +436,10 @@ def save(self, file_name, size=None, **kw_args): if sys.platform != "darwin" and self.off_screen_rendering: interactor = tvtk.RenderWindowInteractor(render_window=temp_renwin) interactor.initialize() - temp_renwin.add_renderer(renderer) - - # resize to the requested size - interactor.size = size - temp_renwin.size = size - interactor.render() - else: - temp_renwin.add_renderer(renderer) - temp_renwin.size = size - self._renwin = temp_renwin + temp_renwin.add_renderer(renderer) + temp_renwin.size = size + self.render() # More rendering occurs in the save method meth(file_name, **kw_args) From fc916f99f0b34f1599bb78683c84ac8dc3ced8c5 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 17:46:20 +0100 Subject: [PATCH 28/32] whenever render is called, disable_render should be honoured --- tvtk/pyface/tvtk_scene.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index 51d0a2dab..12734e4d8 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -448,10 +448,10 @@ def save(self, file_name, size=None, **kw_args): temp_renwin.remove_renderer(renderer) temp_renwin.finalize() orig_renwin.add_renderer(renderer) - orig_renwin.render() # Restore the render window self._renwin = orig_renwin + self.render() self._record_methods('save(%r, %r)'%(file_name, size)) else: From 8996ce29e46f850f720037539b323781ea9570bf Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Thu, 31 Mar 2016 17:52:27 +0100 Subject: [PATCH 29/32] fix comment --- tvtk/pyface/ui/wx/scene.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tvtk/pyface/ui/wx/scene.py b/tvtk/pyface/ui/wx/scene.py index 26e11e5ae..3aabb73cd 100644 --- a/tvtk/pyface/ui/wx/scene.py +++ b/tvtk/pyface/ui/wx/scene.py @@ -664,10 +664,9 @@ def _show_parent_hack(window, parent): # immediately removed once it executes. This event handler # simply forces a resize to occur. Previously this event # handler is excecuted for the first two idle events. - # However this has caused scene.save to effectively ignore - # the `size` attribute on Mac OS (i.e. scene.save resizes the - # render window to the target size but then the idle handler - # resize it back to the old size before an image is saved. + # However this causes the first resizing event after + # initialization to be effectively ignored: the idle handler + # simply resizes it back to the old size. # Since resizing once seems to be efficient, the idle handler # is only called for the first idle event. def _do_idle(event, window=window): From 2976e907d5483844e259dd29d6361406bbc8d632 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Fri, 1 Apr 2016 10:54:24 +0100 Subject: [PATCH 30/32] changes to read_front_buffer is not needed now --- tvtk/pyface/tvtk_scene.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tvtk/pyface/tvtk_scene.py b/tvtk/pyface/tvtk_scene.py index 12734e4d8..5b9e4b6bb 100644 --- a/tvtk/pyface/tvtk_scene.py +++ b/tvtk/pyface/tvtk_scene.py @@ -462,7 +462,8 @@ def save_ps(self, file_name): """Saves the rendered scene to a rasterized PostScript image. For vector graphics use the save_gl2ps method.""" if len(file_name) != 0: - w2if = tvtk.WindowToImageFilter(read_front_buffer=False) + w2if = tvtk.WindowToImageFilter(read_front_buffer= + not self.off_screen_rendering) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin @@ -474,7 +475,8 @@ def save_ps(self, file_name): def save_bmp(self, file_name): """Save to a BMP image file.""" if len(file_name) != 0: - w2if = tvtk.WindowToImageFilter(read_front_buffer=False) + w2if = tvtk.WindowToImageFilter(read_front_buffer= + not self.off_screen_rendering) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin @@ -486,7 +488,8 @@ def save_bmp(self, file_name): def save_tiff(self, file_name): """Save to a TIFF image file.""" if len(file_name) != 0: - w2if = tvtk.WindowToImageFilter(read_front_buffer=False) + w2if = tvtk.WindowToImageFilter(read_front_buffer= + not self.off_screen_rendering) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin @@ -498,7 +501,8 @@ def save_tiff(self, file_name): def save_png(self, file_name): """Save to a PNG image file.""" if len(file_name) != 0: - w2if = tvtk.WindowToImageFilter(read_front_buffer=False) + w2if = tvtk.WindowToImageFilter(read_front_buffer= + not self.off_screen_rendering) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin @@ -514,7 +518,8 @@ def save_jpg(self, file_name, quality=None, progressive=None): if len(file_name) != 0: if not quality and not progressive: quality, progressive = self.jpeg_quality, self.jpeg_progressive - w2if = tvtk.WindowToImageFilter(read_front_buffer=False) + w2if = tvtk.WindowToImageFilter(read_front_buffer= + not self.off_screen_rendering) w2if.magnification = self.magnification self._lift() w2if.input = self._renwin From 82ece3a3b64a3a10c33dde35360d2c4045878d67 Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Fri, 1 Apr 2016 12:02:01 +0100 Subject: [PATCH 31/32] better ordering of tests --- integrationtests/mayavi/test_mlab_savefig.py | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py index d8656d7c8..c3ba608b9 100644 --- a/integrationtests/mayavi/test_mlab_savefig.py +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -168,18 +168,6 @@ def test_savefig_with_size_and_magnification_offscreen_with_engine(self): # check if the image size is twice as big self.check_image((434, 262)) - def check_image(self, size=None): - image = numpy.array(Image.open(self.filename))[:, :, :3] - - # check the size is correct - if size: - self.assertEqual(image.shape[:2], size) - - # check if the image has black spots - if (numpy.sum(image == [0, 0, 0], axis=2) == 3).any(): - message = "The image has black spots" - self.fail(message) - @unittest.skipIf(os.environ.get("TRAVIS", False), ("Offscreen rendering is not tested on Travis " "due to lack of GLX support")) @@ -199,6 +187,18 @@ def test_many_savefig_offscreen(self): savefig(self.filename, size=(131, 217), figure=self.figure) + def check_image(self, size=None): + image = numpy.array(Image.open(self.filename))[:, :, :3] + + # check the size is correct + if size: + self.assertEqual(image.shape[:2], size) + + # check if the image has black spots + if (numpy.sum(image == [0, 0, 0], axis=2) == 3).any(): + message = "The image has black spots" + self.fail(message) + class TestMlabSavefig(TestCase): From f7c6e46a5180872a7682a98512daf96435853e1d Mon Sep 17 00:00:00 2001 From: Kit Yan Choi Date: Wed, 6 Apr 2016 17:44:44 +0100 Subject: [PATCH 32/32] xrange to range --- integrationtests/mayavi/test_mlab_savefig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrationtests/mayavi/test_mlab_savefig.py b/integrationtests/mayavi/test_mlab_savefig.py index c3ba608b9..0d9e06448 100644 --- a/integrationtests/mayavi/test_mlab_savefig.py +++ b/integrationtests/mayavi/test_mlab_savefig.py @@ -174,7 +174,7 @@ def test_savefig_with_size_and_magnification_offscreen_with_engine(self): def test_many_savefig_offscreen(self): """Test saving many figures offscreen""" engine = Engine() - for _ in xrange(5): + for _ in range(5): self.setup_engine_and_figure(engine) # Use off-screen rendering