Exemplo n.º 1
0
class BaseAnnotationItem(ResizableGraphicsItem):

    handler_cache = {}
    styles = ['font-family', 'font-size', 'text-bold', 'text-italic', 'text-underline', 'text-color', 'color-border', 'color-background']

    minSize = ANNOTATION_MINIMUM_QSIZE

    def __init__(self, position=None, *args, **kwargs):
        super(BaseAnnotationItem, self).__init__(*args, **kwargs)
        # Config for each annotation item, holding the settings (styles, etc)
        # update-control via the toolbar using add_handler linking
        self.config = ConfigManager()
        self.config.updated.connect(self.applyStyleConfig)

        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemIsSelectable)
        self.setFlag(QGraphicsItem.ItemIsFocusable)

        if position:
            self.setPos(position)

        self.setZValue(-1)

    def delete(self):
        self.prepareGeometryChange()
        self.scene().annotations.remove(self)
        self.scene().removeItem(self)
        self.removeHandlers()

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Backspace and e.modifiers() == Qt.ControlModifier:
            self.delete()
        else:
            return super(BaseAnnotationItem, self).keyPressEvent(e)

    def importStyleConfig(self, config):
        for k in self.styles:
            self.config.set(k, config.get(k))

    def addHandlers(self):
        m = self.scene().views()[0].m  # Hack; need to switch to importing this
        for k in self.styles:
            self.config.add_handler(k, m.styletoolbarwidgets[k])

    def removeHandlers(self):
        for k in self.styles:
            self.config.remove_handler(k)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSelectedChange:
            if not value:
                self.removeHandlers()

        elif change == QGraphicsItem.ItemSelectedHasChanged:
            if value:
                self.addHandlers()

        return super(BaseAnnotationItem, self).itemChange(change, value)
Exemplo n.º 2
0
class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()

        self.setWindowTitle('PyQtConfig Demo')
        self.config = ConfigManager()

        CHOICE_A = 1
        CHOICE_B = 2
        CHOICE_C = 3
        CHOICE_D = 4

        map_dict = {
            'Choice A': CHOICE_A,
            'Choice B': CHOICE_B,
            'Choice C': CHOICE_C,
            'Choice D': CHOICE_D,
        }

        self.config.set_defaults({
            'number': 13,
            'text': 'hello',
            'active': True,
            'combo': CHOICE_C,
        })

        gd = QGridLayout()

        sb = QSpinBox()
        gd.addWidget(sb, 0, 1)
        self.config.add_handler('number', sb)

        te = QLineEdit()
        gd.addWidget(te, 1, 1)
        self.config.add_handler('text', te)

        cb = QCheckBox()
        gd.addWidget(cb, 2, 1)
        self.config.add_handler('active', cb)

        cmb = QComboBox()
        cmb.addItems(map_dict.keys())
        gd.addWidget(cmb, 3, 1)
        self.config.add_handler('combo', cmb, mapper=map_dict)

        self.current_config_output = QTextEdit()
        gd.addWidget(self.current_config_output, 0, 3, 3, 1)

        self.config.updated.connect(self.show_config)

        self.show_config()

        self.window = QWidget()
        self.window.setLayout(gd)
        self.setCentralWidget(self.window)

    def show_config(self):
        self.current_config_output.setText(str(self.config.as_dict()))
Exemplo n.º 3
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.setWindowTitle('PyQtConfig Demo')
        self.config = ConfigManager()

        CHOICE_A = 1
        CHOICE_B = 2
        CHOICE_C = 3
        CHOICE_D = 4

        map_dict = {
            'Choice A': CHOICE_A,
            'Choice B': CHOICE_B,
            'Choice C': CHOICE_C,
            'Choice D': CHOICE_D,
        }

        self.config.set_defaults({
            'number': 13,
            'text': 'hello',
            'active': True,
            'combo': CHOICE_C,
        })

        gd = QGridLayout()

        sb = QSpinBox()
        gd.addWidget(sb, 0, 1)
        self.config.add_handler('number', sb)

        te = QLineEdit()
        gd.addWidget(te, 1, 1)
        self.config.add_handler('text', te)

        cb = QCheckBox()
        gd.addWidget(cb, 2, 1)
        self.config.add_handler('active', cb)

        cmb = QComboBox()
        cmb.addItems(map_dict.keys())
        gd.addWidget(cmb, 3, 1)
        self.config.add_handler('combo', cmb, mapper=map_dict)

        self.current_config_output = QTextEdit()
        gd.addWidget(self.current_config_output, 0, 3, 3, 1)

        self.config.updated.connect(self.show_config)

        self.show_config()

        self.window = QWidget()
        self.window.setLayout(gd)
        self.setCentralWidget(self.window)

    def show_config(self):
        self.current_config_output.setText(str(self.config.as_dict()))
Exemplo n.º 4
0
class LisaConfigWindow(QDialog):
# class LisaConfigWindow(QMainWindow):

    def __init__(self, config_in, ncols=2):
        super(LisaConfigWindow, self).__init__()

        self.setWindowTitle('Lisa Config')
        self.config = ConfigManager()
        self.ncols = ncols
# used with other module. If it is set, lisa config is deleted
        self.reset_config = False

        CHOICE_A = "{pairwise_alpha_per_mm2: 45, return_only_object_with_seeds: true}"
        # CHOICE_A = 23

        CHOICE_B = 2
        CHOICE_C = 3
        CHOICE_D = 4

        map_dict = {
            'Graph-Cut': CHOICE_A,
            'Choice B': CHOICE_B,
            'Choice C': CHOICE_C,
            'Choice D': CHOICE_D,
        }
        config_def = {
            'working_voxelsize_mm': 2.0,
            'save_filetype': 'pklz',
            # 'manualroi': True,
            'segparams': CHOICE_A,
        }
        
        config_def.update(config_in)
        
        self.config.set_defaults(config_def)

        gd = QGridLayout()
        gd_max_i = 0
        for key, value in config_in.iteritems():
            if type(value) is int:
                sb = QSpinBox()
                sb.setRange(-100000, 100000)
            elif type(value) is float:
                sb = QDoubleSpinBox()
            elif type(value) is str:
                sb = QLineEdit()
            elif type(value) is bool:
                sb = QCheckBox()
            else:
                logger.error("Unexpected type in config dictionary")

            row = gd_max_i / self.ncols
            col = (gd_max_i % self.ncols) * 2

            gd.addWidget(QLabel(key),row, col +1) 
            gd.addWidget(sb, row, col + 2)
            self.config.add_handler(key, sb)
            gd_max_i += 1




        # gd.addWidget(QLabel("save filetype"), 1, 1)
        # te = QLineEdit()
        # gd.addWidget(te, 1, 2)
        # self.config.add_handler('save_filetype', te)
        #
        # gd.addWidget(QLabel("segmentation parameters"), 2, 1)
        # te = QLineEdit()
        # gd.addWidget(te, 2, 2)
        # self.config.add_handler('segparams', te)

        # cb = QCheckBox()
        # gd.addWidget(cb, 2, 2)
        # self.config.add_handler('active', cb)

        # gd.addWidget(QLabel("segmentation parameters"), 3, 1)
        # cmb = QComboBox()
        # cmb.addItems(map_dict.keys())
        # gd.addWidget(cmb, 3, 2)
        # self.config.add_handler('segparams', cmb, mapper=map_dict)

        self.current_config_output = QTextEdit()
        # rid.setColumnMinimumWidth(3, logo.width()/2)
        text_col = (self.ncols * 2) + 3
        gd.setColumnMinimumWidth(text_col, 500)
        gd.addWidget(self.current_config_output, 1, text_col, (gd_max_i/2)-1, 1)

        btn_reset_config = QPushButton("Reset and quit", self)
        btn_reset_config.clicked.connect(self.btnResetConfig)
        gd.addWidget(btn_reset_config, 0, text_col)

        btn_save_config = QPushButton("Save and quit", self)
        btn_save_config.clicked.connect(self.btnSaveConfig)
        gd.addWidget(btn_save_config, (gd_max_i / 2), text_col)

        self.config.updated.connect(self.show_config)

        self.show_config()

        # my line
        self.setLayout(gd)

        # self.window = QWidget()
        # self.window.setLayout(gd)
        # self.setCentralWidget(self.window)
    def add_grid_line(self, key, value):
        pass

    def get_config_as_dict(self):
        dictionary = self.config.as_dict()
        for key, value in dictionary.iteritems():
            from PyQt4.QtCore import pyqtRemoveInputHook
            pyqtRemoveInputHook()
            # import ipdb; ipdb.set_trace() #  noqa BREAKPOINT
            if type(value) == PyQt4.QtCore.QString:
                value = str(value)
            dictionary[key] = value

        return dictionary

    def btnResetConfig(self, event=None):
        self.reset_config = True
        self.close()

    def btnSaveConfig(self, event=None):
        self.reset_config = False
        self.close()


    def show_config(self):
        text = str(self.get_config_as_dict())
        self.current_config_output.setText(text)
Exemplo n.º 5
0
class dialogPluginManagement(ui.GenericDialog):

    def populate_plugin_list(self):

        disabled_plugins = self.config.get('Plugins/Disabled')

        while self.plugins_lw.count() > 0:  # Empty list
            self.plugins_lw.takeItem(0)

        for id, plugin in plugin_metadata.items():
            item = QListWidgetItem()

            item.plugin_metadata = plugin
            item.plugin_shortname = id

            if 'image' in plugin:
                item.setData(Qt.DecorationRole, plugin['image'])

            item.setData(Qt.DisplayRole, "%s (v%s)" % (plugin['name'], plugin['version']))
            item.setData(Qt.UserRole, plugin['description'])
            item.setData(Qt.UserRole + 1, plugin['author'])
            if plugin['path'] not in disabled_plugins:
                item.setData(Qt.UserRole + 2, "Active")

            self.plugins_lw.addItem(item)

    def onActivate(self):
        items = self.plugins_lw.selectedItems()
        disabled_plugins = self.config.get('Plugins/Disabled')

        for i in items:
            plugin_path = plugin_metadata[i.plugin_shortname]['path']
            if plugin_path in disabled_plugins:
                disabled_plugins.remove(plugin_path)

        self.config.set('Plugins/Disabled', disabled_plugins)
        self.populate_plugin_list()

    def onDeactivate(self):
        items = self.plugins_lw.selectedItems()
        disabled_plugins = self.config.get('Plugins/Disabled')

        for i in items:
            plugin_path = plugin_metadata[i.plugin_shortname]['path']
            if plugin_path not in disabled_plugins:
                disabled_plugins.append(plugin_path)

        self.config.set('Plugins/Disabled', disabled_plugins)
        self.populate_plugin_list()

    def onRefresh(self):
        get_available_plugins(self.config.get('Plugins/Paths')[:], include_deactivated=True)
        self.populate_plugin_list()

    def __init__(self, parent, **kwargs):
        super(dialogPluginManagement, self).__init__(parent, **kwargs)

        self.setWindowTitle(tr("Manage Plugins"))

        self.config = ConfigManager()
        self.config.defaults = {
            'Plugins/Paths': settings.get('Plugins/Paths'),
            'Plugins/Disabled': settings.get('Plugins/Disabled'),
        }

        self.m = parent
        self.setFixedSize(self.sizeHint())

        self.plugins_lw = QListWidget()
        self.plugins_lw.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.plugins_lw.setItemDelegate(pluginListDelegate(self.plugins_lw))
        self.plugins_lw.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)

        page = QWidget()
        box = QGridLayout()
        paths = QHBoxLayout()

        self.pathlist = QLineEdit()
        self.config.add_handler('Plugins/Paths', self.pathlist, (lambda x: x.split(';'), lambda x: ';'.join(x)))

        paths.addWidget(QLabel('Search Paths:'))
        paths.addWidget(self.pathlist)

        box.addLayout(paths, 0, 0)
        box.addWidget(self.plugins_lw, 1, 0)

        buttons = QVBoxLayout()

        refresh_btn = QPushButton('Refresh')
        refresh_btn.clicked.connect(self.onRefresh)
        buttons.addWidget(refresh_btn)

        activate_btn = QPushButton('Activate')
        activate_btn.clicked.connect(self.onActivate)
        buttons.addWidget(activate_btn)

        deactivate_btn = QPushButton('Dectivate')
        deactivate_btn.clicked.connect(self.onDeactivate)
        buttons.addWidget(deactivate_btn)

        buttons.addStretch()

        box.addLayout(buttons, 1, 1)
        page.setLayout(box)

        self.layout.addWidget(page)

        # Stack it all up, with extra buttons
        self.dialogFinalise()

        # Refresh the list of available plugins
        self._init_timer = QTimer.singleShot(0, self.onRefresh)

    def sizeHint(self):
        return QSize(600, 300)
