Exemple #1
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()
Exemple #2
0
class VolumeView(BaseQtView):
    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(fov=0,
                                               azimuth=0,
                                               elevation=90,
                                               distance=1000)

        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)

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

    def on_atlas_update(self, volume: ndarray, transform: ndarray):
        self._atlas_volume.set_data(volume,
                                    clim=(np.min(volume), np.max(volume)))
        self._atlas_volume.transform = MatrixTransform(transform.T)
        self._viewbox.camera.center = (0, 0, 0)
        self._viewbox.camera.scale_factor = transform[0, 0] * volume.shape[0]
        self._canvas.update()

    def on_section_loaded(self, image: ndarray, transform: ndarray):
        self._section_image.set_data(image)
        self._section_image.clim = np.min(image), np.max(image)
        if transform is not None:
            self._section_image.transform = MatrixTransform(transform.T)
        self._canvas.update()

    def on_channel_select(self, image: ndarray, channel: int):
        self._section_image.set_data(image)
        self._section_image.clim = np.min(image), np.max(image)
        self._canvas.update()

    def on_section_moved(self, transform: ndarray, atlas_slice_image: ndarray):
        self._section_image.transform = MatrixTransform(transform.T)
        self._canvas.update()

    # Controller Code

    def _handle_vispy_key_press_events(self, event: KeyEvent) -> None:
        """Router: Calls AppCommands functions based on the event that's given."""

        key_commands = {
            '1': lambda: self.select_channel(1),
            '2': lambda: self.select_channel(2),
            '3': lambda: self.select_channel(3),
            '4': lambda: self.select_channel(4),
            'W': lambda: self.move_section(z=30),
            'S': lambda: self.move_section(z=-30),
            'A': lambda: self.move_section(x=-30),
            'D': lambda: self.move_section(x=30),
            'Q': lambda: self.move_section(y=-30),
            'E': lambda: self.move_section(y=30),
            'I': lambda: self.move_section(rz=3),
            'K': lambda: self.move_section(rz=-3),
            'J': lambda: self.move_section(rx=-3),
            'L': lambda: self.move_section(rx=3),
            'U': lambda: self.move_section(ry=-3),
            'O': lambda: self.move_section(ry=3),
            'Escape': use_app().quit,
        }
        if command := key_commands.get(event.key.name):
            command()
Exemple #3
0
class SliceView(BaseQtView):

    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)

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

    def on_section_loaded(self, image: ndarray, transform: ndarray) -> None:
        self.update_slice_image(image=image)

    def on_channel_select(self, image: ndarray, channel: int) -> None:
        self.update_slice_image(image=image)

    def on_section_moved(self, transform: ndarray, atlas_slice_image: ndarray) -> None:
        self.update_ref_slice_image(image=atlas_slice_image)

    def update_slice_image(self, image: ndarray):
        self._slice.set_data(image)
        self._slice.clim = np.min(image), np.max(image)
        self._viewbox.camera.center = image.shape[1] / 2, image.shape[0] / 2, 0.
        self._viewbox.camera.scale_factor = image.shape[1]
        self._canvas.update()

    def update_ref_slice_image(self, image: ndarray):
        self._reference_slice.set_data(image)
        self._reference_slice.clim = (np.min(image), np.max(image))  if np.max(image) - np.min(image) > 0 else (0, 1)
        self._canvas.update()

    def _vispy_mouse_event(self, event: SceneMouseEvent) -> None:
        if event.type == 'mouse_press':
            event.handled = True

        elif event.type == 'mouse_move':
            if event.press_event is None:
                return
            x1, y1 = event.last_event.pos
            x2, y2 = event.pos
            if event.button == 1:  # Left Mouse Button
                self._on_left_mouse_drag(x1=x1, y1=y1, x2=x2, y2=y2)
            elif event.button == 2:  # Right Mouse Button
                self._on_right_mouse_drag(x1=x1, y1=y1, x2=x2, y2=y2)

        elif event.type == 'mouse_wheel':
            self._on_mousewheel_move(increment=int(event.delta[1]))


    def _on_left_mouse_drag(self, x1: int, y1: int, x2: int, y2: int):
        x_amp = abs(x2 - x1)
        y_amp = abs(y2 - y1)
        x_dir = ((x2 > x1) * 2) - 1
        y_dir = ((y2 > y1) * 2) - 1
        scale = 4.
        x_slice_offset = x_amp * x_dir * scale
        y_slice_offset = y_amp * y_dir * scale
        self.move_section(x=x_slice_offset, y=y_slice_offset)
        self.get_coord_data(i=0, j=0)  # todo: replace with mouse highlighting

    def _on_right_mouse_drag(self, x1: int, y1: int, x2: int, y2: int):
        x_amp = abs(x2 - x1)
        x_dir = ((x2 > x1) * 2) - 1
        scale = .1
        x_slice_offset = x_amp * x_dir * scale
        self.move_section(ry=x_slice_offset)

    def _on_mousewheel_move(self, increment: int):
        self.move_section(z=10 * increment)

    def move_section(self, x=0., y=0., z=0., rx=0., ry=0., rz=0.) -> None:
        raise NotImplementedError("Wire up to MoveSectionCommand to use this.")

    def get_coord_data(self, i: int, j: int):
        raise NotImplementedError("Wire up to GetPixelRegistrationDataCommand to use this.")
Exemple #4
0
class SliceView(BaseQtWidget):
    def __init__(self, _model: SliceViewModel):
        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._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.mouse_press)
        self._canvas.events.mouse_move.connect(self.mouse_move)
        self._canvas.events.mouse_wheel.connect(self.mouse_wheel)

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

    def mouse_press(self, event: SceneMouseEvent) -> None:
        event.handled = True

    def mouse_move(self, event: SceneMouseEvent) -> None:
        if event.press_event is None:
            return
        x1, y1 = event.last_event.pos
        x2, y2 = event.pos
        if event.button == 1:  # Left Mouse Button
            self._model.on_left_mouse_drag(x1=x1, x2=x2, y1=y1, y2=y2)
        elif event.button == 2:  # Right Mouse Button
            self._model.on_right_mouse_drag(x1=x1, y1=y1, x2=x2, y2=y2)

    def mouse_wheel(self, event: SceneMouseEvent):
        self._model.on_mousewheel_move(increment=int(event.delta[1]))

    def update(self, changed: str) -> None:
        render_funs = {
            'section_image': self._render_section_image,
            'clim': self._render_section_clim,
            'atlas_image': self._render_atlas_image,
        }
        render_funs[changed]()

    def _render_atlas_image(self):
        image = self._model.atlas_image
        self._reference_slice.set_data(image)
        self._reference_slice.clim = (
            np.min(image),
            np.max(image)) if np.max(image) - np.min(image) > 0 else (0, 1)
        self._canvas.update()

    def _render_section_clim(self):
        self._slice.clim = self._model.clim
        self._canvas.update()

    def _render_section_image(self):
        image = self._model.section_image
        self._slice.set_data(image)
        self._viewbox.camera.center = image.shape[1] / 2, image.shape[0] / 2, 0.
        self._viewbox.camera.scale_factor = image.shape[1]
        self._canvas.update()