Source code for fury.widget

"""Widgets are different than actors in that they can interact with events.

To do so they need as input a vtkRenderWindowInteractor also known as iren.
"""

import numpy as np
import vtk


[docs]def slider(iren, ren, callback, min_value=0, max_value=255, value=125, label="Slider", right_normalized_pos=(0.9, 0.5), size=(50, 0), label_format="%0.0lf", color=(0.5, 0.5, 0.5), selected_color=(0.9, 0.2, 0.1)): """ A 2D slider widget Parameters ---------- iren : vtkRenderWindowInteractor Used to process events and handle them to the slider. Can also be given by the attribute ``ShowManager.iren``. ren : vtkRenderer or Renderer Used to update the slider's position when the window changes. Can also be given by the ``ShowManager.ren`` attribute. callback : function Function that has at least ``obj`` and ``event`` as parameters. It will be called when the slider's bar has changed. min_value : float Minimum value of slider. max_value : float Maximum value of slider. value : Default value of slider. label : str Slider's caption. right_normalized_pos : tuple 2d tuple holding the normalized right (X, Y) position of the slider. size: tuple 2d tuple holding the size of the slider in pixels. label_format: str Formating in which the slider's value will appear for example "%0.2lf" allows for 2 decimal values. Returns ------- slider : SliderObject This object inherits from vtkSliderWidget and has additional method called ``place`` which allows to update the position of the slider when for example the window is resized. """ slider_rep = vtk.vtkSliderRepresentation2D() slider_rep.SetMinimumValue(min_value) slider_rep.SetMaximumValue(max_value) slider_rep.SetValue(value) slider_rep.SetTitleText(label) slider_rep.GetPoint2Coordinate().SetCoordinateSystemToNormalizedDisplay() slider_rep.GetPoint2Coordinate().SetValue(*right_normalized_pos) coord2 = slider_rep.GetPoint2Coordinate().GetComputedDisplayValue(ren) slider_rep.GetPoint1Coordinate().SetCoordinateSystemToDisplay() slider_rep.GetPoint1Coordinate().SetValue(coord2[0] - size[0], coord2[1] - size[1]) initial_window_size = ren.GetSize() length = 0.04 width = 0.04 cap_length = 0.01 cap_width = 0.01 tube_width = 0.005 slider_rep.SetSliderLength(length) slider_rep.SetSliderWidth(width) slider_rep.SetEndCapLength(cap_length) slider_rep.SetEndCapWidth(cap_width) slider_rep.SetTubeWidth(tube_width) slider_rep.SetLabelFormat(label_format) slider_rep.GetLabelProperty().SetColor(*color) slider_rep.GetTubeProperty().SetColor(*color) slider_rep.GetCapProperty().SetColor(*color) slider_rep.GetTitleProperty().SetColor(*color) slider_rep.GetSelectedProperty().SetColor(*selected_color) slider_rep.GetSliderProperty().SetColor(*color) slider_rep.GetLabelProperty().SetShadow(0) slider_rep.GetTitleProperty().SetShadow(0) class SliderWidget(vtk.vtkSliderWidget): def place(self, ren): slider_rep = self.GetRepresentation() coord2_norm = slider_rep.GetPoint2Coordinate() coord2_norm.SetCoordinateSystemToNormalizedDisplay() coord2_norm.SetValue(*right_normalized_pos) coord2 = coord2_norm.GetComputedDisplayValue(ren) slider_rep.GetPoint1Coordinate().SetCoordinateSystemToDisplay() slider_rep.GetPoint1Coordinate().SetValue(coord2[0] - size[0], coord2[1] - size[1]) window_size = ren.GetSize() length = initial_window_size[0] * 0.04 / window_size[0] width = initial_window_size[1] * 0.04 / window_size[1] slider_rep.SetSliderLength(length) slider_rep.SetSliderWidth(width) def set_value(self, value): return self.GetSliderRepresentation().SetValue(value) def get_value(self): return self.GetSliderRepresentation().GetValue() slider = SliderWidget() slider.SetInteractor(iren) slider.SetRepresentation(slider_rep) slider.SetAnimationModeToAnimate() slider.KeyPressActivationOff() slider.AddObserver("InteractionEvent", callback) slider.SetEnabled(True) # Place widget after window resizing. def _place_widget(obj, event): slider.place(ren) iren.GetRenderWindow().AddObserver( vtk.vtkCommand.StartEvent, _place_widget) iren.GetRenderWindow().AddObserver( vtk.vtkCommand.ModifiedEvent, _place_widget) return slider
[docs]def button_display_coordinates(renderer, normalized_display_position, size): upperRight = vtk.vtkCoordinate() upperRight.SetCoordinateSystemToNormalizedDisplay() upperRight.SetValue(normalized_display_position[0], normalized_display_position[1]) bds = [0.0] * 6 bds[0] = upperRight.GetComputedDisplayValue(renderer)[0] - size[0] bds[1] = bds[0] + size[0] bds[2] = upperRight.GetComputedDisplayValue(renderer)[1] - size[1] bds[3] = bds[2] + size[1] return bds
[docs]def button(iren, ren, callback, fname, right_normalized_pos=(.98, .9), size=(50, 50)): """ A textured two state button widget Parameters ---------- iren : vtkRenderWindowInteractor Used to process events and handle them to the button. Can also be given by the attribute ``ShowManager.iren``. ren : vtkRenderer or Renderer Used to update the slider's position when the window changes. Can also be given by the ``ShowManager.ren`` attribute. callback : function Function that has at least ``obj`` and ``event`` as parameters. It will be called when the button is pressed. fname : str PNG file path of the icon used for the button. right_normalized_pos : tuple 2d tuple holding the normalized right (X, Y) position of the slider. size: tuple 2d tuple holding the size of the slider in pixels. Returns ------- button : ButtonWidget This object inherits from vtkButtonWidget and has an additional method called ``place`` which allows to update the position of the slider if necessary. For example when the renderer size changes. Notes ------ The button and slider widgets have similar positioning system. This enables the developers to create a HUD-like collections of buttons and sliders on the right side of the window that always stays in place when the dimensions of the window change. """ image1 = vtk.vtkPNGReader() image1.SetFileName(fname) image1.Update() button_rep = vtk.vtkTexturedButtonRepresentation2D() button_rep.SetNumberOfStates(2) button_rep.SetButtonTexture(0, image1.GetOutput()) button_rep.SetButtonTexture(1, image1.GetOutput()) class ButtonWidget(vtk.vtkButtonWidget): def place(self, renderer): bds = button_display_coordinates(renderer, right_normalized_pos, size) self.GetRepresentation().SetPlaceFactor(1) self.GetRepresentation().PlaceWidget(bds) self.On() button = ButtonWidget() button.SetInteractor(iren) button.SetRepresentation(button_rep) button.AddObserver(vtk.vtkCommand.StateChangedEvent, callback) # Place widget after window resizing. def _place_widget(obj, event): button.place(ren) iren.GetRenderWindow().AddObserver( vtk.vtkCommand.StartEvent, _place_widget) iren.GetRenderWindow().AddObserver( vtk.vtkCommand.ModifiedEvent, _place_widget) return button
[docs]def text(iren, ren, callback, message="FURY", left_down_pos=(0.8, 0.5), right_top_pos=(0.9, 0.5), color=(1., .5, .0), opacity=1., border=False): """ 2D text that can be clicked and process events Parameters ---------- iren : vtkRenderWindowInteractor Used to process events and handle them to the button. Can also be given by the attribute ``ShowManager.iren``. ren : vtkRenderer or Renderer Used to update the slider's position when the window changes. Can also be given by the ``ShowManager.ren`` attribute. callback : function Function that has at least ``obj`` and ``event`` as parameters. It will be called when the button is pressed. message : str Message to be shown in the text widget left_down_pos : tuple Coordinates for left down corner of text. If float are provided, the normalized coordinate system is used, otherwise the coordinates represent pixel positions. Default is (0.8, 0.5). right_top_pos : tuple Coordinates for right top corner of text. If float are provided, the normalized coordinate system is used, otherwise the coordinates represent pixel positions. Default is (0.9, 0.5). color : tuple Foreground RGB color of text. Default is (1., .5, .0). opacity : float Takes values from 0 to 1. Default is 1. border : bool Show text border. Default is False. Returns ------- text : TextWidget This object inherits from ``vtkTextWidget`` has an additional method called ``place`` which allows to update the position of the text if necessary. """ # Create the TextActor text_actor = vtk.vtkTextActor() text_actor.SetInput(message) text_actor.GetTextProperty().SetColor(color) text_actor.GetTextProperty().SetOpacity(opacity) # Create the text representation. Used for positioning the text_actor text_rep = vtk.vtkTextRepresentation() text_rep.SetTextActor(text_actor) if border: text_rep.SetShowBorderToOn() else: text_rep.SetShowBorderToOff() class TextWidget(vtk.vtkTextWidget): def place(self, renderer): text_rep = self.GetRepresentation() position = text_rep.GetPositionCoordinate() position2 = text_rep.GetPosition2Coordinate() # The dtype of `left_down_pos` determines coordinate system type. if np.issubdtype(np.asarray(left_down_pos).dtype, np.integer): position.SetCoordinateSystemToDisplay() else: position.SetCoordinateSystemToNormalizedDisplay() # The dtype of `right_top_pos` determines coordinate system type. if np.issubdtype(np.asarray(right_top_pos).dtype, np.integer): position2.SetCoordinateSystemToDisplay() else: position2.SetCoordinateSystemToNormalizedDisplay() position.SetValue(*left_down_pos) position2.SetValue(*right_top_pos) text_widget = TextWidget() text_widget.SetRepresentation(text_rep) text_widget.SetInteractor(iren) text_widget.SelectableOn() text_widget.ResizableOff() text_widget.AddObserver(vtk.vtkCommand.WidgetActivateEvent, callback) # Place widget after window resizing. def _place_widget(obj, event): text_widget.place(ren) iren.GetRenderWindow().AddObserver( vtk.vtkCommand.StartEvent, _place_widget) iren.GetRenderWindow().AddObserver( vtk.vtkCommand.ModifiedEvent, _place_widget) text_widget.On() return text_widget