示例#1
0
class Viewer:
    """
    abstraction layer on viewer that dispatches visualisation to specific components
    and implements widgets for DataSet functionality
    """
    def __init__(self, dataset):
        self.dataset = dataset

        self.napari_viewer = None
        self.plots = None
        self.blik_widget = None

    def show(self, napari_viewer=None, **kwargs):
        self.ensure_ready(napari_viewer=napari_viewer)
        for db in self.dataset:
            db.init_depictor(**kwargs)
        if self.dataset.volumes:
            self.show_volume(list(self.dataset.volumes.keys())[0])
        if self.dataset.plots:
            self.plots.show()

    @property
    def shown(self):
        if self.napari_viewer and self.volume_selector:
            return self.dataset.volumes[self.volume_selector.currentText()]
        return None

    def ensure_ready(self, napari_viewer=None):
        if napari_viewer is not None:
            self._init_viewer(napari_viewer)
            self._init_plots()
            self._init_blik_widget()
            self._hook_keybindings()
        # check if viewer exists and is still open
        try:
            self.napari_viewer.window.qt_viewer.actions()
        except (AttributeError, RuntimeError):
            self._init_viewer()
            self._init_plots()
            self._init_blik_widget()
            self._hook_keybindings()

    def _init_viewer(self, napari_viewer=None):
        if napari_viewer is not None:
            self.napari_viewer = napari_viewer
        else:
            self.napari_viewer = napari.Viewer(title='napari - Blik')
        self.napari_viewer.scale_bar.unit = '0.1nm'
        self.napari_viewer.scale_bar.visible = True
        # TODO: workaround until layer issues are fixed (napari #2110)
        self.napari_viewer.window.qt_viewer.destroyed.connect(self.dataset.purge_gui)

    def _init_plots(self):
        self.plots = GraphicsLayoutWidget()
        self._plots_napari_widget = self.napari_viewer.window.add_dock_widget(self.plots,
                                                                              name='Blik - Plots',
                                                                              area='bottom')
        # use napari hide and show methods
        self.plots.show = self._plots_napari_widget.show
        self.plots.hide = self._plots_napari_widget.hide
        self.plots.hide()

    def _init_blik_widget(self):
        self.blik_widget = QWidget()
        layout = QVBoxLayout()
        self.blik_widget.setLayout(layout)

        self.volume_selector = QComboBox(self.blik_widget)
        self.volume_selector.addItems(self.dataset.volumes.keys())
        self.volume_selector.currentTextChanged.connect(self.show_volume)
        layout.addWidget(self.volume_selector)

        self.plots_toggler = QPushButton('Show / Hide Plots')
        self.plots_toggler.clicked.connect(self.toggle_plots)
        layout.addWidget(self.plots_toggler)

        self._blik_napari_widget = self.napari_viewer.window.add_dock_widget(self.blik_widget,
                                                                           name='Blik',
                                                                           area='left')
        # use napari hide and show methods
        self.blik_widget.show = self._blik_napari_widget.show
        self.blik_widget.hide = self._blik_napari_widget.hide

    def _hook_keybindings(self):
        self.napari_viewer.bind_key('PageUp', self.previous_volume)
        self.napari_viewer.bind_key('PageDown', self.next_volume)

    def update_blik_widget(self):
        if self.blik_widget is not None:
            current_text = self.volume_selector.currentText()
            with block_signals(self.volume_selector):
                self.volume_selector.clear()
                self.volume_selector.addItems(self.dataset.volumes.keys())
                self.volume_selector.setCurrentText(current_text)
        self.show()

    def clear_shown(self):
        for layer in self.napari_viewer.layers.copy():
            if layer in self.dataset.napari_layers:
                self.napari_viewer.layers.remove(layer)
        self.plots.clear()

    def show_volume(self, volume):
        if volume is None:
            return
        self.volume_selector.setCurrentText(volume)
        datablocks = self.dataset.omni + self.dataset.volumes[volume]

        layers = []
        plots = []
        for db in datablocks:
            for dep in db.depictors:
                if hasattr(dep, 'layers'):
                    if not dep.layers:
                        dep.depict()
                    layers.extend(dep.layers)
                elif hasattr(dep, 'plot'):
                    if not dep.plot.curves:
                        dep.depict()
                    plots.append(dep.plot)
        layers = sorted(layers, key=lambda l: isinstance(l, napari.layers.Image), reverse=True)

        self.clear_shown()
        self.napari_viewer.layers.extend(layers)
        for plt in plots:
            self.plots.addItem(plt)

    def previous_volume(self, viewer=None):
        idx = self.volume_selector.currentIndex()
        previous_idx = (idx - 1) % self.volume_selector.count()
        self.volume_selector.setCurrentIndex(previous_idx)

    def next_volume(self, viewer=None):
        idx = self.volume_selector.currentIndex()
        next_idx = (idx + 1) % self.volume_selector.count()
        self.volume_selector.setCurrentIndex(next_idx)

    def toggle_plots(self):
        if self.plots.isVisible():
            self.plots.hide()
        else:
            self.plots.show()
