class Annotater(Component):

    color = ColorTrait((0.0, 0.0, 0.0, 0.2))
    style = Trait("rectangular", TraitPrefixList(["rectangular", 'freehand']))
    annotation = Event

    traits_view = View(Group('<component>', id='component'),
                       Group('<links>', id='links'),
                       Group('color', 'style', id='annotater', style='custom'))

    #---------------------------------------------------------------------------
    # Mouse event handlers
    #---------------------------------------------------------------------------

    def _left_down_changed(self, event):
        event.handled = True
        self.window.mouse_owner = self
        self._cur_x, self._cur_y = event.x, event.y
        self._start_x, self._start_y = event.x, event.y
        return

    def _left_up_changed(self, event):
        event.handled = True
        self.window.mouse_owner = None
        if self.xy_in_bounds(event):
            self.annotation = (min(self._start_x,
                                   event.x), min(self._start_y, event.y),
                               abs(self._start_x - event.x),
                               abs(self._start_y - event.y))
        self._start_x = self._start_y = self._cur_x = self._cur_y = None
        self.redraw()
        return

    def _mouse_move_changed(self, event):
        event.handled = True
        if self._start_x is not None:
            x = max(min(event.x, self.right - 1.0), self.x)
            y = max(min(event.y, self.top - 1.0), self.y)
            if (x != self._cur_x) or (y != self._cur_y):
                self._cur_x, self._cur_y = x, y
                self.redraw()
        return

    #---------------------------------------------------------------------------
    # "Component" interface
    #---------------------------------------------------------------------------

    def _draw(self, gc):
        "Draw the contents of the control"
        if self._start_x is not None:
            with gc:
                gc.set_fill_color(self.color_)
                gc.begin_path()
                gc.rect(min(self._start_x, self._cur_x),
                        min(self._start_y, self._cur_y),
                        abs(self._start_x - self._cur_x),
                        abs(self._start_y - self._cur_y))
                gc.fill_path()
        return
