Exemple #1
0
    def SetRenderWindow(self,w):
        """ SetRenderWindow(w: vtkRenderWindow)        
        Set a new render window to QVTKWidget and initialize the
        interactor as well
        
        """
        if w == self.mRenWin:
            return
        
        if self.mRenWin:
            if system.systemType!='Linux':
                self.mRenWin.SetInteractor(None)
            if self.mRenWin.GetMapped():
                self.mRenWin.Finalize()
            
        self.mRenWin = w

        if self.mRenWin:
            self.mRenWin.Register(None)
            if self.mRenWin.GetMapped():
                self.mRenWin.Finalize()
            if system.systemType=='Linux':
                display = None
                try:
                    display = int(QtGui.QX11Info.display())
                except TypeError:
                    # This was changed for PyQt4.2
                    if isinstance(QtGui.QX11Info.display(), QtGui.Display):
                        display = sip.unwrapinstance(QtGui.QX11Info.display())
                if display is not None:
                    v = vtk.vtkVersion()
                    version = [v.GetVTKMajorVersion(),
                               v.GetVTKMinorVersion(),
                               v.GetVTKBuildVersion()]
                    display = hex(display)[2:]
                    if version < [5, 7, 0]:
                        vp = ('_%s_void_p\0x00' % display)
                    elif version < [6, 2, 0]:
                        vp = ('_%s_void_p' % display)
                    else:
                        vp = ('_%s_p_void' % display)
                    self.mRenWin.SetDisplayId(vp)
                self.resizeWindow(1,1)
            self.mRenWin.SetWindowInfo(str(int(self.winId())))
            if self.isVisible():
                self.mRenWin.Start()

            if not self.mRenWin.GetInteractor():
                #iren = vtk.vtkRenderWindowInteractor()
                iren = QVTKRenderWindowInteractor()
#                if system.systemType=='Darwin':
#                    iren.InstallMessageProcOff()
                iren.SetRenderWindow(self.mRenWin)
                iren.Initialize()
#                if system.systemType=='Linux':
#                    system.XDestroyWindow(self.mRenWin.GetGenericDisplayId(),
#                                          self.mRenWin.GetGenericWindowId())
                self.mRenWin.SetWindowInfo(str(int(self.winId())))
                self.resizeWindow(self.width(), self.height())
                self.mRenWin.SetPosition(self.x(), self.y())
Exemple #2
0
def QVTKRenderWidgetConeExample():
    """A simple example that uses the QVTKRenderWindowInteractor class."""

    # every QT app needs an app
    app = QtGui.QApplication(['QVTKRenderWindowInteractor'])

    # create the widget
    widget = QVTKRenderWindowInteractor()
    widget.Initialize()
    widget.Start()
    # if you dont want the 'q' key to exit comment this.
    widget.AddObserver("ExitEvent", lambda o, e, a=app: a.quit())

    ren = vtk.vtkRenderer()
    widget.GetRenderWindow().AddRenderer(ren)

    cone = vtk.vtkConeSource()
    cone.SetResolution(8)

    coneMapper = vtk.vtkPolyDataMapper()
    coneMapper.SetInputConnection(cone.GetOutputPort())

    coneActor = vtk.vtkActor()
    coneActor.SetMapper(coneMapper)

    ren.AddActor(coneActor)

    # show the widget
    widget.show()
    # start event processing
    app.exec_()
class RotationViewer(module_template.Viewer):
    """Uses mayavi to plot a sphere made up of small spheres as pixels. The
    colors indicate the responsability density."""
    def __init__(self, parent=None):
        super(RotationViewer, self).__init__()
        #self._widget = QtGui.QWidget(parent)
        self._vtk_widget = QVTKRenderWindowInteractor(self._widget) # _vtk_widget is actually the RenderWindowInteractor
        self._vtk_widget.SetInteractorStyle(vtk.vtkInteractorStyleRubberBandPick())

        #self._vtk_widget.Initialize()
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self._vtk_widget)
        self._widget.setLayout(layout)

        self._renderer = vtk.vtkRenderer()
        self._vtk_widget.GetRenderWindow().AddRenderer(self._renderer)

        #self._mlab_widget = embedded_mayavi.MlabWidget()
        self._setup_done = False
        self._points = None
        self._default_sphere_n = 10
        self._sphere = vtk_tools.SphereMap(self._default_sphere_n)
        self._renderer.AddViewProp(self._sphere.get_actor())
        self._renderer.SetBackground(1., 1., 1.)
        #self._renderer.Render()

    def initialize(self):
        self._vtk_widget.Initialize()

    # def get_widget(self):
    #     """Return the widget containing the view."""
    #     return self._vtk_widget

    def set_sampling_n(self, sampling_n):
        """Rerun when the array size changes."""
        self._sphere.set_n(sampling_n)

    def get_coordinates(self):
        return self._sphere.get_coordinates()

    def get_number_of_points():
        pass

    def plot_rotations(self, values):
        """Update the viewer to show the new values."""
        if len(values) != self._sphere.get_number_of_points():
            #raise ValueError("values must be array of length {0}. Length {1} array received.".format(self._sphere.get_number_of_points(), len(values)))
            sampling_n = icosahedral_sphere.points_to_n(len(values))
            self.set_sampling_n(sampling_n)
        self._sphere.set_lookup_table(vtk_tools.get_lookup_table(0., values.max(), log=False, colorscale="jet", number_of_colors=1000))
        self._sphere.set_values(values)
        #self._sphere
        #self._renderer.Render()
        self._vtk_widget.Render()
