示例#1
0
    def _show_about():
        """
        Show the about text.

        Arguments:
        None

        Return:
        None
        """
        text = (
            "\n"
            "TranSPHIRE is supposed to help with the cryo-EM data collection\n"
            "Copyright (C) 2017 Markus Stabrin\n"
            "\n"
            "This program is free software: you can redistribute it and/or modify\n"
            "it under the terms of the GNU General Public License as published by\n"
            "the Free Software Foundation, either version 3 of the License, or\n"
            "(at your option) any later version.\n"
            "\n"
            "This program is distributed in the hope that it will be useful,\n"
            "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
            "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
            "GNU General Public License for more details.\n"
            "\n"
            "You should have received a copy of the GNU General Public License\n"
            "along with this program.  If not, see <http://www.gnu.org/licenses/>.\n"
        )
        tu.message(text)
示例#2
0
    def accept(self):
        """
        Modified accept event to check if the sudopassword is valid.

        Arguments:
        None

        Returns:
        None
        """
        self.password = self.textValue()

        child = pe.spawnu('sudo -S -k ls')
        child.sendline(self.password)
        try:
            idx = child.expect([pe.EOF, 'sudo: 1 incorrect password attempt', 'Sorry, try again'], timeout=10)
        except pe.exceptions.TIMEOUT:
            print('Wrong sudo password!')
            tu.message('Wrong sudo password!')
            return None
        else:
            if idx == 0:
                super().accept()
            else:
                print('Wrong sudo password!')
                tu.message('Wrong sudo password!')
                return None
示例#3
0
    def _specify_hdd(self):
        """
        Specify which HDD to unmount.

        Arguments:
        None

        Return:
        HDD text
        """
        text, result = QInputDialog().getText(
            self,
            'Specify hdd',
            'choose hdd to unmount,\n"all" will unmount all mounted hdd\'s',
            QLineEdit.Normal,
            'all'
            )
        if result:
            text = text.lower()
            if text.startswith('hdd_'):
                return text
            elif text.startswith('hdd '):
                return text
            elif text == 'all':
                return text
            else:
                tu.message('Input needs to be "all" or "hdd_{number}" or "hdd {number}')
                return None
        else:
            tu.message('Input needs to be "all" or "hdd_{number} or "hdd {number}"')
            return None
示例#4
0
    def mount(self):
        """
        Mount device preparation

        Arguments:
        None

        Return:
        None
        """
        # Mount external hdd
        if self.typ == 'Copy_hdd':
            self.mount_worker.sig_mount_hdd.emit(self.mount_folder)
        else:
            user, password, folder = self._check_user(
                login=bool(self.login == 'True')
                )
            if user:
                self.mount_worker.sig_mount.emit(
                    self.mount_folder,
                    user,
                    password,
                    folder,
                    self.ip_adress,
                    self.protocol,
                    self.domain,
                    self.version,
                    self.sec,
                    self.gid,
                    )
            else:
                print('Wrong identity')
                tu.message('Wrong identity, check command line for more information')
示例#5
0
    def get_settings(self):
        """
        Get the settings from the child widgets.

        Arguments:
        None

        Return:
        List of settings
        """
        settings_list = []
        error_occured = False
        for entry in self.content:
            widget = entry['widget']
            widget_2 = entry['widget_2']
            settings = copy.deepcopy(entry['settings'])
            dtype = settings['dtype']
            key = settings['name']
            if isinstance(widget, QComboBox):
                value = widget.currentText()
            elif isinstance(widget, QLineEdit):
                value = widget.text()
            else:
                message = '{0}: Type {1} not known!'.format(key, type(widget))
                print(message)
                tu.message(message)
                sys.exit()

            if isinstance(widget_2, QComboBox):
                settings['widget_2'] = widget_2.currentText()
                widget_2.setStyleSheet(tu.get_style(typ='pass'))
            else:
                assert widget_2 is None
                settings['widget_2'] = widget_2

            if value:
                if tu.check_instance(value=value, typ=dtype):
                    widget.setStyleSheet(tu.get_style(typ='pass'))
                else:
                    widget.setStyleSheet(tu.get_style(typ='error'))
                    message = '{0}: {1} needs to be {2}'.format(
                        key, value, dtype)
                    print(message)
                    tu.message(message)
                    error_occured = True
            else:
                pass

            if key == 'Typ' and not widget.isEnabled():
                value = 'Copy_hdd'
            elif key == 'Protocol' and not widget.isEnabled():
                value = 'hdd'
            else:
                pass
            settings_list.append({key: [value, settings]})

        if error_occured:
            return None
        else:
            return settings_list