Exemplo n.º 6
0
class DictWidget(QtGui.QWidget):
    def __init__(self, config_in, ncols=2, captions=None, hide_keys=None,
                 horizontal=False, show_captions=True, accept_button=False,
                 config_manager=None, radiobuttons=None, dropdownboxes=None):
        """

        :param config_in:  dictionary
        :param ncols:
        :param captions:
        :param radiobuttons: {"name_of_radiobutton": [
                                 ["orig_caption_1", orig_caption_2],
                                 default_value]
                                 ]
                            }
        """
        super(DictWidget, self).__init__()
        if captions is None:
            captions = {}
        if hide_keys is None:
            hide_keys = []
        self.config_in = config_in
        self.ncols = ncols
        self.captions = captions
        self.accept_button = accept_button
        self.hide_keys = copy.copy(hide_keys)
        self.horizontal = horizontal
        self.show_captions = show_captions
        if radiobuttons is None:
            radiobuttons = {}
        self.radiobuttons = radiobuttons
        if dropdownboxes is None:
            dropdownboxes = {}
        self.dropdownboxes = dropdownboxes

        # hide also temp keys for lists and ndarrays
        # due to load default params
        self._get_tmp_composed_keys(config_in)
        self.hide_keys.extend(self._tmp_composed_keys_list)

        if config_manager is None:
            self.config = ConfigManager()
            self.config.set_defaults(config_in)
        else:
            self.config = config_manager
        self.mainLayout = QGridLayout(self)
        self.setLayout(self.mainLayout)
        self.widgets = {}
        self.grid_i = 0
        self.init_ui()

    def _get_tmp_composed_keys(self, cfg):
        """
        Get list of temporary keys for lists and ndarrays. This keys are used for reconstruction.

        vytvoří to seznam pomocných klíčů pro seznamy a ndarray
        :param cfg:
        :return:
        """
        self._tmp_composed_keys_dict = {}
        self._tmp_composed_keys_list = []
        toappend = {}
        for key, value in cfg.iteritems():
            if key in self.dropdownboxes.keys():
                continue
            if key in self.radiobuttons.keys():
                continue
            if type(value) in (list, np.ndarray):
                self._tmp_composed_keys_dict[key] = []
                array = np.asarray(value)
                key_array_i = 0
                for val in array.tolist():
                    # key_i = (key, key_array_i)
                    key_i = ComposedDictMetadata((key, key_array_i))
                    self._tmp_composed_keys_dict[key].append(key_i)
                    self._tmp_composed_keys_list.append(key_i)
                    key_array_i += 1
                    toappend[key_i] = val
        cfg.update(toappend)

    def _create_dropdownbox(self, key, value):
        # atomic_widget = QWidget()
        row, col = self.__calculate_new_grid_position()
        # layout = QBoxLayout(self.horizontal)
        atomic_widget = QComboBox()
        # atomic_widget.addItem("C")
        # atomic_widget.addItem("C++")
        values = self.dropdownboxes[key]
        # values = self.dropdownboxes[key][0]
        if value is not None and value in values:
            # vali = atomic_widget.findText(value)
            atomic_widget.findText(value)
        atomic_widget.addItems(values)
        # this does not work. I used findText()
        # atomic_widget.setCurrentIndex(vali)
        # layout.addWidget(cb)

        # atomic_widget.setLayout(layout)
        return atomic_widget

    def _create_radiobutton(self, key, value):
        atomic_widget = QWidget()
        layout = QBoxLayout(self.horizontal)
        for i, rbkey in enumerate(self.radiobuttons[key][0]):
            b1 = QRadioButton("Button1")
            if i == self.radiobuttons[key][1]:
                b1.setChecked(True)
            # b1.toggled.connect(lambda:self.btnstate(self.b1))
            layout.addWidget(b1)
        atomic_widget.setLayout(layout)
        return atomic_widget

    def init_ui(self):
        # self.widgets = {}
        # self.grid_i = 0
        grid = self.mainLayout

        for key, value in self.config_in.iteritems():

            if key in self.hide_keys:
                continue
            if key in self.captions.keys():
                caption = self.captions[key]
            else:
                caption = key

            atomic_widget = self.__get_widget_for_primitive_types(key, value)
            if atomic_widget is None:
                if type(value) in (list, np.ndarray):
                    array = np.asarray(value)
                    atomic_widget = self._create_sub_grid_from_ndarray(key, array)
                    row, col = self.__calculate_new_grid_position()
                    grid.addWidget(QLabel(caption), row, col + 1)
                    grid.addLayout(atomic_widget, row, col + 2)
                    continue
                else:
                    logger.error("Unexpected type in config dictionary")

                continue

            # import ipdb; ipdb.set_trace()
            row, col = self.__calculate_new_grid_position()
            grid.addWidget(QLabel(caption), row, col + 1)
            grid.addWidget(atomic_widget, row, col + 2)

        # gd.setColumnMinimumWidth(text_col, 500)

        if self.accept_button:
            btn_accept = QPushButton("Accept", self)
            btn_accept.clicked.connect(self.btn_accept)
            text_col = (self.ncols * 2) + 3
            grid.addWidget(btn_accept, (self.grid_i / 2), text_col)

        self.config.updated.connect(self.on_config_update)

    # def __add_line
    def __get_widget_for_primitive_types(self, key, value):

        """
        return right widget and connect the value with config_manager
        :param key:
        :param value:
        :return:
        """

        if key in self.dropdownboxes.keys():
            atomic_widget = self._create_dropdownbox(key,value)
            self.config.add_handler(key, atomic_widget)
        elif key in self.radiobuttons.keys():
            atomic_widget = self._create_radiobutton(key,value)
            self.config.add_handler(key, atomic_widget)
        elif type(value) is int:
            atomic_widget = QSpinBox()
            atomic_widget.setRange(-100000, 100000)
            self.config.add_handler(key, atomic_widget)
        elif type(value) is float:
            atomic_widget = QDoubleSpinBox()
            atomic_widget.setDecimals(6)
            atomic_widget.setMaximum(1000000000)
            self.config.add_handler(key, atomic_widget)
        elif type(value) is str:
            atomic_widget = QLineEdit()
            self.config.add_handler(key, atomic_widget)
        elif type(value) is bool:
            atomic_widget = QCheckBox()
            self.config.add_handler(key, atomic_widget)
        else:
            return None
        return atomic_widget

    def _create_sub_grid_from_ndarray(self, key, ndarray):
        hgrid = QGridLayout(self)
        hgrid_i = 0
        for val in ndarray.tolist():
            # key_i = key + str(hgrid_i)
            key_i = (key, hgrid_i)
            atomic_widget = self.__get_widget_for_primitive_types(key_i, val)

            hgrid.addWidget(atomic_widget, 0, hgrid_i)
            hgrid_i += 1

        return hgrid

    def __calculate_new_grid_position(self):
        row = self.grid_i / self.ncols
        col = (self.grid_i % self.ncols) * 2
        self.grid_i += 1
        if self.horizontal:
            return col, row
        return row, col

    def btn_accept(self):
        print ("btn_accept: " + str(self.config_as_dict()))

    def on_config_update(self):
        pass

    def config_as_dict(self):
        def _primitive_type(value):
            if type(value) == PyQt4.QtCore.QString:
                value = str(value)
            return value

        dictionary = self.config.as_dict()
        dictionary = copy.copy(dictionary)
        for key, value in dictionary.iteritems():
            from PyQt4.QtCore import pyqtRemoveInputHook
            #pyqtRemoveInputHook()
            # import ipdb; ipdb.set_trace() #  noqa BREAKPOINT
            # if type(key) == tuple:
            if type(key) == ComposedDictMetadata:

                dict_key, value_index = key
                dict_key = (dict_key)
                # if dict_key not in dictionary.keys():
                #     dictionary[dict_key] = {}

                dictionary[dict_key][value_index] = _primitive_type(value)

            else:
                dictionary[key] = _primitive_type(value)

        for key in dictionary.keys():
            # if type(key) == tuple:
            if type(key) == ComposedDictMetadata:
                dictionary.pop(key)

        # for key, value in dictionary.iteritems():
        #     if type(key) == tuple:
        #         dictionary

        return dictionary
