Example #1
0
 def execute(self, settings: Settings) -> bool:
     self.loadSetiings(settings)
     if self.exec() != QDialog.Accepted:
         return False
     self.saveSetiings(settings)
     settings.write()
     return True
Example #2
0
def pack(args: Namespace) -> None:
    settings = Settings.from_env()
    projects: list[str]
    if args.all:
        librarian = Librarian(settings)
        projects = librarian.get_expanded_epubs().get(args.type, [])
    else:
        projects = args.projects
    if len(projects) > 0:
        print("Packing projects...")
        packer = Packer(settings)
        packer.pack_projects(projects, args.type, args.compression)
Example #3
0
def build(args: Namespace) -> None:
    settings = Settings.from_env()
    projects: list[str]
    if args.all:
        librarian = Librarian(settings)
        projects = librarian.get_projects()
    else:
        projects = args.projects
    if len(projects) > 0:
        print("Building projects...")
        builder = Builder(settings)
        builder.build_projects(projects, args.type, args.bundles)
Example #4
0
def main() -> None:
    default_settings = Settings()
    installer = Installer(default_settings)
    installer.install_epubcheck()
    project_types = sorted(
        path.name
        for path in default_settings.expanded_epubs_directory.iterdir()
        if path.is_dir())
    for project_type in project_types:
        pack_all(default_settings, project_type)
        check_all(default_settings, project_type)
        release(default_settings, project_type)
    summary_file = summarize(default_settings)
    release_summary(summary_file)
Example #5
0
def check(args: Namespace) -> None:
    settings = Settings.from_env()
    if args.install:
        print("Installing EPUBCheck...")
        installer = Installer(settings)
        installer.install_epubcheck()
    projects: list[str]
    if args.all:
        librarian = Librarian(settings)
        projects = librarian.get_packaged_epubs().get(args.type, [])
    else:
        projects = args.projects
    if len(projects) > 0:
        print("Checking projects...")
        checker = Checker(settings)
        checker.check_projects(projects, args.type)
Example #6
0
def sync(args: Namespace) -> None:
    settings = Settings.from_env()
    new_books: list[str] = []
    projects: list[str]
    if args.all:
        librarian = Librarian(settings)
        projects = librarian.get_packaged_epubs().get(args.type, [])
    else:
        projects = args.projects
    for project in projects:
        epub_project = EPUBProject(Path(settings.projects_directory, project))
        metadata = epub_project.epub_metadata
        search_terms: list[str] = []
        search_terms.append(f"title:\"={metadata.title}\"")
        for creator_name, creator_roles in metadata.creators.items():
            if not creator_roles or "aut" in creator_roles:
                search_terms.append(f"author:\"={creator_name}\"")
        search_expression = " ".join(search_terms)
        book_ids = calibredb.search(search_expression,
                                    with_library=args.with_library,
                                    username=args.username,
                                    password=args.password,
                                    timeout=args.timeout)
        ebook_file = Path(settings.packaged_epubs_directory, args.type,
                          f"{project}.{args.type}.epub").as_posix()
        if not book_ids:
            new_books.append(ebook_file)
        elif len(book_ids) == 1:
            a = calibredb.add_format(book_ids[0],
                                     ebook_file,
                                     with_library=args.with_library,
                                     username=args.username,
                                     password=args.password,
                                     timeout=args.timeout)
            print(a)
        else:
            print(f"Skipping {project} due to ambiguous metadata")
    if new_books:
        calibredb.add(new_books,
                      with_library=args.with_library,
                      username=args.username,
                      password=args.password,
                      timeout=args.timeout)
Example #7
0
 def __init__(self):
     self.title = u'Tracks detection'
     # Настройки
     self.settings = Settings()