Exemple #4
0
class MeshRenderWidget(QtGui.QWidget):
    def __init__(self, tree_widget):
        QtGui.QWidget.__init__(self)
        self.tree_widget = tree_widget
        self.tree_widget.mesh_item_changed.connect(self.meshItemChanged)

        self.mesh_file_name = ''

        self.mesh_renderer = None

        self.current_block_actors = {}
        self.current_sideset_actors = {}
        self.current_nodeset_actors = {}

        self.this_layout = QtGui.QVBoxLayout()
        self.setLayout(self.this_layout)

        self.vtkwidget = QVTKRenderWindowInteractor(self)

        self.renderer = vtk.vtkRenderer()
        self.renderer.SetBackground(0.2, 0.2, 0.2)
        self.renderer.SetBackground2(1, 1, 1)
        self.renderer.SetGradientBackground(1)
        self.renderer.ResetCamera()

        self.this_layout.addWidget(self.vtkwidget)
        self.this_layout.setStretchFactor(self.vtkwidget, 10)

        self.vtkwidget.setMinimumHeight(300)

        self.vtkwidget.GetRenderWindow().AddRenderer(self.renderer)
        self.interactor = self.vtkwidget.GetRenderWindow().GetInteractor()

        self.interactor.SetInteractorStyle(
            vtk.vtkInteractorStyleTrackballCamera())

        self.vtkwidget.Initialize()
        self.vtkwidget.Start()

        self.controls_layout = QtGui.QHBoxLayout()

        self.left_controls_layout = QtGui.QVBoxLayout()

        self.block_view_group_box = QtGui.QGroupBox('Show Blocks')
        self.block_view_group_box.setMaximumWidth(150)
        #    self.block_view_group_box.setMaximumHeight(200)

        self.block_view_layout = QtGui.QVBoxLayout()
        self.block_view_list = QtGui.QListView()
        self.block_view_model = QtGui.QStandardItemModel()
        self.block_view_model.itemChanged.connect(self._blockViewItemChanged)
        self.block_view_list.setModel(self.block_view_model)
        self.block_view_layout.addWidget(self.block_view_list)

        self.block_view_group_box.setLayout(self.block_view_layout)
        self.left_controls_layout.addWidget(self.block_view_group_box)
        self.controls_layout.addLayout(self.left_controls_layout)

        self.right_controls_layout = QtGui.QVBoxLayout()
        self.controls_layout.addLayout(self.right_controls_layout)

        self.view_mesh_checkbox = QtGui.QCheckBox('View Mesh')
        self.view_mesh_checkbox.setToolTip('Toggle viewing of mesh elements')
        self.view_mesh_checkbox.setCheckState(QtCore.Qt.Checked)
        self.view_mesh_checkbox.stateChanged.connect(
            self.viewMeshCheckboxChanged)
        self.right_controls_layout.addWidget(self.view_mesh_checkbox)

        self.highlight_group_box = QtGui.QGroupBox('Highlight')
        self.highlight_group_box.setMaximumHeight(70)
        self.highlight_group_box.setSizePolicy(
            QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
        #    self.highlight_group_box.setMaximumWidth(200)
        self.highlight_layout = QtGui.QHBoxLayout()
        self.highlight_group_box.setLayout(self.highlight_layout)
        self.right_controls_layout.addWidget(self.highlight_group_box)

        self.highlight_block_label = QtGui.QLabel('Block:')
        self.highlight_block_label.setAlignment(QtCore.Qt.AlignRight
                                                | QtCore.Qt.AlignVCenter)
        self.highlight_block_combo = QtGui.QComboBox()
        #    self.highlight_block_combo.setMaximumWidth(50)
        self.highlight_block_combo.setSizeAdjustPolicy(
            QtGui.QComboBox.AdjustToMinimumContentsLength)
        self.highlight_block_combo.setSizePolicy(
            QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
        self.highlight_block_combo.setToolTip('Highlight a block in the mesh')
        self.highlight_block_combo.currentIndexChanged[str].connect(
            self.showBlockSelected)
        self.highlight_layout.addWidget(self.highlight_block_label)
        self.highlight_layout.addWidget(self.highlight_block_combo)

        self.highlight_sideset_label = QtGui.QLabel('Sideset:')
        self.highlight_sideset_label.setAlignment(QtCore.Qt.AlignRight
                                                  | QtCore.Qt.AlignVCenter)
        self.highlight_sideset_combo = QtGui.QComboBox()
        #    self.highlight_sideset_combo.setMaximumWidth(50)
        self.highlight_sideset_combo.setSizeAdjustPolicy(
            QtGui.QComboBox.AdjustToMinimumContentsLength)
        self.highlight_sideset_combo.setSizePolicy(
            QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
        self.highlight_sideset_combo.setToolTip(
            'Highlight a sideset in the mesh')
        self.highlight_sideset_combo.currentIndexChanged[str].connect(
            self.showSidesetSelected)
        self.highlight_layout.addWidget(self.highlight_sideset_label)
        self.highlight_layout.addWidget(self.highlight_sideset_combo)

        self.highlight_nodeset_label = QtGui.QLabel('Nodeset:')
        self.highlight_nodeset_label.setAlignment(QtCore.Qt.AlignRight
                                                  | QtCore.Qt.AlignVCenter)
        self.highlight_nodeset_combo = QtGui.QComboBox()
        #    self.highlight_nodeset_combo.setMaximumWidth(50)
        self.highlight_nodeset_combo.setSizeAdjustPolicy(
            QtGui.QComboBox.AdjustToMinimumContentsLength)
        self.highlight_nodeset_combo.setSizePolicy(
            QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
        self.highlight_nodeset_combo.setToolTip(
            'Highlight a nodeset in the mesh')
        self.highlight_nodeset_combo.currentIndexChanged[str].connect(
            self.showNodesetSelected)
        self.highlight_layout.addWidget(self.highlight_nodeset_label)
        self.highlight_layout.addWidget(self.highlight_nodeset_combo)

        self.highlight_clear = QtGui.QPushButton('Clear')
        self.highlight_clear.setToolTip('Clear highlighting')
        self.highlight_clear.setDisabled(True)
        self.highlight_clear.clicked.connect(self.clearHighlight)
        self.highlight_layout.addWidget(self.highlight_clear)

        self.plane = vtk.vtkPlane()
        self.plane.SetOrigin(0, 0, 0)
        self.plane.SetNormal(1, 0, 0)

        self.clip_groupbox = QtGui.QGroupBox("Clip")
        self.clip_groupbox.setToolTip(
            'Toggle clip mode to slice the mesh open along a plane')
        self.clip_groupbox.setCheckable(True)
        self.clip_groupbox.setChecked(False)
        self.clip_groupbox.setMaximumHeight(70)
        self.clip_groupbox.toggled[bool].connect(self._clippingToggled)
        clip_layout = QtGui.QHBoxLayout()

        self.clip_plane_combobox = QtGui.QComboBox()
        self.clip_plane_combobox.setToolTip(
            'Direction of the normal for the clip plane')
        self.clip_plane_combobox.addItem('x')
        self.clip_plane_combobox.addItem('y')
        self.clip_plane_combobox.addItem('z')
        self.clip_plane_combobox.currentIndexChanged[str].connect(
            self._clipNormalChanged)

        clip_layout.addWidget(self.clip_plane_combobox)

        self.clip_plane_slider = QtGui.QSlider(QtCore.Qt.Horizontal)
        self.clip_plane_slider.setToolTip('Slide to change plane position')
        self.clip_plane_slider.setRange(0, 100)
        self.clip_plane_slider.setSliderPosition(50)
        self.clip_plane_slider.sliderMoved[int].connect(self._clipSliderMoved)
        clip_layout.addWidget(self.clip_plane_slider)
        #     vbox->addStretch(1);
        self.clip_groupbox.setLayout(clip_layout)

        self.right_controls_layout.addWidget(self.clip_groupbox)

        self.this_layout.addLayout(self.controls_layout)
        self.this_layout.setStretchFactor(self.controls_layout, 1)

        self.bounds = {}
        self.bounds['x'] = [0.0, 0.0]
        self.bounds['y'] = [0.0, 0.0]
        self.bounds['z'] = [0.0, 0.0]


#    self.draw_edges_checkbox = QtGui.QCheckBox("View Mesh")

#    self.left_controls_layout.addWidget(self.draw_edges_checkbox)

    def clear(self):
        self.highlight_block_combo.clear()
        self.highlight_sideset_combo.clear()
        self.highlight_nodeset_combo.clear()

        for block_actor_name, block_actor in self.current_block_actors.items():
            block_actor.hide()

        for sideset_actor_name, sideset_actor in self.current_sideset_actors.items(
        ):
            sideset_actor.hide()

        for nodeset_actor_name, nodeset_actor in self.current_nodeset_actors.items(
        ):
            nodeset_actor.hide()

        self.current_block_actors = {}
        self.current_sideset_actors = {}
        self.current_nodeset_actors = {}

    def meshItemChanged(self, item):
        # Disconnect some actions while we fill stuff in
        if self.mesh_renderer:
            self.highlight_block_combo.currentIndexChanged[str].disconnect(
                self.showBlockSelected)
            self.highlight_sideset_combo.currentIndexChanged[str].disconnect(
                self.showSidesetSelected)
            self.highlight_nodeset_combo.currentIndexChanged[str].disconnect(
                self.showNodesetSelected)

        self.clear()

        self.mesh_renderer = RendererFactory.getRenderer(self, item.table_data)

        if self.mesh_renderer:
            self.show()
        else:
            self.hide()
            return

        self.current_block_actors = self.mesh_renderer.block_actors
        self.current_sideset_actors = self.mesh_renderer.sideset_actors
        self.current_nodeset_actors = self.mesh_renderer.nodeset_actors

        self.block_view_model.clear()
        for block in self.mesh_renderer.blocks:
            block_display_name = str(block)
            if block in self.mesh_renderer.block_id_to_name:
                block_display_name += ' : ' + self.mesh_renderer.block_id_to_name[
                    block]

            item = QtGui.QStandardItem(str(block_display_name))
            item.exodus_block = block
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
                          | QtCore.Qt.ItemIsUserCheckable)
            item.setCheckState(QtCore.Qt.Checked)
            self.block_view_model.appendRow(item)

        for block_actor_name, block_actor in self.current_block_actors.items():
            block_actor.show()
            block_actor.showEdges()

        block_names = []
        for block_actor_id, block_actor in self.current_block_actors.items():
            name = block_actor_id.strip(' ')
            if int(name) in self.mesh_renderer.block_id_to_name:
                name += ' : ' + self.mesh_renderer.block_id_to_name[int(name)]

            block_names.append(name)

        self.highlight_block_combo.addItem('')
        for block_actor_name in sorted(
                block_names, key=lambda name: int(name.split(' ')[0])):
            self.highlight_block_combo.addItem(str(block_actor_name))

        sideset_names = []
        for sideset_actor_id, sideset_actor in self.current_sideset_actors.items(
        ):
            sideset_actor.setColor(red)

            name = sideset_actor_id.strip(' ')
            if int(name) in self.mesh_renderer.sideset_id_to_name:
                name += ' : ' + self.mesh_renderer.sideset_id_to_name[int(
                    name)]

            sideset_names.append(name)

        self.highlight_sideset_combo.addItem('')
        for sideset_actor_name in sorted(
                sideset_names, key=lambda name: int(name.split(' ')[0])):
            self.highlight_sideset_combo.addItem(sideset_actor_name)

        nodeset_names = []
        for nodeset_actor_id, nodeset_actor in self.current_nodeset_actors.items(
        ):
            nodeset_actor.setColor(red)

            name = nodeset_actor_id.strip(' ')
            if int(name) in self.mesh_renderer.nodeset_id_to_name:
                name += ' : ' + self.mesh_renderer.nodeset_id_to_name[int(
                    name)]

            nodeset_names.append(name)

        self.highlight_nodeset_combo.addItem('')
        for nodeset_actor_name in sorted(
                nodeset_names, key=lambda name: int(name.split(' ')[0])):
            self.highlight_nodeset_combo.addItem(nodeset_actor_name)

        self.highlight_block_combo.currentIndexChanged[str].connect(
            self.showBlockSelected)
        self.highlight_sideset_combo.currentIndexChanged[str].connect(
            self.showSidesetSelected)
        self.highlight_nodeset_combo.currentIndexChanged[str].connect(
            self.showNodesetSelected)

        self.setBounds()

        # Avoid z-buffer fighting
        vtk.vtkPolyDataMapper().SetResolveCoincidentTopologyToPolygonOffset()

        self.renderer.ResetCamera()
        self.vtkwidget.repaint()

    def setBounds(self):
        for actor_name, actor in self.current_block_actors.items():
            current_bounds = actor.getBounds()
            self.bounds['x'][0] = min(self.bounds['x'][0], current_bounds[0])
            self.bounds['x'][1] = max(self.bounds['x'][1], current_bounds[1])

            self.bounds['y'][0] = min(self.bounds['y'][0], current_bounds[2])
            self.bounds['y'][1] = max(self.bounds['y'][1], current_bounds[3])

            self.bounds['z'][0] = min(self.bounds['z'][0], current_bounds[4])
            self.bounds['z'][1] = max(self.bounds['z'][1], current_bounds[5])

    def swapActors(self, current, new):
        for old_name, old_actor in current.items():
            new[old_name].sync(old_actor)
            old_actor.hide()

    def _blockViewItemChanged(self, item):
        if item.checkState() == QtCore.Qt.Checked:
            self.current_block_actors[str(item.exodus_block)].show()
        else:
            self.current_block_actors[str(item.exodus_block)].hide()
        self.vtkwidget.repaint()

    def _clippingToggled(self, value):
        if value:
            self.swapActors(self.current_block_actors,
                            self.mesh_renderer.clipped_block_actors)
            self.current_block_actors = self.mesh_renderer.clipped_block_actors
            self.swapActors(self.current_sideset_actors,
                            self.mesh_renderer.clipped_sideset_actors)
            self.current_sideset_actors = self.mesh_renderer.clipped_sideset_actors
            self.swapActors(self.current_nodeset_actors,
                            self.mesh_renderer.clipped_nodeset_actors)
            self.current_nodeset_actors = self.mesh_renderer.clipped_nodeset_actors

            self._clipNormalChanged(self.clip_plane_combobox.currentText())
        else:
            self.swapActors(self.current_block_actors,
                            self.mesh_renderer.block_actors)
            self.current_block_actors = self.mesh_renderer.block_actors
            self.swapActors(self.current_sideset_actors,
                            self.mesh_renderer.sideset_actors)
            self.current_sideset_actors = self.mesh_renderer.sideset_actors
            self.swapActors(self.current_nodeset_actors,
                            self.mesh_renderer.nodeset_actors)
            self.current_nodeset_actors = self.mesh_renderer.nodeset_actors

        self.vtkwidget.repaint()

    def _clipNormalChanged(self, value):
        self.plane.SetOrigin(self.bounds['x'][0], self.bounds['y'][0],
                             self.bounds['z'][0])
        if value == 'x':
            self.plane.SetNormal(1, 0, 0)
        elif value == 'y':
            self.plane.SetNormal(0, 1, 0)
        else:
            self.plane.SetNormal(0, 0, 1)

        self.clip_plane_slider.setSliderPosition(50)
        self._clipSliderMoved(50)

    def _clipSliderMoved(self, value):
        direction = str(self.clip_plane_combobox.currentText())
        step_size = (self.bounds[direction][1] -
                     self.bounds[direction][0]) / 100.0
        steps = value
        distance = float(steps) * step_size
        position = self.bounds[direction][0] + distance

        old = self.plane.GetOrigin()
        self.plane.SetOrigin(position if direction == 'x' else old[0],
                             position if direction == 'y' else old[1],
                             position if direction == 'z' else old[2])

        for actor_name, actor in self.current_sideset_actors.items():
            actor.movePlane()

        for actor_name, actor in self.current_nodeset_actors.items():
            actor.movePlane()

        for actor_name, actor in self.current_block_actors.items():
            actor.movePlane()

        self.vtkwidget.repaint()

    def viewMeshCheckboxChanged(self, value):
        if value == QtCore.Qt.Checked:
            for actor_name, actor in self.current_sideset_actors.items():
                actor.showEdges()
            for actor_name, actor in self.current_nodeset_actors.items():
                actor.showEdges()
            for actor_name, actor in self.current_block_actors.items():
                actor.showEdges()
        else:
            for actor_name, actor in self.current_sideset_actors.items():
                actor.hideEdges()
            for actor_name, actor in self.current_nodeset_actors.items():
                actor.hideEdges()
            for actor_name, actor in self.current_block_actors.items():
                actor.hideEdges()
        self.vtkwidget.repaint()

    def clearBlockComboBox(self):
        self.highlight_block_combo.currentIndexChanged[str].disconnect(
            self.showBlockSelected)
        self.highlight_block_combo.setCurrentIndex(0)
        self.highlight_block_combo.currentIndexChanged[str].connect(
            self.showBlockSelected)

    def clearSidesetComboBox(self):
        self.highlight_sideset_combo.currentIndexChanged[str].disconnect(
            self.showSidesetSelected)
        self.highlight_sideset_combo.setCurrentIndex(0)
        self.highlight_sideset_combo.currentIndexChanged[str].connect(
            self.showSidesetSelected)

    def clearNodesetComboBox(self):
        self.highlight_nodeset_combo.currentIndexChanged[str].disconnect(
            self.showNodesetSelected)
        self.highlight_nodeset_combo.setCurrentIndex(0)
        self.highlight_nodeset_combo.currentIndexChanged[str].connect(
            self.showNodesetSelected)

    def showBlockSelected(self, block_name):
        if block_name != '':
            self.clearSidesetComboBox()
            self.clearNodesetComboBox()
            self.highlightBlock(str(block_name).split(' ')[0])
        else:
            self.clearActors()

    def showSidesetSelected(self, sideset_name):
        if sideset_name != '':
            self.clearBlockComboBox()
            self.clearNodesetComboBox()
            self.highlightBoundary(str(sideset_name).split(' ')[0])
        else:
            self.clearActors()

    def showNodesetSelected(self, nodeset_name):
        if nodeset_name != '':
            self.clearBlockComboBox()
            self.clearSidesetComboBox()
            self.highlightNodeset(str(nodeset_name).split(' ')[0])
        else:
            self.clearActors()

    def highlightBoundary(self, boundary):
        self.highlight_clear.setDisabled(False)
        # Turn off all sidesets
        for actor_name, actor in self.current_sideset_actors.items():
            actor.hide()

        # Turn off all nodesets
        for actor_name, actor in self.current_nodeset_actors.items():
            actor.hide()

        # Turn solids to only edges... but only if they are visible
        for actor_name, actor in self.current_block_actors.items():
            actor.setColor(black)
            actor.goWireframe()

        boundaries = boundary.strip("'").split(' ')
        for the_boundary in boundaries:
            if the_boundary in self.current_sideset_actors:
                self.current_sideset_actors[the_boundary].show()
            elif the_boundary in self.current_nodeset_actors:
                self.current_nodeset_actors[the_boundary].show()
            elif the_boundary in self.mesh_renderer.name_to_sideset_id:
                self.current_sideset_actors[str(
                    self.mesh_renderer.name_to_sideset_id[the_boundary])].show(
                    )
            elif the_boundary in self.mesh_renderer.name_to_nodeset_id:
                self.current_nodeset_actors[str(
                    self.mesh_renderer.name_to_nodeset_id[the_boundary])].show(
                    )

        self.vtkwidget.repaint()

    def highlightNodeset(self, boundary):
        self.highlight_clear.setDisabled(False)
        # Turn off all sidesets
        for actor_name, actor in self.current_sideset_actors.items():
            actor.hide()

        # Turn off all nodesets
        for actor_name, actor in self.current_nodeset_actors.items():
            actor.hide()

        # Turn solids to only edges... but only if they are visible
        for actor_name, actor in self.current_block_actors.items():
            actor.setColor(black)
            actor.goWireframe()

        boundaries = boundary.strip("'").split(' ')
        for the_boundary in boundaries:
            if the_boundary in self.current_nodeset_actors:
                self.current_nodeset_actors[the_boundary].show()
            elif the_boundary in self.mesh_renderer.name_to_nodeset_id:
                self.current_nodeset_actors[str(
                    self.mesh_renderer.name_to_nodeset_id[the_boundary])].show(
                    )

        self.vtkwidget.repaint()

    def highlightBlock(self, block):
        self.highlight_clear.setDisabled(False)
        # Turn off all sidesets
        for actor_name, actor in self.current_sideset_actors.items():
            actor.hide()

        # Turn off all nodesets
        for actor_name, actor in self.current_nodeset_actors.items():
            actor.hide()

        # Turn solids to only edges...
        for actor_name, actor in self.current_block_actors.items():
            actor.setColor(black)
            actor.goWireframe()

        blocks = block.strip("'").split(' ')
        for the_block in blocks:
            if the_block in self.current_block_actors:
                self.current_block_actors[the_block].setColor(red)
                self.current_block_actors[the_block].goSolid()
            elif the_block in self.mesh_renderer.name_to_block_id:
                self.current_block_actors[str(
                    self.mesh_renderer.name_to_block_id[the_block])].setColor(
                        red)
                self.current_block_actors[str(
                    self.mesh_renderer.name_to_block_id[the_block])].goSolid()

        self.vtkwidget.repaint()

    def clearActors(self):
        # Turn off all sidesets
        for actor_name, actor in self.current_sideset_actors.items():
            actor.hide()

        # Turn off all nodesets
        for actor_name, actor in self.current_nodeset_actors.items():
            actor.hide()

        # Show solids and edges - but only if something is visible
        for actor_name, actor in self.current_block_actors.items():
            actor.setColor(white)
            actor.goSolid()

        self.vtkwidget.repaint()

    def clearHighlight(self):
        self.highlight_block_combo.setCurrentIndex(0)
        self.highlight_sideset_combo.setCurrentIndex(0)
        self.highlight_nodeset_combo.setCurrentIndex(0)
        self.highlight_clear.setDisabled(True)
        self.clearActors()
class Main(QtGui.QMainWindow):
    def resizeEvent(self, Event):
        pass
        #self.ModelView.resize(self.ui.ModelFrame.geometry().width()-15,self.ui.ModelFrame.geometry().height()-39)

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowTitle(
            QtGui.QApplication.translate("MainWindow", "3DLP Slicer", None,
                                         QtGui.QApplication.UnicodeUTF8))

        #load previous settings from config file here:
        self.parser = SafeConfigParser()
        filename = 'sliceconfig.ini'
        if hasattr(sys, '_MEIPASS'):
            # PyInstaller >= 1.6
            os.chdir(sys._MEIPASS)
            filename = os.path.join(sys._MEIPASS, filename)
            APPNAME = '3DLP'
            APPDATA = os.path.join(os.environ['APPDATA'], APPNAME)
            if not os.path.isdir(os.path.join(APPDATA)):
                os.mkdir(os.path.join(APPDATA))
                shutil.copy(filename, os.path.join(APPDATA, ''))
                self.parser.read(os.path.join(APPDATA, 'sliceconfig.ini'))
                self.LoadSettingsFromConfigFile()
            else:
                if not os.path.isfile(os.path.join(APPDATA,
                                                   'sliceconfig.ini')):
                    shutil.copy(filename, os.path.join(APPDATA))
                else:
                    self.parser.read(os.path.join(APPDATA, 'sliceconfig.ini'))
                    self.LoadSettingsFromConfigFile()
        else:  #otherwise it's running in pydev environment: use the dev config file
            os.chdir(os.path.dirname(sys.argv[0]))
            filename = os.path.join(os.path.dirname(sys.argv[0]), filename)
            self.parser.read('sliceconfig.ini')
            self.LoadSettingsFromConfigFile()

        self.ren = vtk.vtkRenderer()
        self.ren.SetBackground(.4, .4, .4)

        # create the modelview widget
        self.ModelView = QVTKRenderWindowInteractor(self.ui.ModelFrame)
        self.ModelView.SetInteractorStyle(MyInteractorStyle())
        self.ModelView.Initialize()
        self.ModelView.Start()

        self.renWin = self.ModelView.GetRenderWindow()
        self.renWin.AddRenderer(self.ren)
        self.ModelView.show()

        self.ModelView.resize(1006 - 17, 716 - 39)
        #self.ModelView.resize(self.ui.ModelFrame.geometry().width()-1,self.ui.ModelFrame.geometry().height()-1)

        self.modelList = []

    def AddModel(self):
        filename = QtGui.QFileDialog.getOpenFileName(self, 'Open 3D Model',
                                                     '.', '*.stl')
        if filename == '':  #user hit cancel
            return
        modelObject = model(self, filename)
        self.modelList.append(modelObject)
        self.ui.modelList.addItem(os.path.basename(str(filename)))
        if len(self.modelList) == 1:
            self.FirstOpen()

        self.ren.ResetCamera()
        self.ModelView.Render()  #update model view

    def FirstOpen(self):
        #create annotated cube anchor actor
        self.axesActor = vtk.vtkAnnotatedCubeActor()
        self.axesActor.SetXPlusFaceText('Right')
        self.axesActor.SetXMinusFaceText('Left')
        self.axesActor.SetYMinusFaceText('Front')
        self.axesActor.SetYPlusFaceText('Back')
        self.axesActor.SetZMinusFaceText('Bot')
        self.axesActor.SetZPlusFaceText('Top')
        self.axesActor.GetTextEdgesProperty().SetColor(.8, .8, .8)
        self.axesActor.GetZPlusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetZMinusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetXPlusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetXMinusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetYPlusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetYMinusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetTextEdgesProperty().SetLineWidth(2)
        self.axesActor.GetCubeProperty().SetColor(.2, .2, .2)
        self.axesActor.SetFaceTextScale(0.25)
        self.axesActor.SetZFaceTextRotation(90)

        #create orientation markers
        self.axes = vtk.vtkOrientationMarkerWidget()
        self.axes.SetOrientationMarker(self.axesActor)
        self.axes.SetInteractor(self.ModelView)
        self.axes.EnabledOn()
        self.axes.InteractiveOff()

        self.ui.Transform_groupbox.setEnabled(True)

    def SliceModel(self):
        try:
            if self.modelActor:  #check to see if a model is loaded, if not it will throw an exception
                pass
        except:  #self.modelActor doesn't exist (hasn't been instantiated with a model yet)
            QtGui.QMessageBox.critical(
                self, 'Error slicing model',
                "You must first load a model to slice it!",
                QtGui.QMessageBox.Ok)
            return
        self.outputFile = str(
            QFileDialog.getSaveFileName(self, "Save file", "", ".3dlp"))
        self.slicer = slicer.slicer(self)
        self.slicer.imageheight = int(self.imageHeight)
        self.slicer.imagewidth = int(self.imageWidth)
        # check to see if starting depth is less than ending depth!! this assumption is crucial
        self.slicer.startingdepth = float(self.startingDepth)
        self.slicer.endingdepth = float(self.endingDepth)
        self.slicer.layerincrement = float(self.slicingIncrement)
        self.slicer.OpenModel(self.filename)
        self.slicer.slice()

    def UpdateModelOpacity(self):
        try:
            if self.modelActor:  #check to see if a model is loaded, if not it will throw an exception
                opacity, ok = QtGui.QInputDialog.getText(
                    self, 'Model Opacity',
                    'Enter the desired opacity (0-100):')
                if not ok:  #the user hit the "cancel" button
                    return
                self.modelActor.GetProperty().SetOpacity(float(opacity) / 100)
                self.ren.Render()
                self.ModelView.Render()
        except:  #self.modelActor doesn't exist (hasn't been instantiated with a model yet)
            QtGui.QMessageBox.critical(
                self, 'Error setting opacity',
                "You must first load a model to change its opacity!",
                QtGui.QMessageBox.Ok)

    def ModelIndexChanged(self, new, previous):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        self.ui.positionX.setValue(modelObject.CurrentXPosition)
        self.ui.positionY.setValue(modelObject.CurrentYPosition)
        self.ui.positionZ.setValue(modelObject.CurrentZPosition)
        self.ui.rotationX.setValue(modelObject.CurrentXRotation)
        self.ui.rotationY.setValue(modelObject.CurrentYRotation)
        self.ui.rotationZ.setValue(modelObject.CurrentZRotation)
        self.ui.scale.setValue(modelObject.CurrentScale)

    def Update_Position_X(self, position):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.Translate((float(position) - modelObject.CurrentXPosition),
                            0.0, 0.0)
        modelObject.CurrentXPosition = modelObject.CurrentXPosition + (
            float(position) - modelObject.CurrentXPosition)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Position_Y(self, position):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.Translate(0.0,
                            (float(position) - modelObject.CurrentYPosition),
                            0.0)
        modelObject.CurrentYPosition = modelObject.CurrentYPosition + (
            float(position) - modelObject.CurrentYPosition)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Position_Z(self, position):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.Translate(0.0, 0.0,
                            (float(position) - modelObject.CurrentZPosition))
        modelObject.CurrentZPosition = modelObject.CurrentZPosition + (
            float(position) - modelObject.CurrentZPosition)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Rotation_X(self, rotation):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.RotateX((float(rotation) - modelObject.CurrentXRotation))
        modelObject.CurrentXRotation = modelObject.CurrentXRotation + (
            float(rotation) - modelObject.CurrentXRotation)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Rotation_Y(self, rotation):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.RotateY((float(rotation) - modelObject.CurrentYRotation))
        modelObject.CurrentYRotation = modelObject.CurrentYRotation + (
            float(rotation) - modelObject.CurrentYRotation)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Rotation_Z(self, rotation):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.RotateZ((float(rotation) - modelObject.CurrentZRotation))
        modelObject.CurrentZRotation = modelObject.CurrentZRotation + (
            float(rotation) - modelObject.CurrentZRotation)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Scale(self, scale):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform

        self.reader = vtk.vtkSTLReader()
        self.reader.SetFileName(str(self.filename))

        self.mapper = vtk.vtkPolyDataMapper()
        self.mapper.SetInputConnection(self.reader.GetOutputPort())

        #create model actor
        self.actor = vtk.vtkActor()
        self.actor.GetProperty().SetColor(1, 1, 1)
        self.actor.GetProperty().SetOpacity(1)
        self.actor.SetMapper(self.mapper)

        #create outline mapper
        self.outline = vtk.vtkOutlineFilter()
        self.outline.SetInputConnection(self.reader.GetOutputPort())
        self.outlineMapper = vtk.vtkPolyDataMapper()
        self.outlineMapper.SetInputConnection(self.outline.GetOutputPort())

        #create outline actor
        self.outlineActor = vtk.vtkActor()
        self.outlineActor.SetMapper(self.outlineMapper)

        #add actors to parent render window
        self.parent.ren.AddActor(self.actor)
        self.parent.ren.AddActor(self.outlineActor)

        delta = modelObject.PreviousScale - modelObject.CurrentScale
        modelObject.transform
        #transform.Scale((float(scale)-modelObject.CurrentScale)/100.0, (float(scale)-modelObject.CurrentScale)/100.0, (float(scale)-modelObject.CurrentScale)/100.0)
        transform.Scale
        modelObject.CurrentScale = modelObject.CurrentScale + (
            float(scale) - modelObject.CurrentScale)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(modelObject.transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def LoadSettingsFromConfigFile(self):
        self.imageHeight = int(
            self.parser.get('slicing_settings', 'Image_Height'))
        self.imageWidth = int(
            self.parser.get('slicing_settings', 'Image_Width'))
        self.startingDepth = int(
            self.parser.get('slicing_settings', 'Starting_Depth'))
        self.endingDepth = int(
            self.parser.get('slicing_settings', 'Ending_Depth'))
        self.slicingIncrement = int(
            self.parser.get('slicing_settings', 'Slicing_Increment'))
        self.slicingplane = self.parser.get('slicing_settings',
                                            'Slicing_Plane')

    def OpenSettingsDialog(self):
        self.SettingsDialog = StartSettingsDialog(self)
        self.connect(self.SettingsDialog, QtCore.SIGNAL('ApplySettings()'),
                     self.getSettingsDialogValues)
        self.SettingsDialog.imageHeight.setText(str(self.imageHeight))
        self.SettingsDialog.imageWidth.setText(str(self.imageWidth))
        self.SettingsDialog.startingDepth.setText(str(self.startingDepth))
        self.SettingsDialog.endingDepth.setText(str(self.endingDepth))
        self.SettingsDialog.slicingIncrement.setText(str(
            self.slicingIncrement))
        self.slicingplaneDict = {"XZ": 0, "XY": 1, "YZ": 2}
        try:
            self.SettingsDialog.slicingPlane.setCurrentIndex(
                self.slicingplaneDict[self.slicingplane])
        except:  #anything other than a valid entry will default to XZ (index 0)
            self.SettingsDialog.slicingPlane.setCurrentIndex(0)
        self.SettingsDialog.exec_()

    def getSettingsDialogValues(self):
        self.imageHeight = int(self.SettingsDialog.imageHeight.text())
        self.parser.set('slicing_settings', 'Image_Height',
                        "%s" % self.imageHeight)
        self.imageWidth = int(self.SettingsDialog.imageWidth.text())
        self.parser.set('slicing_settings', 'Image_Width',
                        "%s" % self.imageWidth)
        self.startingDepth = int(self.SettingsDialog.startingDepth.text())
        self.parser.set('slicing_settings', 'Starting_Depth',
                        "%s" % self.startingDepth)
        self.endingDepth = int(self.SettingsDialog.endingDepth.text())
        self.parser.set('slicing_settings', 'Ending_Depth',
                        "%s" % self.endingDepth)
        self.slicingIncrement = int(
            self.SettingsDialog.slicingIncrement.text())
        self.parser.set('slicing_settings', 'Slicing_Increment',
                        "%s" % self.slicingIncrement)
        self.slicingplane = self.SettingsDialog.slicingPlane.currentText()
        self.parser.set('slicing_settings', 'Slicing_Plane',
                        "%s" % self.slicingplane)

        filename = 'sliceconfig.ini'
        if hasattr(sys, '_MEIPASS'):
            # PyInstaller >= 1.6
            APPNAME = '3DLP'
            APPDATA = os.path.join(os.environ['APPDATA'], APPNAME)
            filename = os.path.join(APPDATA, filename)
            outputini = open(
                filename, 'w'
            )  #open a file pointer for the config file parser to write changes to
            self.parser.write(outputini)
            outputini.close()  #done writing config file changes
        else:  #otherwise it's running in pydev environment: use the dev config file
            os.chdir(os.path.dirname(sys.argv[0]))
            filename = os.path.join(os.path.dirname(sys.argv[0]), filename)
            outputini = open(
                filename, 'w'
            )  #open a file pointer for the config file parser to write changes to
            self.parser.write(outputini)
            outputini.close()  #done writing config file changes
class MainWindow(QtGui.QMainWindow, display.Ui_MainWindow):

    write = pyqtSignal(float, float, int, list)
    pointcloud_changed = pyqtSignal(list)
    need_pointcloud_setup = pyqtSignal()

    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)

        #Instance Variables
        self.point_array = []
        self.vl = QtGui.QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.vl.addWidget(self.vtkWidget)
        self.frame.setLayout(self.vl)
        print(self.frame.height, self.frame.width)
        self.renderer = vtk.vtkRenderer()
        self.pointCloud = v.VtkPointCloud()
        self.renderWindowInteractor = vtk.vtkRenderWindowInteractor()
        self.setup_vtk
        self.ser = 0

        #Signal slots of buttons
        self.startButton.clicked.connect(lambda: self.start_scanning(self.ser))
        self.stopButton.clicked.connect(lambda: self.stop_scanning(self.ser))

        #Actions for menu bar
        self.actionSave_CSV.triggered.connect(
            lambda: write_CSV(self.point_array))
        self.actionSave_STL.triggered.connect(
            lambda: write_STL(self.pointCloud))
        self.actionClear.triggered.connect(lambda: self.clear_pointcloud())

        #Scan thread
        self.scan_thread = ScanThread(self)
        self.write.connect(self.write_to_browser)
        self.pointcloud_changed.connect(self.update_pointcloud)
        self.need_pointcloud_setup.connect(self.setup_vtk)

    def write_something(self, x):
        self.textBrowser.append(x)

    def setup_vtk(self):
        # Renderer
        self.renderer.AddActor(self.pointCloud.vtkActor)
        self.renderer.SetBackground(0.0, 0.0, 0.0)
        self.renderer.ResetCamera()

        self.vtkWidget.GetRenderWindow().AddRenderer(self.renderer)
        self.vtkWidget.GetRenderWindow().Render()
        #self.vtkWidget.GetRenderWindow().SetSize(732,487)
        self.vtkWidget.Initialize()

    def update_vtk(self):
        # Renderer
        self.renderer.ResetCamera()
        # Render Window
        self.vtkWidget.GetRenderWindow().Render()

    def start_scanning(self, ser):
        #This is the enable signal to start scanning
        self.textBrowser.append("Start Scanning \n")
        QtGui.QApplication.processEvents()
        self.serial_setup()
        #Set the correct speed
        if (self.radioButton_slow.isChecked()):
            self.ser.write('2')
            self.textBrowser.append("Speed set to slow \n")
        elif (self.radioButton_medium.isChecked()):
            self.ser.write('3')
            self.textBrowser.append("Speed set to medium \n")
        elif (self.radioButton_fast.isChecked()):
            self.textBrowser.append("Speed set to fast \n")
            self.ser.write('4')
        #Send enable setting
        self.ser.write('1')
        #self.generate_pointcloud()
        if not self.scan_thread.isRunning():
            self.scan_thread.start()

    def stop_scanning(self, ser):
        if self.scan_thread.isRunning():
            self.scan_thread.terminate()

#Disable signal for scanning
        self.textBrowser.append("Stop Scanning \n")
        QtGui.QApplication.processEvents()
        ser.write('0')
        #self.vtkWidget.Start()

    def serial_setup(self):
        if self.ser == 0:
            self.ser = serial.Serial('COM3', 9600)
            #On windows, starting the serial port takes sometime. According to the arduino website, sleeping for 2 seconds kis a way of getting around it.
            time.sleep(2)

    def write_to_browser(self, pan_angle, tilt_angle, distance, point):
        self.textBrowser.append("pan: %f tilt: %f distance:%f \n" %
                                (pan_angle, tilt_angle, distance))
        self.textBrowser.append("x: %f y: %f z: %f \n" %
                                (point[0], point[1], point[2]))

    def update_pointcloud(self, point):
        self.point_array.append(point)
        self.pointCloud.addPoint(point)
        self.update_vtk()

    def clear_pointcloud(self):
        del self.point_array[:]
        self.textBrowser.setText("")
        self.pointCloud.clearPoints()
        self.update_vtk()
Exemple #7
0
class ParallelCoordinatesWidget(QCellWidget):
    def __init__(self, parent=None):
        QCellWidget.__init__(self, parent)

        centralLayout = QtGui.QVBoxLayout()
        self.setLayout(centralLayout)
        centralLayout.setMargin(0)
        centralLayout.setSpacing(0)

        self.view = vtk.vtkContextView()
        self.widget = QVTKRenderWindowInteractor(
            self,
            rw=self.view.GetRenderWindow(),
            iren=self.view.GetInteractor())

        self.chart = vtk.vtkChartParallelCoordinates()
        self.view.GetScene().AddItem(self.chart)

        self.layout().addWidget(self.widget)

        # Create a annotation link to access selection in parallel coordinates view
        self.annotationLink = vtk.vtkAnnotationLink()
        # If you don't set the FieldType explicitly it ends up as UNKNOWN (as of 21 Feb 2010)
        # See vtkSelectionNode doc for field and content type enum values
        self.annotationLink.GetCurrentSelection().GetNode(0).SetFieldType(
            1)  # Point
        self.annotationLink.GetCurrentSelection().GetNode(0).SetContentType(
            4)  # Indices
        # Connect the annotation link to the parallel coordinates representation
        self.chart.SetAnnotationLink(self.annotationLink)
        self.annotationLink.AddObserver("AnnotationChangedEvent",
                                        self.selectionCallback)

    def updateContents(self, inputPorts):
        (self.coord, matrix) = inputPorts
        if self.coord is not None: self.coord.register(self)

        self.createTable(matrix)
        self.widget.Initialize()

        # Capture window into history for playback
        # Call this at the end to capture the image after rendering
        QCellWidget.updateContents(self, inputPorts)

    def updateSelection(self, selectedIds):
        if len(selectedIds) == 0: return

        Ids = VN.numpy_to_vtkIdTypeArray(np.array(selectedIds), deep=True)

        node = vtk.vtkSelectionNode()
        node.SetContentType(vtk.vtkSelectionNode.INDICES)
        node.SetFieldType(vtk.vtkSelectionNode.POINT)
        node.SetSelectionList(Ids)

        selection = vtk.vtkSelection()
        selection.AddNode(node)

        self.annotationLink.SetCurrentSelection(selection)
        self.widget.Render()

    def createTable(self, matrix):
        table = vtk.vtkTable()
        for col, attr in zip(matrix.values.T, matrix.attributes):
            column = VN.numpy_to_vtk(col.copy(), deep=True)
            column.SetName(attr)
            table.AddColumn(column)
        self.chart.GetPlot(0).SetInput(table)

        min_ = matrix.values.min() - 0.01
        max_ = matrix.values.max() + 0.01
        for i in range(self.chart.GetNumberOfAxes()):
            self.chart.GetAxis(i).SetRange(min_, max_)
            self.chart.GetAxis(i).SetBehavior(vtk.vtkAxis.FIXED)


#            self.chart.GetAxis(i).SetPosition(vtk.vtkAxis.LEFT)
#            self.chart.GetAxis(i).GetTitleProperties().SetOrientation(30)

    def selectionCallback(self, caller, event):
        if self.coord is None: return

        annSel = self.annotationLink.GetCurrentSelection()
        if annSel.GetNumberOfNodes() > 0:
            idxArr = annSel.GetNode(0).GetSelectionList()
            if idxArr.GetNumberOfTuples() > 0:
                self.coord.unregister(self)
                self.coord.notifyModules(VN.vtk_to_numpy(idxArr))
                self.coord.register(self)
Exemple #8
0
class ModelmapViewer(module_template.Viewer):
    """Uses vtk to display the model in 3D as an isosurface or a slice. This is
    not a widget but contains one, accessible with get_widget()"""
    def __init__(self, parent=None):
        super(ModelmapViewer, self).__init__(parent)

        self._surface_algorithm = None
        self._surface_actor = None
        self._volume_scalars = None
        self._volume = None
        self._surface_level = 0.5
        self._color = (0.2, 0.8, 0.2)
        self._planes = []
        self._volume_max = 0.
        self._volume_numpy = None

        self._vtk_widget = QVTKRenderWindowInteractor(
            self._widget)  # _vtk_widget is actually the RenderWindowInteractor
        self._vtk_widget.SetInteractorStyle(
            vtk.vtkInteractorStyleRubberBandPick())
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self._vtk_widget)

        self._widget.setLayout(layout)
        #self._vtk_widget.Initialize()
        #self._vtk_widget.Start()

        self._renderer = vtk.vtkRenderer()
        self._renderer.SetDraw(0)
        self._vtk_render_window = self._vtk_widget.GetRenderWindow()
        self._vtk_render_window.AddRenderer(self._renderer)
        #self._renderer = self._vtk_widget.GetRenderWindow().GetRenderer()
        self._lut = vtk_tools.get_lookup_table(0.,
                                               1.,
                                               log=False,
                                               colorscale="jet")

        self._create_volume_map()
        #self._setup_slices()
        #self._setup_surface()

        white = (1., 1., 1.)
        self._renderer.SetBackground(white)
        #self.set_view_type(VIEW_TYPE.slice)
        #self._vtk_widget.GetRenderWindow().Render()

    def initialize(self):
        super(ModelmapViewer, self).initialize()
        self._vtk_widget.Initialize()
        self._setup_slices()
        self._setup_surface()
        #self.set_view_type(VIEW_TYPE.surface)
        self.set_view_type(VIEW_TYPE.slice)
        #self._vtk_widget.GetRenderWindow().Render()
        self._renderer.ResetCamera()
        # camera = self._renderer.GetActiveCamera()
        # camera.SetPosition(2., 2., 2.)
        # camera.SetFocalPoint(0., 0., 0.)
        self._vtk_render_window.Render()
        # print self._renderer.GetVolumes()
        # print self._renderer.VisibleActorCount()
        # print self._surface_actor.GetBounds()
        # print self._renderer.GetActiveCamera().GetPosition()

    def set_active(self, state):
        super(ModelmapViewer, self).set_active(state)
        self._renderer.SetDraw(int(state))

    def _create_volume_map(self):
        """Create the vtk objects containing the data."""
        self._volume_max = 1.

        self._volume = vtk.vtkImageData()
        default_side = 100
        self._volume.SetExtent(0, default_side - 1, 0, default_side - 1, 0,
                               default_side - 1)

        self._volume_numpy = numpy.zeros((default_side, ) * 3,
                                         dtype="float32",
                                         order="C")
        self._volume_numpy[:] = 0.
        self._volume_max = self._volume_numpy.max()
        self._volume_scalars = vtk.vtkFloatArray()
        self._volume_scalars.SetNumberOfValues(default_side**3)
        self._volume_scalars.SetNumberOfComponents(1)
        self._volume_scalars.SetName("Values")
        self._volume_scalars.SetVoidArray(self._volume_numpy, default_side**3,
                                          1)

        self._volume.GetPointData().SetScalars(self._volume_scalars)

    def _setup_surface(self):
        """Create the isosurface object, mapper and actor"""
        self._surface_level = INIT_SURFACE_LEVEL
        self._surface_algorithm = vtk.vtkMarchingCubes()
        if VTK_VERSION < 6:
            self._surface_algorithm.SetInput(self._volume)
        else:
            self._surface_algorithm.SetInputData(self._volume)
        self._surface_algorithm.ComputeNormalsOn()
        self._surface_algorithm.SetValue(0, self._surface_level)

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(self._surface_algorithm.GetOutputPort())
        mapper.ScalarVisibilityOff()
        self._surface_actor = vtk.vtkActor()
        self._surface_actor.GetProperty().SetColor(self._color[0],
                                                   self._color[1],
                                                   self._color[2])
        self._surface_actor.SetMapper(mapper)

        self._renderer.AddViewProp(self._surface_actor)

    def _setup_slices(self):
        """Create the slices. No actor required in this case"""
        picker = vtk.vtkCellPicker()
        picker_tolerance = 0.005
        picker.SetTolerance(picker_tolerance)
        text_color = (0., 0., 0.)

        if len(self._planes) != 0:
            raise RuntimeError("planes initialized twice")
        self._planes.append(vtk.vtkImagePlaneWidget())
        if VTK_VERSION < 6:
            self._planes[0].SetInput(self._volume)
        else:
            self._planes[0].SetInputData(self._volume)
        self._planes[0].UserControlledLookupTableOn()
        self._planes[0].SetLookupTable(self._lut)
        self._planes[0].SetPlaneOrientationToXAxes()
        self._planes[0].SetSliceIndex(
            self._volume.GetExtent()[1] /
            2)  # GetExtent returns a six length array, begin-end pairs
        self._planes[0].DisplayTextOn()
        self._planes[0].GetTextProperty().SetColor(text_color)
        self._planes[0].SetPicker(picker)
        self._planes[0].SetLeftButtonAction(1)
        self._planes[0].SetMiddleButtonAction(2)
        self._planes[0].SetRightButtonAction(0)
        self._planes[0].SetInteractor(self._vtk_widget)
        # self._planes[0].On()

        self._planes.append(vtk.vtkImagePlaneWidget())
        if VTK_VERSION < 6:
            self._planes[1].SetInput(self._volume)
        else:
            self._planes[1].SetInputData(self._volume)
        self._planes[1].UserControlledLookupTableOn()
        self._planes[1].SetLookupTable(self._lut)
        self._planes[1].SetPlaneOrientationToZAxes()
        self._planes[1].SetSliceIndex(
            self._volume.GetExtent()[5] /
            2)  # GetExtent returns a six length array, begin-end pairs
        self._planes[1].DisplayTextOn()
        self._planes[1].GetTextProperty().SetColor(text_color)
        self._planes[1].SetPicker(picker)
        self._planes[1].SetLeftButtonAction(1)
        self._planes[1].SetMiddleButtonAction(2)
        self._planes[1].SetRightButtonAction(0)
        self._planes[1].SetInteractor(self._vtk_widget)
        # self._planes[1].On()

    def set_surface_visibility(self, state):
        """Hide or show the surface, used when swithching between the surface and"""
        if state:
            self._surface_actor.SetVisibility(1)
        else:
            self._surface_actor.SetVisibility(0)

    def set_slice_visibility(self, state):
        """Hide or show the slices, used when swithching between the surface and"""
        if state:
            self._planes[0].SetEnabled(1)
            self._planes[1].SetEnabled(1)
        else:
            self._planes[0].SetEnabled(0)
            self._planes[1].SetEnabled(0)

    def set_view_type(self, view_type):
        """Switch between viewing slices or isosurface."""
        if view_type == VIEW_TYPE.surface:
            self.set_slice_visibility(False)
            self.set_surface_visibility(True)
        elif view_type == VIEW_TYPE.slice:
            self.set_surface_visibility(False)
            self.set_slice_visibility(True)

    def _update_surface_level(self):
        """Set the isosurface level based on the relative level in _surface_level
        and the maximum value of the current model."""
        if self._surface_algorithm != None:
            self._surface_algorithm.SetValue(
                0, self._surface_level * self._volume_max)
            self._surface_algorithm.Modified()
            self._vtk_widget.Render()

    def set_surface_level(self, value):
        """Change the relative isosurface level"""
        if value < 0. or value > 1.:
            raise ValueError("Surface value must be in [0.,1.], was %g\n",
                             value)
        self._surface_level = value
        self._update_surface_level()

    def get_surface_level(self):
        """Get the relative isosurface level"""
        return self._surface_level

    def plot_map(self, new_data_array):
        """Update the viwer to show the provided map."""
        if (new_data_array.shape != self._volume_numpy.shape):
            self.plot_map_init(new_data_array)
            return
        self._volume_numpy[:, :, :] = new_data_array
        self._volume_max = new_data_array.max()
        self._lut.SetTableRange(new_data_array.min(), new_data_array.max())
        self._update_surface_level()
        self._volume_scalars.Modified()
        #self._vtk_widget.GetRenderWindow().Render()
        self._vtk_render_window.Render()

    def plot_map_init(self, new_data_array):
        """As opposed to plot_map() this function accepts maps of different side than
        the active one"""
        self._volume_max = new_data_array.max()

        old_extent = numpy.array(self._volume.GetExtent())

        self._volume.SetExtent(0, new_data_array.shape[0] - 1, 0,
                               new_data_array.shape[1] - 1, 0,
                               new_data_array.shape[2] - 1)

        self._volume_numpy = numpy.ascontiguousarray(new_data_array,
                                                     dtype="float32")

        self._volume_scalars = vtk.vtkFloatArray()
        self._volume_scalars.SetNumberOfValues(
            numpy.product(self._volume_numpy.shape))
        self._volume_scalars.SetNumberOfComponents(1)
        self._volume_scalars.SetName("Values")
        self._volume_scalars.SetVoidArray(
            self._volume_numpy, numpy.product(self._volume_numpy.shape), 1)

        self._volume.GetPointData().SetScalars(self._volume_scalars)

        # self._volume_scalars.SetNumberOfValues(new_data_array.shape[0]*new_data_array.shape[1]*new_data_array.shape[2])

        # for i, this_value in enumerate(numpy.ravel(new_data_array.swapaxes(0, 2))):
        #     self._volume_scalars.SetValue(i, this_value)

        self._lut.SetTableRange(new_data_array.min(), new_data_array.max())
        #self._volume.GetPointData().SetScalars(self._volume_scalars)
        self._update_surface_level()
        self._volume_scalars.Modified()
        self._volume.Modified()
        new_extent = numpy.array(self._volume.GetExtent())
        scaling_factors = numpy.float64(new_extent[1::2]) / numpy.float64(
            old_extent[1::2])

        self._planes[0].SetOrigin(
            numpy.array(self._planes[0].GetOrigin() * scaling_factors))
        self._planes[0].SetPoint1(
            numpy.array(self._planes[0].GetPoint1() * scaling_factors))
        self._planes[0].SetPoint2(
            numpy.array(self._planes[0].GetPoint2() * scaling_factors))
        self._planes[1].SetOrigin(
            numpy.array(self._planes[1].GetOrigin() * scaling_factors))
        self._planes[1].SetPoint1(
            numpy.array(self._planes[1].GetPoint1() * scaling_factors))
        self._planes[1].SetPoint2(
            numpy.array(self._planes[1].GetPoint2() * scaling_factors))
        # self._planes[0].Modified()
        # self._planes[1].Modified()
        self._planes[0].UpdatePlacement()
        self._planes[1].UpdatePlacement()

        self._vtk_widget.Render()
        self._renderer.Render()
Exemple #9
0
class SliceViewer(module_template.Viewer):
    """Plots the slices using vtk."""
    def __init__(self, data, parent):
        super(SliceViewer, self).__init__()
        self._data = data
        self._lut = None
        self._actors = {}
        self._camera = None

        #self._slice_generator = SliceGenerator(self._data.get_image_side(), self._data.get_curvature())
        #self._workspace = QtGui.QWorkspace()
        self._widget = QtGui.QWidget(parent)
        self._vtk_widget = QVTKRenderWindowInteractor(self._widget)
        self._vtk_widget.SetInteractorStyle(
            vtk.vtkInteractorStyleRubberBandPick())
        #self._vtk_widget = QtGui.QPushButton("Foo", parent=self._widget)
        layout = QtGui.QVBoxLayout()
        #layout.addWidget(self._workspace)
        layout.addWidget(self._vtk_widget)
        #self._workspace.addWindow(self._vtk_widget)
        self._widget.setLayout(layout)
        # self._vtk_widget.Initialize()
        # self._vtk_widget.Start()
        self._renderer = vtk.vtkRenderer()
        self._renderer.SetDraw(0)
        self._vtk_render_window = self._vtk_widget.GetRenderWindow()
        self._vtk_render_window.AddRenderer(self._renderer)
        #self._setup_slice_view()

    def initialize(self):
        #pass
        self._vtk_widget.Initialize()
        self._setup_slice_view()
        self._slice_generator = SliceGenerator(self._data.get_image_side(),
                                               self._data.get_curvature())

    def set_active(self, state):
        super(SliceViewer, self).set_active(state)
        self._renderer.SetDraw(int(state))

    def _draw(self):
        if VTK_VERSION < 6:
            self._vtk_render_window.Render()
        else:
            if self._vtk_render_window.IsDrawable():
                self._vtk_render_window.Render()

    def _setup_slice_view(self):
        """Setup background, camera and LUT."""
        self._renderer.SetBackground(1, 1, 1)

        # camera
        self._camera = vtk.vtkCamera()
        self._camera.SetPosition(130, 130, 170)
        self._camera.SetFocalPoint(0., 0., 0.)
        self._camera.SetViewUp(0, 0, 1)
        self._renderer.SetActiveCamera(self._camera)

        # self._lut = vtk_tools.get_lookup_table(self._data.get_total_min(), self._data.get_total_max(),
        #                                        log=True, colorscale="jet")
        self._lut = vtk_tools.get_lookup_table(0.1,
                                               10.,
                                               log=True,
                                               colorscale="jet")

    def _update_lut(self):
        """Call after new images were added to update the LUT to include
        the entire range."""
        # self._lut = vtk_tools.get_lookup_table(self._data.get_total_min(), self._data.get_total_max(),
        #                                        log=True, colorscale="jet")
        #self._lut.SetTableRange(self._data.get_total_min(), self._data.get_total_max())
        self._lut.SetTableRange(
            max(self._data.get_total_min(),
                0.0001 * self._data.get_total_max()),
            self._data.get_total_max())
        self._lut.Build()
        self._draw()

    def _add_poly_data(self, this_poly_data, identifier):
        """Add a polydata and give it an id by which it can be accessed later."""
        if identifier in self._actors:
            raise ValueError("Actor with identifier %d is already plotted" %
                             identifier)
        mapper = vtk.vtkPolyDataMapper()
        #mapper.SetInput(this_poly_data)
        if VTK_VERSION < 6:
            mapper.SetInput(this_poly_data)
        else:
            mapper.SetInputData(this_poly_data)
        mapper.SetScalarModeToUsePointData()
        mapper.UseLookupTableScalarRangeOn()
        self._update_lut()
        mapper.SetLookupTable(self._lut)

        actor = vtk.vtkActor()
        actor.SetMapper(mapper)
        #actor.GetProperty().SetOpacity(0.999999)
        self._actors[identifier] = actor

        self._renderer.AddActor(actor)
        #self._renderer.UseDepthPeelingOn()

    def _remove_poly_data(self, identifier):
        """Remove polydata with the specified id."""
        if not identifier in self._actors:
            raise ValueError(
                "Trying to remove actor with id %d that doesn't exist." %
                identifier)
        self._renderer.RemoveActor(self._actors[identifier])
        del self._actors[identifier]

    def add_slice(self, index):
        """Add the image with the specified index to the view."""
        self._add_poly_data(
            self._slice_generator.get_slice(self._data.get_image(index),
                                            self._data.get_rotation(index)),
            index)
        self._draw()

    def add_multiple_slices(self, index_list):
        """Add all the specified images to the view."""
        for index in index_list:
            self._add_poly_data(
                self._slice_generator.get_slice(
                    self._data.get_image(index),
                    self._data.get_rotation(index)), index)
        self._draw()

    def remove_slice(self, index, render=True):
        """Remove the specified image from the view."""
        self._remove_poly_data(index)
        #self._vtk_widget.GetRenderWindow().Render()
        if render:
            self._draw()

    def remove_all_slices(self):
        """Clear the view."""
        for index in self.get_all_indices():
            self._remove_poly_data(index)

    def get_all_indices(self):
        """Get all ids currently known to the viewer."""
        return self._actors.keys()
Exemple #10
0
class SimulationGui(QtGui.QMainWindow):
    """
    class for the graphical user interface
    """
    # TODO enable closing plot docks by right-clicking their name
    # TODO add ability to stop an simulation
    # TODO add ability to stop regime execution

    runSimulation = pyqtSignal()
    playbackTimeChanged = pyqtSignal()
    regimeFinished = pyqtSignal()
    finishedRegimeBatch = pyqtSignal()

    def __init__(self):
        # constructor of the base class
        QtGui.QMainWindow.__init__(self)

        self._logger = logging.getLogger(self.__class__.__name__)

        # Create Simulation Backend
        self.guiProgress = None
        self.cmdProgress = None
        self.sim = SimulatorInteractor(self)
        self.runSimulation.connect(self.sim.run_simulation)
        self.sim.simulation_finished.connect(self.simulation_finished)
        self.sim.simulation_failed.connect(self.simulation_failed)
        self.currentDataset = None

        # sim setup viewer
        self.targetView = SimulatorView(self)
        self.targetView.setModel(self.sim.target_model)
        self.targetView.expanded.connect(self.target_view_changed)
        self.targetView.collapsed.connect(self.target_view_changed)

        # sim results viewer
        self.result_view = QtGui.QTreeView()

        # the docking area allows to rearrange the user interface at runtime
        self.area = pg.dockarea.DockArea()

        # Window properties
        self.setCentralWidget(self.area)
        self.resize(1000, 700)
        self.setWindowTitle("PyMoskito")
        res_path = get_resource("mosquito.png")
        icon = QtGui.QIcon(res_path)
        self.setWindowIcon(icon)

        # create docks
        self.propertyDock = pg.dockarea.Dock("Properties")
        self.vtkDock = pg.dockarea.Dock("Simulation")
        self.regimeDock = pg.dockarea.Dock("Regimes")
        self.dataDock = pg.dockarea.Dock("Data")
        self.logDock = pg.dockarea.Dock("Log")
        self.plotDocks = []
        self.plotDocks.append(pg.dockarea.Dock("Placeholder"))
        self.plotWidgets = []
        self.timeLines = []

        # arrange docks
        self.area.addDock(self.vtkDock, "right")
        self.area.addDock(self.regimeDock, "left", self.vtkDock)
        self.area.addDock(self.propertyDock, "bottom", self.regimeDock)
        self.area.addDock(self.dataDock, "bottom", self.propertyDock)
        self.area.addDock(self.plotDocks[-1], "bottom", self.vtkDock)
        self.area.addDock(self.logDock, "bottom", self.dataDock)

        # add widgets to the docks
        self.propertyDock.addWidget(self.targetView)

        # vtk window
        self.vtkLayout = QtGui.QVBoxLayout()
        self.frame = QtGui.QFrame()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.vtkLayout.addWidget(self.vtkWidget)
        self.frame.setLayout(self.vtkLayout)
        self.vtkDock.addWidget(self.frame)
        self.vtk_renderer = vtk.vtkRenderer()
        self.vtkWidget.GetRenderWindow().AddRenderer(self.vtk_renderer)
        # check if there is a registered visualizer
        available_vis = get_registered_visualizers()
        self._logger.info("found visualizers: {}".format(
            [name for cls, name in available_vis]))
        if available_vis:
            # instantiate the first one
            self._logger.info("loading visualizer '{}'".format(
                available_vis[0][1]))
            self.visualizer = available_vis[0][0](self.vtk_renderer)
            self.vtkWidget.Initialize()
        else:
            self.visualizer = None

        # regime window
        self.regime_list = QtGui.QListWidget(self)
        self.regime_list.setSelectionMode(
            QtGui.QAbstractItemView.ExtendedSelection)
        self.regimeDock.addWidget(self.regime_list)
        self.regime_list.itemDoubleClicked.connect(self.regime_dclicked)
        self._regimes = []
        self.regime_file_name = ""

        # data window
        self.dataList = QtGui.QListWidget(self)
        self.dataDock.addWidget(self.dataList)
        self.dataList.itemDoubleClicked.connect(self.create_plot)

        # actions for simulation control
        self.actSimulate = QtGui.QAction(self)
        self.actSimulate.setText("Simulate")
        self.actSimulate.setIcon(QtGui.QIcon(get_resource("simulate.png")))
        self.actSimulate.triggered.connect(self.start_simulation)

        # actions for animation control
        self.actPlayPause = QtGui.QAction(self)
        self.actPlayPause.setText("Play")
        self.actPlayPause.setIcon(QtGui.QIcon(get_resource("play.png")))
        self.actPlayPause.setDisabled(True)
        self.actPlayPause.triggered.connect(self.play_animation)

        self.actStop = QtGui.QAction(self)
        self.actStop.setText("Stop")
        self.actStop.setIcon(QtGui.QIcon(get_resource("stop.png")))
        self.actStop.setDisabled(True)
        self.actStop.triggered.connect(self.stop_animation)

        self.speedDial = QtGui.QDial()
        self.speedDial.setDisabled(True)
        self.speedDial.setMinimum(0)
        self.speedDial.setMaximum(100)
        self.speedDial.setValue(50)
        self.speedDial.setSingleStep(1)
        self.speedDial.resize(24, 24)
        self.speedDial.valueChanged.connect(self.update_playback_gain)

        self.timeSlider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        self.timeSlider.setMinimum(0)
        self.timeSliderRange = 1000
        self.timeSlider.setMaximum(self.timeSliderRange)
        self.timeSlider.setTickInterval(1)
        self.timeSlider.setTracking(True)
        self.timeSlider.setDisabled(True)
        self.timeSlider.valueChanged.connect(self.update_playback_time)

        self.playbackTime = 0
        self.playbackGain = 1
        self.currentStepSize = 0
        self.currentEndTime = 0
        self.playbackTimer = QTimer()
        self.playbackTimer.timeout.connect(self.increment_playback_time)
        self.playbackTimeChanged.connect(self.update_gui)
        self.playbackTimeout = 33  # in [ms] -> 30 fps

        self.actSave = QtGui.QAction(self)
        self.actSave.setText('Save')
        self.actSave.setIcon(QtGui.QIcon(get_resource("save.png")))
        self.actSave.setDisabled(True)
        self.actSave.triggered.connect(self.export_simulation_data)

        self.actLoadRegimes = QtGui.QAction(self)
        self.actLoadRegimes.setText("load regimes")
        self.actLoadRegimes.setIcon(QtGui.QIcon(get_resource("load.png")))
        self.actLoadRegimes.setDisabled(False)
        self.actLoadRegimes.triggered.connect(self.load_regime_dialog)

        self.actExecuteRegimes = QtGui.QAction(self)
        self.actExecuteRegimes.setText("execute all regimes")
        self.actExecuteRegimes.setIcon(
            QtGui.QIcon(get_resource("execute_regimes.png")))
        self.actExecuteRegimes.setDisabled(True)
        self.actExecuteRegimes.triggered.connect(self.execute_regimes_clicked)

        self.actPostprocessing = QtGui.QAction(self)
        self.actPostprocessing.setText("launch postprocessor")
        self.actPostprocessing.setIcon(
            QtGui.QIcon(get_resource("processing.png")))
        self.actPostprocessing.setDisabled(False)
        self.actPostprocessing.triggered.connect(self.postprocessing_clicked)

        self.act_reset_camera = QtGui.QAction(self)
        self.act_reset_camera.setText("reset camera")
        self.act_reset_camera.setIcon(
            QtGui.QIcon(get_resource("reset_camera.png")))
        self.act_reset_camera.setDisabled(not self.visualizer.can_reset_view)
        self.act_reset_camera.triggered.connect(self.reset_camera_clicked)

        # toolbar for control
        self.toolbarSim = QtGui.QToolBar("Simulation")
        self.toolbarSim.setIconSize(QtCore.QSize(32, 32))
        self.addToolBar(self.toolbarSim)
        self.toolbarSim.addAction(self.actLoadRegimes)
        self.toolbarSim.addAction(self.actSave)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actSimulate)
        self.toolbarSim.addAction(self.actExecuteRegimes)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actPlayPause)
        self.toolbarSim.addAction(self.actStop)
        self.toolbarSim.addWidget(self.speedDial)
        self.toolbarSim.addWidget(self.timeSlider)
        self.toolbarSim.addAction(self.actPostprocessing)
        self.toolbarSim.addAction(self.act_reset_camera)
        self.postprocessor = None

        # regime management
        self.runningBatch = False
        self._current_regime_index = 0
        self._regimes = []

        self.regimeFinished.connect(self.run_next_regime)
        self.finishedRegimeBatch.connect(self.regime_batch_finished)

        # log dock
        self.logBox = QPlainTextEditLogger(self)
        self.logBox.setLevel(logging.INFO)

        formatter = logging.Formatter(
            fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
            datefmt="%H:%M:%S")
        self.logBox.setFormatter(formatter)

        self.log_filter = PostFilter(invert=True)
        self.logBox.addFilter(self.log_filter)

        logging.getLogger().addHandler(self.logBox)
        self.logDock.addWidget(self.logBox.widget)

        # status bar
        self.status = QtGui.QStatusBar(self)
        self.setStatusBar(self.status)
        self.statusLabel = QtGui.QLabel("Ready.")
        self.statusBar().addPermanentWidget(self.statusLabel)
        self.timeLabel = QtGui.QLabel("current time: 0.0")
        self.statusBar().addPermanentWidget(self.timeLabel)

        # shortcuts
        self.delShort = QtGui.QShortcut(
            QtGui.QKeySequence(QtCore.Qt.Key_Delete), self.regime_list)
        self.delShort.activated.connect(self.remove_regime_items)

        self.shortOpenRegime = QtGui.QShortcut(QtGui.QKeySequence.Open, self)
        self.shortOpenRegime.activated.connect(self.load_regime_dialog)

        self.shortSaveResult = QtGui.QShortcut(QtGui.QKeySequence.Save, self)
        self.shortSaveResult.activated.connect(self.export_simulation_data)
        self.shortSaveResult.setEnabled(False)

        self.shortSpeedUp = QtGui.QShortcut(QtGui.QKeySequence.ZoomIn, self)
        self.shortSpeedUp.activated.connect(self.increment_playback_speed)

        self.shortSpeedDown = QtGui.QShortcut(QtGui.QKeySequence.ZoomOut, self)
        self.shortSpeedDown.activated.connect(self.decrement_playback_speed)

        self.shortSpeedReset = QtGui.QShortcut(
            QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_0), self)
        self.shortSpeedReset.activated.connect(self.reset_playback_speed)

        self.shortRunSimulation = QtGui.QShortcut(QtGui.QKeySequence('F5'),
                                                  self)
        self.shortRunSimulation.activated.connect(self.start_simulation)

        self.shortRunRegimeBatch = QtGui.QShortcut(QtGui.QKeySequence('F6'),
                                                   self)
        self.shortRunRegimeBatch.activated.connect(
            self.execute_regimes_clicked)

        self.shortRunPostprocessing = QtGui.QShortcut(QtGui.QKeySequence('F7'),
                                                      self)
        self.shortRunPostprocessing.activated.connect(
            self.postprocessing_clicked)

        self.shortPlayPause = QtGui.QShortcut(
            QtGui.QKeySequence(QtCore.Qt.Key_Space), self)
        self.shortPlayPause.activated.connect(self.play_animation)
        self.shortPlayPause.setEnabled(False)

        self.postprocessor = None
        self._logger.info("Simulation GUI is up and running.")

    def set_visualizer(self, vis):
        self.visualizer = vis
        self.vtkWidget.Initialize()

    def play_animation(self):
        """
        play the animation
        """
        # self.statusLabel.setText('playing animation')
        self.actPlayPause.setText("Pause")
        self.actPlayPause.setIcon(QtGui.QIcon(get_resource("pause.png")))
        self.actPlayPause.triggered.disconnect(self.play_animation)
        self.actPlayPause.triggered.connect(self.pause_animation)
        self.shortPlayPause.activated.disconnect(self.play_animation)
        self.shortPlayPause.activated.connect(self.pause_animation)
        self.playbackTimer.start(self.playbackTimeout)

    def pause_animation(self):
        """
        pause the animation
        """
        # self.statusLabel.setText('pausing animation')
        self.playbackTimer.stop()
        self.actPlayPause.setText("Play")
        self.actPlayPause.setIcon(QtGui.QIcon(get_resource("play.png")))
        self.actPlayPause.triggered.disconnect(self.pause_animation)
        self.actPlayPause.triggered.connect(self.play_animation)
        self.shortPlayPause.activated.disconnect(self.pause_animation)
        self.shortPlayPause.activated.connect(self.play_animation)

    def stop_animation(self):
        """
        pause the animation
        """
        # self.statusLabel.setText('stopping animation')
        if self.actPlayPause.text() == "Pause":
            # animation is playing -> stop it
            self.playbackTimer.stop()
            self.actPlayPause.setText("Play")
            self.actPlayPause.setIcon(QtGui.QIcon(get_resource("play.png")))
            self.actPlayPause.triggered.disconnect(self.pause_animation)
            self.actPlayPause.triggered.connect(self.play_animation)
            self.shortPlayPause.activated.disconnect(self.pause_animation)
            self.shortPlayPause.activated.connect(self.play_animation)

        self.timeSlider.setValue(0)

    def start_simulation(self):
        """
        start the simulation and disable start button
        """
        regime_name = str(
            self.regime_list.item(self._current_regime_index).text())
        self.statusLabel.setText(u"simulating {}".format(regime_name))
        self._logger.info(u"Simulating: {}".format(regime_name))

        self.actSimulate.setDisabled(True)
        self.shortRunSimulation.setEnabled(False)
        self.shortRunRegimeBatch.setEnabled(False)
        self.actExecuteRegimes.setDisabled(True)
        self.guiProgress = QtGui.QProgressBar(self)
        self.sim.simulationProgressChanged.connect(self.guiProgress.setValue)
        self.statusBar().addWidget(self.guiProgress)
        self.runSimulation.emit()

    def export_simulation_data(self, ok):
        """
        query the user for a custome name and export the current simulation results

        :param ok: unused parameter from QAction.triggered() Signal
        """
        res, ok = QtGui.QInputDialog.getText(
            self, u"PyMoskito", u"Please specify regime a name",
            QtGui.QLineEdit.Normal,
            self._regimes[self._current_regime_index]["Name"])
        if not ok:
            return

        name = unicode(res.toUtf8(), encoding="utf-8")
        if not name:
            self._logger.warning(u"empty regime name specified!")

        self._save_data(name)

    def _save_data(self, name):
        """
        save current data-set

        :param name: name of the file
        """
        self.currentDataset.update({"regime name": name})
        path = os.path.join(os.path.pardir, "results", "simulation",
                            self.regime_file_name)

        # check for path existence
        if not os.path.isdir(path):
            os.makedirs(path)

        # pmr - PyMoskito Result
        file_name = os.path.join(
            path,
            time.strftime("%Y%m%d-%H%M%S") + "_" + name + ".pmr")
        with open(file_name.encode("utf-8"), "wb") as f:
            cPickle.dump(self.currentDataset, f, protocol=2)

        self.statusLabel.setText(u"results saved to {}".format(file_name))
        self._logger.info(u"results saved to {}".format(file_name))

    def load_regime_dialog(self):
        regime_path = os.path.join("../regimes/")
        file_name = unicode(QtGui.QFileDialog.getOpenFileName(
            self, "Open Regime File", regime_path,
            "Simulation Regime files (*.sreg)").toUtf8(),
                            encoding="utf-8")
        if not file_name:
            return

        self.load_regimes_from_file(file_name)

    def load_regimes_from_file(self, file_name):
        """
        load simulation regime from file
        :param file_name:
        """
        self.regime_file_name = os.path.split(file_name)[-1][:-5]
        self._logger.info(u"loading regime file: {0}".format(
            self.regime_file_name))
        with open(file_name.encode("utf-8"), "r") as f:
            self._regimes += yaml.load(f)

        self._update_regime_list()

        if self._regimes:
            self.actExecuteRegimes.setDisabled(False)

        self._logger.info("loaded {} regimes".format(len(self._regimes)))
        self.statusBar().showMessage(
            u"loaded {} regimes.".format(len(self._regimes)), 1000)
        return

    def _update_regime_list(self):
        self.regime_list.clear()
        for reg in self._regimes:
            self._logger.debug("adding '{}' to regime list".format(
                reg["Name"]))
            self.regime_list.addItem(reg["Name"])

    def remove_regime_items(self):
        if self.regime_list.currentRow() >= 0:
            # flag all selected files as invalid
            items = self.regime_list.selectedItems()
            for item in items:
                del self._regimes[self.regime_list.row(item)]
                self.regime_list.takeItem(self.regime_list.row(item))

    def regime_dclicked(self, item):
        """
        applies the selected regime to the current target
        :param item:
        """
        self.apply_regime_by_name(str(item.text()))

    def apply_regime_by_name(self, regime_name):
        """
        :param regime_name:
        :return:
        """
        # get regime idx
        try:
            idx = map(itemgetter("Name"), self._regimes).index(regime_name)
        except ValueError as e:
            self._logger.info(
                "apply_regime_by_name(): Error no regime called {0}".format(
                    regime_name))
            return

        # apply
        self._apply_regime_by_idx(idx)

    def _apply_regime_by_idx(self, index=0):
        if index >= len(self._regimes):
            self._logger.error("applyRegime: index error! ({})".format(index))
            return

        reg_name = self._regimes[index]["Name"]
        self.statusBar().showMessage("regime {} applied.".format(reg_name),
                                     1000)
        self._logger.info("applying regime '{}'".format(reg_name))

        self._current_regime_index = index
        self.sim.set_regime(self._regimes[index])

    def execute_regimes_clicked(self):
        """
        execute all regimes in the current list
        """
        self.runningBatch = True
        self._current_regime_index = -1
        self.regimeFinished.emit()

    def run_next_regime(self):
        """
        executes the next regime
        """
        # are we finished?
        if self._current_regime_index == len(self._regimes) - 1:
            self.finishedRegimeBatch.emit()
            return

        self._apply_regime_by_idx(self._current_regime_index + 1)
        self.start_simulation()

    def regime_batch_finished(self):
        self.runningBatch = False
        self.actExecuteRegimes.setDisabled(False)
        # self._current_regime_index = 0
        self.statusLabel.setText("All regimes have been simulated!")
        self.actSave.setDisabled(True)

    def simulation_finished(self, data):
        """
        main hook to be called by the simulation interface if integration is finished
        integration finished, enable play button and update plots

        :param data: dict with simulation data
        """
        self._logger.info(u"simulation finished")
        self.statusLabel.setText(u"simulation finished.")

        self.actSimulate.setDisabled(False)
        self.shortRunSimulation.setEnabled(True)
        self.shortRunRegimeBatch.setEnabled(True)
        self.actPlayPause.setDisabled(False)
        self.shortPlayPause.setEnabled(True)
        self.shortSaveResult.setEnabled(True)
        self.actStop.setDisabled(False)
        self.actSave.setDisabled(False)
        self.speedDial.setDisabled(False)
        self.timeSlider.setDisabled(False)

        self.sim.simulationProgressChanged.disconnect(
            self.guiProgress.setValue)
        self.statusBar().removeWidget(self.guiProgress)

        self.timeSlider.triggerAction(QtGui.QAbstractSlider.SliderToMinimum)

        self.currentDataset = data
        self._read_results()
        self._update_data_list()
        self._update_plots()

        self.stop_animation()
        # self.playAnimation()

        if self.runningBatch:
            regime_name = self._regimes[self._current_regime_index]["Name"]
            self._save_data(regime_name)
            self.regimeFinished.emit()
        else:
            self.actExecuteRegimes.setDisabled(False)

    def simulation_failed(self, data):
        """
        integration failed, enable play button and update plots

        :param data:
        """
        self.statusLabel.setText(u"simulation failed!")
        self.simulation_finished(data)

    def _read_results(self):
        self.currentStepSize = 1.0 / self.currentDataset["results"][
            "Simulation"]['measure rate']
        self.currentEndTime = self.currentDataset["results"]["Simulation"][
            "end time"]
        self.validData = True

    def add_plot_to_dock(self, plot_widget):
        self.d3.addWidget(plot_widget)

    def increment_playback_speed(self):
        self.speedDial.setValue(self.speedDial.value() +
                                self.speedDial.singleStep())

    def decrement_playback_speed(self):
        self.speedDial.setValue(self.speedDial.value() -
                                self.speedDial.singleStep())

    def reset_playback_speed(self):
        self.speedDial.setValue(self.speedDial.range() / 2)

    def increment_playback_time(self):
        """
        go one time step forward in playback
        """
        increment = self.playbackGain * self.playbackTimeout / 1000
        if self.playbackTime + increment <= self.currentEndTime:
            self.playbackTime += increment
            pos = self.playbackTime / self.currentEndTime * self.timeSliderRange
            self.timeSlider.blockSignals(True)
            self.timeSlider.setValue(pos)
            self.timeSlider.blockSignals(False)
            self.playbackTimeChanged.emit()
        else:
            self.pause_animation()
            return

    def update_playback_gain(self, val):
        """
        adjust playback time to slider value

        :param val:
        """
        self.playbackGain = 10**(5.0 * (val - self.speedDial.maximum() / 2) /
                                 self.speedDial.maximum())

    def update_playback_time(self):
        """
        adjust playback time to slider value
        """
        self.playbackTime = self.timeSlider.value(
        ) / self.timeSliderRange * self.currentEndTime
        self.playbackTimeChanged.emit()
        return

    def update_gui(self):
        """
        updates the graphical user interface, including:
            - timestamp
            - visualisation
            - time cursor in diagrams
        """
        if not self.validData:
            return

        self.timeLabel.setText(u"current time: %4f" % self.playbackTime)

        # update time cursor in plots
        self._update_time_cursor()

        # update state of rendering
        if self.visualizer:
            state = self.interpolate(self.currentDataset["results"]["Solver"])
            self.visualizer.update_scene(state)
            self.vtkWidget.GetRenderWindow().Render()

    def interpolate(self, data):
        """
        find corresponding item in data-set that fits the current playback time

        :param data: data-set in which the correct datum has to be found
        :return: datum fitting the current playback time
        """
        idx = next((
            index
            for index, val in enumerate(self.currentDataset["results"]["time"])
            if val >= self.playbackTime), None)

        if idx is None:
            self._logger.info(
                u"interpolate(): Error no entry found for t={0}".format(
                    self.playbackTime))
            return None
        else:
            if len(data.shape) == 1:
                return data[idx]
            elif len(data.shape) == 2:
                return data[idx, :]
            else:
                self._logger.info(
                    u"interpolate(): Error Dimension {0} not understood.".
                    format(data.shape))
                return None

    def _update_data_list(self):
        self.dataList.clear()
        for module, results in self.currentDataset["results"].iteritems():
            if not isinstance(results, np.ndarray):
                continue

            if len(results.shape) == 1:
                self.dataList.insertItem(0, "{0}".format(module))
            elif len(results.shape) == 2:
                for col in range(results.shape[1]):
                    self.dataList.insertItem(0, "{0}.{1}".format(module, col))
            elif len(results.shape) == 3:
                for col in range(results.shape[1]):
                    self.dataList.insertItem(0, "{0}.{1}".format(module, col))

    def create_plot(self, item):
        """
        creates a plot widget corresponding to the ListItem

        :param item: ListItem
        """

        title = str(item.text())
        data = self._get_data_by_name(title)
        t = self.currentDataset["results"]["time"]

        dock = pg.dockarea.Dock(title)
        self.area.addDock(dock, "above", self.plotDocks[-1])

        widget = pg.PlotWidget(title=title)
        widget.plot(x=t, y=data)

        time_line = pg.InfiniteLine(self.playbackTime,
                                    angle=90,
                                    movable=False,
                                    pen=pg.mkPen("#FF0000", width=2.0))
        widget.getPlotItem().addItem(time_line)

        # enable grid
        widget.showGrid(True, True)

        dock.addWidget(widget)

        self.plotDocks.append(dock)
        self.plotWidgets.append(widget)
        self.timeLines.append(time_line)

    def _get_data_by_name(self, name):
        tmp = name.split(".")
        if len(tmp) == 1:
            data = self.currentDataset["results"][tmp[0]]
            # if the data-set contains 1d array -> convert to float
            data = [float(x) for x in data]
        elif len(tmp) == 2:
            if len(self.currentDataset["results"][tmp[0]].shape) == 2:
                data = self.currentDataset["results"][tmp[0]][:, tmp[1]]
            if len(self.currentDataset["results"][tmp[0]].shape
                   ) == 3:  # data-set has the structure [ [[1]], [[2]] ]
                data = self.currentDataset['results'][tmp[0]][..., tmp[1], 0]

        return data

    def _update_time_cursor(self):
        """
        updates the time lines of all plot windows
        """
        for line in self.timeLines:
            line.setValue(self.playbackTime)

    def _update_plots(self):
        """
        plot the fresh simulation data
        """
        for dock in self.plotDocks:
            for widget in dock.widgets:
                if not self.dataList.findItems(dock.name(),
                                               QtCore.Qt.MatchExactly):
                    # no data for this plot -> reset it
                    widget.getPlotItem().clear()
                    # TODO remove tab from dock and del instance
                else:
                    widget.getPlotItem().clear()
                    x_data = self.currentDataset["results"]["time"]
                    y_data = self._get_data_by_name(dock.name())
                    widget.getPlotItem().plot(x=x_data, y=y_data)

    def target_view_changed(self, index):
        self.targetView.resizeColumnToContents(0)

    def postprocessing_clicked(self):
        """
        starts the post- and metaprocessing application
        """
        self._logger.info(u"launching postprocessor")
        self.statusBar().showMessage(u"launching postprocessor", 1000)
        if self.postprocessor is None:
            self.postprocessor = PostProcessor()

        self.postprocessor.show()

    def reset_camera_clicked(self):
        """
        reset camera in vtk window
        """
        self.visualizer.reset_camera()
        self.vtkWidget.GetRenderWindow().Render()
