Exemplo n.º 1
0
    def build_ui(self):

        # Build file loading widgets
        ctrl_panel = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout()
        ctrl_panel.setLayout(layout)
        select_filename_btn = QtWidgets.QPushButton('Select File...')
        self.filename_label = QtWidgets.QLabel(
            'No file selected' if self.filename is None else self.filename)
        select_filename_btn.clicked.connect(self.select_filename)
        reload_btn = QtWidgets.QPushButton('Reload')
        reload_btn.clicked.connect(self.reload)
        layout.addWidget(select_filename_btn)
        layout.addWidget(self.filename_label)
        layout.addWidget(reload_btn)

        #Navigation function
        def move_index_down(_self, _ev):
            if type(_ev) == QtGui.QKeyEvent:
                if _ev.matches(QtGui.QKeySequence.MoveToPreviousPage):
                    inc = -1
                elif _ev.matches(QtGui.QKeySequence.MoveToNextPage):
                    inc = 1
                else:
                    return QtWidgets.QTreeWidget.keyPressEvent(_self, _ev)
                cur = self.tree.currentItem()
                if not cur is None:
                    name = cur.text(0)
                    i = self.item_list.index(cur)
                    found_match = False
                    while not found_match:
                        i += inc
                        if i >= len(self.item_list) or i < 0:
                            found_match = True
                        elif self.item_list[i].text(0) == name:
                            self.tree.setCurrentItem(self.item_list[i])
                            found_match = True
                _ev.accept()

        # Build tree
        self.tree = QtWidgets.QTreeWidget()
        self.tree.currentItemChanged.connect(
            lambda cur, prev: self._new_table_selection(cur))
        layout.addWidget(self.tree)
        self.tree.keyPressEvent = lambda ev: move_index_down(self.tree, ev)

        # Build plot widgets
        self.plot_layout = QtWidgets.QStackedLayout()
        self.line_plot = LinePlotWidget()
        self.img_plot = HeatmapPlotWidget()
        self.plot_layout.addWidget(self.line_plot)
        self.plot_layout.addWidget(self.img_plot)
        self.plot_container = QtWidgets.QWidget()
        self.plot_container.setLayout(self.plot_layout)

        #Build dataframe table
        self.df_table = QtWidgets.QTableView()

        self.tab_container = QtWidgets.QTabWidget()
        self.tab_container.addTab(self.plot_container, 'Plot')
        self.tab_container.addTab(self.df_table, 'Table')

        #Set the main layout
        splitter_config = {
            'main_w': ctrl_panel,
            'side_w': self.tab_container,
            'orientation': SplitterOrientation.vertical_right_button,
        }
        splitter = Splitter(**splitter_config)

        splitter.setSizes([1, 400])
        splitter.setHandleWidth(10)

        layout = QtWidgets.QHBoxLayout()
        layout.addWidget(splitter)
        self.setLayout(layout)
Exemplo n.º 2
0
 def plot2d(self):
     p = HeatmapPlotWidget()
     return p