class complex_value(HasTraits):
    num1 = Trait(1, TraitRange(1, 5), TraitRange(-5, -1))
    num2 = Trait(
        1,
        TraitRange(1, 5),
        TraitPrefixList("one", "two", "three", "four", "five"),
    )
    num3 = Trait(
        1,
        TraitRange(1, 5),
        TraitPrefixMap({"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}),
    )
    num4 = Trait(1, Trait(1, Tuple, slow), 10)
    num5 = Trait(1, 10, Trait(1, Tuple, slow))
Esempio n. 3
0
    def test_handler_warning(self):
        handlers = {
            "TraitDict": TraitDict,
            "TraitList": TraitList,
            "TraitTuple": TraitTuple,
            "TraitPrefixList": lambda: TraitPrefixList("one", "two"),
            "TraitPrefixMap": lambda: TraitPrefixMap({}),
        }

        for name, handler_factory in handlers.items():
            with self.subTest(handler=name):
                with warnings.catch_warnings(record=True):
                    warnings.simplefilter("error", DeprecationWarning)

                    with self.assertRaises(DeprecationWarning) as cm:
                        handler_factory()
                self.assertIn(name, str(cm.exception))
Esempio n. 4
0
class SubsetListEditor(VerticalListEditor):    
    # the name of the trait containing the names --> values dict
    conditions = Str
    
    # the name of the trait containing the metadata dict
    metadata = Str
    
    # a string to evaluate on the metadata to see if we include this condition
    # in the editor
    when = Str
    
    # override some defaults
    style = Trait("custom", TraitPrefixList('simple', 'custom', 'text', 'readonly'))
    mutable = Bool(False)
    
    # use the custom editor above, which extends the qt4.ListEditor class
    def _get_simple_editor_class(self):
        return _SubsetListEditor
Esempio n. 5
0
from __future__ import absolute_import

from pyface.ui_traits import (Alignment, Border, HasBorder, HasMargin, Image,
                             Margin, Position, convert_bitmap, convert_image)
from traits.api import (Any, Delegate, Enum, Expression, Float, HasStrictTraits,
    List, Range, Str, Trait, TraitError, TraitPrefixList, TraitType)
import six

#-------------------------------------------------------------------------
#  Trait definitions:
#-------------------------------------------------------------------------

# Orientation trait:
Orientation = Trait('vertical',
                    TraitPrefixList('vertical', 'horizontal'))

# Styles for user interface elements:
EditorStyle = style_trait = Trait(
    'simple',
    TraitPrefixList(
        'simple',
        'custom',
        'text',
        'readonly'),
    cols=4)

# Group layout trait:
Layout = Trait('normal',
               TraitPrefixList('normal', 'split', 'tabbed', 'flow', 'fold'))
Esempio n. 6
0
class Streamline(Module):

    # The version of this class.  Used for persistence.
    __version__ = 0

    # The streamline generator.
    stream_tracer = Instance(tvtk.StreamTracer, allow_none=False, record=True)

    # The seed for the streamlines.
    seed = Instance(SourceWidget, allow_none=False, record=True)

    # The update mode of the seed -- this is delegated to the
    # SourceWidget.
    update_mode = Delegate('seed', modify=True)

    # Determines if the streamlines are shown as lines or ribbons or
    # tubes.
    streamline_type = Trait('line',
                            TraitPrefixList(['line', 'ribbon', 'tube']),
                            desc='draw streamlines as lines/ribbons/tubes')

    # The ribbon filter.
    ribbon_filter = Instance(tvtk.RibbonFilter, allow_none=False, record=True)

    # The tube filter.
    tube_filter = Instance(tvtk.TubeFilter, allow_none=False, record=True)

    # The actor component that represents the visualization.
    actor = Instance(Actor, allow_none=False, record=True)

    input_info = PipelineInfo(datasets=['any'],
                              attribute_types=['any'],
                              attributes=['vectors'])

    ########################################
    # Private traits.

    _first = Bool(True)

    ########################################
    # View related code.

    # A button to update the streamlines.
    update_streamlines = Button('Update Streamlines')

    _tube_group = Group(Item(name='capping'),
                        Item(name='sides_share_vertices'),
                        Item(name='vary_radius'), Item(name='number_of_sides'),
                        Item(name='radius'), Item(name='radius_factor'),
                        Item(name='offset'), Item(name='on_ratio'))

    _ribbon_group = Group(Item(name='vary_width'), Item(name='width'),
                          Item(name='width_factor'), Item(name='angle'))

    view = View(Group(
        Group(Item(name='update_mode'), ),
        Group(
            Item(name='update_streamlines'),
            show_labels=False,
        ),
        Group(Item(name='streamline_type'),
              Item(name='ribbon_filter',
                   style='custom',
                   visible_when='object.streamline_type == "ribbon"',
                   editor=InstanceEditor(view=View(_ribbon_group))),
              Item(name='tube_filter',
                   style='custom',
                   visible_when='object.streamline_type == "tube"',
                   editor=InstanceEditor(view=View(_tube_group))),
              show_labels=False,
              label='Streamline'),
        label='Streamline'),
                Group(Item(name='seed', style='custom', resizable=True),
                      label='Seed',
                      show_labels=False),
                Group(Item(name='stream_tracer',
                           style='custom',
                           resizable=True),
                      label='StreamTracer',
                      show_labels=False),
                Group(Item(name='actor', style='custom'),
                      label='Actor',
                      show_labels=False),
                resizable=True)

    ######################################################################
    # `Module` interface
    ######################################################################
    def setup_pipeline(self):
        """Override this method so that it *creates* the tvtk
        pipeline.

        This method is invoked when the object is initialized via
        `__init__`.  Note that at the time this method is called, the
        tvtk data pipeline will *not* yet be setup.  So upstream data
        will not be available.  The idea is that you simply create the
        basic objects and setup those parts of the pipeline not
        dependent on upstream sources and filters.  You should also
        set the `actors` attribute up at this point.
        """
        # Create and setup the default objects.
        self.seed = SourceWidget()
        self.stream_tracer = tvtk.StreamTracer(
            maximum_propagation=50,
            integration_direction='forward',
            compute_vorticity=True,
            integrator_type='runge_kutta4',
        )
        self.ribbon_filter = tvtk.RibbonFilter()
        self.tube_filter = tvtk.TubeFilter()

        self.actor = Actor()
        # Setup the actor suitably for this module.
        self.actor.property.line_width = 2.0

    def update_pipeline(self):
        """Override this method so that it *updates* the tvtk pipeline
        when data upstream is known to have changed.

        This method is invoked (automatically) when any of the inputs
        sends a `pipeline_changed` event.
        """
        mm = self.module_manager
        if mm is None:
            return

        src = mm.source
        self.configure_connection(self.stream_tracer, src)
        self.seed.inputs = [src]

        # Setup the radius/width of the tube/ribbon filters based on
        # given input.
        if self._first:
            b = src.outputs[0].bounds
            l = [(b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4])]
            length = sqrt(l[0] * l[0] + l[1] * l[1] + l[2] * l[2])
            self.ribbon_filter.width = length * 0.0075
            self.tube_filter.radius = length * 0.0075
            self._first = False

        self._streamline_type_changed(self.streamline_type)
        # Set the LUT for the mapper.
        self.actor.set_lut(mm.scalar_lut_manager.lut)

        self.pipeline_changed = True

    def update_data(self):
        """Override this method so that it flushes the vtk pipeline if
        that is necessary.

        This method is invoked (automatically) when any of the inputs
        sends a `data_changed` event.
        """
        # Just set data_changed, the components should do the rest if
        # they are connected.
        self.data_changed = True

    ######################################################################
    # Non-public methods.
    ######################################################################
    def _streamline_type_changed(self, value):
        if self.module_manager is None:
            return
        st = self.stream_tracer
        rf = self.ribbon_filter
        tf = self.tube_filter
        if value == 'line':
            configure_outputs(self, st)
        elif value == 'ribbon':
            self.configure_connection(rf, st)
            configure_outputs(self, rf)
        elif value == 'tube':
            self.configure_connection(tf, st)
            configure_outputs(self, tf)
        self.render()

    def _update_streamlines_fired(self):
        self.seed.update_poly_data()
        self.stream_tracer.update()
        self.render()

    def _stream_tracer_changed(self, old, new):
        if old is not None:
            old.on_trait_change(self.render, remove=True)
        seed = self.seed
        if seed is not None:
            self.configure_source_data(new, seed.poly_data)
        new.on_trait_change(self.render)
        mm = self.module_manager
        if mm is not None:
            src = mm.source
            self.configure_connection(new, src)

        # A default output so there are no pipeline errors.  The
        # update_pipeline call corrects this if needed.
        self.outputs = [new.output]

        self.update_pipeline()

    def _seed_changed(self, old, new):
        st = self.stream_tracer
        if st is not None:
            self.configure_source_data(st, new.poly_data)
        self._change_components(old, new)

    def _ribbon_filter_changed(self, old, new):
        if old is not None:
            old.on_trait_change(self.render, remove=True)
        new.on_trait_change(self.render)
        self._streamline_type_changed(self.streamline_type)

    def _tube_filter_changed(self, old, new):
        if old is not None:
            old.on_trait_change(self.render, remove=True)
        new.on_trait_change(self.render)
        self._streamline_type_changed(self.streamline_type)

    def _actor_changed(self, old, new):
        new.scene = self.scene
        new.inputs = [self]
        self._change_components(old, new)
Esempio n. 7
0
#   object and is active only while the mouse pointer is in the dialog.
# * 'info': A temporary, frameless popup dialog that immediately updates the
#   object and is active only while the dialog is still over the invoking
#   control.
# * 'wizard': A wizard modal dialog box. A wizard contains a sequence of
#   pages, which can be accessed by clicking **Next** and **Back** buttons.
#   Changes to attribute values are applied only when the user clicks the
#   **Finish** button on the last page.
AKind = Trait(
    "live",
    TraitPrefixList(
        "panel",
        "subpanel",
        "modal",
        "nonmodal",
        "livemodal",
        "live",
        "popup",
        "popover",
        "info",
        "wizard",
    ),
    desc="the kind of view window to create",
    cols=4,
)

# Apply changes handler:
OnApply = Callable(desc="the routine to call when modal changes are applied "
                   "or reverted")

# Is the dialog window resizable?
IsResizable = Bool(False, desc="whether dialog can be resized or not")
 class A(HasTraits):
     foo = Trait("one", TraitPrefixList("zero", "one", "two"))
Esempio n. 9
0
#   the user commits the change.
# * 'nonmodal':  A nonmodal dialog box that operates on a clone of the object
#   until the user commits the change
# * 'live': A nonmodal dialog box that immediately updates the object.
# * 'livemodal': A modal dialog box that immediately updates the object.
# * 'popup': A temporary, frameless popup dialog that immediately updates the
#   object and is active only while the mouse pointer is in the dialog.
# * 'info': A temporary, frameless popup dialog that immediately updates the
#   object and is active only while the dialog is still over the invoking
#   control.
# * 'wizard': A wizard modal dialog box. A wizard contains a sequence of
#   pages, which can be accessed by clicking **Next** and **Back** buttons.
#   Changes to attribute values are applied only when the user clicks the
#   **Finish** button on the last page.
AKind = Trait('live', TraitPrefixList(
    'panel', 'subpanel', 'modal', 'nonmodal', 'livemodal',
    'live', 'popup', 'popover', 'info', 'wizard'),
    desc='the kind of view window to create',
    cols=4)

# Apply changes handler:
OnApply = Callable(desc='the routine to call when modal changes are applied '
                   'or reverted')

# Is the dialog window resizable?
IsResizable = Bool(False, desc='whether dialog can be resized or not')

# Is the view scrollable?
IsScrollable = Bool(False, desc='whether view should be scrollable or not')

# The valid categories of imported elements that can be dragged into the view:
Esempio n. 10
0
 def PrefixList(list_, default_value=None, **kwargs):
     from traits.api import Trait, TraitPrefixList
     if default_value is None:
         default_value = list_[0]
     return Trait(default_value, TraitPrefixList(list_), **kwargs)
Esempio n. 11
0
    List,
    Range,
    Str,
    Trait,
    TraitError,
    TraitPrefixList,
    TraitType,
)
import six