class VTKCanvas(QtGui.QFrame):
    ''' the Qt4 frame that holds the main VTK canvas '''
    def __init__(self, parent, Qt4GUI):
        super(VTKCanvas, self).__init__(parent)
        # dictionary to keep track of tree widget items that correspond to actors/icons - used to handle vtk->Qt4 scene changes
        self.actors_to_tree_widget_items = {}

        # Qt4 GUI that this canvas is associated with
        self.Qt4GUI = Qt4GUI

        # camera perspective type check
        self.camera_perspective = False

        # setup the vtk renderers - one for objects, one for overlay icons/text (which always renders on top)
        self.vtk_renderer = vtk.vtkRenderer()

        # setup the vtk interactor
        self.vtk_interactor = QVTKRenderWindowInteractor(self)

        # setup the vtk render window
        self.vtk_render_window = self.vtk_interactor.GetRenderWindow()
        self.vtk_render_window.AddRenderer(self.vtk_renderer)
        self.vtk_render_window.SetInteractor(self.vtk_interactor)

        #setup the layout of the vtk interactor in Qt
        self.layout = QtGui.QHBoxLayout()
        self.layout.addWidget(self.vtk_interactor)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.layout)

    def setupTimerCallback(self, targetFPS=30):
        # calling this function will setup a timer and callback to continuously render the scene at the target FPS
        self.vtk_interactor.AddObserver('TimerEvent', self.requestUpdate)
        self.vtk_interactor.CreateRepeatingTimer(long(targetFPS))

    def requestUpdate(self, obj, event):
        # request a render update of the scene
        self.vtk_render_window.Render()

    def start(self):
        # setup the vtk background - as default, set to light
        self.vtk_renderer.GradientBackgroundOn()
        self.setBackgroundLight()

        # setup the default camera
        self.camera_perspective = False
        self.defaultPerspectiveCamera()

        # setup a default light kit (simple sun illumination + camera spotlight)
        self.light_kit = vtk.vtkLightKit()
        self.light_kit.MaintainLuminanceOn()
        self.light_kit.AddLightsToRenderer(self.vtk_renderer)

        # add the orientation axes to the bottom left of the canvas
        self.Qt4GUI.addOrientationAxes()

        # setup the default base grid - 1x1km, 10m squares
        self.Qt4GUI.addGrid(['grids', '1 km x 1 km, 10 m'], 1000, 10)

        # startup vtk
        self.vtk_interactor.Initialize()
        self.vtk_interactor.Start()

    def resetCamera(self):
        if self.camera_perspective:
            self.camera_perspective = False
            self.defaultPerspectiveCamera()
        else:
            self.camera_perspective = True
            self.defaultTopDownCamera()

    def defaultPerspectiveCamera(self):
        self.Qt4GUI.camera_perspective_signal.emit(True)
        if not self.camera_perspective:
            self.vtk_renderer.SetActiveCamera(vtk.vtkCamera())
            self.vtk_interactor.SetInteractorStyle(TerrainInteractorStyle())
            self.vtk_renderer.GetActiveCamera().SetViewUp(0, 0, 1)
            self.vtk_renderer.GetActiveCamera().SetPosition(0, 1, 10)
            self.vtk_renderer.GetActiveCamera().SetFocalPoint(0, 0, 0)
            self.vtk_renderer.GetActiveCamera().Azimuth(135)
            self.vtk_renderer.GetActiveCamera().Elevation(86)
            self.vtk_renderer.GetActiveCamera().Dolly(0.4)
            self.vtk_renderer.GetActiveCamera().Zoom(1)
            self.vtk_renderer.ResetCameraClippingRange()
            self.camera_perspective = True
            self.vtk_interactor.Render()

    def perspectiveCamera(self):
        self.Qt4GUI.camera_perspective_signal.emit(True)
        if not self.camera_perspective:
            curr_fp = self.vtk_renderer.GetActiveCamera().GetFocalPoint()
            curr_pos = [curr_fp[0], curr_fp[1] + 1, 10]
            curr_fp = [curr_fp[0], curr_fp[1], 0]
            self.vtk_renderer.SetActiveCamera(vtk.vtkCamera())
            self.vtk_interactor.SetInteractorStyle(TerrainInteractorStyle())
            self.vtk_renderer.GetActiveCamera().SetViewUp(0, 0, 1)
            self.vtk_renderer.GetActiveCamera().SetPosition(curr_pos)
            self.vtk_renderer.GetActiveCamera().SetFocalPoint(curr_fp)
            self.vtk_renderer.GetActiveCamera().Azimuth(135)
            self.vtk_renderer.GetActiveCamera().Elevation(86)
            self.vtk_renderer.GetActiveCamera().Dolly(0.4)
            self.vtk_renderer.GetActiveCamera().Zoom(1)
            self.vtk_renderer.ResetCameraClippingRange()
            self.camera_perspective = True
            self.vtk_interactor.Render()

    def defaultTopDownCamera(self):
        self.Qt4GUI.camera_perspective_signal.emit(False)
        if self.camera_perspective:
            self.vtk_renderer.SetActiveCamera(vtk.vtkCamera())
            self.vtk_interactor.SetInteractorStyle(TopDownInteractorStyle())
            self.vtk_renderer.GetActiveCamera().SetViewUp(0, 1, 0)
            self.vtk_renderer.GetActiveCamera().ParallelProjectionOn()
            self.vtk_renderer.GetActiveCamera().SetParallelScale(1000)
            self.vtk_renderer.GetActiveCamera().SetPosition(0, 0, 1e4)
            self.vtk_renderer.GetActiveCamera().SetFocalPoint(0, 0, 0)
            self.vtk_renderer.GetActiveCamera().Elevation(0)
            self.vtk_renderer.GetActiveCamera().Azimuth(0)
            self.vtk_renderer.GetActiveCamera().Dolly(0.4)
            self.vtk_renderer.GetActiveCamera().Zoom(100)
            self.vtk_renderer.ResetCameraClippingRange()
            self.camera_perspective = False
            self.vtk_interactor.Render()

    def topDownCamera(self):
        self.Qt4GUI.camera_perspective_signal.emit(False)
        if self.camera_perspective:
            curr_fp = self.vtk_renderer.GetActiveCamera().GetFocalPoint()
            curr_pos = [curr_fp[0], curr_fp[1], 1e4]
            curr_fp = [curr_fp[0], curr_fp[1], 0]
            self.vtk_renderer.SetActiveCamera(vtk.vtkCamera())
            self.vtk_interactor.SetInteractorStyle(TopDownInteractorStyle())
            self.vtk_renderer.GetActiveCamera().SetViewUp(0, 1, 0)
            self.vtk_renderer.GetActiveCamera().ParallelProjectionOn()
            self.vtk_renderer.GetActiveCamera().SetParallelScale(1000)
            self.vtk_renderer.GetActiveCamera().SetPosition(curr_pos)
            self.vtk_renderer.GetActiveCamera().SetFocalPoint(curr_fp)
            self.vtk_renderer.GetActiveCamera().Elevation(0)
            self.vtk_renderer.GetActiveCamera().Azimuth(0)
            self.vtk_renderer.GetActiveCamera().Dolly(0.4)
            self.vtk_renderer.GetActiveCamera().Zoom(100)
            self.vtk_renderer.ResetCameraClippingRange()
            self.camera_perspective = False
            self.vtk_interactor.Render()

    def setBackgroundLight(self):
        self.Qt4GUI.background_light_signal.emit(True)
        self.vtk_renderer.SetBackground2(220.0 / 255, 225.0 / 255, 235.0 / 255)
        self.vtk_renderer.SetBackground(105.0 / 255, 135.0 / 255, 155.0 / 255)
        self.vtk_interactor.Render()

    def setBackgroundDark(self):
        self.Qt4GUI.background_light_signal.emit(False)
        self.vtk_renderer.SetBackground(0.0 / 255, 10.0 / 255, 15.0 / 255)
        self.vtk_renderer.SetBackground2(60.0 / 255, 80.0 / 255, 110.0 / 255)
        self.vtk_interactor.Render()

    def addActorFrameAxes(self, tree_widget):
        frame_axes = Primitives.Axes()
        frame_axes.AxisLabelsOff()
        frame_axes.VisibilityOff()
        self.vtk_renderer.AddActor(frame_axes)
        self.vtk_interactor.Render()
        return frame_axes

    def removeActorFrameAxes(self, actor):
        self.vtk_renderer.RemoveActor(actor)
        self.vtk_interactor.Render()

    def addActor(self, tree_widget, actor):
        self.actors_to_tree_widget_items[actor] = tree_widget
        self.vtk_renderer.AddActor(actor)
        self.vtk_interactor.Render()

    def removeActor(self, actor):
        del self.actors_to_tree_widget_items[actor]
        self.vtk_renderer.RemoveActor(actor)
        self.vtk_interactor.Render()

    def replaceActor(self, remove_actor, tree_widget, actor):
        self.removeActor(remove_actor)
        self.addActor(tree_widget, actor)

    def setActorVisibility(self, actor, visible):
        if visible:
            actor.VisibilityOn()
        else:
            actor.VisibilityOff()
        self.vtk_interactor.Render()

    def setActorScale(self, actor, scale):
        if actor.GetClassName() == "vtkAxesActor":
            actor.SetTotalLength(scale, scale, scale)
        else:
            if actor.__class__ == Billboards.TextBillboard or actor.__class__ == Billboards.ImageBillboard:
                # billboards have no scaling
                return
            actor.SetScale(scale)
        self.vtk_interactor.Render()

    def getActorScale(self, actor):
        if actor.GetClassName() == "vtkAxesActor":
            return actor.GetTotalLength()
        else:
            if actor.__class__ == Billboards.TextBillboard or actor.__class__ == Billboards.ImageBillboard:
                # billboards have no scaling
                return [1, 1, 1]
            return actor.GetScale()

    def setActorOpacity(self, actor, opacity):
        actor.GetProperty().SetOpacity(opacity)
        self.vtk_interactor.Render()

    def getActorOpacity(self, actor):
        return actor.GetProperty().GetOpacity()

    def setActorPointSize(self, actor, size):
        actor.GetProperty().SetPointSize(size)
        self.vtk_interactor.Render()

    def getActorPointSize(self, actor):
        return actor.GetProperty().GetPointSize()

    def setActorLineWidth(self, actor, width):
        actor.GetProperty().SetLineWidth(width)
        self.vtk_interactor.Render()

    def getActorLineWidth(self, actor):
        return actor.GetProperty().GetLineWidth()

    def setActorToSurface(self, actor):
        if actor.__class__ == Billboards.TextBillboard or actor.__class__ == Billboards.ImageBillboard:
            # billboards have no render mode
            return
        actor.GetProperty().EdgeVisibilityOff()
        actor.GetProperty().SetRepresentationToSurface()
        self.vtk_interactor.Render()

    def setActorToWireframe(self, actor):
        if actor.__class__ == Billboards.TextBillboard or actor.__class__ == Billboards.ImageBillboard:
            # billboards have no render mode
            return
        actor.GetProperty().EdgeVisibilityOff()
        actor.GetProperty().SetRepresentationToWireframe()
        self.vtk_interactor.Render()

    def setActorToSurfaceEdges(self, actor):
        if actor.__class__ == Billboards.TextBillboard or actor.__class__ == Billboards.ImageBillboard:
            # billboards have no render mode
            return
        actor.GetProperty().EdgeVisibilityOn()
        actor.GetProperty().SetRepresentationToSurface()
        self.vtk_interactor.Render()

    def setActorToPoints(self, actor):
        if actor.__class__ == Billboards.TextBillboard or actor.__class__ == Billboards.ImageBillboard:
            # billboards have no render mode
            return
        actor.GetProperty().EdgeVisibilityOff()
        actor.GetProperty().SetRepresentationToPoints()
        self.vtk_interactor.Render()

    def getActorRenderMode(self, actor):
        if actor.__class__ == Billboards.TextBillboard or actor.__class__ == Billboards.ImageBillboard:
            # billboards have no render mode
            return None, None
        edge = actor.GetProperty().GetEdgeVisibility()
        mode = actor.GetProperty().GetRepresentation()
        return edge, mode

    def getActorColor(self, actor):
        return actor.GetProperty().GetColor()

    def setActorColor(self, actor, r, g, b):
        actor.GetProperty().SetColor(r, g, b)
        self.vtk_interactor.Render()

    def setActorTexture(self, actor, image_path):
        if actor.__class__ == Billboards.TextBillboard:
            # text billboards have no texture
            return
        if image_path[-4:].lower() == '.jpg' or image_path[-4:].lower(
        ) == '.jpeg':
            reader = vtk.vtkJPEGReader()
            reader.SetFileName(image_path)
            reader.Update()
        elif image_path[-4:].lower() == '.png':
            reader = vtk.vtkPNGReader()
            reader.SetFileName(image_path)
            reader.Update()
        texture = vtk.vtkTexture()
        texture.RepeatOn()
        texture.SetInputConnection(reader.GetOutputPort())

        actor.SetTexture(texture)

        # polydata = actor.GetMapper().GetInput()
        # pointdata = polydata.GetPointData()
        # celldata = polydata.GetCellData()
        # numtuples = celldata.GetNumberOfTuples()
        # numpolygons = polydata.GetNumberOfPolys()

        self.vtk_interactor.Render()

    def removeActorTexture(self, actor):
        actor.SetTexture(None)
        self.vtk_interactor.Render()

    def setActorOffset(self, actor, x_offset, y_offset, z_offset):
        if actor.__class__ == Billboards.TextBillboard or actor.__class__ == Billboards.ImageBillboard:
            # billboards are unaffected by offset changes
            pass
        else:
            actor.SetPosition(x_offset, y_offset, z_offset)
            self.vtk_interactor.Render()

    def setActorOrientation(self, actor, roll, pitch, yaw):
        actor.SetOrientation(roll, pitch, yaw)
        self.vtk_interactor.Render()
