Beispiel #1
0
 def onItemSelected(self, selected, deselected):
     """Executed when an episode in the tableview is clicked"""
     # Get the information of last selected item
     if not selected and not deselected:
         return
     try:
         ind = selected.indexes()[-1].row()
     except:
         ind = deselected.indexes()[-1].row()
     sequence = self.tableview.sequence
     drugName = sequence['Drug Name'][ind]
     if not drugName:  # in case of empty string
         drugName = str(sequence['Drug Level'][ind])
     ep_info_str = "ts: {:0.1f} ms; Drug: {} ({})".format(
         sequence['Sampling Rate'][ind], drugName,
         sequence['Drug Time'][ind])
     self.statusBar().showMessage(ep_info_str)
     self.setWindowTitle("{}  {}".format(__version__,
                                         sequence['Dirs'][ind]))
     # Get selected row
     indexes = self.tableview.selectionModel().selectedRows()
     rows = [index.row() for index in sorted(indexes)]
     # if not rows: # When nothing is selected, keep the last selected item on the Scope
     #     return
     # Call scope window
     if not hasattr(self, 'sw'):  # Start up a new window
         # self.sw = ScopeWindow(parent=self)
         self.sw = ScopeWindow(partner=self,
                               hideDock=self.hideScopeToolbox,
                               layout=self.scopeLayout)  # new window
     if self.sw.isclosed:
         self.sw.show()
         self.sw.isclosed = False
     # update existing window
     self.sw.updateEpisodes(episodes=sequence, index=rows)
Beispiel #2
0
 def onItemClicked(self, index):
     """Executed when an episode in the tableview is clicked"""
     # self.tableview.model.selectedRow = index.row()
     # print('clicked row:%d, col:%d'%(index.row(), index.column()))
     # Get the information of currently selected item
     ind = index.row()
     sequence = self.tableview.sequence
     drugName = sequence['Drug Name'][ind]
     if not drugName:  # in case of empty string
         drugName = str(sequence['Drug Level'][ind])
     ep_info_str = "ts: {:0.1f} ms; Drug: {} ({})".format(
         sequence['Sampling Rate'][ind], drugName,
         sequence['Drug Time'][ind])
     self.statusBar().showMessage(ep_info_str)
     self.setWindowTitle("{}  {}".format(__version__,
                                         sequence['Dirs'][ind]))
     # Get selected row
     indexes = self.tableview.selectionModel().selectedRows()
     rows = [index.row() for index in sorted(indexes)]
     # Call scope window
     if not hasattr(self, 'sw'):  # Start up a new window
         self.sw = ScopeWindow(parent=self)
     if self.sw.isclosed:
         self.sw.show()
         self.sw.isclosed = False
     # update existing window
     self.sw.updateEpisodes(episodes=sequence, index=rows)
Beispiel #3
0
 def onItemSelected(self, selected, deselected):
     """Executed when an episode in the tableview is clicked"""
     # Get the information of last selected item
     if not selected and not deselected:
         return
     try:
         ind = selected.indexes()[-1].row()
     except:
         ind = deselected.indexes()[-1].row()
     sequence = self.tableview.sequence
     drugName = sequence['Drug Name'][ind]
     if not drugName: # in case of empty string
         drugName = str(sequence['Drug Level'][ind])
     ep_info_str = "ts: {:0.1f} ms; Drug: {} ({})".format(sequence['Sampling Rate'][ind], drugName, sequence['Drug Time'][ind])
     self.statusBar().showMessage(ep_info_str)
     self.setWindowTitle("{}  {}".format(__version__, sequence['Dirs'][ind]))
     # Get selected row
     indexes = self.tableview.selectionModel().selectedRows()
     rows = [index.row() for index in sorted(indexes)]
     # if not rows: # When nothing is selected, keep the last selected item on the Scope
     #     return
     # Call scope window
     if not hasattr(self, 'sw'): # Start up a new window
         # self.sw = ScopeWindow(parent=self)
         self.sw = ScopeWindow(partner=self, hideDock=self.hideScopeToolbox, layout=self.scopeLayout) # new window
     if self.sw.isclosed:
         self.sw.show()
         self.sw.isclosed = False
     # update existing window
     self.sw.updateEpisodes(episodes=sequence, index=rows)