# -------------------------------------------------------------------------
#  Trait definitions:
# -------------------------------------------------------------------------

# Orientation trait:
Orientation = Trait("vertical", TraitPrefixList("vertical", "horizontal"))

# Styles for user interface elements:
EditorStyle = style_trait = Trait("simple",
                                  TraitPrefixList("simple", "custom", "text",
                                                  "readonly"),
                                  cols=4)

# Group layout trait:
Layout = Trait("normal",
               TraitPrefixList("normal", "split", "tabbed", "flow", "fold"))

# Trait for the default object being edited:
AnObject = Expression("object")

# The default dock style to use:
Esempio n. 12
0
class SourceWidget(Component):

    # The version of this class.  Used for persistence.
    __version__ = 0

    # The actual poly data source widget.
    widget = Instance(tvtk.ThreeDWidget, record=True)

    # Specifies the updation mode of the poly_data attribute.  There
    # are three modes: 1) 'interactive' -- the poly_data attribute is
    # updated as the widget is interacted with, 2) 'semi-interactive'
    # -- poly_data attribute is updated when the traits of the widget
    # change and when the widget interaction is complete, 3)
    # 'non-interactive' -- poly_data is updated only explicitly at
    # users request by calling `object.update_poly_data`.
    update_mode = Trait(
        'interactive',
        TraitPrefixList(['interactive', 'semi-interactive',
                         'non-interactive']),
        desc='the speed at which the poly data is updated')

    # A list of predefined glyph sources that can be used.
    widget_list = List(tvtk.Object, record=False)

    # The poly data that the widget manages.
    poly_data = Instance(tvtk.PolyData, args=())

    ########################################
    # Private traits.

    _first = Bool(True)
    _busy = Bool(False)
    _unpickling = Bool(False)

    ########################################
    # View related traits.

    view = View(
        Group(
            Item(name='widget',
                 style='custom',
                 resizable=True,
                 editor=InstanceEditor(name='widget_list')),
            label='Source Widget',
            show_labels=False,
        ),
        resizable=True,
    )

    ######################################################################
    # `Base` interface
    ######################################################################
    def __get_pure_state__(self):
        d = super(SourceWidget, self).__get_pure_state__()
        for attr in ('poly_data', '_unpickling', '_first', '_busy'):
            d.pop(attr, None)
        return d

    def __set_pure_state__(self, state):
        self._unpickling = True
        # First create all the allowed widgets in the widget_list attr.
        handle_children_state(self.widget_list, state.widget_list)
        # Now set their state.
        set_state(self, state, first=['widget_list'], ignore=['*'])
        # Set the widget attr depending on value saved.
        m = [x.__class__.__name__ for x in self.widget_list]
        w_c_name = state.widget.__metadata__['class_name']
        w = self.widget = self.widget_list[m.index(w_c_name)]
        # Set the input.
        if len(self.inputs) > 0:
            self.configure_input_data(w, self.inputs[0].outputs[0])
        # Fix for the point widget.
        if w_c_name == 'PointWidget':
            w.place_widget()
        # Set state of rest of the attributes ignoring the widget_list.
        set_state(self, state, ignore=['widget_list'])
        # Some widgets need some cajoling to get their setup right.
        w.update_traits()
        if w_c_name == 'PlaneWidget':
            w.origin = state.widget.origin
            w.normal = state.widget.normal
            w.update_placement()
            w.get_poly_data(self.poly_data)
        elif w_c_name == 'SphereWidget':
            # XXX: This hack is necessary because the sphere widget
            # does not update its poly data even when its ivars are
            # set (plus it does not have an update_placement method
            # which is a bug).  So we force this by creating a similar
            # sphere source and copy its output.
            s = tvtk.SphereSource(center=w.center,
                                  radius=w.radius,
                                  theta_resolution=w.theta_resolution,
                                  phi_resolution=w.phi_resolution,
                                  lat_long_tessellation=True)
            s.update()
            self.poly_data.shallow_copy(s.output)
        else:
            w.get_poly_data(self.poly_data)
        self._unpickling = False
        # Set the widgets trait so that the widget is rendered if needed.
        self.widgets = [w]

    ######################################################################
    # `Component` interface
    ######################################################################
    def setup_pipeline(self):
        """Override this method so that it *creates* the tvtk
        pipeline.

        This method is invoked when the object is initialized via
        `__init__`.  Note that at the time this method is called, the
        tvtk data pipeline will *not* yet be setup.  So upstream data
        will not be available.  The idea is that you simply create the
        basic objects and setup those parts of the pipeline not
        dependent on upstream sources and filters.  You should also
        set the `actors` attribute up at this point.
        """
        # Setup the glyphs.
        sources = [
            tvtk.SphereWidget(theta_resolution=8, phi_resolution=6),
            tvtk.LineWidget(clamp_to_bounds=False),
            tvtk.PlaneWidget(),
            tvtk.PointWidget(outline=False,
                             x_shadows=False,
                             y_shadows=False,
                             z_shadows=False),
        ]
        self.widget_list = sources
        # The 'widgets' trait is set in the '_widget_changed' handler.
        self.widget = sources[0]

        for s in sources:
            self._connect(s)

    def update_pipeline(self):
        """Override this method so that it *updates* the tvtk pipeline
        when data upstream is known to have changed.

        This method is invoked (automatically) when any of the inputs
        sends a `pipeline_changed` event.
        """
        if len(self.inputs) == 0:
            return
        inp = self.inputs[0].outputs[0]
        w = self.widget
        self.configure_input(w, inp)
        if self._first:
            w.place_widget()
            self._first = False

        # If the dataset is effectively 2D switch to using the line
        # widget since that works best.
        b = inp.bounds
        l = [(b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4])]
        max_l = max(l)
        for i, x in enumerate(l):
            if x / max_l < 1.0e-6:
                w = self.widget = self.widget_list[1]
                w.clamp_to_bounds = True
                w.align = ['z_axis', 'z_axis', 'y_axis'][i]
                break

        # Set our output.
        w.get_poly_data(self.poly_data)
        self.outputs = [self.poly_data]

        self.pipeline_changed = True

    def update_data(self):
        """Override this method so that it flushes the vtk pipeline if
        that is necessary.

        This method is invoked (automatically) when any of the inputs
        sends a `data_changed` event.
        """
        self.data_changed = True

    ######################################################################
    # `SourceWidget` interface
    ######################################################################
    def update_poly_data(self):
        self.widget.get_poly_data(self.poly_data)

    ######################################################################
    # Non-public traits.
    ######################################################################
    def _widget_changed(self, value):
        # If we are being unpickled do nothing.
        if self._unpickling:
            return
        if value not in self.widget_list:
            classes = [o.__class__ for o in self.widget_list]
            vc = value.__class__
            self._connect(value)
            if vc in classes:
                self.widget_list[classes.index(vc)] = value
            else:
                self.widget_list.append(value)

        recorder = self.recorder
        if recorder is not None:
            idx = self.widget_list.index(value)
            name = recorder.get_script_id(self)
            lhs = '%s.widget' % name
            rhs = '%s.widget_list[%d]' % (name, idx)
            recorder.record('%s = %s' % (lhs, rhs))

        if len(self.inputs) > 0:
            configure_input_data(value, self.inputs[0].outputs[0])
            value.place_widget()

        value.on_trait_change(self.render)
        self.widgets = [value]

    def _update_mode_changed(self, value):
        if value in ['interactive', 'semi-interactive']:
            self.update_poly_data()
            self.render()

    def _on_interaction_event(self, obj, event):
        if (not self._busy) and (self.update_mode == 'interactive'):
            self._busy = True
            self.update_poly_data()
            self._busy = False

    def _on_widget_trait_changed(self):
        if (not self._busy) and (self.update_mode != 'non-interactive'):
            self._busy = True
            # This render call forces any changes to the trait to be
            # rendered only then will updating the poly data make
            # sense.
            self.render()
            self.update_poly_data()
            self._busy = False

    def _on_alignment_set(self):
        w = self.widget
        w.place_widget()
        w.update_traits()

    def _connect(self, obj):
        """Wires up all the event handlers."""
        obj.add_observer('InteractionEvent', self._on_interaction_event)
        if isinstance(obj, tvtk.PlaneWidget):
            obj.on_trait_change(self._on_alignment_set, 'normal_to_x_axis')
            obj.on_trait_change(self._on_alignment_set, 'normal_to_y_axis')
            obj.on_trait_change(self._on_alignment_set, 'normal_to_z_axis')
        elif isinstance(obj, tvtk.LineWidget):
            obj.on_trait_change(self._on_alignment_set, 'align')

        # Setup the widgets colors.
        fg = (1, 1, 1)
        if self.scene is not None:
            fg = self.scene.foreground
        self._setup_widget_colors(obj, fg)

        obj.on_trait_change(self._on_widget_trait_changed)
        obj.on_trait_change(self.render)

    def _setup_widget_colors(self, widget, color):
        trait_names = widget.trait_names()
        props = [
            x for x in trait_names if 'property' in x and 'selected' not in x
        ]
        sel_props = [
            x for x in trait_names if 'property' in x and 'selected' in x
        ]
        for p in props:
            setattr(getattr(widget, p), 'color', color)
            setattr(getattr(widget, p), 'line_width', 2)
        for p in sel_props:
            # Set the selected color to 'red'.
            setattr(getattr(widget, p), 'color', (1, 0, 0))
            setattr(getattr(widget, p), 'line_width', 2)
        self.render()

    def _foreground_changed_for_scene(self, old, new):
        # Change the default color for the actor.
        for w in self.widget_list:
            self._setup_widget_colors(w, new)
        self.render()

    def _scene_changed(self, old, new):
        super(SourceWidget, self)._scene_changed(old, new)
        self._foreground_changed_for_scene(None, new.foreground)
