def reset(self):
        """ Reset. """
        # last key press (it should have a mutex, but visualization is not
        # safety critical, so let's do things wrong)
        self.action = "no"  # no, next, back, quit are the possibilities

        # new canvas prepared for visualizing data
        self.canvas = SceneCanvas(keys='interactive',
                                  show=True,
                                  size=self.canvas_size)
        # interface (n next, b back, q quit, very simple)
        self.canvas.events.key_press.connect(self.key_press)
        self.canvas.events.draw.connect(self.draw)

        # laserscan part
        self.scan_view = vispy.scene.widgets.ViewBox(border_color='white',
                                                     parent=self.canvas.scene)
        self.scan_view.camera = vispy.scene.TurntableCamera(elevation=30,
                                                            azimuth=-90,
                                                            distance=30,
                                                            translate_speed=30,
                                                            up='+z')
        # grid
        self.grid = self.canvas.central_widget.add_grid()
        self.grid.add_widget(self.scan_view)

        self.scan_vis = visuals.Markers(parent=self.scan_view.scene)
        self.scan_vis.antialias = 0
        # self.scan_view.add(self.scan_vis)
        visuals.XYZAxis(parent=self.scan_view.scene)

        self.line = visuals.Line(width=1,
                                 method='gl',
                                 parent=self.scan_view.scene)
        self.text = visuals.Text(color='red',
                                 font_size=600,
                                 bold=True,
                                 parent=self.scan_view.scene)
        self.gt_line = visuals.Line(width=1000, parent=self.scan_view.scene)
        # self.sem_view.camera.link(self.scan_view.camera)

        if self.show_img:
            # img canvas size

            # new canvas for img
            self.img_canvas = SceneCanvas(keys='interactive',
                                          show=True,
                                          size=(1242, 375))
            # grid
            self.img_grid = self.img_canvas.central_widget.add_grid()
            # interface (n next, b back, q quit, very simple)
            self.img_canvas.events.key_press.connect(self.key_press)
            self.img_canvas.events.draw.connect(self.draw)

            # add a view for the depth
            self.img_view = vispy.scene.widgets.ViewBox(
                border_color='white', parent=self.img_canvas.scene)
            self.img_grid.add_widget(self.img_view, 0, 0)
            self.img_vis = visuals.Image(cmap='viridis')
            self.img_view.add(self.img_vis)
Beispiel #2
0
    def __init__(self):

        self._canvas = SceneCanvas()

        self._viewbox = ViewBox(parent=self._canvas.scene)
        self._canvas.central_widget.add_widget(self._viewbox)

        self._viewbox.camera = TurntableCamera(
            interactive=False,
            fov=0,  # Makes it an ortho camera.
            azimuth=0,
            elevation=-90,
        )

        self._reference_slice = Image(cmap='grays', parent=self._viewbox.scene)
        self._reference_slice.attach(ColorFilter((1., .5, 0., 1.)))
        self._reference_slice.set_gl_state('additive', depth_test=False)

        self._slice = Image(cmap='grays', parent=self._viewbox.scene)
        self._slice.attach(ColorFilter((0., .5, 1., 1.)))
        self._slice.set_gl_state('additive', depth_test=False)

        self._canvas.events.mouse_press.connect(self._vispy_mouse_event)
        self._canvas.events.mouse_move.connect(self._vispy_mouse_event)
        self._canvas.events.mouse_release.connect(self._vispy_mouse_event)
        self._canvas.events.mouse_wheel.connect(self._vispy_mouse_event)
class Visualizer(object):
    '''Visualizer class\n
    Base class for the simulation of the swarm behavior.
    Args:
        width (int): defines the width of the window
        height (int): defines the height of the window
    '''
    def __init__(self, width=800, height=800, show_axis=True):
        self.canvas = SceneCanvas(size=(width, height), position=(0,0), keys='interactive', title=self.__class__.__name__)
        self.view = self.canvas.central_widget.add_view()
        self.view.camera = 'turntable'
        if show_axis:
            self.axis = visuals.XYZAxis(parent=self.view.scene)
        self.canvas.show()

    def __bool__(self):
        return not self.canvas._closed

    def update(self):
        vispy.app.process_events()        
        self.canvas.update()
        time.sleep(0.01)

    def animation(self, t):
        self.update()
        return _screenshot((0,0,self.canvas.size[0],self.canvas.size[1]))[:,:,:3]
Beispiel #4
0
    def __init__(self):
        super(Window, self).__init__()
        box = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
        self.resize(500, 200)
        self.setLayout(box)

        self.canvas_0 = SceneCanvas(bgcolor='w')
        self.vb_0 = ViewBox(parent=self.canvas_0.scene, bgcolor='r')
        self.vb_0.camera.rect = -1, -1, 2, 2
        self.canvas_0.events.initialize.connect(self.on_init)
        self.canvas_0.events.resize.connect(partial(on_resize,
                                                    self.canvas_0,
                                                    self.vb_0))
        box.addWidget(self.canvas_0.native)

        # pass the context from the first canvas to the second
        self.canvas_1 = SceneCanvas(bgcolor='w', shared=self.canvas_0.context)
        self.vb_1 = ViewBox(parent=self.canvas_1.scene, bgcolor='b')
        self.vb_1.camera.rect = -1, -1, 2, 2
        self.canvas_1.events.resize.connect(partial(on_resize,
                                                    self.canvas_1,
                                                    self.vb_1))
        box.addWidget(self.canvas_1.native)

        self.tick_count = 0
        self.timer = Timer(interval=1., connect=self.on_timer, start=True)
        self.setWindowTitle('Shared contexts')
        self.show()
Beispiel #5
0
    def __init__(self):
        global pos
        self.visuals = []
        polygon = visuals.Polygon(pos=pos, color=(0.8, .2, 0, 1),
                                  border_color=(1, 1, 1, 1))
        polygon.transform = transforms.STTransform(scale=(200, 200),
                                                   translate=(600, 600))
        self.visuals.append(polygon)

        ellipse = visuals.Ellipse(pos=(0, 0, 0), radius=(100, 150),
                                  color=(0.2, 0.2, 0.8, 1),
                                  border_color=(1, 1, 1, 1),
                                  start_angle=180., span_angle=150.)
        ellipse.transform = transforms.STTransform(scale=(0.9, 1.5),
                                                   translate=(200, 300))
        self.visuals.append(ellipse)

        rect = visuals.Rectangle(pos=(600, 200, 0), height=200.,
                                 width=300.,
                                 radius=[30., 30., 0., 0.],
                                 color=(0.5, 0.5, 0.2, 1),
                                 border_color='white')
        self.visuals.append(rect)

        rpolygon = visuals.RegularPolygon(pos=(200., 600., 0), radius=160,
                                          color=(0.2, 0.8, 0.2, 1),
                                          border_color=(1, 1, 1, 1),
                                          sides=6)
        self.visuals.append(rpolygon)

        SceneCanvas.__init__(self, keys='interactive')
        self.size = (800, 800)
        self.show()
Beispiel #6
0
    def __init__(self, _model: AtlasSectionViewModel):
        self._model = _model
        self._model.register(self.update)

        self._canvas = SceneCanvas()

        self._viewbox = ViewBox(parent=self._canvas.scene)
        self._canvas.central_widget.add_widget(self._viewbox)

        self._viewbox.camera = TurntableCamera(
            interactive=False,
            fov=0,  # Makes it an ortho camera.
            azimuth=0,
            elevation=90,
        )

        self._slice = Image(cmap='grays', parent=self._viewbox.scene)
        self._slice.transform = MatrixTransform()
        self._slice.set_data(self._model.atlas_section_image)
        self._slice.clim = self._model.clim
        self._viewbox.camera.center = self._model.camera_center
        self._viewbox.camera.scale_factor = self._viewbox.camera.scale_factor

        self._vertical_line = InfiniteLine(pos=0,
                                           vertical=True,
                                           parent=self._viewbox.scene)
        self._horizontal_line = InfiniteLine(pos=0,
                                             vertical=False,
                                             parent=self._viewbox.scene)

        self._canvas.events.mouse_press.connect(self.mouse_press)
        self._canvas.events.mouse_move.connect(self.mouse_move)

        self._vertical_line.set_data(color=self._model.vertical_line_color)
        self._horizontal_line.set_data(color=self._model.horizontal_line_color)
Beispiel #7
0
    def __init__(self, N, width=600, height=600, decay_rate=1.0, hormone_secretion=None):
        from PIL.Image import open as open_image
        # setup simulation
        self._N = N
        self._INITIAL_FIELD = np.array(open_image(path.join(ENV_MAP_PATH, 'envmap01.png'))).astype(np.float32) / 255.
        #self._INITIAL_FIELD = np.zeros(self._INITIAL_FIELD.shape)
        self._FIELD_WIDTH = self._INITIAL_FIELD.shape[1]
        self._FIELD_HEIGHT = self._INITIAL_FIELD.shape[0]
        self._FIELD_DECAY_RATE = decay_rate
        self._SECRATION = hormone_secretion
        sensor_th = np.linspace(0, 2*np.pi, self.SENSOR_NUM, endpoint=False)
        self._SENSOR_POSITION = self.AGENT_RADIUS * np.array([np.cos(sensor_th), np.sin(sensor_th)]).T
        self.reset()  # initialize all variables, position, velocity and field status

        # setup display
        self._canvas = SceneCanvas(size=(width, height), position=(0,0), keys='interactive', title="ALife book "+self.__class__.__name__)
        self._canvas.events.mouse_double_click.connect(self._on_mouse_double_click)
        self._view = self._canvas.central_widget.add_view()
        self._view.camera = PanZoomCamera((0, 0, self._FIELD_WIDTH, self._FIELD_HEIGHT), aspect=1)
        self._field_image = Image(self._field, interpolation='nearest', parent=self._view.scene, method='subdivide', clim=(0,1))
        self._agent_polygon = []
        for i in range(self._N):
            p = AntSimulator._generate_agent_visual_polygon(self.AGENT_RADIUS)
            p.parent = self._field_image
            self._agent_polygon.append(p)
        self._canvas.show()