示例#6
0
    def umount(self):
        """
        Umount device signal preparation

        Arguments:
        None

        Return:
        None
        """
        if self.typ == 'Copy_hdd':
            hdd_folder = '{0}/{1}'.format(
                self.mount_worker.mount_directory,
                self.mount_folder
                )
            if not os.path.exists(hdd_folder):
                self.mount_worker.sig_info.emit(
                    'First mount {0}'.format(self.mount_folder)
                    )
                return None
            else:
                pass

            folders = os.listdir(hdd_folder)
            hdd_name = self._specify_hdd()
            if hdd_name is None:
                return None
            else:
                hdd_name = hdd_name.replace(' ', '_').upper()

            if hdd_name == 'ALL':
                for entry in folders:
                    self.mount_worker.sig_umount.emit(
                        self.mount_folder,
                        entry,
                        self.thread_object
                        )
            elif hdd_name.startswith('HDD_'):
                if hdd_name in folders:
                    self.mount_worker.sig_umount.emit(
                        self.mount_folder,
                        hdd_name,
                        self.thread_object
                        )
                else:
                    tu.message('{0} is not mounted!'.format(hdd_name))
            else:
                print('Unmount hdd: Unreachable code')
                print(hdd_name, self.mount_folder, folders)

        else:
            self.mount_worker.sig_umount.emit(
                self.mount_folder,
                self.mount_folder,
                self.thread_object
                )
示例#7
0
    def _mount_info(text):
        """
        Information for the user

        Arguments:
        text - Text to show

        Returns:
        None
        """
        tu.message(text)
示例#8
0
    def _process_error(self, text):
        """
        Error in a process

        Arguments:
        text - Text to show

        Returns:
        None
        """
        tu.message(text)
        self.sig_refresh_quota.emit()
示例#9
0
    def _mount_error(self, text, device):
        """
        Mount was not successfull

        Arguments:
        text - Text to show
        device - Device name

        Returns:
        None
        """
        if device != 'None':
            self.content[device].sig_change_info_name.emit(
                'Not connected', 'red')
        tu.message(text)
示例#10
0
    def get_settings(self, quiet=False):
        """
        Get the settings as dict.

        Arguments:
        quiet - True, if prints should not be shown.

        Returns:
        None, if an error occured.
        Settings as dictionary.
        """
        settings = {}
        if isinstance(self.edit, QComboBox):
            value = self.edit.currentText()

        elif isinstance(self.edit, QLineEdit):
            value = self.edit.text()

        else:
            message = 'Unreachable code! Please contact the TranSPHIRE authors!'
            print(message)
            tu.message(message)
            return None

        if value:

            if tu.check_instance(value=value, typ=self.dtype):
                self.edit.setStyleSheet(tu.get_style(typ='pass'))

            else:
                self.edit.setStyleSheet(tu.get_style(typ='error'))
                message = '{0}: {1} needs to be {2}'.format(
                    self.label.text(), value, self.dtype)

                if not quiet:
                    print(message)
                    tu.message(message)

                else:
                    pass
                return None

        else:
            pass

        settings[self.name] = value

        return settings
示例#11
0
    def _mount_success(self, text, device, color):
        """
        Mount was successfull.

        Arguments:
        text - Text to show
        device - Device name
        color - Color of the text

        Returns:
        None
        """
        self.content[device].sig_change_info_name.emit(text, color)
        if device != 'scratch' and device != 'project':
            tu.message('{0} Mount/Unmount successfull!'.format(device))
        else:
            pass
示例#12
0
    def stop_dialog(self):
        """
        Check if the user really wants to stop the process.

        Arguments:
        None

        Return:
        None
        """
        result = self.continue_dialog(
            text1='Do you really want to stop?',
            text2='Do you really want to stop!\nType: YES!')
        if result:
            self.stop()
        else:
            tu.message('Input needs to be "YES!" to work')
示例#13
0
    def _modify_settings(self):
        """
        Open default settings dialog.
        Called when the Default settings button is clicked.

        Arguments:
        None

        Return:
        None
        """

        temp_save_file = 'temp_reset_save_1'
        content, apply = DefaultSettings.get_content_default(
            edit_settings=True,
            apply=True,
            settings_folder=self.parent.settings_folder)
        if not apply:
            tu.message('Restart GUI to apply saved changes')

        elif apply:
            content_gui = tu.get_content_gui(content=content)
            self.parent.enable(var=False, use_all=True)
            # result is True if No is chosen
            result = tu.question(
                head='Keep current values',
                text='Do you want to keep your current settings?\n' +
                'Otherwhise they will be overwritten by the default values.',
                parent=self)
            app = QApplication.instance()
            app.setStyleSheet(
                tu.look_and_feel(app=app, default=content['Font']))

            if not result:
                self.parent.save(temp_save_file)
                self.parent.reset_gui(content_gui=content_gui,
                                      content_pipeline=content['Pipeline'],
                                      load_file=temp_save_file)
            else:
                self.parent.reset_gui(content_gui=content_gui,
                                      content_pipeline=content['Pipeline'],
                                      load_file=None)

        else:
            pass