示例#2
0
class EEGViewer(QThread):
    """docstring for EEGViewer"""

    StoppedState = 0
    PausedState = 1
    RunningState = 2

    def __init__(self, mode='single', rows=4):
        super(EEGViewer, self).__init__()
        self.mode = mode
        self.rows = rows
        self.view = GraphicsLayoutWidget()
        self.view.setAntialiasing(True)
        self.view.setWindowTitle('EEG Viewer')
        self.state = self.StoppedState
        self.position = 0
        self.maxPosition = 0
        self.plotItem = list()
        self.plotTrace = dict()
        # Holders
        self.wait = 0
        self.wsize = 0
        self.hsize = 0
        self.color = dict()
        self.window = list([0, 0])
        self.channel = list()

    def widget(self):
        return self.view

    def show(self):
        self.view.show()

    def hide(self):
        self.view.hide()

    def getState(self):
        return self.state

    def isVisible(self):
        return self.view.isVisible()

    def setSize(self, width, height):
        self.view.resize(width, height)

    def configure(self, channel, color, wsize, fs=0):
        # Link params
        nCh = len(channel)
        self.wait = 1 / (fs * nCh) if fs > 0 else 0
        self.wsize = wsize
        self.hsize = wsize / 2
        self.color = color
        self.channel = channel
        self.window = np.array([0, wsize])
        # Remove previous items and traces
        self.view.clear()
        self.plotItem.clear()
        self.plotTrace.clear()
        # Create new canvas
        if self.mode == 'single':
            self.singleLayout()
        else:
            self.multipleLayout()

    def singleLayout(self):
        canvas = self.view.addPlot(0, 0)
        canvas.disableAutoRange()
        canvas.setClipToView(True)
        canvas.setLimits(yMin=0, yMax=1)
        canvas.setDownsampling(mode='subsample')
        canvas.showGrid(x=True, y=True, alpha=0.25)
        for ch in self.channel:
            pen = mkPen(color=self.color[ch], width=2)
            self.plotTrace[ch] = canvas.plot(pen=pen)
        self.plotItem.append(canvas)

    def multipleLayout(self):
        col = 0
        rowLimit = self.rows
        for i, ch in enumerate(self.channel):
            pen = mkPen(color=self.color[ch], width=2)
            canvas = self.view.addPlot(i % rowLimit, col)
            canvas.disableAutoRange()
            canvas.setClipToView(True)
            canvas.setLimits(yMin=0, yMax=1)
            canvas.setDownsampling(mode='subsample')
            canvas.showGrid(x=True, y=True, alpha=0.25)
            self.plotItem.append(canvas)
            self.plotTrace[ch] = canvas.plot(pen=pen)
            if (i + 1) % rowLimit == 0:
                col += 1

    def plotData(self, D):
        for ch in self.channel:
            self.plotTrace[ch].setData(D[ch].values)
        self.position = 0
        self.maxPosition = D.index.size

    def addMark(self, position, label=None):
        for canvas in self.plotItem:
            pen = mkPen(color='g', width=2.5, style=Qt.DashLine)
            hpen = mkPen(color='r', width=2.5, style=Qt.DashLine)
            mark = canvas.addLine(x=position,
                                  pen=pen,
                                  label=label,
                                  labelOpts={'position': 0.9},
                                  movable=True,
                                  hoverPen=hpen)
            return mark

    def setPosition(self, position):
        self.window[0] = position - self.hsize
        self.window[1] = position + self.hsize
        self.position = position
        self.update()

    def update(self):
        for plot in self.plotItem:
            plot.setRange(xRange=self.window)
        self.position += 1 if self.position < self.maxPosition else 0

    def play(self):
        self.state = self.RunningState
        self.start()

    def pause(self):
        self.state = self.PausedState

    def toggle(self):
        self.state = self.PausedState if self.state == self.RunningState else self.RunningState

    def stop(self):
        self.state = self.StoppedState
        self.quit()
        self.setPosition(0)

    def run(self):
        while True:
            if self.state == self.RunningState:
                self.setPosition(self.position)
            elif self.state == self.PausedState:
                pass
            else:
                break
            sleep(self.wait)