Example #8
0
class Application:
    def __init__(self):
        self.title = u'Tracks detection'
        # Настройки
        self.settings = Settings()

    def application_init(self):
        '''Инициализация Qt приложения'''
        # Создание приложение
        self.qapp = QApplication(sys.argv)
        self.__app_working_status = True
        # Установка локлизатора
        translator = QTranslator(self.qapp)
        translator.load('lang/tr_ru', os.path.dirname(__file__))
        self.qapp.installTranslator(translator)

        self.mainDialog = MainDialog(self, self.title)
        self.mainDialog.closeApp.connect(self.__finalize_before_quit)

        self.controls = {
            'step': ['X', 'Y', 'Z', 'A'],
            'servo': ['B', 'C'],
            'pins': {
                'P1': [],
                'P2': ['UV', 'VIS']
            }
        }

        self.mainDialog.show()
        self.project_init()
        self.gui_init()
        self.communication_init()

        sys.exit(self.qapp.exec_())

    def __finalize_before_quit(self):
        self.__app_working_status = False
        if self.grbl.connection: self.grbl.connection.close()
        if self.communication_thread: self.communication_thread.join()
        self.qapp.exit()

    def retuenicon(self, name):
        return QIcon(
            QPixmap(
                os.path.normpath(
                    os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                 '', name + '.png'))))

    def project_init(self):
        self.project = Project('New')

    def async_sleep(self, sleep):
        for i in range(sleep):
            time.sleep(1)
            if not self.__app_working_status: break

    def __connection_worker(self):
        while self.__app_working_status:
            status = self.__current_conacion_procedure()
            if status: break
            if status:
                self.__current_conacion_procedure = self.grbl.getStatus
            else:
                self.__current_conacion_procedure = self.__auto_seach__
            self.async_sleep(5)
            self.cnc_indicator.setStatus(status)

    def communication_init(self):
        self.grbl = GRBL(HOST=self.settings.grblip)
        self.__current_conacion_procedure = self.__auto_seach__
        self.communication_thread = threading.Thread(
            target=self.__connection_worker)
        self.communication_thread.setDaemon(True)
        self.communication_thread.start()

    def gui_init(self):

        pref_menu = menu_item(u'Preferences')
        ref_menu = menu_item(u'Reference')
        gen_menu = menu_item(u'Device')

        gen_menu.addChildren(menu_item(u'GRBL', self.showGrblDialog))

        file_menu = menu_item(self.qapp.tr(u'File'))
        file_menu.addChildren(menu_item(u'New', self.newProject),
                              menu_item(u'Open', self.openProject),
                              menu_item(u'Import...', self.openFile),
                              menu_item(u'Save', self.saveProject),
                              menu_item(u'Exit', self.qapp.exit))

        pref_menu.addChildren(gen_menu, menu_item(u'Settings'))

        ref_menu.addChildren(menu_item(u'Help'),
                             menu_item(u'About', self.showAbout))

        self.mainDialog.addMenuItems(file_menu, pref_menu, ref_menu)

        self.cnc_indicator = work_indicator(u'CNC')
        self.mainDialog.addStatusObj(self.cnc_indicator)

        self.progressBar = QProgressBar()
        self.progressBar.setTextVisible(True)
        self.progressBar.setAlignment(Qt.AlignCenter)
        self.progressBar.minimum = 1
        self.progressBar.maximum = 100
        self.mainDialog.addPermanentStatusObj(self.progressBar)
        '''Инициализациия таблицы содержания'''
        treeDock = QDockWidget(self.qapp.tr(u'Project tree'), self.mainDialog)
        treeDock.setAllowedAreas(Qt.LeftDockWidgetArea
                                 | Qt.RightDockWidgetArea)
        self.mainDialog.addDockWidget(Qt.LeftDockWidgetArea, treeDock)

        self.mainnodes = [Node("Samples"), Node("Other")]
        self.project_tree = ProjectTree(self, self.mainnodes)
        self.project_tree.doubleClicked.connect(self.on_tree_clicked)
        treeDock.setWidget(self.project_tree)
        '''Инициализациия центра'''
        jog = JogWidget(app=self.qapp,
                        axies=self.controls,
                        pinAcions=self.pinAcions,
                        motorActions=self.send_to_grbl)
        self.mainDialog.addToCenter(jog)
        jog.raise_()

    def send_to_grbl(self, text, send_type):
        if len(text):
            self.grbl.send_task(text, send_type)

    def pinAcions(self, status, pin):
        task = 'M62 {pin}'.format(pin=pin) if status else 'M63 {pin}'.format(
            pin=pin)
        self.grbl.send_task(task, SENDTYPE.IDLE)

    def setProgress(self, step, steps):
        value = step / float(len(steps)) * 100.
        indx = int(ceil(step - 1))
        text = self.qapp.tr(steps[indx])
        self.progressBar.setFormat("{0} - {1}%".format(text, round(value, 0)))
        self.progressBar.setValue(value)
        self.qapp.processEvents()

    def on_tree_clicked(self, index):
        item = self.project_tree.selectedIndexes()[0]
        if self.project.current_sample != item.model().itemFromIndex(
                index).obj:
            self.project.current_sample = item.model().itemFromIndex(index).obj
            self.refresh()

    def newProject(self):
        self.mainDialog.PreparedArea.clear()
        self.mainDialog.ThroughArea.clear()
        self.mainDialog.BacklightArea.clear()
        self.mainnodes = [Node("Samples"), Node("Other")]
        self.project_tree.setMainNodes(self.mainnodes)
        self.project = Project('TEMP')
        self.refresh()

    def openProject(self):

        fileName, _ = QFileDialog.getOpenFileName(
            self.mainDialog, self.qapp.tr("Load project"), ".\\",
            self.qapp.tr("Project file (*.tpr)"))

        infile = open(fileName, 'rb')
        self.project = pickle.load(infile)
        infile.close()

        self.mainDialog.PreparedArea.clear()
        self.mainDialog.ThroughArea.clear()
        self.mainDialog.BacklightArea.clear()
        self.mainnodes = [Node("Samples"), Node("Other")]
        self.project_tree.setMainNodes(self.mainnodes)
        self.refresh()

    def saveProject(self):
        fileName, _ = QFileDialog.getSaveFileName(
            self.mainDialog, self.qapp.tr("Save project"), ".\\",
            self.qapp.tr("Project file (*.tpr)"))
        outfile = open(fileName, "wb")
        pickle.dump(self.project, outfile)
        outfile.close()

    def draw_tree(self):
        target = self.mainnodes[0]
        children = target.children()
        samples_in_tree = []

        for sample in self.project.samples.get_sorted_by_id():
            if len(children) > 0:
                samples_in_tree = [node.obj for node in children]
            if sample not in samples_in_tree:
                target.addChild(Node(sample))

        self.project_tree.refresh()

    def openFile(self):
        path_to_file, _ = QFileDialog.getOpenFileName(
            self.mainDialog, self.qapp.tr("Load Image"),
            self.qapp.tr(u".\example_imgs"), self.qapp.tr("Images (*.jpg)"))
        # path_to_file, _ = QFileDialog.getOpenFileName(self.mainDialog, self.app.tr("Load Image"), self.app.tr("~/Desktop/"), self.app.tr("Images (*.jpg)"))

        # Определяем тип файла на просвет или на подсветку
        tools.processing(path_to_file, self.project, self.separator,
                         self.segmentation, self.counter, self.setProgress)
        self.refresh()

    def refresh(self):
        self.draw_tree()
        self.fill_table()
        self.updete_viewers()

    def fill_table(self):
        data = []
        sample = self.project.current_sample

        if not sample:
            data = [['', '', '']]
            self.mainDialog.tablemodel.setData(data)
            return

        for track in sample.tracks.get_sorted():
            data.append([str(track.id), str(track.count), str(track.area)])

        self.mainDialog.tablemodel.setData(data)
        self.mainDialog.table.resizeRowsToContents()
        self.mainDialog.table.resizeColumnsToContents()

        count = round(
            np.sum([track.count
                    for track in sample.tracks.get_sorted_by_id()]), 2)
        general_area = round(
            np.sum([track.area for track in sample.tracks.get_sorted_by_id()]),
            2)

        self.mainDialog.infolabel.setText('''
                        <p align="center">General tracks count<br>{tracks_count}</p>
                        <p align="center">General tracks area (%)<br>{general_area}</p>
                        '''.format(tracks_count=count,
                                   general_area=general_area))

    def draw_objects(self, viewer, sample):
        for track in sample.tracks.get_sorted():
            viewer.add_rect(track.left, track.rigth, track.top, track.bottom)
            viewer.add_Polygon(track.contour, track.left, track.top)
            text = 'Count: {tracks_count}\nArea (%): {general_area}'.format(
                tracks_count=track.count, general_area=track.area)

            viewer.add_Text(text, track.left, track.top)

    def updete_viewers(self):
        sample = self.project.current_sample

        if not sample:
            return

        self.mainDialog.ThroughArea.load_image(sample.through)
        self.mainDialog.BacklightArea.load_image(sample.backlight)
        self.mainDialog.PreparedArea.load_image(sample.prepared)

        self.draw_objects(self.mainDialog.ThroughArea, sample)
        self.draw_objects(self.mainDialog.BacklightArea, sample)
        self.draw_objects(self.mainDialog.PreparedArea, sample)

    def __connect_to_grbl__(self):
        '''Функция подключения к CNC сканера, которая передается в настройки станка'''
        status = self.grbl.connect()
        if not status: return
        self.cnc_indicator.setStatus(-1)
        self.grbl.reset_alarm()
        self.cnc_indicator.setStatus(status)
        return status

    def __check_ip__(self, ip):
        status = False
        test_grbl = GRBL(HOST=self.settings.grblip)
        test_grbl.setHost(ip)
        try:
            status = test_grbl.connect(check=False)
            test_grbl.connection.close()
        except OSError:
            pass
        return ip if status else None

    def __auto_seach__(self, property=None):
        '''Функция авто поиска IP станка
        property нужен, чтобы вернуть результат в inputField окна настроек
        '''
        if self.grbl.connection: self.grbl.connection.close()
        devices = [device for device in os.popen('arp -a')]
        ip_candidates = [
            re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", device)[0]
            for device in devices if
            len(re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b",
                           device)) != 0
        ]
        if self.settings.grblip in ip_candidates:
            ip_candidates.remove(self.settings.grblip)
            ip_candidates.insert(0, self.settings.grblip)

        pool = ThreadPool(4)
        results = pool.map(self.__check_ip__, ip_candidates)
        index = np.where(results != None)[0][0]
        if not results[index]:
            # print(self.qapp.tr('There is not  devices in current net'))
            return
        pool.close()
        pool.join()

        self.grbl.setHost(results[index])
        self.__connect_to_grbl__()

        if property:
            property.setText(
                results[index]
            )  # property нужен, чтобы вернуть результат в inputField

        self.settings.grblip = results[index]
        self.settings.write()
        print(self.qapp.tr('Connected to') + ' {ip}'.format(ip=results[index]))
        return True

    def showAbout(self):
        about = about_dialog(self)
        about.open()

    def showGrblDialog(self):
        dialog = grblDialog(self,
                            connection_func=self.__connect_to_grbl__,
                            auto_seach_func=self.__auto_seach__)
        dialog.execute(self.settings)