示例#14
0
    def closeEvent(self, event):
        """
        Quit threads before close and check if the process is still running

        Arguments:
        event - QCloseEvent.

        Return:
        None
        """
        if self.content['Button'].start_button.text() == 'Stop':
            event.ignore()
            tu.message('First stop the program before closing')
            return None
        elif not self.save_temp_settings():
            result = tu.question(
                head='Error saving file!',
                text='Wrong setting detected! Quit without saving?',
            )
            # Result is true if the answer is No
            if not result:
                pass
            else:
                event.ignore()
                return None
        else:
            pass

        self.thread_mount.quit()
        self.thread_mount.wait()
        self.thread_process.quit()
        self.thread_process.wait()
        self.thread_plot.quit()
        self.thread_plot.wait()
        for key in self.content['Mount'].content:
            thread = self.mount_thread_list[key]['thread']
            calculator = self.mount_thread_list[key]['object']
            calculator.kill_thread = True
            thread.quit()
            thread.wait()
        message = 'Bye Bye'
        print(message)
        super(MainWindow, self).closeEvent(event)
示例#15
0
    def postprocess_content(self, error_list):
        """
        Do postprocessing of creating GUI content, like connecting signals.

        Arguments:
        error_list - List of errors that occured.

        Return:
        True, if saving was succesful.
        """
        for entry in error_list:
            tu.message(entry)

        self.process_worker.sig_finished.connect(self._finished)
        self.process_worker.sig_plot_ctf.connect(
            self.plot_worker.calculate_array_ctf)
        self.process_worker.sig_plot_motion.connect(
            self.plot_worker.calculate_array_motion)
        self.plot_worker.sig_message.connect(lambda msg: tu.message(msg))

        self.mount_thread_list = {}
        for key in self.content['Mount'].content:
            thread = QThread(self)
            thread.start()
            mount_calculator = MountCalculator(name=key)
            mount_calculator.moveToThread(thread)
            self.mount_thread_list[key] = {
                'thread': thread,
                'object': mount_calculator
            }
            mount_calculator.sig_finished.connect(
                self.content['Status'].refresh_quota)
            mount_calculator.sig_finished.connect(self.abort_finished)
            self.mount_worker.sig_calculate_ssh_quota.connect(
                mount_calculator.calculate_ssh_quota)
            self.mount_worker.sig_calculate_df_quota.connect(
                mount_calculator.calculate_df_quota)
            self.mount_worker.sig_calculate_get_quota.connect(
                mount_calculator.calculate_get_quota)
        self.content['Mount'].set_threadlist(
            thread_list=self.mount_thread_list)
示例#16
0
    def send_to_user(self, user_id, text, name):
        """
        Send a message to all users.

        Arguments:
        user_id - User id of the receiving person
        text - Text of the message
        name - Name of the sender

        Returns:
        None
        """
        try:
            self.bot.sendMessage(
                user_id,
                '{0}\n{1}: {2}'.format(os.uname()[1], name, text)
                )
        except telepot.exception.BotWasBlockedError as err:
            tu.message('{0}\n{1}\t{2}'.format(
                os.uname()[1],
                name,
                err
                ))
示例#17
0
    def add_widget(self):
        """
        Add a FrameWidget widget to the dynamic layout.
        Called when the add button is clicked.

        Arguments:
        None

        Returns:
        None
        """
        first = self.first.text()
        last = self.last.text()
        name = '{0},{1}'.format(first, last)

        try:
            first = int(first)
            last = int(last)
        except ValueError:
            tu.message('Not castable, input needs to be integer value.')
            return None

        if first <= 0:
            tu.message('No values below 1.')
            return None

        elif first > last:
            tu.message('Last must be smaller or equals first.')
            return None

        elif name in set(self.content_frames):
            tu.message('Already got frame combination {0} {1}'.format(
                first, last))
            return None

        else:
            pass

        widget = FrameWidget(first=first,
                             last=last,
                             dose_weight=False,
                             default=False)
        widget.delete.connect(self._del_widget)
        self.layout.addWidget(widget)
        self.content.append(widget)
        self.content_frames.append(name)