Beispiel #4
0
 def onItemClicked(self, index):
     """Executed when an episode in the tableview is clicked"""
     # self.tableview.model.selectedRow = index.row()
     # print('clicked row:%d, col:%d'%(index.row(), index.column()))
     # Get the information of currently selected item
     ind = index.row()
     sequence = self.tableview.sequence
     drugName = sequence['Drug Name'][ind]
     if not drugName: # in case of empty string
         drugName = str(sequence['Drug Level'][ind])
     ep_info_str = "ts: {:0.1f} ms; Drug: {} ({})".format(sequence['Sampling Rate'][ind], drugName, sequence['Drug Time'][ind])
     self.statusBar().showMessage(ep_info_str)
     self.setWindowTitle("{}  {}".format(__version__, sequence['Dirs'][ind]))
     # Get selected row
     indexes = self.tableview.selectionModel().selectedRows()
     rows = [index.row() for index in sorted(indexes)]
     # Call scope window
     if not hasattr(self, 'sw'): # Start up a new window
         self.sw = ScopeWindow(parent=self)
     if self.sw.isclosed:
         self.sw.show()
         self.sw.isclosed = False
     # update existing window
     self.sw.updateEpisodes(episodes=sequence, index=rows)
Beispiel #5
0
class Synapse_MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Synapse_MainWindow, self).__init__(parent)
        # Set up the GUI window
        self.setupUi(self)
        # Set the treeview model for directory
        self.setDataBrowserTreeView()

    def setupUi(self, MainWindow):
        """This function is converted from the .ui file from the designer"""
        # Set up basic layout of the main window
        MainWindow.setObjectName(_fromUtf8("Synpase TreeView"))
        MainWindow.resize(1000, 500)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))

        # Set splitter for two panels
        self.splitter = QtGui.QSplitter(self.centralwidget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.splitter.sizePolicy().hasHeightForWidth())
        self.splitter.setSizePolicy(sizePolicy)
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter.setObjectName(_fromUtf8("splitter"))

        # Set treeview
        self.treeview = QtGui.QTreeView(self.splitter)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.treeview.sizePolicy().hasHeightForWidth())
        self.treeview.setSizePolicy(sizePolicy)
        self.treeview.setTextElideMode(QtCore.Qt.ElideNone)
        self.treeview.setObjectName(_fromUtf8("treeview"))


        # Set up Episode list table view
        self.tableview = QtGui.QTableView(self.splitter)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(3)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.tableview.sizePolicy().hasHeightForWidth())
        self.tableview.setSizePolicy(sizePolicy)
        self.tableview.setObjectName(_fromUtf8("tableview"))
        # additional tableview customizations
        self.tableview.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.tableview.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.tableview.setItemDelegate(TablviewDelegate(self.tableview))
        self.tableview.headers = ['Epi', 'Time', 'Duration', 'Drug Level', 'Drug Name', 'Drug Time', 'Comment','Dirs']
        self.tableview.hiddenColumnList = [4, 5, 7] # Drug Name, Drug Time, Dirs

        self.horizontalLayout.addWidget(self.splitter)
        MainWindow.setCentralWidget(self.centralwidget)

        # Set up menu bar
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 638, 100))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.setMenuBarItems() # call function to set menubar
        MainWindow.setMenuBar(self.menubar)

        # Set up status bar
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        # Execution
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    # ---------------- Additional main window behaviors -----------------------
    def setMenuBarItems(self):
         # File Menu
        fileMenu = self.menubar.addMenu('&File')

        # File: Exit
        exitAction = QtGui.QAction(QtGui.QIcon('exit.png'),'Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit Synapse')
        exitAction.triggered.connect(self.close)
        fileMenu.addAction(exitAction)

        # View Menu
        viewMenu = self.menubar.addMenu('&View')

        # View: Column
        columnMenu = viewMenu.addMenu('&Additional Columns')
        drugNameAction = QtGui.QAction('Drug Name', self, checkable=True, checked=False)
        drugNameAction.triggered.connect(lambda: self.toggleTableViewColumnAction(4, drugNameAction))
        columnMenu.addAction(drugNameAction)

        drugTimeAction = QtGui.QAction('Drug Time', self, checkable=True, checked=False)
        drugTimeAction.triggered.connect(lambda: self.toggleTableViewColumnAction(5, drugTimeAction))
        columnMenu.addAction(drugTimeAction)

        dirsAction = QtGui.QAction('Directory', self, checkable=True, checked=False)
        dirsAction.triggered.connect(lambda: self.toggleTableViewColumnAction(7, dirsAction))
        columnMenu.addAction(dirsAction)

    def toggleTableViewColumnAction(self, column, action):
        if self.tableview.isColumnHidden(column):
            self.tableview.showColumn(column)
            action.setChecked(True)
            self.tableview.hiddenColumnList.remove(column)
        else:
            self.tableview.hideColumn(column)
            action.setChecked(False)
            self.tableview.hiddenColumnList.append(column)

    def closeEvent(self, event):
        """Override default behavior when closing the main window"""
        #quit_msg = "Are you sure you want to exit the program?"
        #reply = QtGui.QMessageBox.question(self, 'Message', quit_msg,
        #                                   QtGui.QMessageBox.Yes,
        #                                   QtGui.QMessageBox.No)
        #if reply == QtGui.QMessageBox.Yes:
        #    event.accept()
        #else:
        #    event.ignore()

    def retranslateUi(self, MainWindow):
        """Set window title and other miscellaneous"""
        MainWindow.setWindowTitle(_translate(__version__, __version__, None))

    # ---------------- Data browser behaviors ---------------------------------
    def setDataBrowserTreeView(self):
        # Set file system as model of the tree view
        # self.treeview.model = QtGui.QFileSystemModel()
        self.treeview.model = FileSystemTreeModel()
        self.treeview.setModel(self.treeview.model)
        # Set behavior upon clicked
        self.treeview.clicked.connect(self.onSequenceClicked)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def onSequenceClicked(self, index):
        """ Display a list of episodes upon sequence clicked"""
        #indexItem = self.treeview.model.index(index.row(), 0, index.parent())
        node = self.treeview.model.getNode(index)
        # Check if the item clicked is sequence instead of a folder / file
        if node.type == "sequence":
            # populuate the table view on the other panel
            self.setEpisodeListTableView(node.info)

    # --------------- Episode list behaviors ----------------------------------
    def setEpisodeListTableView(self, sequence=None):
        if not sequence:
            return # do nothing if there is no sequence information
        # Render the data frame from sequence
        df = pd.DataFrame.from_dict(sequence)
        # sort the data frame by 'Epi' column
        epi_sort = df['Epi'].tolist()
        ind = pd.DataFrame([[int(k) for k in re.findall('\d+', m)] \
                                    for m in epi_sort])
        ind = ind.sort_values([0,1], ascending=[1,1]).index.tolist()
        df = df.reindex_axis(ind, axis=0)
        self.tableview.sequence = df.reset_index(drop=True).to_dict('list') # data information
        self.tableview.sequence['Name'] = self.tableview.sequence['Name'][0] # remove any duplication
        # get the subset of columns based on column settings
        df = df.reindex_axis(self.tableview.headers, axis=1)
        self.tableview.model = EpisodeTableModel(df)
        self.tableview.setModel(self.tableview.model)
        self.tableview.verticalHeader().hide()
        # Hide some columns from display
        for c in self.tableview.hiddenColumnList: # Drug Name, Drug Time, Dirs
            self.tableview.setColumnHidden(c, True)
        # Set behavior upon selection
        self.tableview.clicked.connect(self.onItemClicked)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def onItemClicked(self, index):
        """Executed when an episode in the tableview is clicked"""
        # self.tableview.model.selectedRow = index.row()
        # print('clicked row:%d, col:%d'%(index.row(), index.column()))
        # Get the information of currently selected item
        ind = index.row()
        sequence = self.tableview.sequence
        drugName = sequence['Drug Name'][ind]
        if not drugName: # in case of empty string
            drugName = str(sequence['Drug Level'][ind])
        ep_info_str = "ts: {:0.1f} ms; Drug: {} ({})".format(sequence['Sampling Rate'][ind], drugName, sequence['Drug Time'][ind])
        self.statusBar().showMessage(ep_info_str)
        self.setWindowTitle("{}  {}".format(__version__, sequence['Dirs'][ind]))
        # Get selected row
        indexes = self.tableview.selectionModel().selectedRows()
        rows = [index.row() for index in sorted(indexes)]
        # Call scope window
        if not hasattr(self, 'sw'): # Start up a new window
            self.sw = ScopeWindow(parent=self)
        if self.sw.isclosed:
            self.sw.show()
            self.sw.isclosed = False
        # update existing window
        self.sw.updateEpisodes(episodes=sequence, index=rows)