Beispiel #8
0
    def resetTwo(self):
        """ Reset. """
        # last key press (it should have a mutex, but visualization is not
        # safety critical, so let's do things wrong)
        self.action = "no"  # no, next, back, quit are the possibilities

        # new canvas prepared for visualizing data
        self.canvas = SceneCanvas(keys='interactive', show=True)
        # interface (n next, b back, q quit, very simple)
        self.canvas.events.key_press.connect(self.key_press)
        self.canvas.events.draw.connect(self.draw)
        # grid
        self.grid = self.canvas.central_widget.add_grid()

        # laserscan part
        self.scan_view = vispy.scene.widgets.ViewBox(border_color='white',
                                                     parent=self.canvas.scene)
        self.grid.add_widget(self.scan_view, 0, 0)
        self.scan_vis = visuals.Markers()
        self.scan_view.camera = 'turntable'
        self.scan_view.add(self.scan_vis)
        visuals.XYZAxis(parent=self.scan_view.scene)

        #if self.instances:
        print("Using instances in visualizer")
        self.inst_view = vispy.scene.widgets.ViewBox(border_color='white',
                                                     parent=self.canvas.scene)
        self.grid.add_widget(self.inst_view, 0, 1)
        self.inst_vis = visuals.Markers()
        self.inst_view.camera = 'turntable'
        self.inst_view.add(self.inst_vis)
        visuals.XYZAxis(parent=self.inst_view.scene)
 def __init__(self, width=800, height=800, show_axis=True):
     self.canvas = SceneCanvas(size=(width, height), position=(0,0), keys='interactive', title=self.__class__.__name__)
     self.view = self.canvas.central_widget.add_view()
     self.view.camera = 'turntable'
     if show_axis:
         self.axis = visuals.XYZAxis(parent=self.view.scene)
     self.canvas.show()
Beispiel #10
0
    def __init__(self):
        super(Window, self).__init__()
        box = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
        self.resize(500, 200)
        self.setLayout(box)

        self.canvas_0 = SceneCanvas(bgcolor='w')
        self.vb_0 = ViewBox(parent=self.canvas_0.scene, bgcolor='r')
        self.vb_0.camera.rect = -1, -1, 2, 2
        self.canvas_0.events.initialize.connect(self.on_init)
        self.canvas_0.events.resize.connect(
            partial(on_resize, self.canvas_0, self.vb_0))
        box.addWidget(self.canvas_0.native)

        # pass the context from the first canvas to the second
        self.canvas_1 = SceneCanvas(bgcolor='w', shared=self.canvas_0.context)
        self.vb_1 = ViewBox(parent=self.canvas_1.scene, bgcolor='b')
        self.vb_1.camera.rect = -1, -1, 2, 2
        self.canvas_1.events.resize.connect(
            partial(on_resize, self.canvas_1, self.vb_1))
        box.addWidget(self.canvas_1.native)

        self.tick_count = 0
        self.timer = Timer(interval=1., connect=self.on_timer, start=True)
        self.setWindowTitle('Shared contexts')
        self.show()
Beispiel #11
0
    def __init__(self):
        self.cube = visuals.Cube((1.0, 0.5, 0.25),
                                 color='red',
                                 edge_color='black')
        self.theta = 0
        self.phi = 0

        SceneCanvas.__init__(self, 'Cube', keys='interactive', size=(400, 400))
        self.cube.transform = transforms.AffineTransform()
        self._timer = Timer('auto', connect=self.on_timer, start=True)
Beispiel #12
0
    def __init__(self):
        self.cube = visuals.Cube((1.0, 0.5, 0.25), color='red',
                                 edge_color='black')
        self.theta = 0
        self.phi = 0

        SceneCanvas.__init__(self, 'Cube', keys='interactive',
                             size=(400, 400))
        self.cube.transform = transforms.AffineTransform()
        self._timer = Timer('auto', connect=self.on_timer, start=True)
Beispiel #13
0
    def __init__(self, viewer):
        super().__init__()

        QCoreApplication.setAttribute(
            Qt.AA_UseStyleSheetPropagationInWidgetStyles, True)
        self.setStyleSheet(self.themed_stylesheet)

        self.viewer = viewer
        self.viewer._qtviewer = self

        self.canvas = SceneCanvas(keys=None, vsync=True)
        self.canvas.native.setMinimumSize(QSize(100, 100))

        self.canvas.connect(self.on_mouse_move)
        self.canvas.connect(self.on_mouse_press)
        self.canvas.connect(self.on_mouse_release)
        self.canvas.connect(self.on_key_press)
        self.canvas.connect(self.on_key_release)

        self.view = self.canvas.central_widget.add_view()
        # Set 2D camera (the camera will scale to the contents in the scene)
        self.view.camera = PanZoomCamera(aspect=1)
        # flip y-axis to have correct aligment
        self.view.camera.flip = (0, 1, 0)
        self.view.camera.set_range()

        self.view.camera.viewbox_key_event = viewbox_key_event

        center = QWidget()
        layout = QVBoxLayout()
        layout.setContentsMargins(15, 20, 15, 10)
        layout.addWidget(self.canvas.native)
        dimsview = QtDims(self.viewer.dims)
        layout.addWidget(dimsview)
        center.setLayout(layout)

        # Add controls, center, and layerlist
        self.control_panel = QtControls(viewer)
        self.addWidget(self.control_panel)
        self.addWidget(center)
        self.addWidget(self.viewer.layers._qt)

        self._cursors = {
            'disabled':
            QCursor(
                QPixmap(':/icons/cursor/cursor_disabled.png').scaled(20, 20)),
            'cross':
            Qt.CrossCursor,
            'forbidden':
            Qt.ForbiddenCursor,
            'pointing':
            Qt.PointingHandCursor,
            'standard':
            QCursor()
        }
Beispiel #14
0
    def __init__(self, *args, **kwargs):
        self.cube = CubeVisual(size=(0.8, 0.5, 0.5),
                               color='red',
                               edge_color="k")
        self.theta = 0
        self.phi = 0
        self.cube_transform = transforms.MatrixTransform()
        self.cube.transform = self.cube_transform

        self._timer = Timer('auto', connect=self.on_timer, start=True)
        SceneCanvas.__init__(self, *args, **kwargs)
    def reset(self, sem_color_dict=None):
        """ Reset. """
        # new canvas prepared for visualizing data
        self.map_color(sem_color_dict=sem_color_dict)
        self.canvas = SceneCanvas(keys='interactive', show=True)
        # grid
        self.grid = self.canvas.central_widget.add_grid()

        # laserscan part
        self.scan_view = vispy.scene.widgets.ViewBox(border_color='white',
                                                     parent=self.canvas.scene)
        self.grid.add_widget(self.scan_view, 0, 0)
        self.scan_view.camera = 'turntable'

        self.scan_vis = visuals.Markers()
        self.scan_view.add(self.scan_vis)

        if self.viz_joint:
            self.joint_vis = visuals.Arrow(connect='segments',
                                           arrow_size=18,
                                           color='blue',
                                           width=10,
                                           arrow_type='angle_60')
            self.arrow_length = 10
            self.scan_view.add(self.joint_vis)
        if self.viz_box:
            vertices, faces, outline = create_box(width=1,
                                                  height=1,
                                                  depth=1,
                                                  width_segments=1,
                                                  height_segments=1,
                                                  depth_segments=1)
            vertices['color'][:, 3] = 0.2
            # breakpoint()
            self.box = visuals.Box(vertex_colors=vertices['color'],
                                   edge_color='b')
            self.box.transform = STTransform(translate=[-2.5, 0, 0])
            self.theta = 0
            self.phi = 0
            self.scan_view.add(self.box)
        visuals.XYZAxis(parent=self.scan_view.scene)

        # add nocs
        if self.viz_label:
            print("Using nocs in visualizer")
            self.nocs_view = vispy.scene.widgets.ViewBox(
                border_color='white', parent=self.canvas.scene)
            self.grid.add_widget(self.nocs_view, 0, 1)
            self.label_vis = visuals.Markers()
            self.nocs_view.camera = 'turntable'
            self.nocs_view.add(self.label_vis)
            visuals.XYZAxis(parent=self.nocs_view.scene)
            self.nocs_view.camera.link(self.scan_view.camera)
Beispiel #16
0
 def __init__(self, width=600, height=600):
     self._canvas = SceneCanvas(size=(width, height),
                                position=(0, 0),
                                keys='interactive',
                                title="ALife book " +
                                self.__class__.__name__)
     self._view = self._canvas.central_widget.add_view()
     #self._view.camera = 'arcball'
     self._view.camera = 'turntable'
     self._axis = visuals.XYZAxis(parent=self._view.scene)
     self._arrows = None
     self._markers = None
     self._canvas.show()
  def __init__(self):
    self.canvas = SceneCanvas(
      title = "Lattice Visualizer",
      keys = 'interactive',
      size = (800, 600),
      show = True,
      bgcolor = self.BACKGROUND_COLOR
      )
    self.canvas.measure_fps()
    self.key_functions = {
      '1': self.reset_camera,
      'd': self.visible_x_up,
      'a': self.visible_x_down,
      'z': self.visible_x_all,
      'w': self.visible_y_up,
      's': self.visible_y_down,
      'x': self.visible_y_all,
      'e': self.visible_z_up,
      'q': self.visible_z_down,
      'c': self.visible_z_all
    }

    # Register key press events
    @self.canvas.events.key_press.connect
    def on_key_press(event):
      if event.text in self.key_functions:
        self.key_functions[event.text]()

    # Set up a viewbox to display the cube with interactive arcball
    self.camera = cameras.ArcballCamera()
    self.view = self.canvas.central_widget.add_view(self.camera)
Beispiel #18
0
class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        box = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight, self)
        self.resize(500, 200)
        self.setLayout(box)

        self.canvas_0 = SceneCanvas(bgcolor='w')
        self.vb_0 = ViewBox(parent=self.canvas_0.scene, bgcolor='r')
        self.vb_0.camera.rect = -1, -1, 2, 2
        self.canvas_0.events.initialize.connect(self.on_init)
        self.canvas_0.events.resize.connect(partial(on_resize,
                                                    self.canvas_0,
                                                    self.vb_0))
        box.addWidget(self.canvas_0.native)

        # pass the context from the first canvas to the second
        self.canvas_1 = SceneCanvas(bgcolor='w', shared=self.canvas_0.context)
        self.vb_1 = ViewBox(parent=self.canvas_1.scene, bgcolor='b')
        self.vb_1.camera.rect = -1, -1, 2, 2
        self.canvas_1.events.resize.connect(partial(on_resize,
                                                    self.canvas_1,
                                                    self.vb_1))
        box.addWidget(self.canvas_1.native)

        self.tick_count = 0
        self.timer = Timer(interval=1., connect=self.on_timer, start=True)
        self.setWindowTitle('Shared contexts')
        self.show()

    def on_init(self, event):
        self.text = Text('Initialized', font_size=40.,
                         anchor_x='left', anchor_y='top',
                         parent=[self.vb_0.scene, self.vb_1.scene])

    def on_timer(self, event):
        self.tick_count += 1
        self.text.text = 'Tick #%s' % self.tick_count
        self.canvas_0.update()
        self.canvas_1.update()

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            self.close()
        elif event.key() == QtCore.Qt.Key_F11:
            self.showNormal() if self.isFullScreen() else self.showFullScreen()