Esempio n. 13
0
class ModuleManager(Base):
    """ The module manager node (represented as 'Colors and Legends').
    """

    # The source object this is connected to.
    source = Instance(Base)

    # The modules contained by this manager.
    children = List(Module, record=True)

    # The data type to use for the LUTs.  Changing this setting will
    # change the data range and name of the lookup table/legend bar.
    # If set to 'auto', it automatically looks for cell and point data
    # with point data being preferred over cell data and chooses the
    # one available.  If set to 'point data' it uses the input point
    # data for the LUT and if set to 'cell data' it uses the input
    # cell data.
    lut_data_mode = Trait(
        'auto',
        TraitPrefixList(LUT_DATA_MODE_TYPES),
        desc='specify the data type used by the lookup tables',
    )

    # The scalar lookup table manager.
    scalar_lut_manager = Instance(LUTManager, args=(), record=True)

    # The vector lookup table manager.
    vector_lut_manager = Instance(LUTManager, args=(), record=True)

    # The name of the ModuleManager.
    name = Str('Colors and legends')

    # The icon
    icon = Str('modulemanager.ico')

    # The human-readable type for this object
    type = Str(' colors and legends')

    # Information about what this object can consume.
    input_info = PipelineInfo(datasets=['any'])

    # Information about what this object can produce.
    output_info = PipelineInfo(datasets=['any'])

    ######################################################################
    # `object` interface
    ######################################################################
    def __get_pure_state__(self):
        d = super(ModuleManager, self).__get_pure_state__()
        # Source is setup dynamically, don't pickle it.
        d.pop('source', None)
        return d

    def __set_pure_state__(self, state):
        # Do everything but our kids.
        set_state(self, state, ignore=['children'])
        # Setup children.
        handle_children_state(self.children, state.children)
        # Now setup the children.
        set_state(self, state, first=['children'], ignore=['*'])
        self.update()

    ######################################################################
    # `ModuleManager` interface
    ######################################################################
    def update(self):
        """Update any internal data.

        This is invoked when the source changes or when there are
        pipeline/data changes upstream.
        """
        if len(self.source.outputs) == 0:
            return
        self._setup_scalar_data()
        self._setup_vector_data()

    ######################################################################
    # `Base` interface
    ######################################################################
    def start(self):
        """This is invoked when this object is added to the mayavi
        pipeline.
        """
        # Do nothing if we are already running.
        if self.running:
            return

        # Setup event handlers.
        self._setup_event_handlers()

        # Start all our children.
        for obj in self.children:
            obj.start()
        for obj in (self.scalar_lut_manager, self.vector_lut_manager):
            obj.start()

        # Call parent method to set the running state.
        super(ModuleManager, self).start()

    def stop(self):
        """Invoked when this object is removed from the mayavi
        pipeline.
        """
        if not self.running:
            return

        # Teardown event handlers.
        self._teardown_event_handlers()

        # Stop all our children.
        for obj in self.children:
            obj.stop()
        for obj in (self.scalar_lut_manager, self.vector_lut_manager):
            obj.stop()

        # Call parent method to set the running state.
        super(ModuleManager, self).stop()

    def add_child(self, child):
        """This method intelligently adds a child to this object in
        the MayaVi pipeline.
        """
        if isinstance(child, Module):
            self.children.append(child)
        else:
            # Ask our source to deal with it.
            self.source.add_child(child)

    def remove_child(self, child):
        """Remove specified child from our children.
        """
        self.children.remove(child)

    ######################################################################
    # `TreeNodeObject` interface
    ######################################################################
    def tno_can_add(self, node, add_object):
        """ Returns whether a given object is droppable on the node.
        """
        try:
            if issubclass(add_object, Module):
                return True
        except TypeError:
            if isinstance(add_object, Module):
                return True
        return False

    def tno_drop_object(self, node, dropped_object):
        """ Returns a droppable version of a specified object.
        """
        if isinstance(dropped_object, Module):
            return dropped_object

    ######################################################################
    # Non-public interface
    ######################################################################
    def _children_changed(self, old, new):
        self._handle_children(old, new)

    def _children_items_changed(self, list_event):
        self._handle_children(list_event.removed, list_event.added)

    def _handle_children(self, removed, added):
        # Stop all the old children.
        for obj in removed:
            obj.stop()
        # Setup and start the new ones.
        for obj in added:
            obj.trait_set(module_manager=self, scene=self.scene, parent=self)
            if self.running:
                # It makes sense to start children only if we are running.
                # If not, the children will be started when we start.
                try:
                    obj.start()
                except:
                    exception()

    def _source_changed(self):
        self.output_info.copy_traits(self.source.output_info)
        self.update()

    def _setup_event_handlers(self):
        src = self.source
        src.on_trait_event(self.update, 'pipeline_changed')
        src.on_trait_event(self.update, 'data_changed')

    def _teardown_event_handlers(self):
        src = self.source
        src.on_trait_event(self.update, 'pipeline_changed', remove=True)
        src.on_trait_event(self.update, 'data_changed', remove=True)

    def _scene_changed(self, value):
        for obj in self.children:
            obj.scene = value
        for obj in (self.scalar_lut_manager, self.vector_lut_manager):
            obj.scene = value

    def _lut_data_mode_changed(self, value):
        self.update()

    def _setup_scalar_data(self):
        """Computes the scalar range and an appropriate name for the
        lookup table."""
        input = get_output(self.source.outputs[0])
        ps = input.point_data.scalars
        cs = input.cell_data.scalars

        data_attr = DataAttributes(name='No scalars')
        point_data_attr = DataAttributes(name='No scalars')
        point_data_attr.compute_scalar(ps, 'point')
        cell_data_attr = DataAttributes(name='No scalars')
        cell_data_attr.compute_scalar(cs, 'cell')

        if self.lut_data_mode == 'auto':
            if len(point_data_attr.range) > 0:
                data_attr.copy_traits(point_data_attr)
            elif len(cell_data_attr.range) > 0:
                data_attr.copy_traits(cell_data_attr)
        elif self.lut_data_mode == 'point data':
            data_attr.copy_traits(point_data_attr)
        elif self.lut_data_mode == 'cell data':
            data_attr.copy_traits(cell_data_attr)

        data_attr.config_lut(self.scalar_lut_manager)

    def _setup_vector_data(self):
        input = get_output(self.source.outputs[0])
        pv = input.point_data.vectors
        cv = input.cell_data.vectors

        data_attr = DataAttributes(name='No vectors')
        point_data_attr = DataAttributes(name='No vectors')
        point_data_attr.compute_vector(pv, 'point')
        cell_data_attr = DataAttributes(name='No vectors')
        cell_data_attr.compute_vector(cv, 'cell')

        if self.lut_data_mode == 'auto':
            if len(point_data_attr.range) > 0:
                data_attr.copy_traits(point_data_attr)
            elif len(cell_data_attr.range) > 0:
                data_attr.copy_traits(cell_data_attr)
        elif self.lut_data_mode == 'point data':
            data_attr.copy_traits(point_data_attr)
        elif self.lut_data_mode == 'cell data':
            data_attr.copy_traits(cell_data_attr)

        data_attr.config_lut(self.vector_lut_manager)

    def _visible_changed(self, value):
        for c in self.children:
            c.visible = value
        self.scalar_lut_manager.visible = value
        self.vector_lut_manager.visible = value

        super(ModuleManager, self)._visible_changed(value)

    def _menu_helper_default(self):
        from mayavi.core.traits_menu import ModuleMenuHelper
        return ModuleMenuHelper(object=self)