Exemplo n.º 7
0
Arquivo: base.py Projeto: pchj/nmrbrew
class ToolBase(QObject):
    '''
    Base tool definition for inclusion in the UI. Define specific config settings;
    attach a panel widget for configuration.
    '''

    is_manual_runnable = True

    is_auto_runnable = True
    is_auto_rerunnable = True
    is_disableable = True

    progress = pyqtSignal(float)
    status = pyqtSignal(str)

    config_panel_size = 250
    view_widget = 'SpectraViewer'

    def __init__(self, parent, *args, **kwargs):
        super(ToolBase, self).__init__(parent, *args, **kwargs)

        self.config = ConfigManager()
        self.config.hooks.update(custom_pyqtconfig_hooks.items())
        self.config.set_defaults({
            'is_active': True,
            'auto_run_on_config_change': True
        })

        self.config.updated.connect(self.auto_run_on_config_change)

        self.buttonBar = QWidget()

        self.configPanels = QWidget()
        self.configLayout = QVBoxLayout()
        self.configLayout.setContentsMargins(0, 0, 0, 0)

        self.configPanels.setLayout(self.configLayout)

        self._previous_config_backup_ = {}

        self._worker_thread_ = None
        self._worker_thread_lock_ = False

        self.data = {
            'spc': None,
        }

        self.current_status = 'ready'
        self.current_progress = 0

        self.progress.connect(self.progress_callback)
        self.status.connect(self.status_callback)

    def addConfigPanel(self, panel):
        self.configLayout.addWidget(panel(self))

    def addButtonBar(self, buttons):
        '''
        Create a button bar

        Supplied with a list of QPushButton objects (already created using helper stubs; see below)

        :param buttons:
        :return:
        '''

        btnlayout = QHBoxLayout()
        btnlayout.addSpacerItem(
            QSpacerItem(250, 1, QSizePolicy.Maximum, QSizePolicy.Maximum))
        for btn in buttons:
            btnlayout.addWidget(btn)

        self.configLayout.addLayout(btnlayout)
        btnlayout.addSpacerItem(
            QSpacerItem(250, 1, QSizePolicy.Maximum, QSizePolicy.Maximum))

    def run_manual(self):
        pass

    def disable(self):
        self.status.emit('inactive')
        self.config.set('is_active', False)
        self.item.setFlags(Qt.NoItemFlags)

    def reset(self):
        self.config.set_many(self.config.defaults)

    def undo(self):
        self.config.set_many(self._config_backup_)

    def deftaultButtons(self):

        buttons = []

        if self.is_disableable:
            disable = QPushButton(
                QIcon(os.path.join(utils.scriptdir, 'icons', 'cross.png')),
                'Disable')
            disable.setToolTip('Disable this tool')
            disable.pressed.connect(self.disable)
            buttons.append(disable)

        reset = QPushButton(
            QIcon(
                os.path.join(utils.scriptdir, 'icons',
                             'arrow-turn-180-left.png')), 'Reset to defaults')
        reset.setToolTip('Reset to defaults')
        reset.pressed.connect(self.reset)
        buttons.append(reset)

        undo = QPushButton(
            QIcon(
                os.path.join(utils.scriptdir, 'icons',
                             'arrow-turn-180-left.png')), 'Undo')
        undo.setToolTip('Undo recent changes')
        undo.pressed.connect(self.undo)
        buttons.append(undo)

        if self.is_auto_runnable:
            auto = QPushButton(
                QIcon(os.path.join(utils.scriptdir, 'icons', 'lightning.png')),
                'Auto')
            auto.setToolTip('Auto-update spectra when settings change')
            auto.setCheckable(True)
            auto.pressed.connect(self.run_manual)
            self.config.add_handler('auto_run_on_config_change', auto)
            buttons.append(auto)

        if self.is_manual_runnable:
            apply = QPushButton(
                QIcon(os.path.join(utils.scriptdir, 'icons', 'play.png')),
                'Apply')
            apply.setToolTip('Apply current settings to spectra')
            apply.pressed.connect(self.run_manual)
            buttons.append(apply)

        return buttons

    def enable(self):
        if self.current_status == 'inactive':
            self.status.emit('ready')
            self.item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)

        self.config.set('is_active', True)

    def activate(self):
        self.parent().current_tool = self
        self.enable()

        self._config_backup_ = self.config.as_dict()

        self._refresh_plot_timer_ = QTimer.singleShot(0, self.plot)

        self.parent().viewStack.setCurrentWidget(self.parent().spectraViewer)

        self.parent().configstack.setCurrentWidget(self.configPanels)
        self.parent().configstack.setMaximumHeight(self.config_panel_size)

    def set_active(self, active):
        self.config.set('is_active', active)

    def get_previous_tool(self):
        # Get the previous ACTIVE tool in the tool table
        n = self.parent().tools.index(self)
        for tool in self.parent().tools[n - 1::-1]:
            if tool.current_status != 'inactive':
                return tool

        else:
            return None

    def get_previous_spc(self):
        t = self.get_previous_tool()
        if t:
            return t.data['spc']
        else:
            return None

    def plot(self, **kwargs):
        if 'spc' in self.data:
            self.parent().spectraViewer.plot(self.data['spc'], **kwargs)

    def get_plotitem(self):
        return self.parent().spectraViewer.spectraViewer.plotItem

    def auto_run_on_config_change(self):
        pass
        #if self.is_auto_runnable and self.config.get('is_active') and self.config.get('auto_run_on_config_change'):
        #    self.run_manual()

    def run(self, fn):
        '''
        Run the target function, passing in the current spectra, and config settings (as dict)
        :param fn:
        :return:
        '''
        if self._worker_thread_lock_:
            return False  # Can't run

        self.progress.emit(0)
        self.status.emit('active')

        spc = self.get_previous_spc()

        self._worker_thread_lock_ = True

        print(self.config.as_dict())
        self._worker_thread_ = Worker(fn=fn,
                                      **{
                                          'spc': deepcopy(spc),
                                          'config': self.config.as_dict(),
                                          'progress_callback':
                                          self.progress.emit,
                                      })

        self._worker_thread_.signals.finished.connect(self.finished)
        self._worker_thread_.signals.result.connect(self.result)
        self._worker_thread_.signals.error.connect(self.error)

        self.parent().threadpool.start(self._worker_thread_)

    def error(self, error):
        self.progress.emit(1.0)
        self.status.emit('error')
        logging.error(error)
        self._worker_thread_lock_ = False

    def result(self, result):
        self.progress.emit(1)
        self.status.emit('complete')

        # Apply post-processing
        if 'spc' in result:
            result['spc'] = self.post_process_spc(result['spc'])

        self.data = result
        self.plot()

    def finished(self):
        # Cleanup
        self._worker_thread_lock_ = False

    def progress_callback(self, progress):
        self.current_progress = progress
        self.item.setData(Qt.UserRole + 2, progress)

    def status_callback(self, status):
        self.current_status = status
        self.item.setData(Qt.UserRole + 3, status)

    def post_process_spc(self, spc):
        '''
        Apply post-processing to the spectra before loading into the data store, e.g. for outlier
        detection, stats etc.

        :param spc:
        :return:
        '''

        # Outliers

        def identify_outliers(data, m=2):
            return abs(data - np.mean(data, axis=0)) < (m *
                                                        np.std(data, axis=0))

        # Identify outliers on a point by point basis. Count up 'outliers' and score ratio of points that are
        # outliers for each specra > 5% (make this configurable) is an outlier.
        spc.outliers = np.sum(~identify_outliers(spc.data), axis=1) / float(
            spc.data.shape[1])
        return spc
Exemplo n.º 8
0
class dialogPluginManagement(ui.GenericDialog):
    def populate_plugin_list(self):

        disabled_plugins = self.config.get('Plugins/Disabled')

        while self.plugins_lw.count() > 0:  # Empty list
            self.plugins_lw.takeItem(0)

        for id, plugin in plugin_metadata.items():
            item = QListWidgetItem()

            item.plugin_metadata = plugin
            item.plugin_shortname = id

            if 'image' in plugin:
                item.setData(Qt.DecorationRole, plugin['image'])

            item.setData(Qt.DisplayRole,
                         "%s (v%s)" % (plugin['name'], plugin['version']))
            item.setData(Qt.UserRole, plugin['description'])
            item.setData(Qt.UserRole + 1, plugin['author'])
            if plugin['path'] not in disabled_plugins:
                item.setData(Qt.UserRole + 2, "Active")

            self.plugins_lw.addItem(item)

    def onActivate(self):
        items = self.plugins_lw.selectedItems()
        disabled_plugins = self.config.get('Plugins/Disabled')

        for i in items:
            plugin_path = plugin_metadata[i.plugin_shortname]['path']
            if plugin_path in disabled_plugins:
                disabled_plugins.remove(plugin_path)

        self.config.set('Plugins/Disabled', disabled_plugins)
        self.populate_plugin_list()

    def onDeactivate(self):
        items = self.plugins_lw.selectedItems()
        disabled_plugins = self.config.get('Plugins/Disabled')

        for i in items:
            plugin_path = plugin_metadata[i.plugin_shortname]['path']
            if plugin_path not in disabled_plugins:
                disabled_plugins.append(plugin_path)

        self.config.set('Plugins/Disabled', disabled_plugins)
        self.populate_plugin_list()

    def onRefresh(self):
        get_available_plugins(self.config.get('Plugins/Paths')[:],
                              include_deactivated=True)
        self.populate_plugin_list()

    def __init__(self, parent, **kwargs):
        super(dialogPluginManagement, self).__init__(parent, **kwargs)

        self.setWindowTitle(tr("Manage Plugins"))

        self.config = ConfigManager()
        self.config.defaults = {
            'Plugins/Paths': settings.get('Plugins/Paths'),
            'Plugins/Disabled': settings.get('Plugins/Disabled'),
        }

        self.m = parent
        self.setFixedSize(self.sizeHint())

        self.plugins_lw = QListWidget()
        self.plugins_lw.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.plugins_lw.setItemDelegate(pluginListDelegate(self.plugins_lw))
        self.plugins_lw.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)

        page = QWidget()
        box = QGridLayout()
        paths = QHBoxLayout()

        self.pathlist = QLineEdit()
        self.config.add_handler(
            'Plugins/Paths', self.pathlist,
            (lambda x: x.split(';'), lambda x: ';'.join(x)))

        paths.addWidget(QLabel('Search Paths:'))
        paths.addWidget(self.pathlist)

        box.addLayout(paths, 0, 0)
        box.addWidget(self.plugins_lw, 1, 0)

        buttons = QVBoxLayout()

        refresh_btn = QPushButton('Refresh')
        refresh_btn.clicked.connect(self.onRefresh)
        buttons.addWidget(refresh_btn)

        activate_btn = QPushButton('Activate')
        activate_btn.clicked.connect(self.onActivate)
        buttons.addWidget(activate_btn)

        deactivate_btn = QPushButton('Dectivate')
        deactivate_btn.clicked.connect(self.onDeactivate)
        buttons.addWidget(deactivate_btn)

        buttons.addStretch()

        box.addLayout(buttons, 1, 1)
        page.setLayout(box)

        self.layout.addWidget(page)

        # Stack it all up, with extra buttons
        self.dialogFinalise()

        # Refresh the list of available plugins
        self._init_timer = QTimer.singleShot(0, self.onRefresh)

    def sizeHint(self):
        return QSize(600, 300)