Beispiel #19
0
class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        box = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.LeftToRight, self)
        self.resize(500, 200)
        self.setLayout(box)

        self.canvas_0 = SceneCanvas(bgcolor='w')
        self.vb_0 = ViewBox(parent=self.canvas_0.scene, bgcolor='r')
        self.vb_0.camera.rect = -1, -1, 2, 2
        self.canvas_0.events.initialize.connect(self.on_init)
        self.canvas_0.events.resize.connect(
            partial(on_resize, self.canvas_0, self.vb_0))
        box.addWidget(self.canvas_0.native)

        # pass the context from the first canvas to the second
        self.canvas_1 = SceneCanvas(bgcolor='w', shared=self.canvas_0.context)
        self.vb_1 = ViewBox(parent=self.canvas_1.scene, bgcolor='b')
        self.vb_1.camera.rect = -1, -1, 2, 2
        self.canvas_1.events.resize.connect(
            partial(on_resize, self.canvas_1, self.vb_1))
        box.addWidget(self.canvas_1.native)

        self.tick_count = 0
        self.timer = Timer(interval=1., connect=self.on_timer, start=True)
        self.setWindowTitle('Shared contexts')
        self.show()

    def on_init(self, event):
        self.text = Text('Initialized',
                         font_size=40.,
                         anchor_x='left',
                         anchor_y='top',
                         parent=[self.vb_0.scene, self.vb_1.scene])

    def on_timer(self, event):
        self.tick_count += 1
        self.text.text = 'Tick #%s' % self.tick_count
        self.canvas_0.update()
        self.canvas_1.update()

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            self.close()
        elif event.key() == QtCore.Qt.Key_F11:
            self.showNormal() if self.isFullScreen() else self.showFullScreen()
Beispiel #20
0
class VolumeView(BaseQtWidget):

    def __init__(self, _model: VolumeViewModel):

        self._model = _model
        self._model.register(self.update)

        self._canvas = SceneCanvas()

        self._viewbox = ViewBox(parent=self._canvas.scene)
        self._canvas.central_widget.add_widget(self._viewbox)
        self._viewbox.camera = ArcballCamera(fov=0)

        self._atlas_volume = Volume(self._model.atlas_volume, parent=self._viewbox.scene)  # , interpolation='nearest')
        self._atlas_volume.attach(filters.ColorFilter((1., .5, 0., 1.)))
        self._atlas_volume.set_gl_state('additive', depth_test=False)

        self._section_image = Image(parent=self._viewbox.scene, cmap='grays')
        self._section_image.attach(filters.ColorFilter((0., .5, 1., 1.)))
        self._section_image.set_gl_state('additive', depth_test=False)

        self._canvas.events.key_press.connect(lambda event: self._model.press_key(event.key.name))

    @property
    def qt_widget(self) -> QWidget:
        return self._canvas.native

    def update(self, changed: str) -> None:
        render_funs = {
            'atlas_volume': self._render_volume,
            'section_image': self._render_section,
            'section_transform': self._render_section_transform,
            'clim': self._render_section_clim,
            'sections': (lambda: ...),
        }
        render_funs[changed]()

    def _render_section_clim(self) -> None:
        self._section_image.clim = self._model.clim
        self._canvas.update()

    def _render_section_transform(self) -> None:
        self._section_image.transform = MatrixTransform(self._model.section_transform.T)
        self._canvas.update()

    def _render_section(self) -> None:
        self._section_image.set_data(self._model.section_image.T)
        self._canvas.update()

    def _render_volume(self) -> None:
        model = self._model
        self._atlas_volume.set_data(model.atlas_volume.swapaxes(0, 2), clim=model.volume_clim)
        self._viewbox.camera.center = model.camera_center
        self._viewbox.camera.scale_factor = model.camera_distance
        self._canvas.update()
Beispiel #21
0
    def reset(self):
        """ Reset. """
        # last key press (it should have a mutex, but visualization is not
        # safety critical, so let's do things wrong)
        self.action = "no"  # no, next, back, quit are the possibilities

        # new canvas prepared for visualizing data
        self.canvas = SceneCanvas(keys='interactive', show=True)
        # interface (n next, b back, q quit, very simple)
        self.canvas.events.key_press.connect(self.key_press)
        self.canvas.events.draw.connect(self.draw)
        # grid
        self.grid = self.canvas.central_widget.add_grid()

        # laserscan part
        self.scan_view = vispy.scene.widgets.ViewBox(
            border_color='white', parent=self.canvas.scene)
        self.grid.add_widget(self.scan_view, 0, 0)
        self.scan_vis = visuals.Markers()
        self.scan_view.camera = 'turntable'
        self.scan_view.add(self.scan_vis)
        visuals.XYZAxis(parent=self.scan_view.scene)

        # img canvas size
        self.multiplier = 1
        self.canvas_W = 1024
        self.canvas_H = 64

        # new canvas for img
        self.img_canvas = SceneCanvas(keys='interactive', show=True,
                                      size=(self.canvas_W, self.canvas_H * self.multiplier))
        # grid
        self.img_grid = self.img_canvas.central_widget.add_grid()
        # interface (n next, b back, q quit, very simple)
        self.img_canvas.events.key_press.connect(self.key_press)
        self.img_canvas.events.draw.connect(self.draw)

        # add a view for the depth
        self.img_view = vispy.scene.widgets.ViewBox(
            border_color='white', parent=self.img_canvas.scene)
        self.img_grid.add_widget(self.img_view, 0, 0)
        self.img_vis = visuals.Image(cmap='viridis')
        self.img_view.add(self.img_vis)
Beispiel #22
0
    def __init__(self, _model: VolumeViewModel):

        self._model = _model
        self._model.register(self.update)

        self._canvas = SceneCanvas()

        self._viewbox = ViewBox(parent=self._canvas.scene)
        self._canvas.central_widget.add_widget(self._viewbox)
        self._viewbox.camera = ArcballCamera(fov=0)

        self._atlas_volume = Volume(self._model.atlas_volume, parent=self._viewbox.scene)  # , interpolation='nearest')
        self._atlas_volume.attach(filters.ColorFilter((1., .5, 0., 1.)))
        self._atlas_volume.set_gl_state('additive', depth_test=False)

        self._section_image = Image(parent=self._viewbox.scene, cmap='grays')
        self._section_image.attach(filters.ColorFilter((0., .5, 1., 1.)))
        self._section_image.set_gl_state('additive', depth_test=False)

        self._canvas.events.key_press.connect(lambda event: self._model.press_key(event.key.name))
Beispiel #23
0
    def __init__(self):

        self._canvas = SceneCanvas()

        self._viewbox = ViewBox(parent=self._canvas.scene)
        self._canvas.central_widget.add_widget(self._viewbox)
        self._viewbox.camera = ArcballCamera(fov=0)

        self._atlas_volume = Volume(
            array([[[1, 2]]]) * 1000,
            parent=self._viewbox.scene)  # , interpolation='nearest')
        self._atlas_volume.attach(filters.ColorFilter((1., .5, 0., 1.)))
        self._atlas_volume.set_gl_state('additive', depth_test=False)

        self._section_image = Image(parent=self._viewbox.scene, cmap='grays')
        self._section_image.attach(filters.ColorFilter((0., .5, 1., 1.)))
        self._section_image.set_gl_state('additive', depth_test=False)

        self._canvas.events.key_press.connect(
            self._handle_vispy_key_press_events)
Beispiel #24
0
    def __init__(self):
        global pos
        self.visuals = []
        polygon = visuals.Polygon(pos=pos,
                                  color=(0.8, .2, 0, 1),
                                  border_color=(1, 1, 1, 1))
        polygon.transform = transforms.STTransform(scale=(200, 200),
                                                   translate=(600, 600))
        self.visuals.append(polygon)

        ellipse = visuals.Ellipse(pos=(0, 0, 0),
                                  radius=(100, 150),
                                  color=(0.2, 0.2, 0.8, 1),
                                  border_color=(1, 1, 1, 1),
                                  start_angle=180.,
                                  span_angle=150.)
        ellipse.transform = transforms.STTransform(scale=(0.9, 1.5),
                                                   translate=(200, 300))
        self.visuals.append(ellipse)

        rect = visuals.Rectangle(pos=(600, 200, 0),
                                 height=200.,
                                 width=300.,
                                 radius=[30., 30., 0., 0.],
                                 color=(0.5, 0.5, 0.2, 1),
                                 border_color='white')
        self.visuals.append(rect)

        rpolygon = visuals.RegularPolygon(pos=(200., 600., 0),
                                          radius=160,
                                          color=(0.2, 0.8, 0.2, 1),
                                          border_color=(1, 1, 1, 1),
                                          sides=6)
        self.visuals.append(rpolygon)

        SceneCanvas.__init__(self, keys='interactive')
        self.size = (800, 800)
        self.show()
Beispiel #25
0
def plots(ids, line=True, subparts=None, mi=True, vc=True, sj=True, centering=True):
    skel   = get_skels(ids)
    canvas = SceneCanvas(keys='interactive', show=True)
    view   = canvas.central_widget.add_view()
    view.camera = 'turntable'
    
    if centering:
        center = skel.hull_coords.mean(0)
    else:
        center=np.asarray([0,0,0])

    plots = plot_hull(skel, subparts, center)
    
    if line:
        plots.extend(plot_line(skel, center))
    if mi or vc or sj:
        plots.extend(plot_objects(skel, mi, vc, sj, center))
    for obj in plots:
        view.add(obj)
    return view
