Open multiple files and load them into tabs

21 views
Skip to first unread message

giammar...@gmail.com

unread,
Oct 24, 2022, 1:08:24 PM10/24/22
to Enthought Tool Suite users
Dear Mayavi and ETS user,

I am trying to open multiple .vtr files from a loop and load them into tabs, here the code.
I have some problems: 1) the second element in loop in main is loaded just upon closing the Mayavi window. Is there a way to avoid it? 2) At the moment, there is a load button to trigger the loading instance, but this is not what I fancy.

I would appreciate some hints or tips.

Best regards,

Dr. Giammarco Nalin

Corran Webster

unread,
Oct 25, 2022, 4:28:30 AM10/25/22
to Enthought Tool Suite users
Hi,

the easiest way to have multiple windows to show at start-up is to call edit_traits() for all but the last view, and then call configure_traits() on the last one.  The difference is that edit_traits() just shows the view, but configure_traits() shows the view and starts the GUI event loop/application. See the TraitsUI documentation for more information.

This will open the Mayavi scenes in different windows.  If you want one window but multiple tabs there are a number of ways of doing it, but possibly the easiest way is to have a new class which holds a list of your ActorViewer classes, and uses a TraitsUI ListEditor with use_notebook=True (see the ListEditor documentation).  Code would look something like (very rough and untested):

class MainView(HasTraits):
    actor_viewers = List(Instance(ActorViewer))
    traits_view = View(
        Item(
            "actor_viewers",
            editor=ListEditor(
                style="custom",  # use the ActiveViewer View for the tab content
                use_notebook=True,
                page_name="label",  # this is the trait on ActorViewer to use for the tab name
                deletable=False,  # if True then the user can close tabs
            ),
        ),
        resizable=True,
    )

if __name__ == "__main__":
    ... # build the list of ActorViewer instances
    main_view = MainView(actor_viewers=...)
    main_view.configure_traits()

Hope this helps.

-- Corran

giammar...@gmail.com

unread,
Oct 31, 2022, 1:33:11 PM10/31/22
to Enthought Tool Suite users
Hi, thank you for your hints. I solved in the following way:
class ActorViewer(HasTraits):
    engine = Instance(Engine, ())
    scene = Instance(MlabSceneModel, ())
    path = Str
    label = Str
    view = View(Item(name='scene',
                    editor=SceneEditor(scene_class=MayaviScene),
                    show_label=False,
                    resizable=True,
                    height=500,
                    width=500
                    ),
                )

    def __init__(self, path, label, engine=None, **traits):
        self.path = path
        self.label = label
        HasTraits.__init__(self, **traits)
        self.engine.start()
        if engine is not None:
            self.scene=MlabSceneModel(engine=self.engine)
        else:
            self.scene=MlabSceneModel()

    @on_trait_change('scene.activated')
    def scene_initiation(self):
        src=self.scene.mlab.pipeline.open(self.path+self.label+'.vtr')
        self.scene.mlab.pipeline.iso_surface(src, contours=60, opacity=0.5)
        out=self.scene.mlab.pipeline.outline(src, figure=self.scene.mayavi_scene, line_width=0.5)
        out.outline_mode = "cornered"
        self.scene.render() #test to prevent active_camera error
        self.scene.mlab.view(40, 50, figure=self.scene.mayavi_scene)
        ut.actor.actor.estimated_render_time = 0.0001
        out.actor.actor.render_time_multiplier = 0.9029244662077185
        out.actor.actor.reference_count = 3


class MainView(HasTraits):
    actor_viewers = List(Instance(ActorViewer))
    traits_view = View(Item("actor_viewers"
,
                            show_label=False,
                            style="custom",
                            editor=ListEditor(style="custom",  # use the ActiveViewer View for the tab content
                                            use_notebook=True,
                                            # dock_style="tab",
                                            page_name=".label",  # this is the trait on ActorViewer to use for the tab name
                                            deletable=True,  # if True then the user can close tabs
                                            ),
                            ),
                        resizable=True,
                        title='Multiple scenes',
                        )