Esempio n. 14
0

from .enable_traits import spacing_trait, padding_trait, margin_trait,\
                          border_size_trait#, image_trait
from .enable_traits import position_trait, font_trait, engraving_trait
from .radio_group import RadioStyle, RadioGroup

#-------------------------------------------------------------------------------
#  Constants:
#-------------------------------------------------------------------------------

empty_text_info = (0, 0, 0, 0)
LEFT_OR_RIGHT = LEFT | RIGHT
TOP_OR_BOTTOM = TOP | BOTTOM

orientation_trait = Trait('text', TraitPrefixList(['text', 'component']))


class LabelTraits(HasTraits):

    text = Str
    font = font_trait
    text_position = position_trait("left")
    color = ColorTrait("black")
    shadow_color = ColorTrait("white")
    style = engraving_trait

    #image = image_trait
    image_position = position_trait("left")
    image_orientation = orientation_trait
Esempio n. 15
0
 class PrefixListTrait(HasTraits):
     value = Trait("one", TraitPrefixList("one", "two", "three"))
Esempio n. 16
0
# Font trait:
font_trait = KivaFont(default_font_name)

# Bounds trait
bounds_trait = CList([0.0, 0.0])  # (w,h)
coordinate_trait = CList([0.0, 0.0])  # (x,y)