Beispiel #26
0
    def __init__(self):
        self.canvas = SceneCanvas(keys='interactive', show=True)
        self.grid = self.canvas.central_widget.add_grid()
        self.view = vispy.scene.widgets.ViewBox(border_color='white',
                                                parent=self.canvas.scene)
        self.grid.add_widget(self.view, 0, 0)

        # Point Cloud Visualizer
        self.sem_vis = visuals.Markers()
        self.view.camera = vispy.scene.cameras.TurntableCamera(up='z',
                                                               azimuth=90)
        self.view.add(self.sem_vis)
        visuals.XYZAxis(parent=self.view.scene)

        # Object Detection Visualizer
        self.obj_vis = visuals.Line()
        self.view.add(self.obj_vis)
        self.connect = np.asarray([[0, 1], [0, 3], [0, 4], [2, 1], [2, 3],
                                   [2, 6], [5, 1], [5, 4], [5, 6], [7, 3],
                                   [7, 4], [7, 6]])
        self.data = load_data(
            'data/data.p')  # Change to data.p for your final submission
Beispiel #27
0
class SwarmVisualizer(object):
    """docstring for SwarmVisualizer."""
    ARROW_SIZE = 20

    def __init__(self, width=600, height=600):
        self._canvas = SceneCanvas(size=(width, height),
                                   position=(0, 0),
                                   keys='interactive',
                                   title="ALife book " +
                                   self.__class__.__name__)
        self._view = self._canvas.central_widget.add_view()
        #self._view.camera = 'arcball'
        self._view.camera = 'turntable'
        self._axis = visuals.XYZAxis(parent=self._view.scene)
        self._arrows = None
        self._markers = None
        self._canvas.show()

    def update(self, position, direction):
        assert position.ndim is 2 and position.shape[1] in (2, 3)
        assert direction.ndim is 2 and direction.shape[1] in (2, 3)
        assert position.shape[0] == direction.shape[0]
        if self._arrows is None:
            self._arrows = visuals.Arrow(arrow_size=self.ARROW_SIZE,
                                         arrow_type='triangle_30',
                                         parent=self._view.scene)
        # arrow_coordinate[0::2] is position of arrow and
        # arrow_coordinate[1::2] is direction of tail (length is ignored)
        arrow_coordinate = np.repeat(position, 2, axis=0)
        arrow_coordinate[::2] -= direction
        self._arrows.set_data(arrows=arrow_coordinate.reshape((-1, 6)))
        self._canvas.update()
        vispy.app.process_events()

    def set_markers(self, position):
        assert position.ndim is 2 and position.shape[-1] in (2, 3)
        if self._markers is None:
            self._markers = visuals.Markers(parent=self._view.scene)
        self._markers.set_data(position, face_color=(1, 0, 0), size=20)
        self._canvas.update()
        vispy.app.process_events()

    def __bool__(self):
        return not self._canvas._closed
Beispiel #28
0
    def __init__(self, viewer):
        super().__init__()
        self.viewer = viewer
        self.sliders = []

        self.canvas = SceneCanvas(keys=None, vsync=True)

        layout = QGridLayout()
        self.setLayout(layout)
        layout.setContentsMargins(0, 0, 0, 0)
        #layout.setColumnStretch(0, 4)

        row = 0
        layout.addWidget(self.canvas.native, row, 0)
        #layout.setRowStretch(row, 1)

        self.view = self.canvas.central_widget.add_view()

        # Set 2D camera (the camera will scale to the contents in the scene)
        self.view.camera = PanZoomCamera(aspect=1)

        # flip y-axis to have correct aligment
        self.view.camera.flip = (0, 1, 0)
        self.view.camera.set_range()
Beispiel #29
0
    def __init__(self, viewer):
        super().__init__()

        self.canvas = SceneCanvas(keys=None, vsync=True)
        self.canvas.native.setMinimumSize(QSize(100, 100))
        self.view = self.canvas.central_widget.add_view()
        # Set 2D camera (the camera will scale to the contents in the scene)
        self.view.camera = PanZoomCamera(aspect=1)
        # flip y-axis to have correct aligment
        self.view.camera.flip = (0, 1, 0)
        self.view.camera.set_range()

        center = QWidget()
        layout = QVBoxLayout()
        layout.addWidget(self.canvas.native)
        layout.addWidget(viewer.dimensions._qt)
        center.setLayout(layout)

        # Add vertical sliders, center, and layerlist
        self.addWidget(viewer.controlBars._qt)
        self.addWidget(center)
        self.addWidget(viewer.layers._qt)

        viewer.dimensions._qt.setFixedHeight(0)
Beispiel #30
0
        v.draw()


def on_resize(event):
    # Set canvas viewport and reconfigure visual transforms to match.
    vp = (0, 0, canvas.physical_size[0], canvas.physical_size[1])
    canvas.context.set_viewport(*vp)
    for v in order:
        v.transforms.configure(canvas=canvas, viewport=vp)


canvas.events.resize.connect(on_resize)
on_resize(None)

Line = create_visual_node(LineVisual)
canvas2 = SceneCanvas(keys='interactive', title='Scene Canvas', show=True)
v = canvas2.central_widget.add_view(margin=10)
v.border_color = (1, 1, 1, 1)
v.bgcolor = (0.3, 0.3, 0.3, 1)
v.camera = 'panzoom'
line2 = Line(pos, parent=v.scene)


def mouse(ev):
    print(ev)


v.events.mouse_press.connect(mouse)

if __name__ == '__main__':
    if sys.flags.interactive != 1:
Beispiel #31
0
    def __init__(self, viewer):
        super().__init__()

        QCoreApplication.setAttribute(
            Qt.AA_UseStyleSheetPropagationInWidgetStyles, True
        )

        self.viewer = viewer
        self.dims = QtDims(self.viewer.dims)
        self.controls = QtControls(self.viewer)
        self.layers = QtLayerList(self.viewer.layers)
        self.buttons = QtLayersButtons(self.viewer)
        self.console = QtConsole({'viewer': self.viewer})

        if self.console.shell is not None:
            self.console.style().unpolish(self.console)
            self.console.style().polish(self.console)
            self.console.hide()
            self.buttons.consoleButton.clicked.connect(
                lambda: self._toggle_console()
            )
        else:
            self.buttons.consoleButton.setEnabled(False)

        self.canvas = SceneCanvas(keys=None, vsync=True)
        self.canvas.native.setMinimumSize(QSize(200, 200))

        self.canvas.connect(self.on_mouse_move)
        self.canvas.connect(self.on_mouse_press)
        self.canvas.connect(self.on_mouse_release)
        self.canvas.connect(self.on_key_press)
        self.canvas.connect(self.on_key_release)
        self.canvas.connect(self.on_draw)

        self.view = self.canvas.central_widget.add_view()
        self._update_camera()

        center = QWidget()
        center_layout = QVBoxLayout()
        center_layout.setContentsMargins(15, 20, 15, 10)
        center_layout.addWidget(self.canvas.native)
        center_layout.addWidget(self.dims)
        center.setLayout(center_layout)

        right = QWidget()
        right_layout = QVBoxLayout()
        right_layout.addWidget(self.layers)
        right_layout.addWidget(self.buttons)
        right.setLayout(right_layout)
        right.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)

        left = self.controls

        top = QWidget()
        top_layout = QHBoxLayout()
        top_layout.addWidget(left)
        top_layout.addWidget(center)
        top_layout.addWidget(right)
        top.setLayout(top_layout)

        self.setOrientation(Qt.Vertical)
        self.addWidget(top)

        if self.console.shell is not None:
            self.addWidget(self.console)

        self._last_visited_dir = str(Path.home())

        self._cursors = {
            'disabled': QCursor(
                QPixmap(':/icons/cursor/cursor_disabled.png').scaled(20, 20)
            ),
            'cross': Qt.CrossCursor,
            'forbidden': Qt.ForbiddenCursor,
            'pointing': Qt.PointingHandCursor,
            'standard': QCursor(),
        }

        self._update_palette(viewer.palette)

        self._key_release_generators = {}

        self.viewer.events.interactive.connect(self._on_interactive)
        self.viewer.events.cursor.connect(self._on_cursor)
        self.viewer.events.reset_view.connect(self._on_reset_view)
        self.viewer.events.palette.connect(
            lambda event: self._update_palette(event.palette)
        )
        self.viewer.layers.events.reordered.connect(self._update_canvas)
        self.viewer.dims.events.display.connect(
            lambda event: self._update_camera()
        )

        self.setAcceptDrops(True)