示例#18
0
    def save(self, file_name=None, temp=False):
        """
        Save GUI status to file.

        Arguments:
        file_name - File name to save settings to.
        temp - File is a temporary save file.

        Return:
        True, if saving was succesful.
        """
        if file_name is None:
            file_name = QFileDialog.getSaveFileName(
                caption='Save settings',
                directory=self.path,
                options=QFileDialog.DontUseNativeDialog,
                filter="Text files (*.txt)")

            if QT_VERSION == 4:
                file_name = file_name
            elif QT_VERSION == 5:
                file_name = file_name[0]
            else:
                raise ImportError(
                    'QT version unknown! Please contact the transphire authors!'
                )

            if not file_name:
                return None
            else:
                pass
        else:
            pass

        if file_name.endswith('.txt'):
            pass
        else:
            file_name = '{0}.txt'.format(file_name)

        # Do not override settings
        if os.path.exists(file_name):
            old_filename = file_name
            for number in range(9999):
                file_name = '{0}_{1}'.format(old_filename, number)
                if os.path.exists(file_name):
                    continue
                else:
                    break
        else:
            pass

        error = False
        with open(file_name, 'w') as write:
            for key in self.content:
                if key == 'Mount':
                    continue
                else:
                    pass
                try:
                    settings = self.content[key].get_settings()
                except AttributeError:
                    continue
                if settings is not None:
                    write.write('###\t{0}\n'.format(key))
                    for entry in settings:
                        for key_entry in entry:
                            write.write('{0}\t{1}\n'.format(
                                key_entry, entry[key_entry]))
                else:
                    error = True
                    message = 'Setting of {0} not valid!'.format(key)
                    tu.message(message)
                    continue
            write.write('###\tEnd\n')
            write.write('The\tEnd\n')

        message_pass = '******'.format(file_name)
        message_error = 'Invalid setting detected! Saveing failed!'
        if error:
            os.remove(file_name)
            tu.message(message_error)
            print(message_error)
            return False
        else:
            if temp:
                pass
            else:
                tu.message(message_pass)
            print(message_pass)
            return True
示例#19
0
    def start(self):
        """
        Start TranSPHIRE processing.

        Arguments:
        None

        Return:
        None
        """
        self.enable(False)
        settings = {}
        # Load settings to pass them to the working threads
        error_list = []
        skip_list = ['Mount', 'Notification', 'Path', 'Frames']
        for key in self.content:
            try:
                settings_widget = self.content[key].get_settings()
            except AttributeError:
                continue
            else:
                settings[key] = {}

            if settings_widget is None:
                self.enable(True)
                return None
            elif key == 'Frames':
                settings_motion = {}
            else:
                pass

            if key == 'Frames':
                skip_name_list = []
            else:
                skip_name_list = tu.get_function_dict()[key]['allow_empty']

            for entry in settings_widget:
                if key not in skip_list:
                    for name in entry:
                        if not entry[name] and name not in skip_name_list:
                            error_list.append(
                                '{0}:{1} is not allowed to be emtpy!'.format(
                                    key, name))
                        else:
                            pass
                else:
                    pass

            for idx, entry in enumerate(settings_widget):
                if key == 'Frames':
                    settings_motion[idx] = entry
                else:
                    settings[key].update(entry)

            if key == 'Frames':
                settings['motion_frames'] = settings_motion
            else:
                pass

        if error_list:
            tu.message('\n'.join(error_list))
            self.enable(True)
            return None
        else:
            pass

        # Get mount information
        for key in settings['Mount']:
            device_name = key.replace(' ', '_')
            save_file = os.path.join(self.settings_folder, device_name)
            try:
                with open(save_file, 'r') as read:
                    lines = read.readlines()
            except FileNotFoundError:
                continue
            for line in lines:
                name = line.split('\t')[0]
                settings['user_{0}'.format(device_name)] = name
        settings['user_Later'] = None

        if not re.match(self.project_name_pattern,
                        settings['General']['Project name']):
            self.enable(True)
            tu.message(
                'Project name needs to match pattern:\n{0}\n For example: {1}'.
                format(self.project_name_pattern,
                       self.project_name_pattern_example))
            return None
        else:
            pass

        # Project folder names
        settings['project_folder'] = os.path.join(
            settings['General']['Project directory'],
            settings['General']['Project name'])
        settings['compress_folder'] = os.path.join(
            settings['General']['Project directory'],
            settings['General']['Project name'])
        settings['motion_folder'] = os.path.join(
            settings['General']['Project directory'],
            settings['General']['Project name'])
        settings['ctf_folder'] = os.path.join(
            settings['General']['Project directory'],
            settings['General']['Project name'])
        settings['scratch_folder'] = os.path.join(
            settings['General']['Scratch directory'],
            settings['General']['Project name'])
        settings['Copy_hdd_folder'] = self.mount_directory
        settings['Copy_backup_folder'] = self.mount_directory
        settings['Copy_work_folder'] = self.mount_directory
        settings['settings_folder'] = os.path.join(settings['project_folder'],
                                                   'settings')
        settings['queue_folder'] = os.path.join(settings['project_folder'],
                                                'queue')
        settings['error_folder'] = os.path.join(settings['project_folder'],
                                                'error')

        # Check for continue mode
        if os.path.exists(settings['project_folder']):
            result = self.continue_dialog(
                text1='Output project folder already exists!',
                text2='Do you really want to continue the old run?\nType: YES!'
            )
            if result:
                result_session = self.continue_dialog(
                    text1='Software metafiles',
                    text2='Software metafiles (Atlas, ...) might be already copied!\n' + \
                        'Do you want to copy them again?\nType: YES!'
                    )
                settings['Copy_software_meta'] = bool(result_session)
            else:
                settings['Copy_software_meta'] = True
        else:
            settings['Copy_software_meta'] = True
            result = True

        # Create project and settings folder
        for name in [
                'project_folder', 'settings_folder', 'scratch_folder',
                'queue_folder', 'error_folder'
        ]:
            try:
                tu.mkdir_p(settings[name])
            except FileNotFoundError:
                tu.message('Project name cannot be empty')
                self.enable(True)
                return None

        # Start or stop procedure
        if result:
            self.content['Button'].start_button.setText('Stop')
            self.plot_worker.settings = settings
            self.process_worker.sig_start.emit(settings)
            self.mount_worker.set_settings(settings=settings)
            self.save(
                file_name=os.path.join(settings['settings_folder'],
                                       settings['General']['Project name']))
            self.save_temp_settings()
        else:
            tu.message('Input needs to be "YES!" to work')
            self.enable(True)