#bounds_trait = Trait((0.0, 0.0, 20.0, 20.0), valid_bounds, editor=bounds_editor)

# Component minimum size trait
# PZW: Make these just floats, or maybe remove them altogether.
ComponentMinSize = Range(0.0, 99999.0)
ComponentMaxSize = ComponentMinSize(99999.0)

# Pointer shape trait:
Pointer = Trait('arrow', TraitPrefixList(pointer_shapes))

# Cursor style trait:
cursor_style_trait = Trait('default', TraitPrefixMap(cursor_styles))

spacing_trait = Range(0, 63, value=4)
padding_trait = Range(0, 63, value=4)
margin_trait = Range(0, 63)
border_size_trait = Range(0, 8, editor=border_size_editor)

# Time interval trait:
TimeInterval = Trait(None, None, Range(0.0, 3600.0))

# Stretch traits:
Stretch = Range(0.0, 1.0, value=1.0)
NoStretch = Stretch(0.0)
class SeedStreamline(Streamline):
    """
    This class is a modification of the mayavi Streamline class that accepts
    an array of seed points as a input rather than a widget.

    Examples
    --------
    Create a new Streamline instance and add it to a pipeline

    >>> from solarbextrapolation.mayavi_seed_streamlines import SeedStreamline
    >>> import numpy as np
    >>> seeds = [[1, 2, 5], [3, 4, 5]]
    >>> field_lines = SeedStreamline(seed_points = np.array(seeds)) #doctest: +SKIP
    >>> myvectorfield.add_child(field_lines) #doctest: +SKIP
    """

    seed_points = Array(allow_none=False)
    seed = Instance(tvtk.PolyData, args=())
    update_mode = Trait(
        'interactive',
        TraitPrefixList(['interactive', 'semi-interactive',
                         'non-interactive']),
        desc='the speed at which the poly data is updated')

    def setup_pipeline(self):
        """Override this method so that it *creates* the tvtk
        pipeline.

        This method is invoked when the object is initialized via
        `__init__`.  Note that at the time this method is called, the
        tvtk data pipeline will *not* yet be setup.  So upstream data
        will not be available.  The idea is that you simply create the
        basic objects and setup those parts of the pipeline not
        dependent on upstream sources and filters.  You should also
        set the `actors` attribute up at this point.
        """
        # Create and setup the default objects.
        self.seed = tvtk.PolyData(points=self.seed_points)
        self.stream_tracer = tvtk.StreamTracer(
            maximum_propagation=2000,
            integration_direction='backward',
            compute_vorticity=False,
            integrator_type='runge_kutta4',
        )
        self.ribbon_filter = tvtk.RibbonFilter()
        self.tube_filter = tvtk.TubeFilter()

        self.actor = mayavi.components.actor.Actor()
        # Setup the actor suitably for this module.
        self.actor.property.line_width = 2.0

    def update_pipeline(self):
        """Override this method so that it *updates* the tvtk pipeline
        when data upstream is known to have changed.

        This method is invoked (automatically) when any of the inputs
        sends a `pipeline_changed` event.
        """
        mm = self.module_manager
        if mm is None:
            return

        src = mm.source
        self.stream_tracer.input = src.outputs[0]
        #self.seed.inputs = [src]

        # Setup the radius/width of the tube/ribbon filters based on
        # given input.
        if self._first:
            b = src.outputs[0].bounds
            l = [(b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4])]
            length = np.sqrt(l[0] * l[0] + l[1] * l[1] + l[2] * l[2])
            self.ribbon_filter.width = length * 0.0075
            self.tube_filter.radius = length * 0.0075
            self._first = False

        self._streamline_type_changed(self.streamline_type)
        # Set the LUT for the mapper.
        self.actor.set_lut(mm.scalar_lut_manager.lut)

        self.pipeline_changed = True

    def _seed_points_changed(self, old, new):
        self.seed = tvtk.PolyData(points=self.seed_points)

    def _stream_tracer_changed(self, old, new):
        if old is not None:
            old.on_trait_change(self.render, remove=True)
        seed = self.seed
        if seed is not None:
            new.source = seed
        new.on_trait_change(self.render)
        mm = self.module_manager
        if mm is not None:
            new.input = mm.source.outputs[0]

        # A default output so there are no pipeline errors.  The
        # update_pipeline call corrects this if needed.
        self.outputs = [new.output]

        self.update_pipeline()

    def _seed_changed(self, old, new):
        st = self.stream_tracer
        if st is not None:
            st.source = new  #.poly_data