Exemplo n.º 9
0
Arquivo: ui.py Projeto: pchj/nmrbrew
class AnnotatePeaks(GenericDialog):
    def __init__(self, parent, config=None, *args, **kwargs):
        super(AnnotatePeaks, self).__init__(parent, *args, **kwargs)

        self.setWindowTitle('Annotate Peaks')

        if config:
            # Copy in starting state
            self.config = ConfigManager()
            self.config.hooks.update(custom_pyqtconfig_hooks.items())

            self.config.set_defaults(config)

        self.fwd_map_cache = {}

        # Correlation variables
        gb = QGroupBox('Peaks')
        vbox = QVBoxLayout()
        # Populate the list boxes
        self.lw_peaks = QListWidgetAddRemove()
        self.lw_peaks.setSelectionMode(QAbstractItemView.ExtendedSelection)
        vbox.addWidget(self.lw_peaks)

        vboxh = QHBoxLayout()

        self.add_label = QLineEdit()
        self.add_start = QDoubleSpinBox()
        self.add_start.setRange(-1, 12)
        self.add_start.setDecimals(3)
        self.add_start.setSuffix('ppm')
        self.add_start.setSingleStep(0.001)

        self.add_end = QDoubleSpinBox()
        self.add_end.setRange(-1, 12)
        self.add_end.setDecimals(3)
        self.add_end.setSuffix('ppm')
        self.add_end.setSingleStep(0.001)

        addc = QPushButton('Add')
        addc.clicked.connect(self.onPeakAdd)

        remc = QPushButton('Remove selected')
        remc.clicked.connect(self.onPeakAdd)

        loadc = QPushButton("Import from file")
        loadc.setIcon(
            QIcon(
                os.path.join(utils.scriptdir, 'icons',
                             'folder-open-document.png')))
        loadc.clicked.connect(self.onPeakImport)

        metabh = QPushButton("Auto match via MetaboHunter")
        metabh.setIcon(
            QIcon(os.path.join(utils.scriptdir, 'icons', 'metabohunter.png')))
        metabh.clicked.connect(self.onPeakImportMetabohunter)

        vboxh.addWidget(self.add_label)
        vboxh.addWidget(self.add_start)
        vboxh.addWidget(self.add_end)

        vboxh.addWidget(addc)

        vbox.addWidget(remc)
        vbox.addLayout(vboxh)
        vbox.addWidget(loadc)
        vbox.addWidget(metabh)

        gb.setLayout(vbox)

        self.layout.addWidget(gb)

        self.config.add_handler('annotation/peaks', self.lw_peaks,
                                (self.map_list_fwd, self.map_list_rev))

        self.dialogFinalise()

    def onPeakAdd(self):
        c = self.config.get(
            'annotation/peaks'
        )[:]  # Create new list to force refresh on reassign
        c.append((self.add_label.text(), float(self.add_start.value()),
                  float(self.add_end.value())))
        self.config.set('annotation/peaks', c)

    def onPeakRemove(self):
        i = self.lw_peaks.removeItemAt(self.lw_peaks.currentRow())
        # c = self.map_list_fwd(i.text())

    def onPeakImport(self):
        filename, _ = QFileDialog.getOpenFileName(
            self.parent(), 'Load peak annotations from file', '',
            "All compatible files (*.csv *.txt *.tsv);;Comma Separated Values (*.csv);;Plain Text Files (*.txt);;Tab Separated Values (*.tsv);;All files (*.*)"
        )
        if filename:
            c = self.config.get(
                'annotation/peaks'
            )[:]  # Create new list to force refresh on reassign

            with open(filename, 'rU') as f:
                reader = csv.reader(f, delimiter=b',', dialect='excel')
                for row in reader:
                    if row not in c:
                        c.append(row[0], float(row[1]), float(row[2]))

            self.config.set('annotation/peaks', c)

    def onPeakImportMetabohunter(self):
        c = self.config.get(
            'annotation/peaks'
        )[:]  # Create new list to force refresh on reassign
        t = self.parent().current_tool

        dlg = MetaboHunter(self)
        if dlg.exec_():

            if 'spc' in t.data:
                # We have a spectra; calcuate mean; reduce size if required
                spc = t.data['spc']
                n = spc.data.shape[1]
                ppm = spc.ppm
                spcd = np.mean(spc.data, axis=0)

                # Set a hard limit on the size of data we submit to be nice.
                if n > 3000:
                    # Calculate the division required to be under the limit
                    d = np.ceil(float(n) / 3000)
                    # Trim axis to multiple of divisor
                    trim = (n // d) * d
                    spcd = spcd[:trim]
                    ppm = ppm[:trim]
                    # Mean d shape
                    spcd = np.mean(spcd.reshape(-1, d), axis=1)
                    ppm = np.mean(ppm.reshape(-1, d), axis=1)

            # Submit with settings
            hmdbs = metabohunter.request(
                ppm,
                spcd,
                metabotype=dlg.config.get('Metabotype'),
                database=dlg.config.get('Database Source'),
                ph=dlg.config.get('Sample pH'),
                solvent=dlg.config.get('Solvent'),
                frequency=dlg.config.get('Frequency'),
                method=dlg.config.get('Method'),
                noise=dlg.config.get('Noise Threshold'),
                confidence=dlg.config.get('Confidence Threshold'),
                tolerance=dlg.config.get('Tolerance'))

            ha = np.array(hmdbs)
            unique_hmdbs = set(hmdbs)
            if None in unique_hmdbs:
                unique_hmdbs.remove(None)

            # Extract out regions
            for hmdb in unique_hmdbs:
                hb = np.diff(ha == hmdb)

                # These are needed to ensure markers are there for objects starting and ending on array edge
                if ha[0] == hmdb:
                    hb[0] == True

                if ha[-1] == hmdb:
                    hb[-1] == True

                idx = np.nonzero(hb)[0]
                idx = idx.reshape(-1, 2)

                if dlg.config.get(
                        'convert_hmdb_ids_to_names'
                ) and hmdb in METABOHUNTER_HMDB_NAME_MAP.keys():
                    label = METABOHUNTER_HMDB_NAME_MAP[hmdb]
                else:
                    label = hmdb

                # Now we have an array of all start, stop positions for this item
                for start, stop in idx:
                    c.append((label, ppm[start], ppm[stop]))

        self.config.set('annotation/peaks', c)

    def map_list_fwd(self, s):
        " Receive text name, return the indexes "
        return self.fwd_map_cache[s]

    def map_list_rev(self, x):
        " Receive the indexes, return the label"
        s = "%s\t%.2f\t%.2f" % tuple(x)
        self.fwd_map_cache[s] = x
        return s
Exemplo n.º 10
0
Arquivo: ui.py Projeto: pchj/nmrbrew
class MetaboHunter(GenericDialog):

    options = {
        'Metabotype': {
            'All': 'All',
            'Drug': 'Drug',
            'Food additive': 'Food additive',
            'Mammalian': 'Mammalian',
            'Microbial': 'Microbial',
            'Plant': 'Plant',
            'Synthetic/Industrial chemical': 'Synthetic/Industrial chemical',
        },
        'Database Source': {
            'Human Metabolome Database (HMDB)': 'HMDB',
            'Madison Metabolomics Consortium Database (MMCD)': 'MMCD',
        },
        'Sample pH': {
            '10.00 - 10.99': 'ph7',
            '7.00 - 9.99': 'ph7',
            '6.00 - 6.99': 'ph6',
            '5.00 - 5.99': 'ph5',
            '4.00 - 4.99': 'ph4',
            '3.00 - 3.99': 'ph3',
        },
        'Solvent': {
            'All': 'all',
            'Water': 'water',
            'CDCl3': 'cdcl3',
            'CD3OD': '5d3od',
            '5% DMSO': '5dmso',
        },
        'Frequency': {
            'All': 'all',
            '600 MHz': '600',
            '500 MHz': '500',
            '400 MHz': '400',
        },
        'Method': {
            'MH1: Highest number of matched peaks':
            'HighestNumber',
            'MH2: Highest number of matched peaks with shift tolerance':
            'HighestNumberNeighbourhood',
            'MH3: Greedy selection of metabolites with disjoint peaks':
            'Greedy2',
            'MH4: Highest number of matched peaks with intensities':
            'HighestNumberHeights',
            'MH5: Greedy selection of metabolites with disjoint peaks and heights':
            'Greedy2Heights',
        },
    }

    def __init__(self, *args, **kwargs):
        super(MetaboHunter, self).__init__(*args, **kwargs)

        self.setWindowTitle('MetaboHunter')
        # Copy in starting state
        self.config = ConfigManager()
        self.config.hooks.update(custom_pyqtconfig_hooks.items())

        self.config.set_defaults({
            'Metabotype': 'All',
            'Database Source': 'HMDB',
            'Sample pH': 'ph7',
            'Solvent': 'water',
            'Frequency': 'all',
            'Method': 'HighestNumberNeighbourhood',
            'Noise Threshold': 0.0001,
            'Confidence Threshold': 0.5,
            'Tolerance': 0.1,
            'convert_hmdb_ids_to_names': True,
        })

        self.lw_combos = {}

        for o in [
                'Metabotype', 'Database Source', 'Sample pH', 'Solvent',
                'Frequency', 'Method'
        ]:
            row = QVBoxLayout()
            cl = QLabel(o)
            cb = QComboBox()

            cb.addItems(list(self.options[o].keys()))
            row.addWidget(cl)
            row.addWidget(cb)
            self.config.add_handler(o, cb, self.options[o])

            self.layout.addLayout(row)

        row = QGridLayout()
        self.lw_spin = {}
        for n, o in enumerate(
            ['Noise Threshold', 'Confidence Threshold', 'Tolerance']):
            cl = QLabel(o)
            cb = QDoubleSpinBox()
            cb.setDecimals(4)
            cb.setRange(0, 1)
            cb.setSingleStep(0.01)
            cb.setValue(float(self.config.get(o)))
            row.addWidget(cl, 0, n)
            row.addWidget(cb, 1, n)

            self.config.add_handler(o, cb)

        self.layout.addLayout(row)

        row = QHBoxLayout()
        row.addWidget(QLabel("Convert HMDB IDs to chemical names?"))
        conv = QCheckBox()
        self.config.add_handler('convert_hmdb_ids_to_names', conv)
        row.addWidget(conv)

        self.layout.addLayout(row)

        self.dialogFinalise()
Exemplo n.º 11
0
class AutomatonDialog(GenericDialog):

    mode_options = {
        'Manual': MODE_MANUAL,
        'Watch files': MODE_WATCH_FILES,
        'Watch folder': MODE_WATCH_FOLDER,
        'Timer': MODE_TIMER,
    }

    def __init__(self, parent, **kwargs):
        super(AutomatonDialog, self).__init__(parent, **kwargs)
        self.setWindowTitle("Edit Automaton")

        self.config = ConfigManager()

        gb = QGroupBox('IPython notebook(s) (*.ipynb)')
        grid = QGridLayout()
        notebook_path_le = QLineEdit()
        self.config.add_handler('notebook_paths', notebook_path_le, mapper=(lambda x: x.split(";"), lambda x: ";".join(x)))
        grid.addWidget(notebook_path_le, 0, 0, 1, 2)

        notebook_path_btn = QToolButton()
        notebook_path_btn.setIcon(QIcon(os.path.join(utils.scriptdir, 'icons', 'document-attribute-i.png')))
        notebook_path_btn.clicked.connect(lambda: self.onNotebookBrowse(notebook_path_le))
        grid.addWidget(notebook_path_btn, 0, 2, 1, 1)
        gb.setLayout(grid)

        self.layout.addWidget(gb)

        gb = QGroupBox('Automaton mode')
        grid = QGridLayout()
        mode_cb = QComboBox()
        mode_cb.addItems(self.mode_options.keys())
        mode_cb.currentIndexChanged.connect(self.onChangeMode)
        self.config.add_handler('mode', mode_cb, mapper=self.mode_options)
        grid.addWidget(QLabel('Mode'), 0, 0)
        grid.addWidget(mode_cb, 0, 1)

        grid.addWidget(QLabel('Hold trigger'), 1, 0)
        fwatcher_hold_sb = QSpinBox()
        fwatcher_hold_sb.setRange(0, 60)
        fwatcher_hold_sb.setSuffix(' secs')
        self.config.add_handler('trigger_hold', fwatcher_hold_sb)
        grid.addWidget(fwatcher_hold_sb, 1, 1)
        gb.setLayout(grid)

        self.layout.addWidget(gb)

        self.watchfile_gb = QGroupBox('Watch files')
        grid = QGridLayout()

        watched_path_le = QLineEdit()
        grid.addWidget(watched_path_le, 0, 0, 1, 2)
        self.config.add_handler('watched_files', watched_path_le, mapper=(lambda x: x.split(";"), lambda x: ";".join(x)))

        watched_path_btn = QToolButton()
        watched_path_btn.setIcon(QIcon(os.path.join(utils.scriptdir, 'icons', 'document-copy.png')))
        watched_path_btn.setStatusTip('Add file(s)')
        watched_path_btn.clicked.connect(lambda: self.onFilesBrowse(watched_path_le))
        grid.addWidget(watched_path_btn, 0, 2, 1, 1)

        grid.addWidget(QLabel('Watch window'), 1, 0)
        watch_window_sb = QSpinBox()
        watch_window_sb.setRange(0, 60)
        watch_window_sb.setSuffix(' secs')
        self.config.add_handler('watch_window', watch_window_sb)
        grid.addWidget(watch_window_sb, 1, 1)

        self.watchfile_gb.setLayout(grid)
        self.layout.addWidget(self.watchfile_gb)

        self.watchfolder_gb = QGroupBox('Watch folder')
        grid = QGridLayout()

        watched_path_le = QLineEdit()
        grid.addWidget(watched_path_le, 0, 0, 1, 3)
        self.config.add_handler('watched_folder', watched_path_le)

        watched_path_btn = QToolButton()
        watched_path_btn.setIcon(QIcon(os.path.join(utils.scriptdir, 'icons', 'folder-horizontal-open.png')))
        watched_path_btn.setStatusTip('Add folder')
        watched_path_btn.clicked.connect(lambda: self.onFolderBrowse(watched_path_le))
        grid.addWidget(watched_path_btn, 0, 3, 1, 1)

        grid.addWidget(QLabel('Iterate files in folder'), 3, 0)
        loop_folder_sb = QCheckBox()
        self.config.add_handler('iterate_watched_folder', loop_folder_sb)
        grid.addWidget(loop_folder_sb, 3, 1)

        loop_wildcard_le = QLineEdit()
        self.config.add_handler('iterate_wildcard', loop_wildcard_le)
        grid.addWidget(loop_wildcard_le, 3, 2)

        self.watchfolder_gb.setLayout(grid)
        self.layout.addWidget(self.watchfolder_gb)

        self.timer_gb = QGroupBox('Timer')
        grid = QGridLayout()

        grid.addWidget(QLabel('Run every'), 0, 0)
        watch_timer_sb = QSpinBox()
        watch_timer_sb.setRange(0, 60)
        watch_timer_sb.setSuffix(' secs')
        self.config.add_handler('timer_seconds', watch_timer_sb)
        grid.addWidget(watch_timer_sb, 0, 1)

        self.timer_gb.setLayout(grid)
        self.layout.addWidget(self.timer_gb)

        self.manual_gb = QGroupBox('Manual')  # No show
        grid = QGridLayout()
        grid.addWidget(QLabel('No configuration'), 0, 0)
        self.manual_gb.setLayout(grid)
        self.layout.addWidget(self.manual_gb)

        gb = QGroupBox('Output')
        grid = QGridLayout()
        output_path_le = QLineEdit()
        self.config.add_handler('output_path', output_path_le)
        grid.addWidget(output_path_le, 0, 0, 1, 2)

        notebook_path_btn = QToolButton()
        notebook_path_btn.setIcon(QIcon(os.path.join(utils.scriptdir, 'icons', 'folder-horizontal-open.png')))
        notebook_path_btn.clicked.connect(lambda: self.onFolderBrowse(notebook_path_le))
        grid.addWidget(notebook_path_btn, 0, 2, 1, 1)

        export_cb = QComboBox()
        export_cb.addItems(IPyexporter_map.keys())
        self.config.add_handler('output_format', export_cb)
        grid.addWidget(QLabel('Notebook output format'), 1, 0)
        grid.addWidget(export_cb, 1, 1)

        gb.setLayout(grid)

        self.layout.addWidget(gb)

        self.layout.addStretch()
        self.finalise()

        self.onChangeMode(mode_cb.currentIndex())

    def onNotebookBrowse(self, t):
        global _w
        filenames, _ = QFileDialog.getOpenFileNames(_w, "Load IPython notebook(s)", '', "IPython Notebooks (*.ipynb);;All files (*.*)")
        if filenames:
            self.config.set('notebook_paths', filenames)

    def onFolderBrowse(self, t):
        global _w
        filename = QFileDialog.getExistingDirectory(_w, "Select folder to watch")
        if filename:
            self.config.set('watched_folder', filename)

    def onFilesBrowse(self, t):
        global _w
        filenames, _ = QFileDialog.getOpenFileNames(_w, "Select file(s) to watch")
        if filenames:
            self.config.set('watched_files', filenames)
        
    def onChangeMode(self, i):
        for m, gb in {MODE_MANUAL: self.manual_gb, MODE_WATCH_FILES: self.watchfile_gb, MODE_WATCH_FOLDER: self.watchfolder_gb, MODE_TIMER: self.timer_gb}.items():
            if m == list(self.mode_options.items())[i][1]:
                gb.show()
            else:
                gb.hide()
        
    def sizeHint(self):
        return QSize(400, 200)
Exemplo n.º 12
0
Arquivo: ui.py Projeto: mfitzp/nmrbrew
class AnnotatePeaks(GenericDialog):

    def __init__(self, parent, config=None, *args, **kwargs):
        super(AnnotatePeaks, self).__init__(parent, *args, **kwargs)

        self.setWindowTitle('Annotate Peaks')

        if config:
            # Copy in starting state
            self.config = ConfigManager()
            self.config.hooks.update(custom_pyqtconfig_hooks.items())

            self.config.set_defaults(config)

        self.fwd_map_cache = {}

        # Correlation variables
        gb = QGroupBox('Peaks')
        vbox = QVBoxLayout()
        # Populate the list boxes
        self.lw_peaks = QListWidgetAddRemove()
        self.lw_peaks.setSelectionMode(QAbstractItemView.ExtendedSelection)
        vbox.addWidget(self.lw_peaks)

        vboxh = QHBoxLayout()

        self.add_label = QLineEdit()
        self.add_start = QDoubleSpinBox()
        self.add_start.setRange(-1, 12)
        self.add_start.setDecimals(3)
        self.add_start.setSuffix('ppm')
        self.add_start.setSingleStep(0.001)

        self.add_end = QDoubleSpinBox()
        self.add_end.setRange(-1, 12)
        self.add_end.setDecimals(3)
        self.add_end.setSuffix('ppm')
        self.add_end.setSingleStep(0.001)

        addc = QPushButton('Add')
        addc.clicked.connect(self.onPeakAdd)

        remc = QPushButton('Remove selected')
        remc.clicked.connect(self.onPeakAdd)

        loadc = QPushButton("Import from file")
        loadc.setIcon(QIcon(os.path.join(utils.scriptdir, 'icons', 'folder-open-document.png')))
        loadc.clicked.connect(self.onPeakImport)


        metabh = QPushButton("Auto match via MetaboHunter")
        metabh.setIcon(QIcon(os.path.join(utils.scriptdir, 'icons', 'metabohunter.png')))
        metabh.clicked.connect(self.onPeakImportMetabohunter)

        vboxh.addWidget(self.add_label)
        vboxh.addWidget(self.add_start)
        vboxh.addWidget(self.add_end)

        vboxh.addWidget(addc)

        vbox.addWidget(remc)
        vbox.addLayout(vboxh)
        vbox.addWidget(loadc)
        vbox.addWidget(metabh)

        gb.setLayout(vbox)

        self.layout.addWidget(gb)

        self.config.add_handler('annotation/peaks', self.lw_peaks, (self.map_list_fwd, self.map_list_rev))

        self.dialogFinalise()

    def onPeakAdd(self):
        c = self.config.get('annotation/peaks')[:]  # Create new list to force refresh on reassign
        c.append( (self.add_label.text(), float(self.add_start.value()), float(self.add_end.value()) ) )
        self.config.set('annotation/peaks', c)

    def onPeakRemove(self):
        i = self.lw_peaks.removeItemAt(self.lw_peaks.currentRow())
        # c = self.map_list_fwd(i.text())

    def onPeakImport(self):
        filename, _ = QFileDialog.getOpenFileName(self.parent(), 'Load peak annotations from file', '', "All compatible files (*.csv *.txt *.tsv);;Comma Separated Values (*.csv);;Plain Text Files (*.txt);;Tab Separated Values (*.tsv);;All files (*.*)")
        if filename:
            c = self.config.get('annotation/peaks')[:]  # Create new list to force refresh on reassign

            with open(filename, 'rU') as f:
                reader = csv.reader(f, delimiter=b',', dialect='excel')
                for row in reader:
                    if row not in c:
                        c.append( row[0], float(row[1]), float(row[2]) )

            self.config.set('annotation/peaks', c)

    def onPeakImportMetabohunter(self):
        c = self.config.get('annotation/peaks')[:]  # Create new list to force refresh on reassign
        t = self.parent().current_tool

        dlg = MetaboHunter(self)
        if dlg.exec_():

            if 'spc' in t.data:
                # We have a spectra; calcuate mean; reduce size if required
                spc = t.data['spc']
                n = spc.data.shape[1]
                ppm = spc.ppm
                spcd = np.mean(spc.data, axis=0)

                # Set a hard limit on the size of data we submit to be nice.
                if n > 3000:
                    # Calculate the division required to be under the limit
                    d = np.ceil(float(n)/3000)
                    # Trim axis to multiple of divisor
                    trim = (n//d)*d
                    spcd = spcd[:trim]
                    ppm = ppm[:trim]
                    # Mean d shape
                    spcd = np.mean( spcd.reshape(-1,d), axis=1)
                    ppm = np.mean( ppm.reshape(-1,d), axis=1)

            # Submit with settings
            hmdbs = metabohunter.request(ppm, spcd,
                  metabotype=dlg.config.get('Metabotype'),
                  database=dlg.config.get('Database Source'),
                  ph=dlg.config.get('Sample pH'),
                  solvent=dlg.config.get('Solvent'),
                  frequency=dlg.config.get('Frequency'),
                  method=dlg.config.get('Method'),
                  noise=dlg.config.get('Noise Threshold'),
                  confidence=dlg.config.get('Confidence Threshold'),
                  tolerance=dlg.config.get('Tolerance')
            )

            ha = np.array(hmdbs)
            unique_hmdbs = set(hmdbs)
            if None in unique_hmdbs:
                unique_hmdbs.remove(None)

            # Extract out regions
            for hmdb in unique_hmdbs:
                hb = np.diff(ha == hmdb)

                # These are needed to ensure markers are there for objects starting and ending on array edge
                if ha[0] == hmdb:
                    hb[0] == True

                if ha[-1] == hmdb:
                    hb[-1] == True

                idx = np.nonzero(hb)[0]
                idx = idx.reshape(-1,2)

                if dlg.config.get('convert_hmdb_ids_to_names') and hmdb in METABOHUNTER_HMDB_NAME_MAP.keys():
                    label = METABOHUNTER_HMDB_NAME_MAP[hmdb]
                else:
                    label = hmdb

                # Now we have an array of all start, stop positions for this item
                for start, stop in idx:
                    c.append( (label, ppm[start], ppm[stop]) )


        self.config.set('annotation/peaks', c)

    def map_list_fwd(self, s):
        " Receive text name, return the indexes "
        return self.fwd_map_cache[s]

    def map_list_rev(self, x):
        " Receive the indexes, return the label"
        s = "%s\t%.2f\t%.2f" % tuple(x)
        self.fwd_map_cache[s] = x
        return s
Exemplo n.º 13
0
Arquivo: ui.py Projeto: mfitzp/nmrbrew
class AnnotateClasses(GenericDialog):

    def __init__(self, parent, config=None, *args, **kwargs):
        super(AnnotateClasses, self).__init__(parent, *args, **kwargs)

        self.setWindowTitle('Annotate Classes')

        if config:
            # Copy in starting state
            self.config = ConfigManager()
            self.config.hooks.update(custom_pyqtconfig_hooks.items())

            self.config.set_defaults(config)

        self.fwd_map_cache = {}

        # Correlation variables
        gb = QGroupBox('Sample classes')
        vbox = QVBoxLayout()
        # Populate the list boxes
        self.lw_classes = QListWidgetAddRemove()
        self.lw_classes.setSelectionMode(QAbstractItemView.ExtendedSelection)
        vbox.addWidget(self.lw_classes)

        vboxh = QHBoxLayout()

        self.add_label = QLineEdit()
        self.add_class = QLineEdit()

        addc = QPushButton('Add')
        addc.clicked.connect(self.onClassAdd)

        remc = QPushButton('Remove selected')
        remc.clicked.connect(self.onClassAdd)

        loadc = QPushButton('Import from file')
        loadc.setIcon(QIcon(os.path.join(utils.scriptdir, 'icons', 'folder-open-document.png')))
        loadc.clicked.connect(self.onClassImport)

        vboxh.addWidget(self.add_label)
        vboxh.addWidget(self.add_class)
        vboxh.addWidget(addc)

        vbox.addWidget(remc)
        vbox.addLayout(vboxh)
        vboxh.addWidget(loadc)

        gb.setLayout(vbox)

        self.layout.addWidget(gb)

        self.config.add_handler('annotation/sample_classes', self.lw_classes, (self.map_list_fwd, self.map_list_rev))

        self.dialogFinalise()

    def onClassAdd(self):
        c = self.config.get('annotation/sample_classes')[:]  # Create new list to force refresh on reassign
        c.append( (self.add_label.text(), self.add_class.text()) )
        self.config.set('annotation/sample_classes', c)

    def onClassRemove(self):
        i = self.lw_classes.removeItemAt(self.lw_classes.currentRow())
        # c = self.map_list_fwd(i.text())

    def onClassImport(self):
        filename, _ = QFileDialog.getOpenFileName(self.parent(), 'Load classifications from file', '', "All compatible files (*.csv *.txt *.tsv);;Comma Separated Values (*.csv);;Plain Text Files (*.txt);;Tab Separated Values (*.tsv);;All files (*.*)")
        if filename:
            c = self.config.get('annotation/sample_classes')[:]  # Create new list to force refresh on reassign

            with open(filename, 'rU') as f:
                reader = csv.reader(f, delimiter=b',', dialect='excel')
                for row in reader:
                    if row not in c:
                        c.append(row[:2])

            self.config.set('annotation/sample_classes', c)

    def map_list_fwd(self, s):
        " Receive text name, return the indexes "
        return self.fwd_map_cache[s]

    def map_list_rev(self, x):
        " Receive the indexes, return the label"
        s = "%s\t%s" % tuple(x)
        self.fwd_map_cache[s] = x
        return s
Exemplo n.º 14
0
Arquivo: ui.py Projeto: mfitzp/nmrbrew
class MetaboHunter(GenericDialog):

    options = {
    'Metabotype': {
        'All': 'All',
        'Drug': 'Drug',
        'Food additive': 'Food additive',
        'Mammalian': 'Mammalian',
        'Microbial': 'Microbial',
        'Plant': 'Plant',
        'Synthetic/Industrial chemical': 'Synthetic/Industrial chemical',
        },
    'Database Source': {
        'Human Metabolome Database (HMDB)': 'HMDB',
        'Madison Metabolomics Consortium Database (MMCD)': 'MMCD',
        },
    'Sample pH': {
        '10.00 - 10.99': 'ph7',
        '7.00 - 9.99': 'ph7',
        '6.00 - 6.99': 'ph6',
        '5.00 - 5.99': 'ph5',
        '4.00 - 4.99': 'ph4',
        '3.00 - 3.99': 'ph3',
    },
    'Solvent': {
        'All': 'all',
        'Water': 'water',
        'CDCl3': 'cdcl3',
        'CD3OD': '5d3od',
        '5% DMSO': '5dmso',
    },
    'Frequency': {
        'All': 'all',
        '600 MHz': '600',
        '500 MHz': '500',
        '400 MHz': '400',
    },
    'Method': {
        'MH1: Highest number of matched peaks': 'HighestNumber',
        'MH2: Highest number of matched peaks with shift tolerance': 'HighestNumberNeighbourhood',
        'MH3: Greedy selection of metabolites with disjoint peaks': 'Greedy2',
        'MH4: Highest number of matched peaks with intensities': 'HighestNumberHeights',
        'MH5: Greedy selection of metabolites with disjoint peaks and heights': 'Greedy2Heights',
    },
    }

    def __init__(self, *args, **kwargs):
        super(MetaboHunter, self).__init__(*args, **kwargs)

        self.setWindowTitle('MetaboHunter')
        # Copy in starting state
        self.config = ConfigManager()
        self.config.hooks.update(custom_pyqtconfig_hooks.items())

        self.config.set_defaults({
            'Metabotype': 'All',
            'Database Source': 'HMDB',
            'Sample pH': 'ph7',
            'Solvent': 'water',
            'Frequency': 'all',
            'Method': 'HighestNumberNeighbourhood',
            'Noise Threshold': 0.0001,
            'Confidence Threshold': 0.5,
            'Tolerance': 0.1,
            'convert_hmdb_ids_to_names': True,
        })

        self.lw_combos = {}

        for o in ['Metabotype', 'Database Source', 'Sample pH', 'Solvent', 'Frequency', 'Method']:
            row = QVBoxLayout()
            cl = QLabel(o)
            cb = QComboBox()

            cb.addItems(list(self.options[o].keys()))
            row.addWidget(cl)
            row.addWidget(cb)
            self.config.add_handler(o, cb, self.options[o])

            self.layout.addLayout(row)

        row = QGridLayout()
        self.lw_spin = {}
        for n, o in enumerate(['Noise Threshold', 'Confidence Threshold', 'Tolerance']):
            cl = QLabel(o)
            cb = QDoubleSpinBox()
            cb.setDecimals(4)
            cb.setRange(0, 1)
            cb.setSingleStep(0.01)
            cb.setValue(float(self.config.get(o)))
            row.addWidget(cl, 0, n)
            row.addWidget(cb, 1, n)

            self.config.add_handler(o, cb)

        self.layout.addLayout(row)

        row = QHBoxLayout()
        row.addWidget(QLabel("Convert HMDB IDs to chemical names?"))
        conv = QCheckBox()
        self.config.add_handler('convert_hmdb_ids_to_names', conv)
        row.addWidget(conv)

        self.layout.addLayout(row)

        self.dialogFinalise()
Exemplo n.º 15
0
class BaseAnnotationItem(ResizableGraphicsItem):

    handler_cache = {}
    styles = [
        'font-family', 'font-size', 'text-bold', 'text-italic',
        'text-underline', 'text-color', 'color-border', 'color-background'
    ]

    minSize = ANNOTATION_MINIMUM_QSIZE

    def __init__(self, position=None, *args, **kwargs):
        super(BaseAnnotationItem, self).__init__(*args, **kwargs)
        # Config for each annotation item, holding the settings (styles, etc)
        # update-control via the toolbar using add_handler linking
        self.config = ConfigManager()
        self.config.updated.connect(self.applyStyleConfig)

        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemIsSelectable)
        self.setFlag(QGraphicsItem.ItemIsFocusable)

        if position:
            self.setPos(position)

        self.setZValue(-1)

    def delete(self):
        self.prepareGeometryChange()
        self.scene().annotations.remove(self)
        self.scene().removeItem(self)
        self.removeHandlers()

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Backspace and e.modifiers() == Qt.ControlModifier:
            self.delete()
        else:
            return super(BaseAnnotationItem, self).keyPressEvent(e)

    def importStyleConfig(self, config):
        for k in self.styles:
            self.config.set(k, config.get(k))

    def addHandlers(self):
        m = self.scene().views()[0].m  # Hack; need to switch to importing this
        for k in self.styles:
            self.config.add_handler(k, m.styletoolbarwidgets[k])

    def removeHandlers(self):
        for k in self.styles:
            self.config.remove_handler(k)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSelectedChange:
            if not value:
                self.removeHandlers()

        elif change == QGraphicsItem.ItemSelectedHasChanged:
            if value:
                self.addHandlers()

        return super(BaseAnnotationItem, self).itemChange(change, value)
Exemplo n.º 16
0
class SerialDialog(QDialog):

    def __init__(self, settings, parent=None):
        super().__init__(parent)
        self.settings = settings
        self.serialports = []

        # port
        self.portLabel = QLabel(self.tr("COM Port:"))
        self.portComboBox = QComboBox()
        self.portLabel.setBuddy(self.portComboBox)
        self.refresh_comports(self.portComboBox)

        # baudrate
        self.baudrateLabel = QLabel(self.tr("Baudrate:"))
        self.baudrateComboBox = QComboBox()
        self.baudrateLabel.setBuddy(self.baudrateComboBox)
        for br in BAUDRATES:
            self.baudrateComboBox.addItem(str(br), br)

        # buttons
        self.dlgbuttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal)
        self.dlgbuttons.rejected.connect(self.reject)
        self.dlgbuttons.accepted.connect(self.accept)

        # layout
        layout = QGridLayout()
        layout.addWidget(self.portLabel, 0, 0)
        layout.addWidget(self.portComboBox, 0, 1)
        layout.addWidget(self.baudrateLabel, 1, 0)
        layout.addWidget(self.baudrateComboBox, 1, 1)
        layout.addWidget(self.dlgbuttons, 2, 0, 1, 2)
        self.setLayout(layout)
        self.setWindowTitle(self.tr("Serial Settings"))

        # settings
        defaults = {
            PORT_SETTING: "",
            BAUDRATE_SETTING: "115200"
        }
        self.tmp_settings = ConfigManager()
        self.tmp_settings.set_defaults(defaults)
        self.tmp_settings.set_many(
            {key: self.settings.get(key) for key in defaults.keys()}
        )
        self.tmp_settings.add_handler(PORT_SETTING, self.portComboBox)
        self.tmp_settings.add_handler(BAUDRATE_SETTING, self.baudrateComboBox)

    def accept(self):
        d = self.tmp_settings.as_dict()
        self.settings.set_many(d)
        super().accept()

    def refresh_comports(self, combobox):
        self.serialports = serial_ports()
        for port in self.serialports:
            combobox.addItem(port)

    @property
    def port(self):
        return self.portComboBox.currentText()

    @port.setter
    def port(self, value):
        if value in self.serialports:
            self.portComboBox.setCurrentIndex(
                self.portComboBox.findText(value))
        else:
            raise ValueError("serial port '%s' not available" % value)

    @property
    def baudrate(self):
        return self.baudrateComboBox.currentData()