Beispiel #32
0
class QtViewer(QSplitter):
    with open(os.path.join(resources_dir, 'stylesheet.qss'), 'r') as f:
        raw_stylesheet = f.read()

    def __init__(self, viewer):
        super().__init__()

        QCoreApplication.setAttribute(
            Qt.AA_UseStyleSheetPropagationInWidgetStyles, True
        )

        self.viewer = viewer
        self.dims = QtDims(self.viewer.dims)
        self.controls = QtControls(self.viewer)
        self.layers = QtLayerList(self.viewer.layers)
        self.buttons = QtLayersButtons(self.viewer)
        self.console = QtConsole({'viewer': self.viewer})

        if self.console.shell is not None:
            self.console.style().unpolish(self.console)
            self.console.style().polish(self.console)
            self.console.hide()
            self.buttons.consoleButton.clicked.connect(
                lambda: self._toggle_console()
            )
        else:
            self.buttons.consoleButton.setEnabled(False)

        self.canvas = SceneCanvas(keys=None, vsync=True)
        self.canvas.native.setMinimumSize(QSize(200, 200))

        self.canvas.connect(self.on_mouse_move)
        self.canvas.connect(self.on_mouse_press)
        self.canvas.connect(self.on_mouse_release)
        self.canvas.connect(self.on_key_press)
        self.canvas.connect(self.on_key_release)
        self.canvas.connect(self.on_draw)

        self.view = self.canvas.central_widget.add_view()
        self._update_camera()

        center = QWidget()
        center_layout = QVBoxLayout()
        center_layout.setContentsMargins(15, 20, 15, 10)
        center_layout.addWidget(self.canvas.native)
        center_layout.addWidget(self.dims)
        center.setLayout(center_layout)

        right = QWidget()
        right_layout = QVBoxLayout()
        right_layout.addWidget(self.layers)
        right_layout.addWidget(self.buttons)
        right.setLayout(right_layout)
        right.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)

        left = self.controls

        top = QWidget()
        top_layout = QHBoxLayout()
        top_layout.addWidget(left)
        top_layout.addWidget(center)
        top_layout.addWidget(right)
        top.setLayout(top_layout)

        self.setOrientation(Qt.Vertical)
        self.addWidget(top)

        if self.console.shell is not None:
            self.addWidget(self.console)

        self._last_visited_dir = str(Path.home())

        self._cursors = {
            'disabled': QCursor(
                QPixmap(':/icons/cursor/cursor_disabled.png').scaled(20, 20)
            ),
            'cross': Qt.CrossCursor,
            'forbidden': Qt.ForbiddenCursor,
            'pointing': Qt.PointingHandCursor,
            'standard': QCursor(),
        }

        self._update_palette(viewer.palette)

        self._key_release_generators = {}

        self.viewer.events.interactive.connect(self._on_interactive)
        self.viewer.events.cursor.connect(self._on_cursor)
        self.viewer.events.reset_view.connect(self._on_reset_view)
        self.viewer.events.palette.connect(
            lambda event: self._update_palette(event.palette)
        )
        self.viewer.layers.events.reordered.connect(self._update_canvas)
        self.viewer.dims.events.display.connect(
            lambda event: self._update_camera()
        )

        self.setAcceptDrops(True)

    def _update_camera(self):
        if np.sum(self.viewer.dims.display) == 3:
            # Set a 3D camera
            self.view.camera = ArcballCamera(name="ArcballCamera")
            # flip y-axis to have correct alignment
            self.view.camera.flip = (0, 1, 0)
            min_shape, max_shape = self.viewer._calc_bbox()
            centroid = np.add(max_shape, min_shape) / 2
            size = np.subtract(max_shape, min_shape)
            # Scale the camera to the contents in the scene
            if len(centroid) > 0:
                centroid = centroid[-3:]
                self.view.camera.center = centroid[::-1]
                self.view.camera.scale_factor = 1.5 * np.mean(size[-3:])
        elif np.sum(self.viewer.dims.display) == 2:
            # Set 2D camera
            self.view.camera = PanZoomCamera(aspect=1, name="PanZoomCamera")
            # flip y-axis to have correct alignment
            self.view.camera.flip = (0, 1, 0)
            # Scale the camera to the contents in the scene
            self.view.camera.set_range()
        else:
            raise ValueError(
                "Invalid display flags set in dimensions {}".format(
                    self.viewer.dims.display
                )
            )

        self.view.camera.viewbox_key_event = viewbox_key_event
        # TO DO: Remove
        self.viewer._view = self.view

    def screenshot(self):
        """Take currently displayed screen and convert to an image array.

        Returns
        -------
        image : array
            Numpy array of type ubyte and shape (h, w, 4). Index [0, 0] is the
            upper-left corner of the rendered region.
        """
        img = self.canvas.native.grabFramebuffer()
        b = img.constBits()
        h, w, c = img.height(), img.width(), 4

        # As vispy doesn't use qtpy we need to reconcile the differences
        # between the `QImage` API for `PySide2` and `PyQt5` on how to convert
        # a QImage to a numpy array.
        if API_NAME == 'PySide2':
            arr = np.array(b).reshape(h, w, c)
        else:
            b.setsize(h * w * c)
            arr = np.frombuffer(b, np.uint8).reshape(h, w, c)

        # Format of QImage is ARGB32_Premultiplied, but color channels are
        # reversed.
        arr = arr[:, :, [2, 1, 0, 3]]
        return arr

    def _open_images(self):
        """Adds image files from the menubar."""
        filenames, _ = QFileDialog.getOpenFileNames(
            parent=self,
            caption='Select image(s)...',
            directory=self._last_visited_dir,  # home dir by default
        )
        self._add_files(filenames)

    def _add_files(self, filenames):
        """Adds an image layer to the viewer.

        Whether the image is multichannel is determined by
        :func:`napari.util.misc.is_multichannel`.

        If multiple images are selected, they are stacked along the 0th
        axis.

        Parameters
        -------
        filenames : list
            List of filenames to be opened
        """
        if len(filenames) > 0:
            image = read(filenames)
            self.viewer.add_image(
                image, multichannel=is_multichannel(image.shape)
            )
            self._last_visited_dir = os.path.dirname(filenames[0])

    def _on_interactive(self, event):
        self.view.interactive = self.viewer.interactive

    def _on_cursor(self, event):
        cursor = self.viewer.cursor
        size = self.viewer.cursor_size
        if cursor == 'square':
            if size < 10 or size > 300:
                q_cursor = self._cursors['cross']
            else:
                q_cursor = QCursor(
                    QPixmap(':/icons/cursor/cursor_square.png').scaledToHeight(
                        size
                    )
                )
        else:
            q_cursor = self._cursors[cursor]
        self.canvas.native.setCursor(q_cursor)

    def _on_reset_view(self, event):
        self.view.camera.rect = event.viewbox

    def _update_canvas(self, event):
        """Clears draw order and refreshes canvas. Usefeul for when layers are
        reoredered.
        """
        self.canvas._draw_order.clear()
        self.canvas.update()

    def _update_palette(self, palette):
        # template and apply the primary stylesheet
        themed_stylesheet = template(self.raw_stylesheet, **palette)
        self.console.style_sheet = themed_stylesheet
        self.console.syntax_style = palette['syntax_style']
        self.setStyleSheet(themed_stylesheet)

    def _toggle_console(self):
        """Toggle console visible and not visible."""
        self.console.setVisible(not self.console.isVisible())
        self.buttons.consoleButton.setProperty(
            'expanded', self.console.isVisible()
        )
        self.buttons.consoleButton.style().unpolish(self.buttons.consoleButton)
        self.buttons.consoleButton.style().polish(self.buttons.consoleButton)

    def on_mouse_move(self, event):
        """Called whenever mouse moves over canvas.
        """
        layer = self.viewer.active_layer
        if layer is not None:
            layer.on_mouse_move(event)

    def on_mouse_press(self, event):
        """Called whenever mouse pressed in canvas.
        """
        layer = self.viewer.active_layer
        if layer is not None:
            layer.on_mouse_press(event)

    def on_mouse_release(self, event):
        """Called whenever mouse released in canvas.
        """
        layer = self.viewer.active_layer
        if layer is not None:
            layer.on_mouse_release(event)

    def on_key_press(self, event):
        """Called whenever key pressed in canvas.
        """
        if event.native.isAutoRepeat() or event.key is None:
            return

        comb = components_to_key_combo(event.key.name, event.modifiers)

        layer = self.viewer.active_layer

        if layer is not None and comb in layer.keymap:
            parent = layer
        elif comb in self.viewer.keymap:
            parent = self.viewer
        else:
            return

        func = parent.keymap[comb]
        gen = func(parent)

        if inspect.isgeneratorfunction(func):
            try:
                next(gen)
            except StopIteration:  # only one statement
                pass
            else:
                self._key_release_generators[event.key] = gen

    def on_key_release(self, event):
        """Called whenever key released in canvas.
        """
        try:
            next(self._key_release_generators[event.key])
        except (KeyError, StopIteration):
            pass

    def on_draw(self, event):
        """Called whenever drawn in canvas. Called for all layers, not just top
        """
        for layer in self.viewer.layers:
            layer.on_draw(event)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        """Add local files and web URLS with drag and drop."""
        filenames = []
        for url in event.mimeData().urls():
            path = url.toString()
            if os.path.isfile(path):
                filenames.append(path)
            elif os.path.isdir(path):
                filenames = filenames + list(glob(os.path.join(path, '*')))
            else:
                filenames.append(path)
        self._add_files(filenames)
    def __init__(self,
                 image=None,
                 image_path=None,
                 input_colourspace='ITU-R BT.709',
                 input_oecf='ITU-R BT.709',
                 input_linear=True,
                 reference_colourspace='CIE xyY',
                 correlate_colourspace='ACEScg',
                 settings=None,
                 layout='layout_1'):
        self._initialised = False

        title = '{0} - {1}'.format(__application_name__, __version__)

        SceneCanvas.__init__(
            self,
            keys='interactive',
            title=('{0} - {1}'.format(title, image_path)
                   if image_path is not None else title),
            size=settings['scene_canvas']['size'],
            bgcolor=settings['scene_canvas']['scene_canvas_background_colour'],
            config={'samples': settings['scene_canvas']['samples']})

        self.unfreeze()

        self._image = None
        self.image = image if image is not None else DEFAULT_FAILSAFE_IMAGE
        self._image_path = None
        self.image_path = image_path
        self._input_colourspace = None
        self.input_colourspace = input_colourspace
        self._input_oecf = None
        self.input_oecf = input_oecf
        self._input_linear = None
        self.input_linear = input_linear
        self._reference_colourspace = None
        self.reference_colourspace = reference_colourspace
        self._correlate_colourspace = None
        self.correlate_colourspace = correlate_colourspace
        self._settings = (json.load(open(SETTINGS_FILE))
                          if settings is None else settings)
        self._layout = None
        self.layout = layout

        self._clamp_blacks = False
        self._clamp_whites = False

        self._layout_presets = OrderedDict()
        self._actions = {}

        self._console_view = None
        self._gamut_view = None
        self._image_view = None
        self._diagram_view = None
        self._views = None

        self._grid = None

        self._RGB_colourspaces_cycle = cycle([
            c for c in sorted(RGB_COLOURSPACES)
            if c not in ('aces', 'adobe1998', 'prophoto')
        ])

        reference_colourspaces_deque = deque(REFERENCE_COLOURSPACES)
        reference_colourspaces_deque.rotate(
            -REFERENCE_COLOURSPACES.index(self._reference_colourspace) - 1)
        self._reference_colourspaces_cycle = cycle(
            reference_colourspaces_deque)

        self._create_layout_presets()
        self._create_actions()
        self._create_views()
        self._layout_views()

        self.show()

        self._initialised = True