if __name__ == '__main__':
    filelist_sort=[]
    actor_viewers_list=[]
    abs_path = "/home/me/Documents/ddscat7.3.3_200717/"
    filelist = os.listdir(abs_path)
    for i in filelist:
        if i.endswith(".vtr"):
            filelist_sort.append(i)
    filelist_sort.sort(key=lambda f: int(re.sub('\D', '', f)))
    for i in filelist_sort:
        if ("E2_" in i):
            print("file name ", i)
            a = ActorViewer(path=abs_path,label=i.strip('.vtr'))
            actor_viewers_list.append(a)
            main_view=main_view = MainView(actor_viewers=actor_viewers_list)
    main_view.configure_traits()
but I get the following error message, despite the view is displayed correctly:

file name  E2_600_1.vtr
Exception occurred in traits notification handler for object: <__main__.ActorViewer object at 0x7f53d2ee4a90>, trait: scene, old value: <mayavi.tools.mlab_scene_model.MlabSceneModel object at 0x7f53d25f2220>, new value: <mayavi.tools.mlab_scene_model.MlabSceneModel object at 0x7f53d25ed1d0>
Traceback (most recent call last):
  File "/home/me/anaconda3/envs/mayavi/lib/python3.8/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/me/anaconda3/envs/mayavi/lib/python3.8/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/home/me/Documents/ddscat7.3.3_200717/this_code.py", line 60, in scene_initiation
    self.scene.mlab.view(40, 50, figure=self.scene.mayavi_scene)
  File "/home/me/anaconda3/envs/mayavi/lib/python3.8/site-packages/mayavi/tools/camera.py", line 255, in view
    cam = scene.camera
  File "/home/me/anaconda3/envs/mayavi/lib/python3.8/site-packages/tvtk/pyface/tvtk_scene.py", line 709, in _get_camera
    return self._renderer.active_camera
AttributeError: 'NoneType' object has no attribute 'active_camera'

Why the object is no type, although the scene has been activated?

Prabhu Ramachandran

unread,
Oct 31, 2022, 2:12:23 PM10/31/22
to giammar...@gmail.com, Enthought Tool Suite users
IIUC your entire `__init__` method is not necessary at all. Furthermore, changing the reference counts seems like a dangerous hack.  BTW, without an example I can run straight away it is hard to offer help. Please do make a standalone example without requiring additional data that is not in the mayavi repo as that makes it easier for people to help.  There are many examples you can see here: https://github.com/enthought/mayavi/tree/master/examples/mayavi/interactive

Prabhu

--
You received this message because you are subscribed to the Google Groups "Enthought Tool Suite users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ets-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ets-users/3080d798-7782-4360-9ff6-e0aac1941537n%40googlegroups.com.

giammar...@gmail.com

unread,
Nov 1, 2022, 8:00:36 AM11/1/22
to Enthought Tool Suite users
Thank you for your reply. I have tested all the suggested examples, but I still think there is no suitable solution for my case there.
The minimal example with two samples .vtr files is:
#!/usr/bin/env python
import os

# Enthought imports.
from traits.api import HasTraits, Instance, List, Str, on_trait_change
from traitsui.api import View, Item, ListEditor
from tvtk.pyface.scene_editor import SceneEditor

from mayavi.core.api import Engine
from mayavi.tools.mlab_scene_model import MlabSceneModel
from mayavi.core.ui.mayavi_scene import MayaviScene
######################################################################
class ActorViewer(HasTraits):
    #Create a mayavi scene with a specified engine
    engine = Instance(Engine, ())
    scene = Instance(MlabSceneModel, ())
    # load_next = Button('Load next')
    path = Str
    label = Str
    # # Using 'scene_class=MayaviScene' adds a Mayavi icon to the toolbar,to pop up a dialog editing the pipeline.

    view = View(Item(name='scene',
                    editor=SceneEditor(scene_class=MayaviScene),
                    show_label=False,
                    resizable=True,
                    height=500,
                    width=500

                    ),
                )

    def __init__(self, infile, label, engine=None, **traits):
        self.insrc = infile
        self.label = label
        HasTraits.__init__(self, **traits)
        self.engine.start()
        