Exemplo n.º 17
0
class AutomatonDialog(GenericDialog):

    mode_options = {
        'Manual': MODE_MANUAL,
        'Watch files': MODE_WATCH_FILES,
        'Watch folder': MODE_WATCH_FOLDER,
        'Timer': MODE_TIMER,
    }

    def __init__(self, parent, **kwargs):
        super(AutomatonDialog, self).__init__(parent, **kwargs)
        self.setWindowTitle("Edit Automaton")

        self.config = ConfigManager()

        gb = QGroupBox('IPython notebook(s) (*.ipynb)')
        grid = QGridLayout()
        notebook_path_le = QLineEdit()
        self.config.add_handler('notebook_paths',
                                notebook_path_le,
                                mapper=(lambda x: x.split(";"),
                                        lambda x: ";".join(x)))
        grid.addWidget(notebook_path_le, 0, 0, 1, 2)

        notebook_path_btn = QToolButton()
        notebook_path_btn.setIcon(
            QIcon(
                os.path.join(utils.scriptdir, 'icons',
                             'document-attribute-i.png')))
        notebook_path_btn.clicked.connect(
            lambda: self.onNotebookBrowse(notebook_path_le))
        grid.addWidget(notebook_path_btn, 0, 2, 1, 1)
        gb.setLayout(grid)

        self.layout.addWidget(gb)

        gb = QGroupBox('Automaton mode')
        grid = QGridLayout()
        mode_cb = QComboBox()
        mode_cb.addItems(self.mode_options.keys())
        mode_cb.currentIndexChanged.connect(self.onChangeMode)
        self.config.add_handler('mode', mode_cb, mapper=self.mode_options)
        grid.addWidget(QLabel('Mode'), 0, 0)
        grid.addWidget(mode_cb, 0, 1)

        grid.addWidget(QLabel('Hold trigger'), 1, 0)
        fwatcher_hold_sb = QSpinBox()
        fwatcher_hold_sb.setRange(0, 60)
        fwatcher_hold_sb.setSuffix(' secs')
        self.config.add_handler('trigger_hold', fwatcher_hold_sb)
        grid.addWidget(fwatcher_hold_sb, 1, 1)
        gb.setLayout(grid)

        self.layout.addWidget(gb)

        self.watchfile_gb = QGroupBox('Watch files')
        grid = QGridLayout()

        watched_path_le = QLineEdit()
        grid.addWidget(watched_path_le, 0, 0, 1, 2)
        self.config.add_handler('watched_files',
                                watched_path_le,
                                mapper=(lambda x: x.split(";"),
                                        lambda x: ";".join(x)))

        watched_path_btn = QToolButton()
        watched_path_btn.setIcon(
            QIcon(os.path.join(utils.scriptdir, 'icons', 'document-copy.png')))
        watched_path_btn.setStatusTip('Add file(s)')
        watched_path_btn.clicked.connect(
            lambda: self.onFilesBrowse(watched_path_le))
        grid.addWidget(watched_path_btn, 0, 2, 1, 1)

        grid.addWidget(QLabel('Watch window'), 1, 0)
        watch_window_sb = QSpinBox()
        watch_window_sb.setRange(0, 60)
        watch_window_sb.setSuffix(' secs')
        self.config.add_handler('watch_window', watch_window_sb)
        grid.addWidget(watch_window_sb, 1, 1)

        self.watchfile_gb.setLayout(grid)
        self.layout.addWidget(self.watchfile_gb)

        self.watchfolder_gb = QGroupBox('Watch folder')
        grid = QGridLayout()

        watched_path_le = QLineEdit()
        grid.addWidget(watched_path_le, 0, 0, 1, 3)
        self.config.add_handler('watched_folder', watched_path_le)

        watched_path_btn = QToolButton()
        watched_path_btn.setIcon(
            QIcon(
                os.path.join(utils.scriptdir, 'icons',
                             'folder-horizontal-open.png')))
        watched_path_btn.setStatusTip('Add folder')
        watched_path_btn.clicked.connect(
            lambda: self.onFolderBrowse(watched_path_le))
        grid.addWidget(watched_path_btn, 0, 3, 1, 1)

        grid.addWidget(QLabel('Iterate files in folder'), 3, 0)
        loop_folder_sb = QCheckBox()
        self.config.add_handler('iterate_watched_folder', loop_folder_sb)
        grid.addWidget(loop_folder_sb, 3, 1)

        loop_wildcard_le = QLineEdit()
        self.config.add_handler('iterate_wildcard', loop_wildcard_le)
        grid.addWidget(loop_wildcard_le, 3, 2)

        self.watchfolder_gb.setLayout(grid)
        self.layout.addWidget(self.watchfolder_gb)

        self.timer_gb = QGroupBox('Timer')
        grid = QGridLayout()

        grid.addWidget(QLabel('Run every'), 0, 0)
        watch_timer_sb = QSpinBox()
        watch_timer_sb.setRange(0, 60)
        watch_timer_sb.setSuffix(' secs')
        self.config.add_handler('timer_seconds', watch_timer_sb)
        grid.addWidget(watch_timer_sb, 0, 1)

        self.timer_gb.setLayout(grid)
        self.layout.addWidget(self.timer_gb)

        self.manual_gb = QGroupBox('Manual')  # No show
        grid = QGridLayout()
        grid.addWidget(QLabel('No configuration'), 0, 0)
        self.manual_gb.setLayout(grid)
        self.layout.addWidget(self.manual_gb)

        gb = QGroupBox('Output')
        grid = QGridLayout()
        output_path_le = QLineEdit()
        self.config.add_handler('output_path', output_path_le)
        grid.addWidget(output_path_le, 0, 0, 1, 2)

        notebook_path_btn = QToolButton()
        notebook_path_btn.setIcon(
            QIcon(
                os.path.join(utils.scriptdir, 'icons',
                             'folder-horizontal-open.png')))
        notebook_path_btn.clicked.connect(
            lambda: self.onFolderBrowse(notebook_path_le))
        grid.addWidget(notebook_path_btn, 0, 2, 1, 1)

        export_cb = QComboBox()
        export_cb.addItems(IPyexporter_map.keys())
        self.config.add_handler('output_format', export_cb)
        grid.addWidget(QLabel('Notebook output format'), 1, 0)
        grid.addWidget(export_cb, 1, 1)

        gb.setLayout(grid)

        self.layout.addWidget(gb)

        self.layout.addStretch()
        self.finalise()

        self.onChangeMode(mode_cb.currentIndex())

    def onNotebookBrowse(self, t):
        global _w
        filenames, _ = QFileDialog.getOpenFileNames(
            _w, "Load IPython notebook(s)", '',
            "IPython Notebooks (*.ipynb);;All files (*.*)")
        if filenames:
            self.config.set('notebook_paths', filenames)

    def onFolderBrowse(self, t):
        global _w
        filename = QFileDialog.getExistingDirectory(_w,
                                                    "Select folder to watch")
        if filename:
            self.config.set('watched_folder', filename)

    def onFilesBrowse(self, t):
        global _w
        filenames, _ = QFileDialog.getOpenFileNames(_w,
                                                    "Select file(s) to watch")
        if filenames:
            self.config.set('watched_files', filenames)

    def onChangeMode(self, i):
        for m, gb in {
                MODE_MANUAL: self.manual_gb,
                MODE_WATCH_FILES: self.watchfile_gb,
                MODE_WATCH_FOLDER: self.watchfolder_gb,
                MODE_TIMER: self.timer_gb
        }.items():
            if m == list(self.mode_options.items())[i][1]:
                gb.show()
            else:
                gb.hide()

    def sizeHint(self):
        return QSize(400, 200)