class ExodusResultRenderWidget(QtGui.QWidget):
  def __init__(self, input_file_widget, execution_widget, qt_app, application):
    QtGui.QWidget.__init__(self)
    self.input_file_widget = input_file_widget
    self.qt_app = qt_app
    self.application = application

    self.plane = vtk.vtkPlane()
    self.plane.SetOrigin(-1000, 0, 0)
    self.plane.SetNormal(1, 0, 0)

    self.exodus_result = None

    # The multiple (from adaptivity)
    self.exodus_results = []

    self.timestep_to_exodus_result = {}

    self.file_name = None

    self.setupLuts()

    # The multiple (from adaptivity) file names we know of
    self.file_names = []

    self.current_max_timestep = 0

    # Whether or not there is new data to read
    self.new_stuff_to_read = False

    self.timer = QtCore.QTimer()
    self.timer.stop()
    self.timer.setInterval(100)
    self.timer.timeout.connect(self._updateData)

    self.execution_widget = execution_widget
    self.execution_widget.run_started.connect(self._runStarted)
    self.execution_widget.run_stopped.connect(self._runStopped)
    self.execution_widget.timestep_begin.connect(self._timestepBegin)
    self.execution_widget.timestep_end.connect(self._timestepEnd)

    self.main_layout = QtGui.QHBoxLayout()