class PointVis:
    """Class that creates and handles a visualizer for a pointcloud"""
    def __init__(self,
                 target_pts=None,
                 viz_dict=None,
                 viz_point=True,
                 viz_label=True,
                 viz_joint=False,
                 viz_box=False):
        self.viz_point = viz_point
        self.viz_label = viz_label
        self.viz_joint = viz_joint
        self.viz_box = viz_box
        self.viz_label = viz_label
        self.reset()

        self.update_scan(target_pts, viz_dict)

    def reset(self, sem_color_dict=None):
        """ Reset. """
        # new canvas prepared for visualizing data
        self.map_color(sem_color_dict=sem_color_dict)
        self.canvas = SceneCanvas(keys='interactive', show=True)
        # grid
        self.grid = self.canvas.central_widget.add_grid()

        # laserscan part
        self.scan_view = vispy.scene.widgets.ViewBox(border_color='white',
                                                     parent=self.canvas.scene)
        self.grid.add_widget(self.scan_view, 0, 0)
        self.scan_view.camera = 'turntable'

        self.scan_vis = visuals.Markers()
        self.scan_view.add(self.scan_vis)

        if self.viz_joint:
            self.joint_vis = visuals.Arrow(connect='segments',
                                           arrow_size=18,
                                           color='blue',
                                           width=10,
                                           arrow_type='angle_60')
            self.arrow_length = 10
            self.scan_view.add(self.joint_vis)
        if self.viz_box:
            vertices, faces, outline = create_box(width=1,
                                                  height=1,
                                                  depth=1,
                                                  width_segments=1,
                                                  height_segments=1,
                                                  depth_segments=1)
            vertices['color'][:, 3] = 0.2
            # breakpoint()
            self.box = visuals.Box(vertex_colors=vertices['color'],
                                   edge_color='b')
            self.box.transform = STTransform(translate=[-2.5, 0, 0])
            self.theta = 0
            self.phi = 0
            self.scan_view.add(self.box)
        visuals.XYZAxis(parent=self.scan_view.scene)

        # add nocs
        if self.viz_label:
            print("Using nocs in visualizer")
            self.nocs_view = vispy.scene.widgets.ViewBox(
                border_color='white', parent=self.canvas.scene)
            self.grid.add_widget(self.nocs_view, 0, 1)
            self.label_vis = visuals.Markers()
            self.nocs_view.camera = 'turntable'
            self.nocs_view.add(self.label_vis)
            visuals.XYZAxis(parent=self.nocs_view.scene)
            self.nocs_view.camera.link(self.scan_view.camera)

    def update_scan(self, points, viz_dict=None):
        # then change names
        self.canvas.title = "scan "
        if viz_dict is not None:
            # input_point_seq  = viz_dict['input']
            # input_index_seq  = viz_dict['coord'] #(3, 150000, 2)
            # # npts = viz_dict['npts'] # (3,)
            # npts = [150000, 150000, 150000]
            # for i, num in enumerate(npts[:1]):
            #     target_pts = input_point_seq[i, 0, :num, 0:3]
            #     indices = input_index_seq[i, 0]
            #     idxs = np.where(indices[:, 0]==200)[0]
            #     target_pts = target_pts[idxs]
            #     indices = indices[idxs]
            #     y_value = [indices[100, 1], indices[800, 1], indices[1200,1]]
            #     idys = list(np.where(indices[:, 1]==y_value[2])[0]) # + list(np.where(indices[:, 1]==y_value[1])[0]) + list(np.where(indices[:, 1]==y_value[2])[0])
            #     target_pts = target_pts[idys]

            target_pts = np.concatenate(
                [viz_dict['input1'], viz_dict['input2']], axis=0)
            gt_labels = np.concatenate([
                viz_dict['label'], 4 * np.ones(
                    (viz_dict['input2'].shape[0]), dtype=np.int32)
            ],
                                       axis=0)
            print(np.max(target_pts, axis=0).reshape(1, 3))
            print(np.min(target_pts, axis=0).reshape(1, 3))
            # target_pts = target_pts - (np.max(target_pts, axis=0) + np.min(target_pts, axis=0))/2

            power = 16
            range_data = np.copy(np.linalg.norm(target_pts, axis=1))
            range_data = range_data**(1 / power)
            viridis_range = ((range_data - range_data.min()) /
                             (range_data.max() - range_data.min()) *
                             255).astype(np.uint8)
            viridis_map = self.get_mpl_colormap("viridis")
            viridis_colors = viridis_map[viridis_range]

            self.scan_vis.set_data(target_pts,
                                   face_color=viridis_colors[..., ::-1],
                                   edge_color=viridis_colors[..., ::-1],
                                   size=5)

            # plot nocs
            if self.viz_label:
                label_colors = self.sem_color_lut[gt_labels]
                label_colors = label_colors.reshape((-1, 3))
                self.label_vis.set_data(target_pts,
                                        face_color=label_colors[..., ::-1],
                                        edge_color=label_colors[..., ::-1],
                                        size=5)
                # time.sleep(15)
        if self.viz_joint:
            self.update_joints()

        if self.viz_box:
            self.update_boxes()

    def map_color(self, max_classes=20, sem_color_dict=None):
        # make semantic colors
        if sem_color_dict:
            # if I have a dict, make it
            max_sem_key = 0
            for key, data in sem_color_dict.items():
                if key + 1 > max_sem_key:
                    max_sem_key = key + 1
            self.sem_color_lut = np.zeros((max_sem_key + 100, 3),
                                          dtype=np.float32)
            for key, value in sem_color_dict.items():
                self.sem_color_lut[key] = np.array(value, np.float32) / 255.0
        else:
            # otherwise make random
            max_sem_key = max_classes
            self.sem_color_lut = np.random.uniform(low=0.0,
                                                   high=1.0,
                                                   size=(max_sem_key, 3))
            # force zero to a gray-ish color
            self.sem_color_lut[0] = np.full((3), 0.2)
            self.sem_color_lut[4] = np.full((3), 0.6)
            self.sem_color_lut[1] = np.array([1.0, 0.0, 0.0])
            self.sem_color_lut[2] = np.array([0.0, 0.0, 1.0])

    def get_mpl_colormap(self, cmap_name):
        cmap = plt.get_cmap(cmap_name)

        # Initialize the matplotlib color map
        sm = plt.cm.ScalarMappable(cmap=cmap)

        # Obtain linear color range
        color_range = sm.to_rgba(np.linspace(0, 1, 256), bytes=True)[:, 2::-1]

        return color_range.reshape(256, 3).astype(np.float32) / 255.0

    def update_joints(self, joints=None):
        # plot
        if joints is not None:
            start_coords = joints['p'].reshape(1, 3)
            point_towards = start_coords + joints['l'].reshape(1, 3)
        else:
            start_coords = np.array([[1, 0, 0], [-1, 0, 0]])
            point_towards = np.array([[0, 0, 1], [0, 0, 1]])
        direction_vectors = (start_coords - point_towards).astype(np.float32)
        norms = np.sqrt(np.sum(direction_vectors**2, axis=-1))
        direction_vectors[:, 0] /= norms
        direction_vectors[:, 1] /= norms
        direction_vectors[:, 2] /= norms

        vertices = np.repeat(start_coords, 2, axis=0)
        vertices[::2] = vertices[::2] + (
            (0.5 * self.arrow_length) * direction_vectors)
        vertices[1::2] = vertices[1::2] - (
            (0.5 * self.arrow_length) * direction_vectors)

        self.joint_vis.set_data(
            pos=vertices,
            arrows=vertices.reshape((len(vertices) // 2, 6)),
        )

    def update_boxes(self):
        pass

    def draw(self, event):
        if self.canvas.events.key_press.blocked():
            self.canvas.events.key_press.unblock()
        if self.img_canvas.events.key_press.blocked():
            self.img_canvas.events.key_press.unblock()

    def destroy(self):
        # destroy the visualization
        self.canvas.close()
        vispy.app.quit()

    def run(self):
        vispy.app.run()
Beispiel #35
0
    def __init__(self, viewer):
        super().__init__()
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.pool = QThreadPool()

        QCoreApplication.setAttribute(
            Qt.AA_UseStyleSheetPropagationInWidgetStyles, True)

        self.viewer = viewer
        self.dims = QtDims(self.viewer.dims)
        self.controls = QtControls(self.viewer)
        self.layers = QtLayerList(self.viewer.layers)
        self.layerButtons = QtLayerButtons(self.viewer)
        self.viewerButtons = QtViewerButtons(self.viewer)
        self.console = QtConsole({'viewer': self.viewer})

        layerList = QWidget()
        layerList.setObjectName('layerList')
        layerListLayout = QVBoxLayout()
        layerListLayout.addWidget(self.layerButtons)
        layerListLayout.addWidget(self.layers)
        layerListLayout.addWidget(self.viewerButtons)
        layerListLayout.setContentsMargins(8, 4, 8, 6)
        layerList.setLayout(layerListLayout)
        self.dockLayerList = QtViewerDockWidget(
            self,
            layerList,
            name='layer list',
            area='left',
            allowed_areas=['left', 'right'],
        )
        self.dockLayerControls = QtViewerDockWidget(
            self,
            self.controls,
            name='layer controls',
            area='left',
            allowed_areas=['left', 'right'],
        )
        self.dockConsole = QtViewerDockWidget(
            self,
            self.console,
            name='console',
            area='bottom',
            allowed_areas=['top', 'bottom'],
            shortcut='Ctrl+Shift+C',
        )
        self.dockConsole.setVisible(False)
        self.dockLayerControls.visibilityChanged.connect(self._constrain_width)
        self.dockLayerList.setMaximumWidth(258)
        self.dockLayerList.setMinimumWidth(258)

        # This dictionary holds the corresponding vispy visual for each layer
        self.layer_to_visual = {}

        if self.console.shell is not None:
            self.viewerButtons.consoleButton.clicked.connect(
                lambda: self.toggle_console())
        else:
            self.viewerButtons.consoleButton.setEnabled(False)

        self.canvas = SceneCanvas(keys=None, vsync=True, parent=self)
        self.canvas.events.ignore_callback_errors = False
        self.canvas.events.draw.connect(self.dims.enable_play)
        self.canvas.native.setMinimumSize(QSize(200, 200))
        self.canvas.context.set_depth_func('lequal')

        self.canvas.connect(self.on_mouse_move)
        self.canvas.connect(self.on_mouse_press)
        self.canvas.connect(self.on_mouse_release)
        self.canvas.connect(self.on_key_press)
        self.canvas.connect(self.on_key_release)
        self.canvas.connect(self.on_draw)

        self.view = self.canvas.central_widget.add_view()
        self._update_camera()

        main_widget = QWidget()
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(10, 22, 10, 2)
        main_layout.addWidget(self.canvas.native)
        main_layout.addWidget(self.dims)
        main_layout.setSpacing(10)
        main_widget.setLayout(main_layout)

        self.setOrientation(Qt.Vertical)
        self.addWidget(main_widget)

        self._last_visited_dir = str(Path.home())

        self._cursors = {
            'disabled':
            QCursor(
                QPixmap(':/icons/cursor/cursor_disabled.png').scaled(20, 20)),
            'cross':
            Qt.CrossCursor,
            'forbidden':
            Qt.ForbiddenCursor,
            'pointing':
            Qt.PointingHandCursor,
            'standard':
            QCursor(),
        }

        self._update_palette(viewer.palette)

        self._key_release_generators = {}

        self.viewer.events.interactive.connect(self._on_interactive)
        self.viewer.events.cursor.connect(self._on_cursor)
        self.viewer.events.reset_view.connect(self._on_reset_view)
        self.viewer.events.palette.connect(
            lambda event: self._update_palette(event.palette))
        self.viewer.layers.events.reordered.connect(self._reorder_layers)
        self.viewer.layers.events.added.connect(self._add_layer)
        self.viewer.layers.events.removed.connect(self._remove_layer)
        self.viewer.dims.events.camera.connect(
            lambda event: self._update_camera())
        # stop any animations whenever the layers change
        self.viewer.events.layers_change.connect(lambda x: self.dims.stop())

        self.setAcceptDrops(True)
Beispiel #36
0
class QtViewer(QSplitter):
    """Qt view for the napari Viewer model.

    Parameters
    ----------
    viewer : napari.components.ViewerModel
        Napari viewer containing the rendered scene, layers, and controls.

    Attributes
    ----------
    canvas : vispy.scene.SceneCanvas
        Canvas for rendering the current view.
    console : QtConsole
        iPython console terminal integrated into the napari GUI.
    controls : QtControls
        Qt view for GUI controls.
    dims : napari.qt_dims.QtDims
        Dimension sliders; Qt View for Dims model.
    dockConsole : QtViewerDockWidget
        QWidget wrapped in a QDockWidget with forwarded viewer events.
    aboutKeybindings : QtAboutKeybindings
        Key bindings for the 'About' Qt dialog.
    dockLayerControls : QtViewerDockWidget
        QWidget wrapped in a QDockWidget with forwarded viewer events.
    dockLayerList : QtViewerDockWidget
        QWidget wrapped in a QDockWidget with forwarded viewer events.
    layerButtons : QtLayerButtons
        Button controls for napari layers.
    layers : QtLayerList
        Qt view for LayerList controls.
    layer_to_visual : dict
        Dictionary mapping napari layers with their corresponding vispy_layers.
    pool : qtpy.QtCore.QThreadPool
        Pool of worker threads.
    view : vispy scene widget
        View displayed by vispy canvas. Adds a vispy ViewBox as a child widget.
    viewer : napari.components.ViewerModel
        Napari viewer containing the rendered scene, layers, and controls.
    viewerButtons : QtViewerButtons
        Button controls for the napari viewer.
    """

    raw_stylesheet = combine_stylesheets()

    def __init__(self, viewer):
        super().__init__()
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.pool = QThreadPool()

        QCoreApplication.setAttribute(
            Qt.AA_UseStyleSheetPropagationInWidgetStyles, True)

        self.viewer = viewer
        self.dims = QtDims(self.viewer.dims)
        self.controls = QtControls(self.viewer)
        self.layers = QtLayerList(self.viewer.layers)
        self.layerButtons = QtLayerButtons(self.viewer)
        self.viewerButtons = QtViewerButtons(self.viewer)
        self.console = QtConsole({'viewer': self.viewer})

        layerList = QWidget()
        layerList.setObjectName('layerList')
        layerListLayout = QVBoxLayout()
        layerListLayout.addWidget(self.layerButtons)
        layerListLayout.addWidget(self.layers)
        layerListLayout.addWidget(self.viewerButtons)
        layerListLayout.setContentsMargins(8, 4, 8, 6)
        layerList.setLayout(layerListLayout)
        self.dockLayerList = QtViewerDockWidget(
            self,
            layerList,
            name='layer list',
            area='left',
            allowed_areas=['left', 'right'],
        )
        self.dockLayerControls = QtViewerDockWidget(
            self,
            self.controls,
            name='layer controls',
            area='left',
            allowed_areas=['left', 'right'],
        )
        self.dockConsole = QtViewerDockWidget(
            self,
            self.console,
            name='console',
            area='bottom',
            allowed_areas=['top', 'bottom'],
            shortcut='Ctrl+Shift+C',
        )
        self.dockConsole.setVisible(False)
        self.dockLayerControls.visibilityChanged.connect(self._constrain_width)
        self.dockLayerList.setMaximumWidth(258)
        self.dockLayerList.setMinimumWidth(258)

        # This dictionary holds the corresponding vispy visual for each layer
        self.layer_to_visual = {}

        if self.console.shell is not None:
            self.viewerButtons.consoleButton.clicked.connect(
                lambda: self.toggle_console())
        else:
            self.viewerButtons.consoleButton.setEnabled(False)

        self.canvas = SceneCanvas(keys=None, vsync=True, parent=self)
        self.canvas.events.ignore_callback_errors = False
        self.canvas.events.draw.connect(self.dims.enable_play)
        self.canvas.native.setMinimumSize(QSize(200, 200))
        self.canvas.context.set_depth_func('lequal')

        self.canvas.connect(self.on_mouse_move)
        self.canvas.connect(self.on_mouse_press)
        self.canvas.connect(self.on_mouse_release)
        self.canvas.connect(self.on_key_press)
        self.canvas.connect(self.on_key_release)
        self.canvas.connect(self.on_draw)

        self.view = self.canvas.central_widget.add_view()
        self._update_camera()

        main_widget = QWidget()
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(10, 22, 10, 2)
        main_layout.addWidget(self.canvas.native)
        main_layout.addWidget(self.dims)
        main_layout.setSpacing(10)
        main_widget.setLayout(main_layout)

        self.setOrientation(Qt.Vertical)
        self.addWidget(main_widget)

        self._last_visited_dir = str(Path.home())

        self._cursors = {
            'disabled':
            QCursor(
                QPixmap(':/icons/cursor/cursor_disabled.png').scaled(20, 20)),
            'cross':
            Qt.CrossCursor,
            'forbidden':
            Qt.ForbiddenCursor,
            'pointing':
            Qt.PointingHandCursor,
            'standard':
            QCursor(),
        }

        self._update_palette(viewer.palette)

        self._key_release_generators = {}

        self.viewer.events.interactive.connect(self._on_interactive)
        self.viewer.events.cursor.connect(self._on_cursor)
        self.viewer.events.reset_view.connect(self._on_reset_view)
        self.viewer.events.palette.connect(
            lambda event: self._update_palette(event.palette))
        self.viewer.layers.events.reordered.connect(self._reorder_layers)
        self.viewer.layers.events.added.connect(self._add_layer)
        self.viewer.layers.events.removed.connect(self._remove_layer)
        self.viewer.dims.events.camera.connect(
            lambda event: self._update_camera())
        # stop any animations whenever the layers change
        self.viewer.events.layers_change.connect(lambda x: self.dims.stop())

        self.setAcceptDrops(True)

    def _constrain_width(self, event):
        """Allow the layer controls to be wider, only if floated.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        if self.dockLayerControls.isFloating():
            self.controls.setMaximumWidth(700)
        else:
            self.controls.setMaximumWidth(220)

    def _add_layer(self, event):
        """When a layer is added, set its parent and order.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        layers = event.source
        layer = event.item
        vispy_layer = create_vispy_visual(layer)
        vispy_layer.camera = self.view.camera
        vispy_layer.node.parent = self.view.scene
        vispy_layer.order = len(layers)
        self.layer_to_visual[layer] = vispy_layer

    def _remove_layer(self, event):
        """When a layer is removed, remove its parent.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        layer = event.item
        vispy_layer = self.layer_to_visual[layer]
        vispy_layer.node.transforms = ChainTransform()
        vispy_layer.node.parent = None
        del self.layer_to_visual[layer]

    def _reorder_layers(self, event):
        """When the list is reordered, propagate changes to draw order.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        for i, layer in enumerate(self.viewer.layers):
            vispy_layer = self.layer_to_visual[layer]
            vispy_layer.order = i
        self.canvas._draw_order.clear()
        self.canvas.update()

    def _update_camera(self):
        """Update the viewer camera."""
        if self.viewer.dims.ndisplay == 3:
            # Set a 3D camera
            if not isinstance(self.view.camera, ArcballCamera):
                self.view.camera = ArcballCamera(name="ArcballCamera", fov=0)
                # flip y-axis to have correct alignment
                # self.view.camera.flip = (0, 1, 0)

                self.view.camera.viewbox_key_event = viewbox_key_event
                self.viewer.reset_view()
        else:
            # Set 2D camera
            if not isinstance(self.view.camera, PanZoomCamera):
                self.view.camera = PanZoomCamera(aspect=1,
                                                 name="PanZoomCamera")
                # flip y-axis to have correct alignment
                self.view.camera.flip = (0, 1, 0)

                self.view.camera.viewbox_key_event = viewbox_key_event
                self.viewer.reset_view()

    def screenshot(self, path=None):
        """Take currently displayed screen and convert to an image array.

        Parmeters
        ---------
        path : str
            Filename for saving screenshot image.

        Returns
        -------
        image : array
            Numpy array of type ubyte and shape (h, w, 4). Index [0, 0] is the
            upper-left corner of the rendered region.
        """
        img = self.canvas.native.grabFramebuffer()
        if path is not None:
            imsave(path, QImg2array(img))  # scikit-image imsave method
        return QImg2array(img)

    def _save_screenshot(self):
        """Save screenshot of current display, default .png"""
        filename, _ = QFileDialog.getSaveFileName(
            parent=self,
            caption='',
            directory=self._last_visited_dir,  # home dir by default
            filter=
            "Image files (*.png *.bmp *.gif *.tif *.tiff)",  # first one used by default
            # jpg and jpeg not included as they don't support an alpha channel
        )
        if (filename != '') and (filename is not None):
            # double check that an appropriate extension has been added as the filter
            # filter option does not always add an extension on linux and windows
            # see https://bugreports.qt.io/browse/QTBUG-27186
            image_extensions = ('.bmp', '.gif', '.png', '.tif', '.tiff')
            if not filename.endswith(image_extensions):
                filename = filename + '.png'
            self.screenshot(path=filename)

    def _open_images(self):
        """Add image files from the menubar."""
        filenames, _ = QFileDialog.getOpenFileNames(
            parent=self,
            caption='Select image(s)...',
            directory=self._last_visited_dir,  # home dir by default
        )
        if (filenames != []) and (filenames is not None):
            self._add_files(filenames)

    def _open_folder(self):
        """Add a folder of files from the menubar."""
        folder = QFileDialog.getExistingDirectory(
            parent=self,
            caption='Select folder...',
            directory=self._last_visited_dir,  # home dir by default
        )
        if folder not in {'', None}:
            self._add_files([folder])

    def _add_files(self, filenames):
        """Add an image layer to the viewer.

        If multiple images are selected, they are stacked along the 0th
        axis.

        Parameters
        -------
        filenames : list
            List of filenames to be opened
        """
        if len(filenames) > 0:
            self.viewer.add_image(path=filenames)
            self._last_visited_dir = os.path.dirname(filenames[0])

    def _on_interactive(self, event):
        """Link interactive attributes of view and viewer.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        self.view.interactive = self.viewer.interactive

    def _on_cursor(self, event):
        """Set the appearance of the mouse cursor.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        cursor = self.viewer.cursor
        size = self.viewer.cursor_size
        if cursor == 'square':
            if size < 10 or size > 300:
                q_cursor = self._cursors['cross']
            else:
                q_cursor = QCursor(
                    QPixmap(':/icons/cursor/cursor_square.png').scaledToHeight(
                        size))
        else:
            q_cursor = self._cursors[cursor]
        self.canvas.native.setCursor(q_cursor)

    def _on_reset_view(self, event):
        """Reset view of the rendered scene.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        if isinstance(self.view.camera, ArcballCamera):
            quat = self.view.camera._quaternion.create_from_axis_angle(
                *event.quaternion)
            self.view.camera._quaternion = quat
            self.view.camera.center = event.center
            self.view.camera.scale_factor = event.scale_factor
        else:
            # Assumes default camera has the same properties as PanZoomCamera
            self.view.camera.rect = event.rect

    def _update_palette(self, palette):
        """Update the napari GUI theme.

        Parameters
        ----------
        palette : dict of str: str
            Color palette with which to style the viewer.
            Property of napari.components.viewer_model.ViewerModel
        """
        # template and apply the primary stylesheet
        themed_stylesheet = template(self.raw_stylesheet, **palette)
        self.console.style_sheet = themed_stylesheet
        self.console.syntax_style = palette['syntax_style']
        bracket_color = QtGui.QColor(*str_to_rgb(palette['highlight']))
        self.console._bracket_matcher.format.setBackground(bracket_color)
        self.setStyleSheet(themed_stylesheet)
        self.canvas.bgcolor = palette['canvas']

    def toggle_console(self):
        """Toggle console visible and not visible."""
        viz = not self.dockConsole.isVisible()
        # modulate visibility at the dock widget level as console is docakable
        self.dockConsole.setVisible(viz)
        if self.dockConsole.isFloating():
            self.dockConsole.setFloating(True)

        self.viewerButtons.consoleButton.setProperty(
            'expanded', self.dockConsole.isVisible())
        self.viewerButtons.consoleButton.style().unpolish(
            self.viewerButtons.consoleButton)
        self.viewerButtons.consoleButton.style().polish(
            self.viewerButtons.consoleButton)

    def show_keybindings_dialog(self, event=None):
        dialog = QtAboutKeybindings(self.viewer, parent=self)
        dialog.show()

    def on_mouse_press(self, event):
        """Called whenever mouse pressed in canvas.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        if event.pos is None:
            return

        event = ReadOnlyWrapper(event)
        mouse_press_callbacks(self.viewer, event)

        layer = self.viewer.active_layer
        if layer is not None:
            # Line bellow needed until layer mouse callbacks are refactored
            self.layer_to_visual[layer].on_mouse_press(event)
            mouse_press_callbacks(layer, event)

    def on_mouse_move(self, event):
        """Called whenever mouse moves over canvas.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        if event.pos is None:
            return

        mouse_move_callbacks(self.viewer, event)

        layer = self.viewer.active_layer
        if layer is not None:
            # Line bellow needed until layer mouse callbacks are refactored
            self.layer_to_visual[layer].on_mouse_move(event)
            mouse_move_callbacks(layer, event)

    def on_mouse_release(self, event):
        """Called whenever mouse released in canvas.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        mouse_release_callbacks(self.viewer, event)

        layer = self.viewer.active_layer
        if layer is not None:
            # Line bellow needed until layer mouse callbacks are refactored
            self.layer_to_visual[layer].on_mouse_release(event)
            mouse_release_callbacks(layer, event)

    def on_key_press(self, event):
        """Called whenever key pressed in canvas.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        if (event.native is not None and event.native.isAutoRepeat()
                and event.key.name not in ['Up', 'Down', 'Left', 'Right'
                                           ]) or event.key is None:
            # pass is no key is present or if key is held down, unless the
            # key being held down is one of the navigation keys
            return

        comb = components_to_key_combo(event.key.name, event.modifiers)

        layer = self.viewer.active_layer

        if layer is not None and comb in layer.keymap:
            parent = layer
        elif comb in self.viewer.keymap:
            parent = self.viewer
        else:
            return

        func = parent.keymap[comb]
        gen = func(parent)

        if inspect.isgenerator(gen):
            try:
                next(gen)
            except StopIteration:  # only one statement
                pass
            else:
                self._key_release_generators[event.key] = gen

    def on_key_release(self, event):
        """Called whenever key released in canvas.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        try:
            next(self._key_release_generators[event.key])
        except (KeyError, StopIteration):
            pass

    def on_draw(self, event):
        """Called whenever drawn in canvas. Called for all layers, not just top

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        for visual in self.layer_to_visual.values():
            visual.on_draw(event)

    def keyPressEvent(self, event):
        """Called whenever a key is pressed.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        self.canvas._backend._keyEvent(self.canvas.events.key_press, event)
        event.accept()

    def keyReleaseEvent(self, event):
        """Called whenever a key is released.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        self.canvas._backend._keyEvent(self.canvas.events.key_release, event)
        event.accept()

    def dragEnterEvent(self, event):
        """Ignore event if not dragging & dropping a file or URL to open.

        Using event.ignore() here allows the event to pass through the
        parent widget to its child widget, otherwise the parent widget
        would catch the event and not pass it on to the child widget.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        """Add local files and web URLS with drag and drop.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        filenames = []
        for url in event.mimeData().urls():
            if url.isLocalFile():
                filenames.append(url.toLocalFile())
            else:
                filenames.append(url.toString())
        self._add_files(filenames)

    def closeEvent(self, event):
        """Clear pool of worker threads and close.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        # if the viewer.QtDims object is playing an axis, we need to terminate
        # the AnimationThread before close, otherwise it will cauyse a segFault
        # or Abort trap. (calling stop() when no animation is occuring is also
        # not a problem)
        self.dims.stop()
        self.canvas.native.deleteLater()
        self.console.close()
        self.dockConsole.deleteLater()
        if not self.pool.waitForDone(10000):
            raise TimeoutError("Timed out waiting for QtViewer.pool to finish")
        event.accept()
class LatticeRenderer:
  BACKGROUND_COLOR = ColorArray('w')
  GROUND_COLOR = ColorArray('#A2C9F5',0.6)
  GROUND_BORDER_COLOR = ColorArray('#A2C9F5')
  d_lattice_node = None
  lattice_node = None
  toolpath_node = None

  def __init__(self):
    self.canvas = SceneCanvas(
      title = "Lattice Visualizer",
      keys = 'interactive',
      size = (800, 600),
      show = True,
      bgcolor = self.BACKGROUND_COLOR
      )
    self.canvas.measure_fps()
    self.key_functions = {
      '1': self.reset_camera,
      'd': self.visible_x_up,
      'a': self.visible_x_down,
      'z': self.visible_x_all,
      'w': self.visible_y_up,
      's': self.visible_y_down,
      'x': self.visible_y_all,
      'e': self.visible_z_up,
      'q': self.visible_z_down,
      'c': self.visible_z_all
    }

    # Register key press events
    @self.canvas.events.key_press.connect
    def on_key_press(event):
      if event.text in self.key_functions:
        self.key_functions[event.text]()

    # Set up a viewbox to display the cube with interactive arcball
    self.camera = cameras.ArcballCamera()
    self.view = self.canvas.central_widget.add_view(self.camera)

  def load_environment(self, dim, cs):
    bounds = dim * cs
    axes = CoolAxes(pos=(-2*cs,-2*cs,-cs),width=2,scale=cs)
    self.camera.center = bounds / 2
    self.camera.set_range((-cs,bounds[0]+cs),(-cs,bounds[1]+cs),(-cs,bounds[2]+cs))
    self.camera.set_default_state()
    ground_plane = visuals.Rectangle(
      pos = (bounds[0] / 2, bounds[1] / 2, 0),
      color = self.GROUND_COLOR,
      width = bounds[0] + 2 * cs,
      height = bounds[1] + 2 * cs,
      border_color = self.GROUND_BORDER_COLOR
      )
    self.view.add(axes)
    self.view.add(ground_plane)

  def load_dynamic_lattice(self, lattice):
    self.load_environment(lattice.dim, lattice.cs)
    self.d_lattice_node = DynamicLatticeNode(lattice, (0,0,0))
    self.view.add(self.d_lattice_node)
    self.lattice_node = LatticeNode(lattice, True)
    self.view.add(self.lattice_node)

  def load_lattice(self, lattice):
    self.load_environment(lattice.dim, lattice.cs)
    self.lattice_node = LatticeNode(lattice)
    self.view.add(self.lattice_node)

  def load_toolpath(self, toolpath):
    self.toolpath_node = visuals.Line(
      np.array(toolpath.vertices),
      connect='strip',
      antialias=True,
      color='b'
      )
    self.view.add(self.toolpath_node)

  def reset_camera(self):
    self.camera.reset()
  def visible_x_up(self): 
    if self.d_lattice_node: self.d_lattice_node.change_visible('x','up')
  def visible_x_down(self): 
    if self.d_lattice_node: self.d_lattice_node.change_visible('x','down')
  def visible_x_all(self): 
    if self.d_lattice_node: self.d_lattice_node.change_visible('x','all')
  def visible_y_up(self): 
    if self.d_lattice_node: self.d_lattice_node.change_visible('y','up')
  def visible_y_down(self): 
    if self.d_lattice_node: self.d_lattice_node.change_visible('y','down')
  def visible_y_all(self): 
    if self.d_lattice_node: self.d_lattice_node.change_visible('y','all')
  def visible_z_up(self): 
    if self.d_lattice_node: self.d_lattice_node.change_visible('z','up')
  def visible_z_down(self): 
    if self.d_lattice_node: self.d_lattice_node.change_visible('z','down')
  def visible_z_all(self): 
    if self.d_lattice_node: self.d_lattice_node.change_visible('z','all')

  def render(self):
    self.canvas.app.run()