Exemplo n.º 3
0
class DataExplorer(QtWidgets.QWidget):
    def __init__(self, parent=None, filename=None):
        super().__init__(parent=parent)
        self.repo = None
        self.item_list = list()
        self.filename = filename
        self.build_ui()
        if not filename is None:
            self.reload()

    def build_ui(self):

        # Build file loading widgets
        ctrl_panel = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout()
        ctrl_panel.setLayout(layout)
        select_filename_btn = QtWidgets.QPushButton('Select File...')
        self.filename_label = QtWidgets.QLabel(
            'No file selected' if self.filename is None else self.filename)
        select_filename_btn.clicked.connect(self.select_filename)
        reload_btn = QtWidgets.QPushButton('Reload')
        reload_btn.clicked.connect(self.reload)
        layout.addWidget(select_filename_btn)
        layout.addWidget(self.filename_label)
        layout.addWidget(reload_btn)

        #Navigation function
        def move_index_down(_self, _ev):
            if type(_ev) == QtGui.QKeyEvent:
                if _ev.matches(QtGui.QKeySequence.MoveToPreviousPage):
                    inc = -1
                elif _ev.matches(QtGui.QKeySequence.MoveToNextPage):
                    inc = 1
                else:
                    return QtWidgets.QTreeWidget.keyPressEvent(_self, _ev)
                cur = self.tree.currentItem()
                if not cur is None:
                    name = cur.text(0)
                    i = self.item_list.index(cur)
                    found_match = False
                    while not found_match:
                        i += inc
                        if i >= len(self.item_list) or i < 0:
                            found_match = True
                        elif self.item_list[i].text(0) == name:
                            self.tree.setCurrentItem(self.item_list[i])
                            found_match = True
                _ev.accept()

        # Build tree
        self.tree = QtWidgets.QTreeWidget()
        self.tree.currentItemChanged.connect(
            lambda cur, prev: self._new_table_selection(cur))
        layout.addWidget(self.tree)
        self.tree.keyPressEvent = lambda ev: move_index_down(self.tree, ev)

        # Build plot widgets
        self.plot_layout = QtWidgets.QStackedLayout()
        self.line_plot = LinePlotWidget()
        self.img_plot = HeatmapPlotWidget()
        self.plot_layout.addWidget(self.line_plot)
        self.plot_layout.addWidget(self.img_plot)
        self.plot_container = QtWidgets.QWidget()
        self.plot_container.setLayout(self.plot_layout)

        #Build dataframe table
        self.df_table = QtWidgets.QTableView()

        self.tab_container = QtWidgets.QTabWidget()
        self.tab_container.addTab(self.plot_container, 'Plot')
        self.tab_container.addTab(self.df_table, 'Table')

        #Set the main layout
        splitter_config = {
            'main_w': ctrl_panel,
            'side_w': self.tab_container,
            'orientation': SplitterOrientation.vertical_right_button,
        }
        splitter = Splitter(**splitter_config)

        splitter.setSizes([1, 400])
        splitter.setHandleWidth(10)

        layout = QtWidgets.QHBoxLayout()
        layout.addWidget(splitter)
        self.setLayout(layout)

    def _new_table_selection(self, item):
        if not item is None:
            self._tabulate_item(item)
            self._plot_item(item)

    def _tabulate_item(self, item):
        path = item.data(0, QtCore.Qt.ToolTipRole)
        if path == '/':
            df = self.repo.get_index(col_order=[
                'uid', 'name', 'spyrelet', 'date', 'time', 'description'
            ])
            pd_model = PandasModel(df)
            model = QtCore.QSortFilterProxyModel()
            model.setSourceModel(pd_model)
            self.df_table.setSortingEnabled(True)
            self.tab_container.setCurrentWidget(self.df_table)
        else:
            df = self.repo[path].get_data()
            self.df_table.setSortingEnabled(False)
            if df is None:
                model = PandasModel(pd.DataFrame({}))
            else:
                model = PandasModel(df)
        self.df_table.setModel(model)

    def _plot_item(self, item):
        path = item.data(0, QtCore.Qt.ToolTipRole)
        self.plot_node(self.repo[path])

    def plot_node(self, node):
        meta = node.get_meta()
        if 'BasePlotWidget_type' in meta:
            if node.get_data() is None or node.get_data().empty:
                return
            if meta['BasePlotWidget_type'] == self.line_plot.plot_type_str:
                self.plot_layout.setCurrentWidget(self.line_plot)
                self.line_plot.load_node(node)
            elif meta['BasePlotWidget_type'] == self.img_plot.plot_type_str:
                self.plot_layout.setCurrentWidget(self.img_plot)
                self.img_plot.load_node(node)
            self.tab_container.setCurrentWidget(self.plot_container)

    def select_filename(self):
        filename, other = QtWidgets.QFileDialog.getOpenFileName(
            None, 'Save repository to...', '', 'HDF5 files (*.h5)')
        if filename:
            self.filename_label.setText(filename)
            self.filename = filename
            self.reload()
        return

    def reload(self):
        if self.filename is None:
            raise Exception('No file selected.  Please select a filename')
        self.repo = Repository(self.filename)
        self._plot_item = lambda _s, _i: None
        self.tree.clear()
        self.tree.addChild = self.tree.addTopLevelItem
        self.item_list = list()

        def add_child(node, parent, path_prefix):
            for name in node.get_child_names(sort=True):
                child = node.get_child(name)
                path = path_prefix + '/' + name
                tree_item = QtWidgets.QTreeWidgetItem([name])
                tree_item.setData(0, QtCore.Qt.ToolTipRole, path)
                parent.addChild(tree_item)
                self.item_list.append(tree_item)
                add_child(child, tree_item, path)

        tree_item = QtWidgets.QTreeWidgetItem(['root'])
        tree_item.setData(0, QtCore.Qt.ToolTipRole, '/')
        self.tree.addChild(tree_item)
        self.item_list.append(tree_item)
        add_child(self.repo.root, self.tree, '')
        self._plot_item = lambda item: self.__class__._plot_item(self, item)

    def get_selection_str(self, col_sep='\t', row_sep='\n'):
        indexes = self.df_table.selectedIndexes()
        model = self.df_table.model()
        if model is None:
            return
        if len(indexes) == 0:
            df = model._data
            return df.to_csv(sep=col_sep)
        else:
            indexes = sorted(indexes,
                             key=lambda idx: (idx.row(), idx.column()))
            nb_column = indexes[-1].column() - indexes[0].column() + 1
            model = self.df_table.model()
            ans = ''
            for i, index in enumerate(indexes):
                ans += model.data(index)
                if (i + 1) % nb_column == 0:
                    ans += row_sep
                else:
                    ans += col_sep
            return ans

    def keyPressEvent(self, ev):
        if type(ev) == QtGui.QKeyEvent:
            if ev.matches(QtGui.QKeySequence.Copy):
                app = QtWidgets.QApplication.instance()
                app.clipboard().setText(self.get_selection_str())
                ev.accept()
            if ev.matches(QtGui.QKeySequence.Save):
                filename, other = QtWidgets.QFileDialog.getSaveFileName(
                    None, 'Save this table to...', '',
                    'Comma Separated Value (*.csv)')
                if filename:
                    df = self.df_table.model()._data
                    df.to_csv(path_or_buf=filename, sep=',')
                ev.accept()