#    self.main_layout.setSpacing(0)

    self.right_layout = QtGui.QVBoxLayout()

    self.left_layout = QtGui.QVBoxLayout()
    self.left_widget = QtGui.QWidget()
    self.left_widget.setMaximumWidth(1)

    self.left_widget.setLayout(self.left_layout)
    self.left_layout.setSizeConstraint(QtGui.QLayout.SetMinimumSize)

    self.main_layout.addWidget(self.left_widget)
    self.right_layout.setStretchFactor(self.left_layout, 0.01)
    self.main_layout.addLayout(self.right_layout)

#    self.setMinimumWidth(700)
    self.setLayout(self.main_layout)

    self.vtkwidget = QVTKRenderWindowInteractor(self)
#    self.vtkwidget.setMinimumHeight(300)

    # Create background, default to the gradient look
    self.renderer = vtk.vtkRenderer()
    self._showBlackBackgroundChanged(0)
    self.renderer.ResetCamera()

    self.right_layout.addWidget(self.vtkwidget)
    self.right_layout.setStretchFactor(self.vtkwidget, 100)

    self.vtkwidget.show()

    self.vtkwidget.GetRenderWindow().AddRenderer(self.renderer)
    self.vtkwidget.GetRenderWindow().GetInteractor().SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
    self.vtkwidget.Initialize()
    self.vtkwidget.Start()

    self.first = True

    self.exodus_result = None

    self.has_displacements = False
    self.current_displacement_magnitude = 1.0

    self.current_scale_x_magnitude = 1.0
    self.current_scale_y_magnitude = 1.0
    self.current_scale_z_magnitude = 1.0

    self.current_variable = None
    self.current_component = None

    # Holds a mapping of variable name to contour choices so they can be restored when variables are selected
    self.contour_choices = {}

    # If we are currently restoring contours then don't save the intermediate ones
    self.currently_restoring_contours = False
    self.setupControls()

    self.modifyUI()

  ''' This will be called after the interface is completely setup to allow an application to modify this tab '''
  def modifyUI(self):
    pass

  ''' Return the name to use for this tab '''
  def name(self):
    return 'Visualize'

  def setupControls(self):
    self.controls_widget = QtGui.QWidget()
    self.controls_layout = QtGui.QVBoxLayout()

    self.bottom_controls_layout = QtGui.QHBoxLayout()

    self.left_layout.addLayout(self.controls_layout)
    self.main_layout.setStretchFactor(self.left_layout, 0.1)