if engine is not None:
            self.scene=MlabSceneModel(engine=self.engine)
        else:
            self.scene=MlabSceneModel()

    @on_trait_change('scene.activated')
    def scene_initiation(self):

        src=self.scene.mlab.pipeline.open(self.insrc)
        self.scene.mlab.pipeline.surface(src)
        out=self.scene.mlab.pipeline.outline(src, figure=self.scene.mayavi_scene, line_width=0.5)
        self.scene.render() #test to prevent active_camera error
        self.scene.mlab.view(40, 50, figure=self.scene.mayavi_scene)

class MainView(HasTraits):
    actor_viewers = List(Instance(ActorViewer))
    traits_view = View(Item("actor_viewers",
                            show_label=False,
                            style="custom",
                            editor=ListEditor(style="custom",  # use the ActiveViewer View for the tab content
                                            use_notebook=True,
                                            # dock_style="tab",
                                            page_name=".label",  # this is the trait on ActorViewer to use for the tab name
                                            deletable=True,  # if True then the user can close tabs
                                            ),
                            ),
                        resizable=True,
                        title='Multiple scenes',
                        )

if __name__ == '__main__'
:
    actor_viewers_list=[]
    filelist = os.listdir()
    
for i in filelist:
        if i.endswith(".vtr"
):
            a = ActorViewer(i, label=i)
            actor_viewers_list.append(a)
            main_view=main_view = MainView(actor_viewers=actor_viewers_list)
    main_view.configure_traits()

Where the __int__ is functional to the import of two variables, path and label, here not really used.

The example files can be called test.vtr and test1.vtr and located in the same folder as the .py script; they have the same content, namely:
<?xml version="1.0"?>
<VTKFile type="RectilinearGrid" version="0.1" byte_order="LittleEndian">
  <RectilinearGrid WholeExtent="0 5 0 5 0 0">
    <Piece Extent="0 5 0 5 0 0">
      <CellData Scalars="cell_scalars">
        <DataArray type="Float32" Name="cell_scalars" format="ascii">
          0.2 0.2 0.2 0.2 0.2
          0.2 0.4 0.6 0.4 0.2
          0.2 0.6 0.8 0.6 0.2
          0.2 0.4 0.6 0.4 0.2
          0.2 0.2 0.2 0.2 0.2
        </DataArray>
      </CellData>
      <PointData Scalars="colorful">
        <DataArray type="Float32" Name="colorful" format="ascii">
          0.2 0.2 0.2 0.2 0.2 0.2
          0.2 0.4 0.6 0.6 0.4 0.2
          0.2 0.6 0.8 0.8 0.6 0.2
          0.2 0.6 0.8 0.8 0.6 0.2
          0.2 0.4 0.6 0.6 0.4 0.2
          0.2 0.2 0.2 0.2 0.2 0.2
        </DataArray>
      </PointData>
      <Coordinates>
        <DataArray type="Float32" format="ascii" RangeMin="0" RangeMax="5">
          0.0 1.0 2.0 3.0 4.0 5.0
        </DataArray>
        <DataArray type="Float32" format="ascii" RangeMin="0" RangeMax="5">
          0.0 1.0 2.0 3.0 4.0 5.0
        </DataArray>
        <DataArray type="Float32" format="ascii">
          0.0
        </DataArray>
      </Coordinates>
    </Piece>
  </RectilinearGrid>
</VTKFile>
I don't understand where am I changing the reference counts. My concern is the error on the camera.

Thank you!

Prabhu Ramachandran

unread,
Nov 1, 2022, 9:29:52 AM11/1/22
to giammar...@gmail.com, Enthought Tool Suite users
Your old code had some reference counts being set. In any case, please find attached a working example. I just changed the following:

1. added an insrc Str trait
2. Removed `__init__` entirely.
3. Called ActorViewer using `ActorViewer(insrc=i, label=i)`

No errors and works correctly.

cheers,
Prabhu

test.py
Reply all
Reply to author
Forward
0 new messages