Beispiel #6
0
class Synapse_MainWindow(QtGui.QMainWindow):
    def __init__(self,
                 parent=None,
                 startpath=None,
                 hideScopeToolbox=True,
                 layout=None):
        super(Synapse_MainWindow, self).__init__(parent)
        # Set up the GUI window
        self.setupUi(self)
        # Set the treeview model for directory
        self.setDataBrowserTreeView(startpath=startpath)
        self.hideScopeToolbox = hideScopeToolbox
        self.scopeLayout = layout

    def setupUi(self, MainWindow):
        """This function is converted from the .ui file from the designer"""
        # Set up basic layout of the main window
        MainWindow.setObjectName(_fromUtf8("Synpase TreeView"))
        MainWindow.resize(1000, 500)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))

        # Set splitter for two panels
        self.splitter = QtGui.QSplitter(self.centralwidget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
                                       QtGui.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.splitter.sizePolicy().hasHeightForWidth())
        self.splitter.setSizePolicy(sizePolicy)
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter.setObjectName(_fromUtf8("splitter"))

        # Set treeview
        self.treeview = QtGui.QTreeView(self.splitter)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,
                                       QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.treeview.sizePolicy().hasHeightForWidth())
        self.treeview.setSizePolicy(sizePolicy)
        # self.treeview.setTextElideMode(QtCore.Qt.ElideNone)
        self.treeview.header().setResizeMode(
            QtGui.QHeaderView.ResizeToContents)
        self.treeview.header().setStretchLastSection(False)
        self.treeview.setObjectName(_fromUtf8("treeview"))

        # Set up Episode list table view
        self.tableview = QtGui.QTableView(self.splitter)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
                                       QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(3)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.tableview.sizePolicy().hasHeightForWidth())
        self.tableview.setSizePolicy(sizePolicy)
        self.tableview.setObjectName(_fromUtf8("tableview"))
        # additional tableview customizations
        self.tableview.setSelectionMode(
            QtGui.QAbstractItemView.ExtendedSelection)
        self.tableview.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.tableview.setItemDelegate(TableviewDelegate(self.tableview))
        self.tableview.headers = [
            'Epi', 'Time', 'Duration', 'Drug Level', 'Drug Name', 'Drug Time',
            'Comment', 'Dirs'
        ]
        self.tableview.hiddenColumnList = [4, 5,
                                           7]  # Drug Name, Drug Time, Dirs
        self.tableview.horizontalHeader().setStretchLastSection(True)
        # self.tableview.setShowGrid(False)
        self.tableview.setStyleSheet(
            """QTableView{border : 20px solid white}""")
        self.horizontalLayout.addWidget(self.splitter)
        MainWindow.setCentralWidget(self.centralwidget)

        # Set up menu bar
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 638, 100))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.setMenuBarItems()  # call function to set menubar
        MainWindow.setMenuBar(self.menubar)

        # Set up status bar
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        # Execution
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    # ---------------- Additional main window behaviors -----------------------
    def setMenuBarItems(self):
        # File Menu
        fileMenu = self.menubar.addMenu('&File')

        # File: Refresh. Refresh currently selected item/directory
        refreshAction = QtGui.QAction('Refresh', self)
        refreshAction.setShortcut('F5')
        refreshAction.setStatusTip(
            'Refresh currently selected item / directory')
        refreshAction.triggered.connect(self.refreshCurrentBranch)
        fileMenu.addAction(refreshAction)

        # File: Settings
        settingsAction = QtGui.QAction("Settings", self)
        settingsAction.setStatusTip('Configure settings of PySynapse')
        settingsAction.triggered.connect(self.openSettingsWindow)
        fileMenu.addAction(settingsAction)

        # File: Exit
        exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), 'Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit Synapse')
        exitAction.triggered.connect(self.close)
        fileMenu.addAction(exitAction)

        # View Menu
        viewMenu = self.menubar.addMenu('&View')

        # View: Column
        columnMenu = viewMenu.addMenu('&Additional Columns')
        drugNameAction = QtGui.QAction('Drug Name',
                                       self,
                                       checkable=True,
                                       checked=False)
        drugNameAction.triggered.connect(
            lambda: self.toggleTableViewColumnAction(4, drugNameAction))
        columnMenu.addAction(drugNameAction)

        drugTimeAction = QtGui.QAction('Drug Time',
                                       self,
                                       checkable=True,
                                       checked=False)
        drugTimeAction.triggered.connect(
            lambda: self.toggleTableViewColumnAction(5, drugTimeAction))
        columnMenu.addAction(drugTimeAction)

        dirsAction = QtGui.QAction('Directory',
                                   self,
                                   checkable=True,
                                   checked=False)
        dirsAction.triggered.connect(
            lambda: self.toggleTableViewColumnAction(7, dirsAction))
        columnMenu.addAction(dirsAction)

    def toggleTableViewColumnAction(self, column, action):
        if self.tableview.isColumnHidden(column):
            self.tableview.showColumn(column)
            action.setChecked(True)
            self.tableview.hiddenColumnList.remove(column)
        else:
            self.tableview.hideColumn(column)
            action.setChecked(False)
            self.tableview.hiddenColumnList.append(column)

    def refreshCurrentBranch(self):
        # Get parent index
        index = self.treeview.selectionModel().currentIndex()
        node = self.treeview.model.getNode(index)
        if node.type == "directory":
            self.treeview.model.refreshNode(index)

    def openSettingsWindow(self):
        if not hasattr(self, 'settingsWidget'):
            self.settingsWidget = Settings()
        if self.settingsWidget.isclosed:
            self.settingsWidget.show()
            self.settingsWidget.isclosed = False

    def closeEvent(self, event):
        """Override default behavior when closing the main window"""
        return
        #quit_msg = "Are you sure you want to exit the program?"
        #reply = QtGui.QMessageBox.question(self, 'Message', quit_msg,
        #                                   QtGui.QMessageBox.Yes,
        #                                   QtGui.QMessageBox.No)
        #if reply == QtGui.QMessageBox.Yes:
        #    event.accept()
        #else:
        #    event.ignore()
        # Consider if close children windows when closing Synapse main window
        # children = ['settingsWidget', 'sw']
        # for c in children:
        #     if hasattr(self, c):
        #         getattr(self, c).close()

    def retranslateUi(self, MainWindow):
        """Set window title and other miscellaneous"""
        MainWindow.setWindowTitle(_translate(__version__, __version__, None))
        MainWindow.setWindowIcon(QtGui.QIcon('resources/icons/Synapse.png'))

    # ---------------- Data browser behaviors ---------------------------------
    def setDataBrowserTreeView(self, startpath=None):
        # Set file system as model of the tree view
        # self.treeview.model = QtGui.QFileSystemModel()
        self.treeview.model = FileSystemTreeModel(path=startpath)
        self.treeview.setModel(self.treeview.model)
        # Set behavior upon clicked
        self.treeview.clicked.connect(self.onSequenceClicked)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def onSequenceClicked(self, index):
        """ Display a list of episodes upon sequence clicked"""
        #indexItem = self.treeview.model.index(index.row(), 0, index.parent())
        self.raise_()
        node = self.treeview.model.getNode(index)
        # Check if the item clicked is sequence instead of a folder / file
        if node.type == "sequence":
            # populuate the table view on the other panel
            self.setEpisodeListTableView(node.info)

    # --------------- Episode list behaviors ----------------------------------
    def setEpisodeListTableView(self, sequence=None):
        if not sequence:
            return  # do nothing if there is no sequence information
        # Render the data frame from sequence
        df = pd.DataFrame.from_dict(sequence)
        # sort the data frame by 'Epi' column
        epi_sort = df['Epi'].tolist()
        ind = pd.DataFrame([[int(k) for k in re.findall('\d+', m)] \
                                    for m in epi_sort])
        ind = ind.sort_values([0, 1], ascending=[1, 1]).index.tolist()
        df = df.reindex_axis(ind, axis=0)
        self.tableview.sequence = df.reset_index(drop=True).to_dict(
            'list')  # data information
        self.tableview.sequence['Name'] = self.tableview.sequence['Name'][
            0]  # remove any duplication
        # get the subset of columns based on column settings
        df = df.reindex_axis(self.tableview.headers, axis=1)
        self.tableview.model = EpisodeTableModel(df)
        self.tableview.setModel(self.tableview.model)
        self.tableview.verticalHeader().hide()
        # Hide some columns from display
        for c in self.tableview.hiddenColumnList:  # Drug Name, Drug Time, Dirs
            self.tableview.setColumnHidden(c, True)
        # Set behavior upon selection
        self.tableview.selectionModel().selectionChanged.connect(
            self.onItemSelected)
        # self.tableview.clicked.connect(self.onItemSelected)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def onItemSelected(self, selected, deselected):
        """Executed when an episode in the tableview is clicked"""
        # Get the information of last selected item
        if not selected and not deselected:
            return
        try:
            ind = selected.indexes()[-1].row()
        except:
            ind = deselected.indexes()[-1].row()
        sequence = self.tableview.sequence
        drugName = sequence['Drug Name'][ind]
        if not drugName:  # in case of empty string
            drugName = str(sequence['Drug Level'][ind])
        ep_info_str = "ts: {:0.1f} ms; Drug: {} ({})".format(
            sequence['Sampling Rate'][ind], drugName,
            sequence['Drug Time'][ind])
        self.statusBar().showMessage(ep_info_str)
        self.setWindowTitle("{}  {}".format(__version__,
                                            sequence['Dirs'][ind]))
        # Get selected row
        indexes = self.tableview.selectionModel().selectedRows()
        rows = [index.row() for index in sorted(indexes)]
        # if not rows: # When nothing is selected, keep the last selected item on the Scope
        #     return
        # Call scope window
        if not hasattr(self, 'sw'):  # Start up a new window
            # self.sw = ScopeWindow(parent=self)
            self.sw = ScopeWindow(partner=self,
                                  hideDock=self.hideScopeToolbox,
                                  layout=self.scopeLayout)  # new window
        if self.sw.isclosed:
            self.sw.show()
            self.sw.isclosed = False
        # update existing window
        self.sw.updateEpisodes(episodes=sequence, index=rows)