#    self.main_layout.addLayout(self.bottom_controls_layout)

    self.leftest_controls_layout = QtGui.QVBoxLayout()
    self.left_controls_layout = QtGui.QVBoxLayout()
    self.right_controls_layout = QtGui.QVBoxLayout()

    self.block_view_group_box = QtGui.QGroupBox('Show Blocks')
#    self.block_view_group_box.setMaximumWidth(200)
#    self.block_view_group_box.setMaximumHeight(200)

    self.block_view_layout = QtGui.QVBoxLayout()
    self.block_view_list = QtGui.QListView()
    self.block_view_model = QtGui.QStandardItemModel()
    self.block_view_model.itemChanged.connect(self._blockViewItemChanged)
    self.block_view_list.setModel(self.block_view_model)
    self.block_view_layout.addWidget(self.block_view_list)

    self.block_view_group_box.setLayout(self.block_view_layout)

    self.leftest_controls_layout.addWidget(self.block_view_group_box)

    self.controls_layout.addLayout(self.leftest_controls_layout)
    self.controls_layout.addLayout(self.left_controls_layout)
    self.controls_layout.addLayout(self.right_controls_layout)

    self.controls_layout.setStretchFactor(self.leftest_controls_layout,1.0)
    self.controls_layout.setStretchFactor(self.left_controls_layout,1.5)
    self.controls_layout.setStretchFactor(self.right_controls_layout,4.0)

    self.automatic_update_checkbox = QtGui.QCheckBox("Automatically Update")
    self.automatic_update_checkbox.setToolTip('Toggle automattically reading new timesteps as they finish computing')
    self.automatic_update_checkbox.setCheckState(QtCore.Qt.Checked)
    self.automatically_update = True
    self.automatic_update_checkbox.stateChanged[int].connect(self._automaticUpdateChanged)
#    self.left_controls_layout.addWidget(self.automatic_update_checkbox)

    # Create Group for viewer controls

    # Create the View Mesh toggle
    self.toggle_groupbox = QtGui.QGroupBox("View")
    self.toggle_groupbox.setMaximumHeight(70)
    self.toggle_layout = QtGui.QHBoxLayout()
    self.toggle_groupbox.setMaximumHeight(70)
    self.draw_edges_checkbox = QtGui.QCheckBox("View Mesh")
    self.draw_edges_checkbox.setToolTip('Show mesh elements')
    self.draw_edges_checkbox.stateChanged[int].connect(self._drawEdgesChanged)
    self.toggle_layout.addWidget(self.draw_edges_checkbox, alignment=QtCore.Qt.AlignHCenter)

    # Add a button for toggling the scalebar legend
    self.hide_scalebar_checkbox = QtGui.QCheckBox("Scalebar")
    self.hide_scalebar_checkbox.setToolTip('Toggle visibility of colorbar')
    self.hide_scalebar_checkbox.setCheckState(QtCore.Qt.Checked)
    self.hide_scalebar_checkbox.stateChanged[int].connect(self._hideScalebarChanged)
    self.toggle_layout.addWidget(self.hide_scalebar_checkbox, alignment=QtCore.Qt.AlignHCenter)

    # Add a button for toggling background to black
    self.show_black_background_checkbox = QtGui.QCheckBox("Black")
    self.show_black_background_checkbox.setToolTip('Toggle a black/gradient background')
    self.show_black_background_checkbox.stateChanged[int].connect(self._showBlackBackgroundChanged)
    self.toggle_layout.addWidget(self.show_black_background_checkbox, alignment=QtCore.Qt.AlignHCenter)

    # Create a vertical layout and add the toggles
    self.toggle_groupbox.setLayout(self.toggle_layout)
    self.reset_layout = QtGui.QVBoxLayout()
    self.reset_layout.addWidget(self.toggle_groupbox)

    self.displace_groupbox = QtGui.QGroupBox("Displace")
    self.displace_groupbox.setCheckable(True)
    self.displace_groupbox.setChecked(True)
    self.displace_groupbox.setDisabled(True)
    self.displace_groupbox.setMaximumHeight(70)
    self.displace_groupbox.toggled[bool].connect(self._displaceToggled)
    self.displace_layout = QtGui.QHBoxLayout()
    self.displace_layout.setSpacing(0)
    self.displace_groupbox.setLayout(self.displace_layout)

    self.displace_magnitude_label = QtGui.QLabel("Multiplier: ")
    self.displace_magnitude_text = QtGui.QLineEdit("1.0")
    self.displace_magnitude_text.setMaximumWidth(50)
    self.displace_magnitude_text.setMinimumWidth(10)
    self.displace_magnitude_text.returnPressed.connect(self._displaceMagnitudeTextReturn)

    self.displace_layout.addWidget(self.displace_magnitude_label, alignment=QtCore.Qt.AlignRight)
    self.displace_layout.addWidget(self.displace_magnitude_text, alignment=QtCore.Qt.AlignLeft)

    self.reset_layout.addWidget(self.displace_groupbox)

    self.scale_groupbox = QtGui.QGroupBox("Scale")
    self.scale_groupbox.setCheckable(True)
    self.scale_groupbox.setChecked(False)
    self.scale_groupbox.setDisabled(False)
    self.scale_groupbox.setMaximumHeight(70)
    self.scale_groupbox.toggled[bool].connect(self._scaleToggled)
    self.scale_layout = QtGui.QHBoxLayout()
    self.scale_layout.setSpacing(0)
    self.scale_groupbox.setLayout(self.scale_layout)

    self.scale_x_label = QtGui.QLabel("x: ")
    self.scale_x_text = QtGui.QLineEdit("1.0")
    self.scale_x_text.setMinimumWidth(10)
    self.scale_x_text.setMaximumWidth(50)

    self.scale_y_label = QtGui.QLabel("y: ")
    self.scale_y_text = QtGui.QLineEdit("1.0")
    self.scale_y_text.setMinimumWidth(10)
    self.scale_y_text.setMaximumWidth(50)

    self.scale_z_label = QtGui.QLabel("z: ")
    self.scale_z_text = QtGui.QLineEdit("1.0")
    self.scale_z_text.setMinimumWidth(10)
    self.scale_z_text.setMaximumWidth(50)

    self.scale_x_text.returnPressed.connect(self._scaleMagnitudeTextReturn)
    self.scale_y_text.returnPressed.connect(self._scaleMagnitudeTextReturn)
    self.scale_z_text.returnPressed.connect(self._scaleMagnitudeTextReturn)

    self.scale_layout.addWidget(self.scale_x_label, alignment=QtCore.Qt.AlignRight)
    self.scale_layout.addWidget(self.scale_x_text, alignment=QtCore.Qt.AlignLeft)

    self.scale_layout.addWidget(self.scale_y_label, alignment=QtCore.Qt.AlignRight)
    self.scale_layout.addWidget(self.scale_y_text, alignment=QtCore.Qt.AlignLeft)

    self.scale_layout.addWidget(self.scale_z_label, alignment=QtCore.Qt.AlignRight)
    self.scale_layout.addWidget(self.scale_z_text, alignment=QtCore.Qt.AlignLeft)

    self.reset_layout.addWidget(self.scale_groupbox)

    self.clip_groupbox = QtGui.QGroupBox("Clip")
    self.clip_groupbox.setToolTip('Toggle clipping mode where the solution can be sliced open')
    self.clip_groupbox.setCheckable(True)
    self.clip_groupbox.setChecked(False)
    self.clip_groupbox.setMaximumHeight(70)
    self.clip_groupbox.toggled[bool].connect(self._clippingToggled)
    clip_layout = QtGui.QHBoxLayout()

    self.clip_plane_combobox = QtGui.QComboBox()
    self.clip_plane_combobox.setToolTip('Direction of the normal for the clip plane')
    self.clip_plane_combobox.addItem('x')
    self.clip_plane_combobox.addItem('y')
    self.clip_plane_combobox.addItem('z')
    self.clip_plane_combobox.currentIndexChanged[str].connect(self._clipNormalChanged)

    clip_layout.addWidget(self.clip_plane_combobox)

    self.clip_plane_slider = QtGui.QSlider(QtCore.Qt.Horizontal)
    self.clip_plane_slider.setToolTip('Slide to change plane position')
    self.clip_plane_slider.setRange(0, 100)
    self.clip_plane_slider.setSliderPosition(50)
    self.clip_plane_slider.sliderReleased.connect(self._clipSliderReleased)
    self.clip_plane_slider.sliderMoved[int].connect(self._clipSliderMoved)
    clip_layout.addWidget(self.clip_plane_slider)
#     vbox->addStretch(1);
    self.clip_groupbox.setLayout(clip_layout)

    self.reset_layout.addWidget(self.clip_groupbox)



    self.view_layout = QtGui.QHBoxLayout()

    self.open_button = QtGui.QPushButton('Open')
    self.open_button.setMaximumWidth(100)
    self.open_button.setToolTip('Open an existing result')
    self.open_button.clicked.connect(self._clickedOpen)
    self.view_layout.addWidget(self.open_button, alignment=QtCore.Qt.AlignHCenter)

    self.save_button = QtGui.QPushButton('Save')
    self.save_button.setMaximumWidth(100)
    self.save_button.setToolTip('Save the current view to a file')
    self.save_button.clicked.connect(self._saveView)
    self.view_layout.addWidget(self.save_button, alignment=QtCore.Qt.AlignHCenter)

    self.reset_button = QtGui.QPushButton('Reset')
    self.reset_button.setMaximumWidth(100)
    self.reset_button.setToolTip('Recenter the camera on the current result')
    self.reset_button.clicked.connect(self._resetView)
    self.view_layout.addWidget(self.reset_button, alignment=QtCore.Qt.AlignHCenter)

    self.reset_layout.addLayout(self.view_layout)

    self.right_controls_layout.addLayout(self.reset_layout)


    self.contour_groupbox = QtGui.QGroupBox("Contour")
#    self.contour_groupbox.setMaximumHeight(10)
#    self.contour_groupbox.setMaximumHeight(70)
#    contour_groupbox_policy = QtGui.QSizePolicy()
    self.contour_groupbox.setSizePolicy(QtGui.QSizePolicy.Fixed,QtGui.QSizePolicy.Fixed)
    self.contour_layout = QtGui.QVBoxLayout()
    self.contour_groupbox.setLayout(self.contour_layout)

    self.variable_contour_layout = QtGui.QHBoxLayout()
    self.contour_layout.addLayout(self.variable_contour_layout)
    self.contour_label = QtGui.QLabel("Contour:")
    self.variable_contour = QtGui.QComboBox()
    self.variable_contour_is_nodal = {}
    self.variable_contour.setToolTip('Which variable to color by')
    self.variable_contour.currentIndexChanged[int].connect(self._contourVariableSelected)
#    self.variable_contour_layout.addWidget(self.contour_label, alignment=QtCore.Qt.AlignRight)
    self.variable_contour_layout.addWidget(self.variable_contour, alignment=QtCore.Qt.AlignHCenter)

#    self.component_layout = QtGui.QHBoxLayout()
    self.component_label = QtGui.QLabel("Component:")
    self.variable_component = QtGui.QComboBox()
    self.variable_component.setToolTip('If the variable is a vector this selects what component of that vector (or the Magnitude) to color by')
    self.variable_component.currentIndexChanged[str].connect(self._variableComponentSelected)
#    self.component_layout.addWidget(self.component_label, alignment=QtCore.Qt.AlignRight)
#    self.component_layout.addWidget(self.variable_component, alignment=QtCore.Qt.AlignLeft)
#    self.variable_contour_layout.addLayout(self.component_layout)
    self.variable_contour_layout.addWidget(self.variable_component, alignment=QtCore.Qt.AlignHCenter)


    self.minmax_contour_layout = QtGui.QVBoxLayout()
    self.contour_layout.addLayout(self.minmax_contour_layout)

    self.min_groupbox = QtGui.QGroupBox("Min")
    self.min_layout = QtGui.QHBoxLayout()
    self.min_groupbox.setLayout(self.min_layout)

    self.min_radio_layout = QtGui.QVBoxLayout()

    self.min_current_radio = QtGui.QRadioButton('Current')
    self.min_current_radio.setChecked(QtCore.Qt.Checked)
    self.min_current_radio.toggled.connect(self._updateContours)
    self.min_global_radio = QtGui.QRadioButton('Global')
    self.min_global_radio.toggled.connect(self._updateContours)
    self.min_radio_layout.addWidget(self.min_current_radio)