Exemplo n.º 18
0
Arquivo: ui.py Projeto: pchj/nmrbrew
class AnnotateClasses(GenericDialog):
    def __init__(self, parent, config=None, *args, **kwargs):
        super(AnnotateClasses, self).__init__(parent, *args, **kwargs)

        self.setWindowTitle('Annotate Classes')

        if config:
            # Copy in starting state
            self.config = ConfigManager()
            self.config.hooks.update(custom_pyqtconfig_hooks.items())

            self.config.set_defaults(config)

        self.fwd_map_cache = {}

        # Correlation variables
        gb = QGroupBox('Sample classes')
        vbox = QVBoxLayout()
        # Populate the list boxes
        self.lw_classes = QListWidgetAddRemove()
        self.lw_classes.setSelectionMode(QAbstractItemView.ExtendedSelection)
        vbox.addWidget(self.lw_classes)

        vboxh = QHBoxLayout()

        self.add_label = QLineEdit()
        self.add_class = QLineEdit()

        addc = QPushButton('Add')
        addc.clicked.connect(self.onClassAdd)

        remc = QPushButton('Remove selected')
        remc.clicked.connect(self.onClassAdd)

        loadc = QPushButton('Import from file')
        loadc.setIcon(
            QIcon(
                os.path.join(utils.scriptdir, 'icons',
                             'folder-open-document.png')))
        loadc.clicked.connect(self.onClassImport)

        vboxh.addWidget(self.add_label)
        vboxh.addWidget(self.add_class)
        vboxh.addWidget(addc)

        vbox.addWidget(remc)
        vbox.addLayout(vboxh)
        vboxh.addWidget(loadc)

        gb.setLayout(vbox)

        self.layout.addWidget(gb)

        self.config.add_handler('annotation/sample_classes', self.lw_classes,
                                (self.map_list_fwd, self.map_list_rev))

        self.dialogFinalise()

    def onClassAdd(self):
        c = self.config.get(
            'annotation/sample_classes'
        )[:]  # Create new list to force refresh on reassign
        c.append((self.add_label.text(), self.add_class.text()))
        self.config.set('annotation/sample_classes', c)

    def onClassRemove(self):
        i = self.lw_classes.removeItemAt(self.lw_classes.currentRow())
        # c = self.map_list_fwd(i.text())

    def onClassImport(self):
        filename, _ = QFileDialog.getOpenFileName(
            self.parent(), 'Load classifications from file', '',
            "All compatible files (*.csv *.txt *.tsv);;Comma Separated Values (*.csv);;Plain Text Files (*.txt);;Tab Separated Values (*.tsv);;All files (*.*)"
        )
        if filename:
            c = self.config.get(
                'annotation/sample_classes'
            )[:]  # Create new list to force refresh on reassign

            with open(filename, 'rU') as f:
                reader = csv.reader(f, delimiter=b',', dialect='excel')
                for row in reader:
                    if row not in c:
                        c.append(row[:2])

            self.config.set('annotation/sample_classes', c)

    def map_list_fwd(self, s):
        " Receive text name, return the indexes "
        return self.fwd_map_cache[s]

    def map_list_rev(self, x):
        " Receive the indexes, return the label"
        s = "%s\t%s" % tuple(x)
        self.fwd_map_cache[s] = x
        return s