Beispiel #7
0
class Synapse_MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None, startpath=None, hideScopeToolbox=True, layout=None):
        super(Synapse_MainWindow, self).__init__(parent)
        # Set up the GUI window
        self.setupUi(self)
        # Set the treeview model for directory
        self.setDataBrowserTreeView(startpath=startpath)
        self.hideScopeToolbox = hideScopeToolbox
        self.scopeLayout = layout
        self.startpath=startpath

    def setupUi(self, MainWindow):
        """This function is converted from the .ui file from the designer"""
        # Set up basic layout of the main window
        MainWindow.setObjectName(_fromUtf8("Synpase TreeView"))
        MainWindow.resize(1000, 500)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))

        # Set splitter for two panels
        self.splitter = QtWidgets.QSplitter(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.splitter.sizePolicy().hasHeightForWidth())
        self.splitter.setSizePolicy(sizePolicy)
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter.setObjectName(_fromUtf8("splitter"))

        # Set treeview
        self.treeview = QtWidgets.QTreeView(self.splitter)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.treeview.sizePolicy().hasHeightForWidth())
        self.treeview.setSizePolicy(sizePolicy)
        # self.treeview.setTextElideMode(QtCore.Qt.ElideNone)
        self.treeview.header().setResizeMode(QtWidgets.QHeaderView.ResizeToContents)
        self.treeview.header().setStretchLastSection(False)
        self.treeview.setObjectName(_fromUtf8("treeview"))

        # Set up Episode list table view
        self.tableview = QtWidgets.QTableView(self.splitter)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(3)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.tableview.sizePolicy().hasHeightForWidth())
        self.tableview.setSizePolicy(sizePolicy)
        self.tableview.setObjectName(_fromUtf8("tableview"))
        # additional tableview customizations
        self.tableview.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
        self.tableview.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.tableview.setItemDelegate(TableviewDelegate(self.tableview))
        self.tableview.horizontalHeader().setStretchLastSection(True)
        # self.tableview.setShowGrid(False)
        self.tableview.setStyleSheet("""QTableView{border : 20px solid white}""")
        self.horizontalLayout.addWidget(self.splitter)
        MainWindow.setCentralWidget(self.centralwidget)

        # Set up menu bar
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 638, 100))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.setMenuBarItems() # call function to set menubar
        MainWindow.setMenuBar(self.menubar)

        # Set up status bar
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        # Execution
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    # ---------------- Additional main window behaviors -----------------------
    def setMenuBarItems(self):
        # File Menu
        fileMenu = self.menubar.addMenu('&File')

        # File: Load csv
        loadDBAction = QtWidgets.QAction('Load Database', self)
        loadDBAction.setStatusTip('Load a database table from a .csv, .xlsx, or .xls file')
        loadDBAction.triggered.connect(self.loadDatabase)
        fileMenu.addAction(loadDBAction)
        
        # File: Refresh. Refresh currently selected item/directory
        refreshAction = QtWidgets.QAction('Refresh', self)
        refreshAction.setShortcut('F5')
        refreshAction.setStatusTip('Refresh currently selected item / directory')
        refreshAction.triggered.connect(self.refreshCurrentBranch)
        fileMenu.addAction(refreshAction)
        
        # File: Settings
        settingsAction = QtWidgets.QAction("Settings", self)
        settingsAction.setStatusTip('Configure settings of PySynapse')
        settingsAction.triggered.connect(self.openSettingsWindow)
        fileMenu.addAction(settingsAction)
        
        # File: Exit
        exitAction = QtWidgets.QAction(QtGui.QIcon('exit.png'),'Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit Synapse')
        exitAction.triggered.connect(self.close)
        fileMenu.addAction(exitAction)
        
        # View Menu
        viewMenu = self.menubar.addMenu('&View')

        # View: Column
        columnMenu = viewMenu.addMenu('&Additional Columns')
        drugNameAction = QtWidgets.QAction('Drug Name', self, checkable=True, checked=False)
        drugNameAction.triggered.connect(lambda: self.toggleTableViewColumnAction(4, drugNameAction))
        columnMenu.addAction(drugNameAction)

        drugTimeAction = QtWidgets.QAction('Drug Time', self, checkable=True, checked=False)
        drugTimeAction.triggered.connect(lambda: self.toggleTableViewColumnAction(5, drugTimeAction))
        columnMenu.addAction(drugTimeAction)

        dirsAction = QtWidgets.QAction('Directory', self, checkable=True, checked=False)
        dirsAction.triggered.connect(lambda: self.toggleTableViewColumnAction(7, dirsAction))
        columnMenu.addAction(dirsAction)

    def toggleTableViewColumnAction(self, column, action):
        if self.tableview.isColumnHidden(column):
            self.tableview.showColumn(column)
            action.setChecked(True)
            self.tableview.hiddenColumnList.remove(column)
        else:
            self.tableview.hideColumn(column)
            action.setChecked(False)
            self.tableview.hiddenColumnList.append(column)

    def loadDatabase(self):
        # TODO: Need to design this more carefully
        #raise(NotImplementedError())
        # Opens up the file explorer
        filename, _ = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', '/', 'Spreadsheet (*.csv *.xlsx *.xls);;All Files (*)')#
        rename_dict = {"Cell":"Name", "Episode":"Epi", "SweepWindow":"Duration","Drug":"Drug Name","DrugTime":"Drug Time","WCTime":"Time", "StimDescription":"Comment"}
        if ".csv" in filename:
            df = pd.read_csv(filename)
        elif ".xlsx" in filename or "xls" in filename:
            df = pd.read_excel(filename)
        else:
            return
        col_lower = [c.lower() for c in df.columns.tolist()]
        if "show" in col_lower:
            df = df.loc[df.iloc[:, col_lower.index("show")],:]
        drop_columns = np.setdiff1d(df.columns.tolist(), list(rename_dict.keys()))
        df = df.drop(drop_columns, axis=1).rename(columns=rename_dict)
        df["Sampling Rate"] = 0.1
        df["Drug Level"] = 0
        df.loc[df["Drug Name"].isnull(), "Drug Name"] = ""
        df["Time"] = [NeuroData.epiTime(ttt) for ttt in df["Time"]]
        df["Drug Time"] = [NeuroData.epiTime(ttt) for ttt in df["Drug Time"]]
        # TODO: Tentitative path
        df["Dirs"] = [os.path.join(self.startpath, get_cellpath(cb, ep)).replace("\\", "/") for cb, ep in zip(df["Name"], df["Epi"])]
        self.tableview.sequence = df.reset_index(drop=True).to_dict('list')
        df = df.reindex(["Name", "Epi", "Time", "Duration", "Drug Name", "Drug Time", "Comment"], axis=1) # drop columns not to be displayed
        # print('loaded')
        # Populate the loaded data unto the table widget
        self.tableview.headers = df.columns.tolist()
        self.tableview.model = EpisodeTableModel(df)
        self.tableview.setModel(self.tableview.model)
        self.tableview.verticalHeader().hide()
        # Show all columns
        for cc in range(len(self.tableview.headers)):
            self.tableview.showColumn(cc)

        self.tableview.selectionModel().selectionChanged.connect(self.onItemSelected)

    def refreshCurrentBranch(self):
        # Get parent index
        index = self.treeview.selectionModel().currentIndex()
        node = self.treeview.model.getNode(index)
        if node.type == "directory":
            self.treeview.model.refreshNode(index)
            
    def openSettingsWindow(self):
        if not hasattr(self, 'settingsWidget'):
            self.settingsWidget = Settings()
        if self.settingsWidget.isclosed:
            self.settingsWidget.show()
            self.settingsWidget.isclosed = False
        
    def closeEvent(self, event):
        """Override default behavior when closing the main window"""
        return
        #quit_msg = "Are you sure you want to exit the program?"
        #reply = QtWidgets.QMessageBox.question(self, 'Message', quit_msg,
        #                                   QtWidgets.QMessageBox.Yes,
        #                                   QtWidgets.QMessageBox.No)
        #if reply == QtWidgets.QMessageBox.Yes:
        #    event.accept()
        #else:
        #    event.ignore()
        # Consider if close children windows when closing Synapse main window
        # children = ['settingsWidget', 'sw']
        # for c in children:
        #     if hasattr(self, c):
        #         getattr(self, c).close()
          
    def retranslateUi(self, MainWindow):
        """Set window title and other miscellaneous"""
        MainWindow.setWindowTitle(_translate(__version__, __version__, None))
        MainWindow.setWindowIcon(QtGui.QIcon('resources/icons/Synapse.png'))

    # ---------------- Data browser behaviors ---------------------------------
    def setDataBrowserTreeView(self, startpath=None):
        # Set file system as model of the tree view
        # self.treeview.model = QtWidgets.QFileSystemModel()
        self.treeview.model = FileSystemTreeModel(path=startpath)
        self.treeview.setModel(self.treeview.model)
        # Set behavior upon clicked
        self.treeview.clicked.connect(self.onSequenceClicked)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def onSequenceClicked(self, index):
        """ Display a list of episodes upon sequence clicked"""
        #indexItem = self.treeview.model.index(index.row(), 0, index.parent())
        self.raise_()
        node = self.treeview.model.getNode(index)
        # Check if the item clicked is sequence instead of a folder / file
        if node.type == "sequence":
            # populate the table view on the other panel
            self.setEpisodeListTableView(node.info)
        
    # --------------- Episode list behaviors ----------------------------------
    def setEpisodeListTableView(self, sequence=None):
        if not sequence:
            return # do nothing if there is no sequence information
        self.tableview.headers = ['Epi', 'Time', 'Duration', 'Drug Level', 'Drug Name', 'Drug Time', 'Comment','Dirs', 'Stimulus', 'StimDuration']
        self.tableview.hiddenColumnList = [4, 5, 7, 8, 9] # Drug Name, Drug Time, Dirs
        # Render the data frame from sequence
        df = pd.DataFrame.from_dict(sequence)
        # sort the data frame by 'Epi' column
        epi_sort = df['Epi'].tolist()
        ind = pd.DataFrame([[int(k) for k in re.findall('\d+', m)] \
                                    for m in epi_sort])
        ind = ind.sort_values([0,1], ascending=[1,1]).index.tolist()
        df = df.reindex(ind, axis=0)
        self.tableview.sequence = df.reset_index(drop=True).to_dict('list') # data information
        # self.tableview.sequence['Name'] = self.tableview.sequence['Name'][0] # remove any duplication
        # get the subset of columns based on column settings
        df = df.reindex(self.tableview.headers, axis=1)
        self.tableview.model = EpisodeTableModel(df)
        self.tableview.setModel(self.tableview.model)
        self.tableview.verticalHeader().hide()
        # Hide some columns from display
        for c in self.tableview.hiddenColumnList: # Drug Name, Drug Time, Dirs
            self.tableview.setColumnHidden(c, True)
        # Set behavior upon selection
        self.tableview.selectionModel().selectionChanged.connect(self.onItemSelected)
        # self.tableview.clicked.connect(self.onItemSelected)

    @QtCore.pyqtSlot(QtCore.QItemSelection, QtCore.QItemSelection)
    def onItemSelected(self, selected, deselected):
        """Executed when an episode in the tableview is clicked"""
        # Get the information of last selected item
        if not selected and not deselected:
            return
        try:
            ind = selected.indexes()[-1].row()
        except:
            ind = deselected.indexes()[-1].row()
        sequence = self.tableview.sequence
        drugName = sequence['Drug Name'][ind]
        if not drugName: # in case of empty string
            drugName = str(sequence['Drug Level'][ind])
        ep_info_str = "ts: {:0.1f} ms; Drug: {} ({})".format(sequence['Sampling Rate'][ind], drugName, sequence['Drug Time'][ind])
        self.statusBar().showMessage(ep_info_str)
        self.setWindowTitle("{}  {}".format(__version__, sequence['Dirs'][ind]))
        # Get selected row
        indexes = self.tableview.selectionModel().selectedRows()
        rows = [index.row() for index in sorted(indexes)]
        # if not rows: # When nothing is selected, keep the last selected item on the Scope
        #     return
        # Call scope window
        if not hasattr(self, 'sw'): # Start up a new window
            # self.sw = ScopeWindow(parent=self)
            self.sw = ScopeWindow(partner=self, hideDock=self.hideScopeToolbox, layout=self.scopeLayout) # new window
        if self.sw.isclosed:
            self.sw.show()
            self.sw.isclosed = False
        # update existing window
        self.sw.updateEpisodes(episodes=sequence, index=rows)