#    self.min_radio_layout.addWidget(self.min_global_radio)

    self.min_custom_layout = QtGui.QHBoxLayout()
    self.min_custom_layout.setSpacing(0)
    self.min_custom_radio = QtGui.QRadioButton()
    self.min_custom_radio.toggled.connect(self._updateContours)
    self.min_custom_text = QtGui.QLineEdit()
    self.min_custom_text.returnPressed.connect(self._updateContours)
    self.min_custom_text.setDisabled(True)
    self.min_custom_text.setMaximumWidth(100)
    self.min_custom_layout.addWidget(self.min_custom_radio, alignment=QtCore.Qt.AlignLeft)
    self.min_custom_layout.addWidget(self.min_custom_text, alignment=QtCore.Qt.AlignLeft)
    self.min_custom_layout.addStretch()

    self.min_layout.addLayout(self.min_radio_layout)
    self.min_layout.addLayout(self.min_custom_layout)

    self.minmax_contour_layout.addWidget(self.min_groupbox)



    self.max_groupbox = QtGui.QGroupBox("Max")
    self.max_layout = QtGui.QHBoxLayout()
    self.max_groupbox.setLayout(self.max_layout)

    self.max_radio_layout = QtGui.QVBoxLayout()

    self.max_current_radio = QtGui.QRadioButton('Current')
    self.max_current_radio.setChecked(QtCore.Qt.Checked)
    self.max_current_radio.toggled.connect(self._updateContours)
    self.max_global_radio = QtGui.QRadioButton('Global')
    self.max_global_radio.toggled.connect(self._updateContours)
    self.max_radio_layout.addWidget(self.max_current_radio)
#    self.max_radio_layout.addWidget(self.max_global_radio)

    self.max_custom_layout = QtGui.QHBoxLayout()
    self.max_custom_layout.setSpacing(0)
    self.max_custom_radio = QtGui.QRadioButton()
    self.max_custom_radio.toggled.connect(self._updateContours)
    self.max_custom_text = QtGui.QLineEdit()
    self.max_custom_text.returnPressed.connect(self._updateContours)
    self.max_custom_text.setDisabled(True)
    self.max_custom_text.setMaximumWidth(100)
    self.max_custom_layout.addWidget(self.max_custom_radio, alignment=QtCore.Qt.AlignLeft)
    self.max_custom_layout.addWidget(self.max_custom_text, alignment=QtCore.Qt.AlignLeft)
    self.max_custom_layout.addStretch()

    self.max_layout.addLayout(self.max_radio_layout)
    self.max_layout.addLayout(self.max_custom_layout)

    self.minmax_contour_layout.addWidget(self.max_groupbox)


#    self.component_layout = QtGui.QHBoxLayout()
    self.color_scheme_label = QtGui.QLabel("Color Scheme:")
    self.color_scheme_component = QtGui.QComboBox()
    self.color_scheme_component.addItem('HSV (Cool to Warm)')
    self.color_scheme_component.addItem('Diverging (Blue to Red)')
    self.color_scheme_component.addItem('Shock')
    self.color_scheme_component.setToolTip('The color scheme used byt the render view')
    self.color_scheme_component.currentIndexChanged[str].connect(self._colorSchemeSelected)

#    self.component_layout.addWidget(self.component_label, alignment=QtCore.Qt.AlignRight)
#    self.component_layout.addWidget(self.variable_component, alignment=QtCore.Qt.AlignLeft)
#    self.variable_contour_layout.addLayout(self.component_layout)

    self.minmax_contour_layout.addWidget(self.color_scheme_component)

    self.left_controls_layout.addWidget(self.contour_groupbox)


    self.beginning_button = QtGui.QToolButton()
    self.beginning_button.setToolTip('Go to first timestep')
    self.beginning_button.setIcon(QtGui.QIcon(pathname + '/resources/from_paraview/pqVcrFirst32.png'))
    self.beginning_button.clicked.connect(self._beginningClicked)

    self.back_button = QtGui.QToolButton()
    self.back_button.setToolTip('Previous timestep')
    self.back_button.setIcon(QtGui.QIcon(pathname + '/resources/from_paraview/pqVcrBack32.png'))
    self.back_button.clicked.connect(self._backClicked)

    self.play_button = QtGui.QToolButton()
    self.play_button.setToolTip('Play through the currently computed timesteps')
    self.play_button.setIcon(QtGui.QIcon(pathname + '/resources/from_paraview/pqVcrPlay32.png'))
    self.play_button.clicked.connect(self._playClicked)

    self.pause_button = QtGui.QToolButton()
    self.pause_button.setToolTip('If playing this will pause playback')
    self.pause_button.setDisabled(True)
    self.pause_button.setIcon(QtGui.QIcon(pathname + '/resources/from_paraview/pqVcrPause32.png'))
    self.pause_button.clicked.connect(self._pauseClicked)

    self.forward_button = QtGui.QToolButton()
    self.forward_button.setToolTip('Next timestep')
    self.forward_button.setIcon(QtGui.QIcon(pathname + '/resources/from_paraview/pqVcrForward32.png'))
    self.forward_button.clicked.connect(self._forwardClicked)

    self.last_button = QtGui.QToolButton()
    self.last_button.setToolTip('Go to last timestep')
    self.last_button.setIcon(QtGui.QIcon(pathname + '/resources/from_paraview/pqVcrLast32.png'))
    self.last_button.clicked.connect(self._lastClicked)

    self.loop_button = QtGui.QToolButton()
    self.loop_button.setToolTip('Toggle replaying all timesteps when the end is reached during playback.  Note that as new timesteps finish they will automatically be picked up and added to the end of the sequence.')
    self.loop_button.setCheckable(True)
    self.loop_button.setIcon(QtGui.QIcon(pathname + '/resources/from_paraview/pqVcrLoop24.png'))
    self.loop_button.toggled.connect(self._loopClicked)

    self.currently_looping = False

    self.time_slider_label = QtGui.QLabel("Timestep:")
    self.time_slider = QtGui.QSlider(QtCore.Qt.Horizontal)
    self.time_slider.setToolTip('Slide to select a timestep to display')
#    self.time_slider.setMaximumWidth(600)

    self.time_slider.valueChanged.connect(self._timeSliderChanged)
    self.time_slider.sliderReleased.connect(self._timeSliderReleased)

    self.time_slider_textbox = QtGui.QLineEdit()
    self.time_slider_textbox.setToolTip('Enter a number and press Enter to go to that timestep')
    self.time_slider_textbox.setMaximumWidth(30)
    self.time_slider_textbox.setMinimumWidth(30)
    self.time_slider_textbox.returnPressed.connect(self._sliderTextboxReturn)

    self.time_groupbox = QtGui.QGroupBox("Time")
    self.time_groupbox.setMaximumHeight(70)

    self.time_layout = QtGui.QHBoxLayout()
    self.time_layout.addWidget(self.beginning_button)
    self.time_layout.addWidget(self.back_button)
    self.time_layout.addWidget(self.play_button)
    self.time_layout.addWidget(self.pause_button)
    self.time_layout.addWidget(self.forward_button)
    self.time_layout.addWidget(self.last_button)
    self.time_layout.addWidget(self.loop_button)
    self.time_layout.addWidget(self.time_slider_label, alignment=QtCore.Qt.AlignRight)
    self.time_layout.addWidget(self.time_slider)
    self.time_layout.addWidget(self.time_slider_textbox, alignment=QtCore.Qt.AlignLeft)

    self.time_groupbox.setLayout(self.time_layout)

    self.right_layout.addWidget(self.time_groupbox)



  def _updateControls(self):
    self.old_contour = self.variable_contour.currentText()
    self.variable_contour.clear()
    self.has_displacements = False
    for variable in self.exodus_result.current_nodal_variables:
      if 'ObjectId' not in variable:
        self.variable_contour.addItem(variable)
        item_num = self.variable_contour.count()-1
        self.variable_contour.setItemIcon(item_num,QtGui.QIcon(pathname + '/resources/from_paraview/pqNodalData16.png'))
        self.variable_contour_is_nodal[item_num] = True
        if 'disp' in variable:
          self.has_displacements = True

    for variable in self.exodus_result.current_elemental_variables:
      if 'ObjectId' not in variable:
        self.variable_contour.addItem(variable)
        item_num = self.variable_contour.count()-1
        self.variable_contour.setItemIcon(item_num,QtGui.QIcon(pathname + '/resources/from_paraview/pqElemData16.png'))
        self.variable_contour_is_nodal[item_num] = False
        if 'disp' in variable:
          self.has_displacements = True

    if self.has_displacements:
      self.displace_groupbox.setDisabled(False)

    self.block_view_model.clear()
    for block in self.exodus_result.blocks:
      block_display_name = str(block)
      if block in self.exodus_result.block_to_name:
        block_display_name += ' : ' + self.exodus_result.block_to_name[block]

      item = QtGui.QStandardItem(str(block_display_name))
      item.exodus_block = block
      item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable)
      item.setCheckState(QtCore.Qt.Checked)
      self.block_view_model.appendRow(item)

    # Try to restore back to the view of the variable we were looking at
    found_index = self.variable_contour.findText(self.old_contour)
    if found_index != -1:
      self.variable_contour.setCurrentIndex(found_index)
    else: # If this variable doesn't exist then we are probably running a new simulation... try to reset the camera
      self._resetView()

    self.time_slider.setMinimum(0)
    self.time_slider.setMaximum(self.current_max_timestep)


  def setupLuts(self):
    self.luts = []

    # HSV (Blue to REd)  Default
    lut = vtk.vtkLookupTable()
    lut.SetHueRange(0.667, 0.0)
    lut.SetNumberOfColors(256)
    lut.Build()
    self.luts.append(lut)

    # Diverging (Cool to Warm) color scheme
    ctf = vtk.vtkColorTransferFunction()
    ctf.SetColorSpaceToDiverging()
    ctf.AddRGBPoint(0.0, 0.230, 0.299, 0.754)
    ctf.AddRGBPoint(1.0, 0.706, 0.016, 0.150)
    cc = list()
    for i in xrange(256):
      cc.append(ctf.GetColor(float(i) / 255.0))
    lut = vtk.vtkLookupTable()
    lut.SetNumberOfColors(256)
    for i, item in enumerate(cc):
      lut.SetTableValue(i, item[0], item[1], item[2], 1.0)
    lut.Build()
    self.luts.append(lut)

    # Shock
    ctf = vtk.vtkColorTransferFunction()
    min = 93698.4
    max = 230532
    ctf.AddRGBPoint(self._normalize(min, max,  93698.4),  0.0,         0.0,      1.0)
    ctf.AddRGBPoint(self._normalize(min, max, 115592.0),  0.0,         0.905882, 1.0)
    ctf.AddRGBPoint(self._normalize(min, max, 138853.0),  0.0941176,   0.733333, 0.027451)
    ctf.AddRGBPoint(self._normalize(min, max, 159378.0),  1.0,         0.913725, 0.00784314)
    ctf.AddRGBPoint(self._normalize(min, max, 181272.0),  1.0,         0.180392, 0.239216)
    ctf.AddRGBPoint(self._normalize(min, max, 203165.0),  1.0,         0.701961, 0.960784)
    ctf.AddRGBPoint(self._normalize(min, max, 230532.0),  1.0,         1.0,      1.0)
    cc = list()
    for i in xrange(256):
      cc.append(ctf.GetColor(float(i) / 255.0))
    lut = vtk.vtkLookupTable()
    lut.SetNumberOfColors(256)
    for i, item in enumerate(cc):
      lut.SetTableValue(i, item[0], item[1], item[2], 1.0)
    lut.Build()
    self.luts.append(lut)

    self.current_lut = self.luts[0]


  def _normalize(self, min, max, value):
    return (value - min) / (max - min)

  def _blockViewItemChanged(self, item):
    if item.checkState() == QtCore.Qt.Checked:
      self.exodus_result.showBlock(item.exodus_block)
      self.exodus_result.reader.Update()
      self.exodus_result.geom.Update()
      self.current_bounds = self.exodus_result.actor.GetBounds()
      self._updateContours()
    else:
      self.exodus_result.hideBlock(item.exodus_block)
      self.exodus_result.reader.Update()
      self.exodus_result.geom.Update()
      self.current_bounds = self.exodus_result.actor.GetBounds()
      self._updateContours()

  def _displaceToggled(self, value):
    self._timeSliderReleased()

  def _scaleToggled(self, value):
    self._timeSliderReleased()

  def _displaceMagnitudeTextReturn(self):
    self.current_displacement_magnitude = float(self.displace_magnitude_text.text())
    self._timeSliderReleased()

  def _scaleMagnitudeTextReturn(self):
    self.current_scale_x_magnitude = float(self.scale_x_text.text())
    self.current_scale_y_magnitude = float(self.scale_y_text.text())
    self.current_scale_z_magnitude = float(self.scale_z_text.text())
    self._timeSliderReleased()

  def _drawEdgesChanged(self, value):
    if value == QtCore.Qt.Checked:
      self.exodus_result.actor.GetProperty().EdgeVisibilityOn()
      self.exodus_result.clip_actor.GetProperty().EdgeVisibilityOn()
    else:
      self.exodus_result.actor.GetProperty().EdgeVisibilityOff()
      self.exodus_result.clip_actor.GetProperty().EdgeVisibilityOff()
    self.vtkwidget.repaint()

  ##
  # A method for toggling visiability of the scale bar legend, it is controlled
  # by the 'Hide Scalebar' toggle on the Visualize tab
  # @param value The interger value from the checkbox (1=checked)
  def _hideScalebarChanged(self, value):

    # Show when checked
    if value == QtCore.Qt.Checked:
      self.exodus_result.scalar_bar.VisibilityOn()

    # Hide when unchecked
    else:
      self.exodus_result.scalar_bar.VisibilityOff()

    # Update the GUI
    self.vtkwidget.repaint()

  ##
  # A method for toggling black background or gradient background, it is controlled
  # by the 'Black Background' toggle on the Visualize tab
  # @param value The interger value from the checkbox (1=checked)
  def _showBlackBackgroundChanged(self, value):

    # Black when checked
    if value == QtCore.Qt.Checked:
      self.renderer.SetBackground(0,0,0)
      self.renderer.SetGradientBackground(0)
      #self.renderer.ResetCamera()

    # Gradient when unchecked
    else:
      self.renderer.SetBackground(0,0,0)
      self.renderer.SetBackground(0.2,0.2,0.2)
      self.renderer.SetBackground2(1,1,1)
      self.renderer.SetGradientBackground(1)
      #self.renderer.ResetCamera()

    # Update thew GUI
    self.vtkwidget.repaint()

  def _fillComponentCombo(self, variable_name, components):
    self.variable_component.clear()
    self.variable_component.addItem('Magnitude')
    num_components = components[variable_name]
    if num_components > 1 and self.exodus_result.current_dim >= 2:
      self.variable_component.setDisabled(False)
      self.variable_component.addItem('X')
      self.variable_component.addItem('Y')
    else:
      self.variable_component.setDisabled(True)

    if num_components > 1 and  self.exodus_result.current_dim == 3:
      self.variable_component.addItem('Z')

  def _contourVariableSelected(self, index):

    value_string = str(self.variable_contour.itemText(index))
    self.current_variable = value_string
    self.current_variable_index = index

    if index in self.variable_contour_is_nodal:
      self.current_variable_is_nodal = self.variable_contour_is_nodal[index]
    else:
      self.current_variable_is_nodal = True

    self.currently_restoring_contours = True

    # Maybe results haven't been written yet...
    if not self.exodus_result.data.GetPointData().GetVectors(value_string) and not self.exodus_result.data.GetCellData().GetVectors(value_string):
      return

    if value_string in self.exodus_result.current_nodal_components:
      self._fillComponentCombo(value_string, self.exodus_result.current_nodal_components)
    elif value_string in self.exodus_result.current_elemental_components:
      self._fillComponentCombo(value_string, self.exodus_result.current_elemental_components)

    if self.current_variable not in self.contour_choices:
      self.contour_choices[self.current_variable] = ContourChoices()

    self.contour_choices[self.current_variable].restore(self)
    self.currently_restoring_contours = False


  def _variableComponentSelected(self, value):
    value_string = str(value)
    self.current_component = value_string
    if value_string == 'Magnitude':
      self.component_index = -1
    elif value_string == 'X':
      self.component_index = 0
    elif value_string == 'Y':
      self.component_index = 1
    elif value_string == 'Z':
      self.component_index = 2

    self._updateContours()

  def _updateContours(self):
    self.exodus_result.setColorScheme(self.current_lut)
    if self.component_index == -1:
      self.exodus_result.lut.SetVectorModeToMagnitude()
    elif self.component_index == 0:
      self.exodus_result.lut.SetVectorModeToComponent()
      self.exodus_result.lut.SetVectorComponent(0)
    elif self.component_index == 1:
      self.exodus_result.lut.SetVectorModeToComponent()
      self.exodus_result.lut.SetVectorComponent(1)
    elif self.component_index == 2:
      self.exodus_result.lut.SetVectorModeToComponent()
      self.exodus_result.lut.SetVectorComponent(2)

    if self.clip_groupbox.isChecked():
      self.exodus_result.clipper.Modified()
      self.exodus_result.clipper.Update()
      self.exodus_result.clip_geom.Update()
      self.exodus_result.clip_mapper.Update()

    data = None
    if self.current_variable_is_nodal and self.current_variable in self.exodus_result.current_nodal_components:
      data = self.exodus_result.data.GetPointData().GetVectors(self.current_variable)
      self.exodus_result.mapper.SetScalarModeToUsePointFieldData()
      self.exodus_result.clip_mapper.SetScalarModeToUsePointFieldData()
    elif self.current_variable in self.exodus_result.current_elemental_components:
      data = self.exodus_result.data.GetCellData().GetVectors(self.current_variable)
      self.exodus_result.mapper.SetScalarModeToUseCellFieldData()
      self.exodus_result.clip_mapper.SetScalarModeToUseCellFieldData()

    self.exodus_result.mapper.SelectColorArray(self.current_variable)
    self.exodus_result.clip_mapper.SelectColorArray(self.current_variable)

    if data:
      self.current_range = data.GetRange(self.component_index)

      if self.min_current_radio.isChecked():
        self.min_custom_text.setText(str(self.current_range[0]))
        self.min_custom_text.setCursorPosition(0)

      if self.max_current_radio.isChecked():
        self.max_custom_text.setText(str(self.current_range[1]))
        self.max_custom_text.setCursorPosition(0)

      if self.min_custom_radio.isChecked():
        self.min_custom_text.setDisabled(False)
      else:
        self.min_custom_text.setDisabled(True)

      if self.max_custom_radio.isChecked():
        self.max_custom_text.setDisabled(False)
      else:
        self.max_custom_text.setDisabled(True)

      min = 0.0
      try:
        min = float(self.min_custom_text.displayText())
      except:
        min = 0.0

      max = 0.0
      try:
        max = float(self.max_custom_text.displayText())
      except:
        max = 0.0

      if self.current_variable not in self.contour_choices:
        self.contour_choices[self.current_variable] = ContourChoices()

      if not self.currently_restoring_contours:
        self.contour_choices[self.current_variable].save(self)

      the_range = (min, max)

      if min <= max:
        self.exodus_result.mapper.SetScalarRange(the_range)
        self.exodus_result.clip_mapper.SetScalarRange(the_range)


    self.exodus_result.scalar_bar.SetTitle(self.current_variable)
    self.renderer.AddActor2D(self.exodus_result.scalar_bar)
    self.vtkwidget.repaint()

  def _colorSchemeSelected(self, value):
    self.current_lut = self.luts[self.color_scheme_component.currentIndex()]
    self._updateContours()

  def _openFile(self, file_name):
    self._clear()

    self.base_stamp = os.path.getmtime(file_name)
    self.file_name = str(file_name)

    self.new_stuff_to_read = True
    self._updateData()
    self._updateData() # Call it again to read any adaptive results

    self._lastClicked() # Go to the last timestep

    self._resetView() # Reset the camera

  def _clickedOpen(self):
    file_name = QtGui.QFileDialog.getOpenFileName(self, "Open Result", "~/", "Input Files (*.e)")

    if not isinstance(file_name, basestring): # This happens when using pyside
        file_name = file_name[0]

    if file_name:
      self._openFile(file_name)

  def _resetView(self):
    self.renderer.ResetCamera()
    fp = self.renderer.GetActiveCamera().GetFocalPoint()
    p = self.renderer.GetActiveCamera().GetPosition()
    dist = math.sqrt( (p[0]-fp[0])**2 + (p[1]-fp[1])**2 + (p[2]-fp[2])**2 )
    self.renderer.GetActiveCamera().SetPosition(fp[0], fp[1], fp[2]+dist)
    self.renderer.GetActiveCamera().SetViewUp(0.0, 1.0, 0.0)
    self.vtkwidget.repaint()

  def _saveView(self):
    file_name = QtGui.QFileDialog.getSaveFileName(self, "Image File Name", "~/", "Image Files (*.png)")

    if not isinstance(file_name, basestring): # This happens when using pyside
        file_name = file_name[0]

    if file_name != '':
      w2i = vtk.vtkWindowToImageFilter()
      writer = vtk.vtkPNGWriter()
      w2i.SetInput(self.vtkwidget.GetRenderWindow())
      w2i.Update()
      writer.SetInputConnection(w2i.GetOutputPort())
      writer.SetFileName(str(file_name))
      self.vtkwidget.GetRenderWindow().Render()
      writer.Write()

  def _automaticUpdateChanged(self, value):
    if value == QtCore.Qt.Checked:
      self.automatically_update = True
    else:
      self.automatically_update = False

  def _beginningClicked(self):
    self.time_slider.setSliderPosition(0)
    self._timeSliderReleased()

  def _backClicked(self):
    self.time_slider.setSliderPosition(self.time_slider.sliderPosition()-1)
    self._timeSliderReleased()

  def _playClicked(self):
    self.play_button.setDisabled(True)
    self.pause_button.setDisabled(False)
    self.currently_playing = True

    first = True
    while((first or self.currently_looping) and self.currently_playing):
      first = False

      # If the slider is at the end then start over
      self.qt_app.processEvents()
      time.sleep(0.02)
      self.qt_app.processEvents()
      if self.time_slider.sliderPosition() == self.time_slider.maximum():
        self.time_slider.setSliderPosition(0)

      while self.time_slider.sliderPosition() < self.time_slider.maximum():
        self.time_slider.setSliderPosition(self.time_slider.sliderPosition()+1)
        self.qt_app.processEvents()
        self._timeSliderReleased()
        time.sleep(0.02)
        self.qt_app.processEvents()
        if not self.currently_playing:
          break

    self.play_button.setDisabled(False)
    self.pause_button.setDisabled(True)

  def _pauseClicked(self):
    self.play_button.setDisabled(False)
    self.pause_button.setDisabled(True)
    self.currently_playing = False

  def _forwardClicked(self):
    self.time_slider.setSliderPosition(self.time_slider.sliderPosition()+1)
    self._timeSliderReleased()

  def _lastClicked(self):
    self.time_slider.setSliderPosition(self.time_slider.maximum())
    self._timeSliderReleased()

  def _loopClicked(self, state):
    if state:
      self.currently_looping = True
    else:
      self.currently_looping = False

  def _timeSliderChanged(self):
    self.time_slider_textbox.setText(str(self.time_slider.sliderPosition()))

  def _timeSliderReleased(self):
    textbox_string = self.time_slider_textbox.text()
    if textbox_string == '':
      textbox_string = str(self.exodus_result.min_timestep)

    if int(textbox_string) in self.timestep_to_exodus_result:
      for actor in self.exodus_result.current_actors:
        self.renderer.RemoveActor(actor)
      self.exodus_result = self.timestep_to_exodus_result[int(textbox_string)]

      if self.clip_groupbox.isChecked():
        self.renderer.AddActor(self.exodus_result.clip_actor)
        if self.draw_edges_checkbox.checkState() == QtCore.Qt.Checked:
          self.exodus_result.clip_actor.GetProperty().EdgeVisibilityOn()
        else:
          self.exodus_result.clip_actor.GetProperty().EdgeVisibilityOff()
      else:
        self.renderer.AddActor(self.exodus_result.actor)
        if self.draw_edges_checkbox.checkState() == QtCore.Qt.Checked:
          self.exodus_result.actor.GetProperty().EdgeVisibilityOn()
        else:
          self.exodus_result.actor.GetProperty().EdgeVisibilityOff()

      num_block_view_items = self.block_view_model.rowCount()
      for i in xrange(num_block_view_items):
        item = self.block_view_model.item(i)
        if item.checkState() == QtCore.Qt.Checked:
          self.exodus_result.showBlock(item.exodus_block)
        else:
          self.exodus_result.hideBlock(item.exodus_block)

      if self.has_displacements and self.displace_groupbox.isChecked():
        self.exodus_result.reader.SetApplyDisplacements(1)
        self.exodus_result.reader.SetDisplacementMagnitude(float(self.current_displacement_magnitude))
      else:
        self.exodus_result.reader.SetApplyDisplacements(0)

      if self.scale_groupbox.isChecked():
        self.exodus_result.actor.SetScale(self.current_scale_x_magnitude, self.current_scale_y_magnitude, self.current_scale_z_magnitude)
      else:
        self.exodus_result.actor.SetScale(1.0, 1.0, 1.0)

    if self.exodus_result.reader:
      self.exodus_result.reader.SetTimeStep(self.timestep_to_timestep[int(textbox_string)])
      self.exodus_result.reader.Update()
      self.exodus_result.geom.Update()
      self.current_bounds = self.exodus_result.actor.GetBounds()
      self._updateContours()

  def _sliderTextboxReturn(self):
    self.time_slider.setSliderPosition(int(self.time_slider_textbox.text()))
    self._timeSliderReleased()

  def _associateResultsWithTimesteps(self):
    self.timestep_to_exodus_result = {}
    self.timestep_to_timestep = {}
    self.current_max_timestep = -1
    for result in self.exodus_results:
      result.reader.UpdateTimeInformation()
      min = result.reader.GetTimeStepRange()[0]
      max = result.reader.GetTimeStepRange()[1]
      for timestep in xrange(min, max+1):
        self.current_max_timestep += 1
        self.timestep_to_exodus_result[self.current_max_timestep] = result
        self.timestep_to_timestep[self.current_max_timestep] = timestep

  def _updateData(self):
    # Check to see if there are new exodus files with adapted timesteps in them.
    if self.file_name and self.exodus_result:
      for file_name in sorted(glob.glob(self.file_name + '-s*')):
        file_stamp = os.path.getmtime(file_name)
        if int(file_stamp) >= int(self.base_stamp) and int(file_stamp) <= int(time.time() - 1) and file_name not in self.file_names:
          self.file_names.append(file_name)
          exodus_result = ExodusResult(self, self.plane)
          exodus_result.setFileName(file_name, self.current_lut)
          self.exodus_results.append(exodus_result)
          self.new_stuff_to_read = True

    if not self.exodus_result:
      if not self.file_name: # Might have been set by opening a file
        output_file_names = self.input_file_widget.getOutputFileNames()
      else:
        output_file_names = [self.file_name]

      output_file = ''

      for file_name in output_file_names:
        if '.e' in file_name and os.path.exists(file_name):
          file_stamp = os.path.getmtime(file_name)

          if int(file_stamp) >= int(self.base_stamp) and int(file_stamp) <= int(time.time() - 1) and file_name not in self.file_names:
            self.file_name = file_name
            self.exodus_result = ExodusResult(self, self.plane)
            self.exodus_result.setFileName(file_name, self.current_lut)
            self.exodus_results.append(self.exodus_result)
            self.current_max_timestep = self.exodus_result.max_timestep
            self.renderer.AddActor(self.exodus_result.actor)
            self._drawEdgesChanged(self.draw_edges_checkbox.checkState())

            if self.first:
              self.first = False
              self.renderer.ResetCamera()

            # Avoid z-buffer fighting
            vtk.vtkPolyDataMapper().SetResolveCoincidentTopologyToPolygonOffset()

            if self.clip_groupbox.isChecked():
              _clippingToggled(True)

            self.vtkwidget.repaint()
            self._updateControls()
            self.time_slider.setSliderPosition(self.current_max_timestep)

    if self.new_stuff_to_read and self.exodus_result and self.automatically_update:
      self._associateResultsWithTimesteps()