Example #9
0
from app import db, Settings

db.create_all()

default_settings = Settings(owner_id=None, feedback=1, constant_time_version=0, t_value=2500, trial_count=15)

db.session.add(default_settings)
db.session.commit()
Example #10
0
 def openSettingsWindow(self):
     if not hasattr(self, 'settingsWidget'):
         self.settingsWidget = Settings()
     if self.settingsWidget.isclosed:
         self.settingsWidget.show()
         self.settingsWidget.isclosed = False
Example #11
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)
Example #12
0
 def openSettingsWindow(self):
     if not hasattr(self, 'settingsWidget'):
         self.settingsWidget = Settings()
     if self.settingsWidget.isclosed:
         self.settingsWidget.show()
         self.settingsWidget.isclosed = False
Example #13
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)
Example #14
0
 def saveSetiings(self, settings: Settings):
     settings.grblip = self._ip_label.text
Example #15
0
    def setUp(self):
        app.config['TESTING'] = True
        app.config['BASE_URI'] = 'http://*****:*****@somewhere-org'
        settings.test_business_id = 'test.someone@somewhere-org'
        settings.submission_url = 'http://not-a-real-url'
        settings.test_submission_url = 'http://test-not-a-real-url'
        settings.verification_url = 'http://not-a-real-verification-url'
        settings.test_verification_url = 'http://test-not-a-real-verification-url'
        settings.smtp_host = 'somewhere-org'
        settings.smtp_port = 465
        settings.smtp_login = '******'
        settings.smtp_pass = '******'
        settings.notification_email = 'someone.who.cares@somewhere-org'
        settings.test_notification_email = 'test.someone.who.cares@somewhere-org'
        settings.contact_email = 'someone.who.cares@somewhere-org'
        settings.test_contact_email = 'test.someone.who.cares@somewhere-org'
        settings.organization_name = 'Somewhere'
        settings.organization_url = 'http://somewhere-org'
        settings.paypal_rate = 0.022
        settings.paypal_surcharge = 0.30

        db.session.add(settings)
        db.session.commit()