Esempio n. 18
0
class GlyphSource(Component):

    # The version of this class.  Used for persistence.
    __version__ = 1

    # Glyph position.  This can be one of ['head', 'tail', 'center'],
    # and indicates the position of the glyph with respect to the
    # input point data.  Please note that this will work correctly
    # only if you do not mess with the source glyph's basic size.  For
    # example if you use a ConeSource and set its height != 1, then the
    # 'head' and 'tail' options will not work correctly.
    glyph_position = Trait('center',
                           TraitPrefixList(['head', 'tail', 'center']),
                           desc='position of glyph w.r.t. data point')

    # The Source to use for the glyph.  This is chosen from
    # `self._glyph_list` or `self.glyph_dict`.
    glyph_source = Instance(tvtk.Object, allow_none=False, record=True)

    # A dict of glyphs to use.
    glyph_dict = Dict(desc='the glyph sources to select from', record=False)

    # A list of predefined glyph sources that can be used.
    glyph_list = Property(List(tvtk.Object), record=False)

    ########################################
    # Private traits.

    # The transformation to use to place glyph appropriately.
    _trfm = Instance(tvtk.TransformFilter, args=())

    # Used for optimization.
    _updating = Bool(False)

    ########################################
    # View related traits.

    view = View(Group(
        Group(Item(name='glyph_position')),
        Group(Item(
            name='glyph_source',
            style='custom',
            resizable=True,
            editor=InstanceEditor(name='glyph_list'),
        ),
              label='Glyph Source',
              show_labels=False)),
                resizable=True)

    ######################################################################
    # `Base` interface
    ######################################################################
    def __get_pure_state__(self):
        d = super(GlyphSource, self).__get_pure_state__()
        for attr in ('_updating', 'glyph_list'):
            d.pop(attr, None)
        return d

    def __set_pure_state__(self, state):
        if 'glyph_dict' in state:
            # Set their state.
            set_state(self, state, first=['glyph_dict'], ignore=['*'])
            ignore = ['glyph_dict']
        else:
            # Set the dict state using the persisted list.
            gd = self.glyph_dict
            gl = self.glyph_list
            handle_children_state(gl, state.glyph_list)
            for g, gs in zip(gl, state.glyph_list):
                name = camel2enthought(g.__class__.__name__)
                if name not in gd:
                    gd[name] = g
                # Set the glyph source's state.
                set_state(g, gs)
            ignore = ['glyph_list']
        g_name = state.glyph_source.__metadata__['class_name']
        name = camel2enthought(g_name)
        # Set the correct glyph_source.
        self.glyph_source = self.glyph_dict[name]
        set_state(self, state, ignore=ignore)

    ######################################################################
    # `Component` interface
    ######################################################################
    def setup_pipeline(self):
        """Override this method so that it *creates* the tvtk
        pipeline.

        This method is invoked when the object is initialized via
        `__init__`.  Note that at the time this method is called, the
        tvtk data pipeline will *not* yet be setup.  So upstream data
        will not be available.  The idea is that you simply create the
        basic objects and setup those parts of the pipeline not
        dependent on upstream sources and filters.  You should also
        set the `actors` attribute up at this point.
        """

        self._trfm.transform = tvtk.Transform()
        # Setup the glyphs.
        self.glyph_source = self.glyph_dict['glyph_source2d']

    def update_pipeline(self):
        """Override this method so that it *updates* the tvtk pipeline
        when data upstream is known to have changed.

        This method is invoked (automatically) when any of the inputs
        sends a `pipeline_changed` event.
        """
        self._glyph_position_changed(self.glyph_position)
        self.pipeline_changed = True

    def update_data(self):
        """Override this method so that it flushes the vtk pipeline if
        that is necessary.

        This method is invoked (automatically) when any of the inputs
        sends a `data_changed` event.
        """
        self.data_changed = True

    def render(self):
        if not self._updating:
            super(GlyphSource, self).render()

    ######################################################################
    # Non-public methods.
    ######################################################################
    def _glyph_source_changed(self, value):
        if self._updating:
            return

        gd = self.glyph_dict
        value_cls = camel2enthought(value.__class__.__name__)
        if value not in gd.values():
            gd[value_cls] = value

        # Now change the glyph's source trait.
        self._updating = True
        recorder = self.recorder
        if recorder is not None:
            name = recorder.get_script_id(self)
            lhs = '%s.glyph_source' % name
            rhs = '%s.glyph_dict[%r]' % (name, value_cls)
            recorder.record('%s = %s' % (lhs, rhs))

        name = value.__class__.__name__
        if name == 'GlyphSource2D':
            self.outputs = [value]
        else:
            self.configure_input(self._trfm, value)
            self.outputs = [self._trfm]
        value.on_trait_change(self.render)
        self._updating = False

        # Now update the glyph position since the transformation might
        # be different.
        self._glyph_position_changed(self.glyph_position)

    def _glyph_position_changed(self, value):
        if self._updating:
            return

        self._updating = True
        tr = self._trfm.transform
        tr.identity()

        g = self.glyph_source
        name = g.__class__.__name__
        # Compute transformation factor
        if name == 'CubeSource':
            tr_factor = g.x_length / 2.0
        elif name == 'CylinderSource':
            tr_factor = -g.height / 2.0
        elif name == 'ConeSource':
            tr_factor = g.height / 2.0
        elif name == 'SphereSource':
            tr_factor = g.radius
        else:
            tr_factor = 1.
        # Translate the glyph
        if value == 'tail':
            if name == 'GlyphSource2D':
                g.center = 0.5, 0.0, 0.0
            elif name == 'ArrowSource':
                pass
            elif name == 'CylinderSource':
                g.center = 0, tr_factor, 0.0
            elif hasattr(g, 'center'):
                g.center = tr_factor, 0.0, 0.0
        elif value == 'head':
            if name == 'GlyphSource2D':
                g.center = -0.5, 0.0, 0.0
            elif name == 'ArrowSource':
                tr.translate(-1, 0, 0)
            elif name == 'CylinderSource':
                g.center = 0, -tr_factor, 0.0
            else:
                g.center = -tr_factor, 0.0, 0.0
        else:
            if name == 'ArrowSource':
                tr.translate(-0.5, 0, 0)
            elif name != 'Axes':
                g.center = 0.0, 0.0, 0.0

        if name == 'CylinderSource':
            tr.rotate_z(90)

        self._updating = False
        self.render()

    def _get_glyph_list(self):
        # Return the glyph list as per the original order in earlier
        # implementation.
        order = [
            'glyph_source2d', 'arrow_source', 'cone_source', 'cylinder_source',
            'sphere_source', 'cube_source', 'axes'
        ]
        gd = self.glyph_dict
        for key in gd:
            if key not in order:
                order.append(key)
        return [gd[key] for key in order]

    def _glyph_dict_default(self):
        g = {
            'glyph_source2d':
            tvtk.GlyphSource2D(glyph_type='arrow', filled=False),
            'arrow_source':
            tvtk.ArrowSource(),
            'cone_source':
            tvtk.ConeSource(height=1.0, radius=0.2, resolution=15),
            'cylinder_source':
            tvtk.CylinderSource(height=1.0, radius=0.15, resolution=10),
            'sphere_source':
            tvtk.SphereSource(),
            'cube_source':
            tvtk.CubeSource(),
            'axes':
            tvtk.Axes(symmetric=1)
        }
        return g
Esempio n. 19
0
 def __init__(self, list_, **kwargs):
     super().__init__(kwargs['default_value'], TraitPrefixList(list_),
                      **kwargs)