#      self.exodus_result.reader.UpdateTimeInformation()
#      range = self.exodus_result.reader.GetTimeStepRange()
#      self.exodus_result.min_timestep = range[0]
#      self.exodus_result.max_timestep = range[1]
      self.time_slider.setMinimum(0)

      # Only automatically move forward if they're on the current step
      if self.time_slider.sliderPosition() == self.time_slider.maximum():
        self.time_slider.setMaximum(self.current_max_timestep)
        self.time_slider.setSliderPosition(self.current_max_timestep)
        self._timeSliderReleased()
        if self.clip_groupbox.isChecked():
          self._clipSliderReleased()
        self.vtkwidget.repaint()
      else:
        self.time_slider.setMaximum(self.current_max_timestep)

    self.new_stuff_to_read = False

  def _timestepBegin(self):
    self.new_stuff_to_read = True

  def _timestepEnd(self):
    pass


  def _clear(self):
    self.application.addExodusResultActors(self.renderer)
    self.file_name = None
    self.file_names = []

    if not self.exodus_result:
      return

    for actor in self.exodus_result.current_actors:
      self.renderer.RemoveActor(actor)

    del self.exodus_result.current_actors[:]

    self.exodus_result = None
    self.exodus_results = []
    self.timestep_to_exodus_result = {}

  def _runStarted(self):
    # Set the base time
    self.base_stamp = time.time()
    self._clear()
    self.timer.start()

  def _finalRead(self):
    self.new_stuff_to_read = True # Set this to true so we get one more update
    # Do it twice in case of adapted results
    self._updateData()
    self._updateData()

  def _runStopped(self):
    self.timer.stop()
    self.run_stopped_timer = QtCore.QTimer()
    self.run_stopped_timer.setInterval(1000) # Wait a second before updating the plots one last time
    self.run_stopped_timer.setSingleShot(True)
    self.run_stopped_timer.timeout.connect(self._finalRead)
    self.run_stopped_timer.start()

  def _clippingToggled(self, value):
    if value:
      self.renderer.RemoveActor(self.exodus_result.current_actor)
      self.renderer.AddActor(self.exodus_result.clip_actor)
      self.exodus_result.current_actor = self.exodus_result.clip_actor
      self.clip_plane_slider.setSliderPosition(50)
      self._clipSliderMoved(50)
      self._clipSliderReleased()
    else:
      self.renderer.RemoveActor(self.exodus_result.current_actor)
      self.renderer.AddActor(self.exodus_result.actor)
      self.exodus_result.current_actor = self.exodus_result.actor

    self.vtkwidget.repaint()

  def _clipNormalChanged(self, value):
    self.plane.SetOrigin(self.current_bounds[0],
                         self.current_bounds[2],
                         self.current_bounds[4])
    if value == 'x':
      self.plane.SetNormal(1, 0, 0)
    elif value == 'y':
      self.plane.SetNormal(0, 1, 0)
    else:
      self.plane.SetNormal(0, 0, 1)

    self.clip_plane_slider.setSliderPosition(50)
    self._clipSliderMoved(50)

    self.vtkwidget.repaint()

  def _clipSliderReleased(self):
    self._updateContours()
    self.vtkwidget.repaint()

  def _clipSliderMoved(self, value):
    direction = str(self.clip_plane_combobox.currentText())

    min = 0
    max = 0

    if direction == 'x':
      min = self.current_bounds[0]
      max = self.current_bounds[1]
    elif direction == 'y':
      min = self.current_bounds[2]
      max = self.current_bounds[3]
    elif direction == 'z':
      min = self.current_bounds[4]
      max = self.current_bounds[5]

    step_size = (max - min)/100.0
    steps = value
    distance = float(steps)*step_size
    position = min + distance

    old = self.plane.GetOrigin()
    self.plane.SetOrigin(position if direction == 'x' else old[0],
                         position if direction == 'y' else old[1],
                         position if direction == 'z' else old[2])

    self._updateContours()
    self.vtkwidget.repaint()
Exemple #13
0
 tool2.toggled.connect(editSwc)
 toolbar1.addAction(tool2)
 tool3 = QtGui.QAction(toolbar1)
 tool3_icon = QtGui.QIcon()
 tool3_icon.addFile(r'G:\sulei\workplace\TraceTool\Resource\Science.png')
 tool3.setIcon(tool3_icon)
 tool3.triggered.connect(changeLineWidth)
 toolbar1.addAction(tool3)
 
 
 mainwin.addToolBar(toolbar1)
 mainwin.setMenuBar(menubar1)
 mainwin_location = QtCore.QRect(600, 300, 400, 400)
 mainwin.setMaximumSize(400, 400)
 mainwin.setGeometry(mainwin_location)
 central_widget = QtGui.QWidget(mainwin)
 mainwin.setCentralWidget(central_widget)
 layout1 = QtGui.QHBoxLayout()
 central_widget.setLayout(layout1)
 vtk_widget = QVTKRenderWindowInteractor(central_widget)
 vtk_widget.setMinimumSize(50, 50)
 layout1.addWidget(vtk_widget)
 vtk_widget.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
 ren = vtk.vtkRenderer()
 style1 = SwcEditStyle()
 iren = vtk_widget.GetRenderWindow().GetInteractor()
 iren.SetInteractorStyle(style1)
 vtk_widget.Initialize()
 vtk_widget.Start()
 mainwin.show()
 sys.exit(app.exec_())
Exemple #14
0
class MeshViewer(QtGui.QWidget):

    app = QtGui.QApplication(sys.argv)
    
    """
    Qt GUI for visu. the output
    """
    def __init__(self, truss, algo): 
        QtGui.QWidget.__init__(self) 
        
        self.truss = truss
        self.algo = algo
        self.algo.dhook = self
        
        self.running = 'init'
        
        print "starting MeshViewer init..."
        
        self.__setupGUI()
        self.__setupVTK()
        
        self.app.lastWindowClosed.connect(self.app.quit)
        self.show() 
        print "MeshViewer ready." 
        
    def closeEvent(self, event):
        self.algo.stopit=True 
        self.running='running' # sort de "while self.running=='pause'"      
        print "GUI killed!"
        QtGui.QWidget.closeEvent(self,event)


    def start(self):
        self.app.exec_()

    def __setupGUI(self):

        self.setWindowTitle("MeshViewer")
        self.resize(800, 600)
        
        # vtk window
        
        self.vtkwidget = QVTKRenderWindowInteractor(self) # "self" sinon, rien ne s'affiche
        self.vtkwidget.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, 
                                                  QtGui.QSizePolicy.Expanding))
        self.vtkwidget.setMinimumSize(QtCore.QSize(300, 300));
        self.vtkwidget.setSizePolicy(QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding)
        
                      
        self.vtkwidget.Initialize() 
                       
        self.renderer = vtk.vtkRenderer()
        self.renderer.SetBackground(1.0, 1.0, 1.0)     
        self.vtkwidget.GetRenderWindow().AddRenderer(self.renderer) 
        
        style = vtk.vtkInteractorStyleTrackballCamera()
        self.vtkwidget.SetInteractorStyle(style) 


        hbox = QtGui.QHBoxLayout()
        self.setLayout(hbox)
        hbox.addWidget(self.vtkwidget)
        
        pan = QtGui.QFrame()
        pan.setMaximumSize(QtCore.QSize(200,999999))
        hbox.addWidget(pan)
        
        vbox = QtGui.QVBoxLayout()
        pan.setLayout(vbox)
        
        self.startBut = QtGui.QPushButton(self.tr("start!"))
        self.connect(self.startBut, QtCore.SIGNAL("clicked()"), self.startSlot)
        vbox.addWidget(self.startBut)
        
        groupBox = QtGui.QGroupBox("Infos")
        self.steplabel = QtGui.QLabel("step # 0")
        self.loadlabel = QtGui.QLabel("lambda = %2.8f" % 0)
        gbox = QtGui.QVBoxLayout()
        groupBox.setLayout(gbox) 
        gbox.addWidget(self.steplabel)   
        gbox.addWidget(self.loadlabel)   
        vbox.addWidget(groupBox)
        
        vbox.addStretch(1)
        
    def startSlot(self):
        if self.running=='init':  
            self.startBut.setText('Pause') # on demarre et on affiche "pause"
            self.running='running'
            self.algo.run()
            self.startBut.setText("Quit")
            self.running='quit'
        elif self.running=='running':  # on stoppe et on affiche 'continue"
            self.running='pause'
            self.startBut.setText("Continue")
            while self.running=='pause':
                self.app.processEvents(QtCore.QEventLoop.WaitForMoreEvents)
        elif self.running=='pause':
            self.running='running'
            self.startBut.setText("Pause")
        elif self.running=='quit':
            self.app.quit()
        
    def disableStart(self):
        self.startBut.setDisabled(True)
        
    def __setupVTK(self):
        # polydata
        self.__createPolyData()
        self.poly = PolyData(self.polydata)
        self.renderer.AddActor(self.poly.actor)
        self.renderer.AddActor2D(self.poly.pointLabels)
        
        self.resetCamera() 

    def resetCamera(self):
        self.renderer.ResetCamera()
        cam1 = self.renderer.GetActiveCamera()
        # 3D
        if 0:
            cam1.Elevation(35)
            cam1.SetViewUp(0, 1, 0)
            cam1.Azimuth(30)
        #2D
        else:
            cam1.Elevation(0)
            cam1.SetViewUp(0, 1, 0)
            cam1.Azimuth(0)
            self.renderer.ResetCameraClippingRange()        
        
    def display(self, step, lamda):
        
        self.steplabel.setText("step # %d" % step)
        self.loadlabel.setText("lambda = %2.8f" % lamda)
        
        self.points.Reset()
        self.vertices.Reset()
        self.lines.Reset()
        self.scalars.Reset()
        
        # points
        nmap={}
        i=0
        for nod in self.truss.nodes:
            nmap[nod.nb]=i
            self.points.InsertPoint(i, nod.x, nod.y, 0.0)
            self.scalars.InsertNextValue(nod.nb)
            # node cells
            vertex = vtk.vtkVertex()
            vertex.GetPointIds().SetId(0, i)
            self.vertices.InsertNextCell(vertex)
            i+=1
        self.points.Modified()
        self.vertices.Modified()
        
        for bar in self.truss.bars:
            line = vtk.vtkLine()
            ids = line.GetPointIds()
            ids.SetNumberOfIds(2)
            for j in range(len(bar.nodes)):
                ids.SetId(j, nmap[bar.nodes[j].nb])
            self.lines.InsertNextCell(line) 
        self.lines.Modified()
        
        self.polydata.Modified()
        
        self.render()
    
    def ragequit(self):
        print "rage quit!"
        self.algo.stopit=True
        self.app.quit()
        
    def render(self): 
        # draw the scene
        self.vtkwidget.Render()
        self.app.processEvents()
    
    def refresh(self):
        self.app.processEvents()
        
    def __createPolyData(self):
        print 'creating vtkPolyData...'
        self.points = vtk.vtkPoints()
        self.polydata  = vtk.vtkPolyData()
        self.vertices = vtk.vtkCellArray()
        self.lines = vtk.vtkCellArray()
        
        self.polydata.SetPoints(self.points)
        self.polydata.SetVerts(self.vertices)
        self.polydata.SetLines(self.lines)
        
        # points
        self.scalars = vtk.vtkFloatArray()
        self.scalars.SetNumberOfComponents(1)
        self.polydata.GetPointData().SetScalars(self.scalars)
     
        nmap={}
        i=0
        for nod in self.truss.nodes:
            nmap[nod.nb]=i
            self.points.InsertPoint(i, nod.x, nod.y, 0.0)
            self.scalars.InsertNextValue(nod.nb)
            # node cells
            vertex = vtk.vtkVertex()
            vertex.GetPointIds().SetId(0, i)
            self.vertices.InsertNextCell(vertex)
            i+=1
        self.points.Modified()
        self.vertices.Modified()
        
        for bar in self.truss.bars:
            line = vtk.vtkLine()
            ids = line.GetPointIds()
            ids.SetNumberOfIds(2)
            for j in range(len(bar.nodes)):
                ids.SetId(j, nmap[bar.nodes[j].nb])
            self.lines.InsertNextCell(line) 
        self.lines.Modified()