Exemplo n.º 19
0
class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()

        self.setWindowTitle('PyQtConfig Demo')
        self.vis = ConfigManager()
        #
        # CHOICE_A = 1
        # CHOICE_B = 2
        # CHOICE_C = 3
        # CHOICE_D = 4
        #
        # map_dict = {
        #     'Choice A': CHOICE_A,
        #     'Choice B': CHOICE_B,
        #     'Choice C': CHOICE_C,
        #     'Choice D': CHOICE_D,
        # }

        self.vis.set_defaults({
            'text1': 'hello1',
            'text2': 'hello2',
            'text3': 'hello3',
            'text4': 'hello4',
        })

        # self.vis.set_defaults({
        #     'number': 13,
        #     'text': 'hello',
        #     'active': True,
        #     'combo': CHOICE_C,
        # })

        gd = QGridLayout()
        #
        # sb = QSpinBox()
        # gd.addWidget(sb, 0, 1)
        # self.vis.add_handler('number', sb)
        #
        # te = QLineEdit()
        # gd.addWidget(te, 1, 1)
        # self.vis.add_handler('text', te)
        #
        # cb = QCheckBox()
        # gd.addWidget(cb, 2, 1)
        # self.vis.add_handler('active', cb)
        #
        # cmb = QComboBox()
        # cmb.addItems(map_dict.keys())
        # gd.addWidget(cmb, 3, 1)
        # self.vis.add_handler('combo', cmb, mapper=map_dict)
        #
        # self.current_config_output = QTextEdit()
        # gd.addWidget(self.current_config_output, 0, 3, 3, 1)

        i=0
        print self.vis.as_dict()
        for item in self.vis.as_dict().keys():
            te = QLineEdit()
            te.setEnabled(False)
            self.vis.add_handler(item,te)
            gd.addWidget(te,i,1)
            i=i+1

        # self.vis.updated.connect(self.show_config)

        # self.show_config()

        self.window = QWidget()
        self.window.setLayout(gd)
        self.setCentralWidget(self.window)