示例#20
0
    def send_notification(self, text):
        """
        Send a notification to specified users.

        Arguments:
        text - Text to send

        Returns:
        None
        """

        text = '{0}:\n{1}'.format(os.uname()[1], text)
        chosen_users = self.get_settings()
        for entry in chosen_users:
            for key in entry:
                name, state = entry[key].split('\t')

                if self.enable_telegram:
                    telegram_name = name[2:]

                    if telegram_name in self.users_telegram and \
                            state == 'True' and \
                            name.startswith('T '):
                        user_id = self.users_telegram[telegram_name]
                        try:
                            self.bot.sendMessage(user_id, text)
                        except telepot.exception.BotWasBlockedError as err:
                            if user_id in self.block_list:
                                pass
                            else:
                                self.block_list.append(user_id)
                                tu.message('{0}\n{1}\t{2}'.format(
                                    os.uname()[1],
                                    name,
                                    err
                                    ))
                        except telepot.exception.TelegramError as err:
                            if user_id in self.block_list:
                                pass
                            else:
                                self.block_list.append(user_id)
                                tu.message('{0}\n{1}\t{2}'.format(
                                    os.uname()[1],
                                    name,
                                    err
                                    ))
                        else:
                            if user_id in self.block_list:
                                self.block_list.remove(user_id)
                            else:
                                pass

                    else:
                        pass

                else:
                    pass

                if self.enable_email:
                    email_name = name[2:]

                    if email_name in self.users_email and \
                            state == 'True' and \
                            name.startswith('@ '):
                        email = self.users_email[email_name]
                        msg = MIMEText(text)
                        msg['Subject'] = 'Transphire message {0}'.format(
                            os.uname()[1]
                            )
                        msg['From'] = self.sending_email
                        msg['To'] = email
                        try:
                            server = smtplib.SMTP(self.smtp_server, timeout=10)
                        except smtplib.SMTPServerDisconnected:
                            print('Could not send to:', name)
                            continue
                        try:
                            server.sendmail(self.sending_email, [email], msg.as_string())
                        except smtplib.SMTPServerDisconnected:
                            print('Could not send to:', name)
                            continue
                        try:
                            server.quit()
                        except smtplib.SMTPServerDisconnected:
                            print('Could not send to:', name)
                            continue
                    else:
                        pass

                else:
                    pass

        else:
            pass