Exemplo n.º 20
0
class DictGui(QDialog):
    # class LisaConfigWindow(QMainWindow):

    def __init__(self, config_in, ncols=2):
        super(DictGui, self).__init__()

        self.setWindowTitle('Lisa Config')
        self.config = ConfigManager()
        self.ncols = ncols
        # used with other module. If it is set, lisa config is deleted
        self.reset_config = False

        CHOICE_A = "{pairwise_alpha_per_mm2: 45, return_only_object_with_seeds: true}"
        # CHOICE_A = 23

        CHOICE_B = 2
        CHOICE_C = 3
        CHOICE_D = 4

        map_dict = {
            'Graph-Cut': CHOICE_A,
            'Choice B': CHOICE_B,
            'Choice C': CHOICE_C,
            'Choice D': CHOICE_D,
        }
        config_def = {
            'working_voxelsize_mm': 2.0,
            'save_filetype': 'pklz',
            # 'manualroi': True,
            'segparams': CHOICE_A,
        }

        config_def.update(config_in)

        self.config.set_defaults(config_def)

        gd = QGridLayout()
        gd_max_i = 0
        for key, value in config_in.items():
            if type(value) is int:
                sb = QSpinBox()
                sb.setRange(-100000, 100000)
            elif type(value) is float:
                sb = QDoubleSpinBox()
            elif type(value) is str:
                sb = QLineEdit()
            elif type(value) is bool:
                sb = QCheckBox()
            else:
                logger.error("Unexpected type in config dictionary")

            row = gd_max_i / self.ncols
            col = (gd_max_i % self.ncols) * 2

            gd.addWidget(QLabel(key), row, col + 1)
            gd.addWidget(sb, row, col + 2)
            self.config.add_handler(key, sb)
            gd_max_i += 1

        # gd.addWidget(QLabel("save filetype"), 1, 1)
        # te = QLineEdit()
        # gd.addWidget(te, 1, 2)
        # self.config.add_handler('save_filetype', te)
        #
        # gd.addWidget(QLabel("segmentation parameters"), 2, 1)
        # te = QLineEdit()
        # gd.addWidget(te, 2, 2)
        # self.config.add_handler('segparams', te)

        # cb = QCheckBox()
        # gd.addWidget(cb, 2, 2)
        # self.config.add_handler('active', cb)

        # gd.addWidget(QLabel("segmentation parameters"), 3, 1)
        # cmb = QComboBox()
        # cmb.addItems(map_dict.keys())
        # gd.addWidget(cmb, 3, 2)
        # self.config.add_handler('segparams', cmb, mapper=map_dict)

        self.current_config_output = QTextEdit()
        # rid.setColumnMinimumWidth(3, logo.width()/2)
        text_col = (self.ncols * 2) + 3
        gd.setColumnMinimumWidth(text_col, 500)
        gd.addWidget(self.current_config_output, 1, text_col,
                     (gd_max_i / 2) - 1, 1)

        btn_reset_config = QPushButton("Default", self)
        btn_reset_config.clicked.connect(self.btnResetConfig)
        gd.addWidget(btn_reset_config, 0, text_col)

        btn_save_config = QPushButton("Ok", self)
        btn_save_config.clicked.connect(self.btnSaveConfig)
        gd.addWidget(btn_save_config, (gd_max_i / 2), text_col)

        self.config.updated.connect(self.show_config)

        self.show_config()

        # my line
        self.setLayout(gd)

        # self.window = QWidget()
        # self.window.setLayout(gd)
        # self.setCentralWidget(self.window)
    def add_grid_line(self, key, value):
        pass

    def get_config_as_dict(self):
        dictionary = self.config.as_dict()
        for key, value in dictionary.items():
            from PyQt4.QtCore import pyqtRemoveInputHook
            pyqtRemoveInputHook()
            # import ipdb; ipdb.set_trace() #  noqa BREAKPOINT
            if type(value) == QString:
                value = str(value)
            dictionary[key] = value

        return dictionary

    def btnResetConfig(self, event=None):
        self.reset_config = True
        self.close()

    def btnSaveConfig(self, event=None):
        self.reset_config = False
        self.close()

    def show_config(self):
        text = str(self.get_config_as_dict())
        self.current_config_output.setText(text)
Exemplo n.º 21
0
class ToolBase(QObject):
    '''
    Base tool definition for inclusion in the UI. Define specific config settings;
    attach a panel widget for configuration.
    '''

    is_manual_runnable = True

    is_auto_runnable = True
    is_auto_rerunnable = True
    is_disableable = True

    progress = pyqtSignal(float)
    status = pyqtSignal(str)

    config_panel_size = 250
    view_widget = 'SpectraViewer'

    def __init__(self, parent, *args, **kwargs):
        super(ToolBase, self).__init__(parent, *args, **kwargs)

        self.config = ConfigManager()
        self.config.hooks.update(custom_pyqtconfig_hooks.items())
        self.config.set_defaults({
            'is_active': True,
            'auto_run_on_config_change': True
            })

        self.config.updated.connect(self.auto_run_on_config_change)

        self.buttonBar = QWidget()

        self.configPanels = QWidget()
        self.configLayout = QVBoxLayout()
        self.configLayout.setContentsMargins(0,0,0,0)

        self.configPanels.setLayout(self.configLayout)

        self._previous_config_backup_ = {}

        self._worker_thread_ = None
        self._worker_thread_lock_ = False

        self.data = {
            'spc': None,

        }

        self.current_status = 'ready'
        self.current_progress = 0

        self.progress.connect(self.progress_callback)
        self.status.connect(self.status_callback)

    def addConfigPanel(self, panel):
        self.configLayout.addWidget( panel(self) )

    def addButtonBar(self, buttons):
        '''
        Create a button bar

        Supplied with a list of QPushButton objects (already created using helper stubs; see below)

        :param buttons:
        :return:
        '''

        btnlayout = QHBoxLayout()
        btnlayout.addSpacerItem(QSpacerItem(250, 1, QSizePolicy.Maximum, QSizePolicy.Maximum))
        for btn in buttons:
            btnlayout.addWidget(btn)

        self.configLayout.addLayout(btnlayout)
        btnlayout.addSpacerItem(QSpacerItem(250, 1, QSizePolicy.Maximum, QSizePolicy.Maximum))

    def run_manual(self):
        pass


    def disable(self):
        self.status.emit('inactive')
        self.config.set('is_active', False)
        self.item.setFlags(Qt.NoItemFlags)

    def reset(self):
        self.config.set_many( self.config.defaults )

    def undo(self):
        self.config.set_many(self._config_backup_)

    def deftaultButtons(self):

        buttons = []

        if self.is_disableable:
            disable = QPushButton(QIcon(os.path.join(utils.scriptdir, 'icons', 'cross.png')), 'Disable')
            disable.setToolTip('Disable this tool')
            disable.pressed.connect(self.disable)
            buttons.append(disable)

        reset = QPushButton(QIcon(os.path.join(utils.scriptdir, 'icons', 'arrow-turn-180-left.png')), 'Reset to defaults')
        reset.setToolTip('Reset to defaults')
        reset.pressed.connect(self.reset)
        buttons.append(reset)

        undo = QPushButton(QIcon(os.path.join(utils.scriptdir, 'icons', 'arrow-turn-180-left.png')), 'Undo')
        undo.setToolTip('Undo recent changes')
        undo.pressed.connect(self.undo)
        buttons.append(undo)

        if self.is_auto_runnable:
            auto = QPushButton(QIcon(os.path.join(utils.scriptdir, 'icons', 'lightning.png')), 'Auto')
            auto.setToolTip('Auto-update spectra when settings change')
            auto.setCheckable(True)
            auto.pressed.connect(self.run_manual)
            self.config.add_handler('auto_run_on_config_change', auto)
            buttons.append(auto)

        if self.is_manual_runnable:
            apply = QPushButton(QIcon(os.path.join(utils.scriptdir, 'icons', 'play.png')), 'Apply')
            apply.setToolTip('Apply current settings to spectra')
            apply.pressed.connect(self.run_manual)
            buttons.append(apply)

        return buttons

    def enable(self):
        if self.current_status == 'inactive':
            self.status.emit('ready')
            self.item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)

        self.config.set('is_active', True)


    def activate(self):
        self.parent().current_tool = self
        self.enable()

        self._config_backup_ = self.config.as_dict()

        self._refresh_plot_timer_ = QTimer.singleShot(0, self.plot)

        self.parent().viewStack.setCurrentWidget(self.parent().spectraViewer)

        self.parent().configstack.setCurrentWidget(self.configPanels)
        self.parent().configstack.setMaximumHeight(self.config_panel_size)

    def set_active(self, active):
        self.config.set('is_active', active)

    def get_previous_tool(self):
        # Get the previous ACTIVE tool in the tool table
        n = self.parent().tools.index(self)
        for tool in self.parent().tools[n-1::-1]:
            if tool.current_status != 'inactive':
                return tool

        else:
            return None


    def get_previous_spc(self):
        t = self.get_previous_tool()
        if t:
            return t.data['spc']
        else:
            return None

    def plot(self, **kwargs):
        if 'spc' in self.data:
            self.parent().spectraViewer.plot(self.data['spc'], **kwargs)

    def get_plotitem(self):
        return self.parent().spectraViewer.spectraViewer.plotItem

    def auto_run_on_config_change(self):
        pass
        #if self.is_auto_runnable and self.config.get('is_active') and self.config.get('auto_run_on_config_change'):
        #    self.run_manual()

    def run(self, fn):
        '''
        Run the target function, passing in the current spectra, and config settings (as dict)
        :param fn:
        :return:
        '''
        if self._worker_thread_lock_:
            return False # Can't run

        self.progress.emit(0)
        self.status.emit('active')

        spc = self.get_previous_spc()

        self._worker_thread_lock_ = True

        print(self.config.as_dict())
        self._worker_thread_ = Worker(fn = fn, **{
            'spc': deepcopy(spc),
            'config': self.config.as_dict(),
            'progress_callback': self.progress.emit,
        })

        self._worker_thread_.signals.finished.connect(self.finished)
        self._worker_thread_.signals.result.connect(self.result)
        self._worker_thread_.signals.error.connect(self.error)

        self.parent().threadpool.start(self._worker_thread_)


    def error(self, error):
        self.progress.emit(1.0)
        self.status.emit('error')
        logging.error(error)
        self._worker_thread_lock_ = False

    def result(self, result):
        self.progress.emit(1)
        self.status.emit('complete')

        # Apply post-processing
        if 'spc' in result:
            result['spc'] = self.post_process_spc(result['spc'])

        self.data = result
        self.plot()

    def finished(self):
        # Cleanup
        self._worker_thread_lock_ = False


    def progress_callback(self, progress):
        self.current_progress = progress
        self.item.setData(Qt.UserRole + 2, progress)

    def status_callback(self, status):
        self.current_status = status
        self.item.setData(Qt.UserRole + 3, status)

    def post_process_spc(self, spc):
        '''
        Apply post-processing to the spectra before loading into the data store, e.g. for outlier
        detection, stats etc.

        :param spc:
        :return:
        '''

        # Outliers

        def identify_outliers(data, m=2):
            return abs(data - np.mean(data, axis=0)) < (m * np.std(data,axis=0))

        # Identify outliers on a point by point basis. Count up 'outliers' and score ratio of points that are
        # outliers for each specra > 5% (make this configurable) is an outlier.
        spc.outliers = np.sum( ~identify_outliers(spc.data), axis=1 ) / float(spc.data.shape[1])
        return spc