Ejemplo n.º 1
0
class ProbeSim(BaseDialog):
    def __init__(self, parent=None):
        super(ProbeSim, self).__init__(parent=parent)

        self.info = Info()
        self.log = Log

        self.close_button = QPushButton("Touch")
        self.pulse_checkbox = QCheckBox("Pulse")

        main_layout = QVBoxLayout()

        main_layout.addWidget(self.close_button)
        main_layout.addWidget(self.pulse_checkbox)

        self.setLayout(main_layout)
        self.setWindowTitle("Simulate touch probe")

        self.close_button.pressed.connect(self.touch_on)
        self.close_button.released.connect(self.touch_off)

        self.timer = QTimer()
        self.timer.timeout.connect(self.pulse_off)
        self.timer.setSingleShot(True)

    def touch_on(self):

        if self.pulse_checkbox.checkState():
            self.timer.start(1000)
            subprocess.Popen(['halcmd', 'setp', 'motion.probe-input', '1'])

        else:
            subprocess.Popen(['halcmd', 'setp', 'motion.probe-input', '1'])

    def touch_off(self):

        if self.pulse_checkbox.checkState():
            return

        subprocess.Popen(['halcmd', 'setp', 'motion.probe-input', '0'])

    def pulse_off(self):
        subprocess.Popen(['halcmd', 'setp', 'motion.probe-input', '0'])

    def close(self):
        self.hide()
Ejemplo n.º 2
0
class EFMtoolDialog(QDialog):
    """A dialog to set up EFM calculation"""

    def __init__(self, appdata: CnaData, centralwidget):
        QDialog.__init__(self)
        self.setWindowTitle("Elementary Flux Mode Computation")

        self.appdata = appdata
        self.centralwidget = centralwidget

        self.layout = QVBoxLayout()

        l1 = QHBoxLayout()
        self.constraints = QCheckBox("consider 0 in current scenario as off")
        self.constraints.setCheckState(Qt.Checked)
        l1.addWidget(self.constraints)
        self.layout.addItem(l1)

        lx = QHBoxLayout()
        self.button = QPushButton("Compute")
        self.cancel = QPushButton("Close")
        lx.addWidget(self.button)
        lx.addWidget(self.cancel)
        self.layout.addItem(lx)

        self.setLayout(self.layout)

        # Connecting the signal
        self.cancel.clicked.connect(self.reject)
        self.button.clicked.connect(self.compute)

    def compute(self):
        self.setCursor(Qt.BusyCursor)
        (ems, scenario) = cnapy.core.efm_computation(
            self.appdata.project.cobra_py_model, self.appdata.project.scen_values,
            self.constraints.checkState() == Qt.Checked)

        self.setCursor(Qt.ArrowCursor)
        if ems is None:
            QMessageBox.information(self, 'No modes',
                                    'An error occured and modes have not been calculated.')
        else:
            if len(ems) == 0:
                QMessageBox.information(self, 'No modes',
                                        'No elementary modes exist.')
            else:
                print(scenario)
                self.appdata.project.modes = ems
                self.centralwidget.mode_navigator.current = 0
                self.centralwidget.mode_navigator.scenario = scenario
                self.centralwidget.mode_navigator.title.setText(
                    "Mode Navigation")
                self.centralwidget.update_mode()
Ejemplo n.º 3
0
class QuitApplicationDialog(DialogBase):
    """
    """
    def __init__(self, *args, **kwargs):
        super(QuitApplicationDialog, self).__init__(*args, **kwargs)
        self.label_icon = QLabel()
        self.label_about = QLabel('Quit Anaconda Navigator?')
        self.button_ok = QPushButton('Yes')
        self.button_cancel = ButtonCancel('No')
        self.buttonbox = QDialogButtonBox(Qt.Horizontal)
        self.checkbox = QCheckBox("Don't show again")

        # Widget setup
        if CONF.get('main', 'hide_quit_dialog'):
            hide_dialog = Qt.Checked
        else:
            hide_dialog = Qt.Unchecked

        self.checkbox.setChecked(hide_dialog)
        self.buttonbox.addButton(self.button_ok, QDialogButtonBox.ActionRole)
        self.buttonbox.addButton(self.button_cancel,
                                 QDialogButtonBox.ActionRole)
        self.label_icon.setPixmap(QPixmap(images.ANACONDA_ICON_64_PATH))
        self.setWindowTitle("Quit application")

        # Layouts
        h_layout = QHBoxLayout()
        h_layout.addWidget(self.label_icon, 0, Qt.AlignTop)
        h_layout.addSpacing(10)
        h_layout.addWidget(self.label_about)

        main_layout = QVBoxLayout()
        main_layout.addLayout(h_layout)
        main_layout.addWidget(self.checkbox, 0, Qt.AlignRight)
        main_layout.addSpacing(24)
        main_layout.addWidget(self.buttonbox)
        self.setLayout(main_layout)

        # Signals
        self.button_ok.clicked.connect(self.accept)
        self.button_cancel.clicked.connect(self.reject)

        # Setup
        self.update_style_sheet()

    def accept(self):
        hide_dialog = self.checkbox.checkState() == Qt.Checked
        CONF.set('main', 'hide_quit_dialog', hide_dialog)
        super(QuitApplicationDialog, self).accept()
Ejemplo n.º 4
0
class FirstSplash(DialogBase):
    """Startup splash to display the first time that Navigator runs."""
    def __init__(self, parent=None):
        """Startup splash to display the first time that Navigator runs."""
        super(FirstSplash, self).__init__(parent=parent)

        text = """
        Thanks for installing Anaconda!

        Anaconda Navigator helps you easily start important Python applications
        and manage the packages in your local Anaconda installation. It also
        connects you to online resources for learning and engaging with the
        Python, SciPy, and PyData community.

        To help us improve Anaconda Navigator, fix bugs, and make it even
        easier for everyone to use Python, we gather anonymized usage
        information, just like most web browsers and mobile apps.

        To opt out of this, please uncheck below (You can always change this
        setting in the Preferences menu).
        """
        # Variables
        self.config = CONF

        # Widgets
        self.button_ok = ButtonNormal('Ok')
        self.button_ok_dont_show = ButtonPrimary("Ok, and don't show again")
        self.checkbox_track = QCheckBox("Yes, I'd like to help improve "
                                        "Anaconda.")
        self.label_about = QLabel(text)
        self.widget_icon = QSvgWidget(ANACONDA_NAVIGATOR_LOGO)

        # Widget setup
        self.frame_title_bar.hide()
        self.widget_icon.setFixedSize(self.widget_icon.size_for_width(400))

        # Layouts
        layout_buttons = QHBoxLayout()
        layout_buttons.addStretch()
        layout_buttons.addWidget(self.button_ok)
        layout_buttons.addWidget(SpacerHorizontal())
        layout_buttons.addWidget(self.button_ok_dont_show)

        layout = QVBoxLayout()
        layout.addWidget(self.widget_icon, 0, Qt.AlignCenter)
        layout.addWidget(self.label_about)
        layout.addWidget(self.checkbox_track, 0, Qt.AlignCenter)
        layout.addWidget(SpacerVertical())
        layout.addWidget(SpacerVertical())
        layout.addLayout(layout_buttons)
        self.setLayout(layout)

        # Signals
        self.button_ok.clicked.connect(lambda: self.accept(show_startup=True))
        self.button_ok_dont_show.clicked.connect(
            lambda: self.accept(show_startup=False))

        self.setup()

    def setup(self):
        """Setup widget content."""
        provide_analytics = self.config.get('main', 'provide_analytics')
        self.checkbox_track.setChecked(provide_analytics)

    def accept(self, show_startup):
        """Override Qt method."""
        provide_analytics = self.checkbox_track.checkState() == Qt.Checked
        self.config.set('main', 'provide_analytics', provide_analytics)
        self.config.set('main', 'show_startup', show_startup)
        DialogBase.accept(self)

    def reject(self):
        """
        Override Qt method.

        Force user to select one of the two options bellow and disalow
        canceling the dialog (pressing escape)
        """
        pass
Ejemplo n.º 5
0
class CondaPackageActionDialog(QDialog):
    """ """
    def __init__(self, parent, env, name, action, version, versions):
        super(CondaPackageActionDialog, self).__init__(parent)
        self._parent = parent
        self._env = env
        self._version_text = None
        self._name = name
        self._dependencies_dic = {}
        self._conda_process = \
            conda_api_q.CondaProcess(self, self._on_process_finished)

        # widgets
        self.label = QLabel(self)
        self.combobox_version = QComboBox()
        self.label_version = QLabel(self)
        self.widget_version = None
        self.table_dependencies = None

        self.checkbox = QCheckBox(_('Install dependencies (recommended)'))
        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok |
                                     QDialogButtonBox.Cancel, Qt.Horizontal,
                                     self)

        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        self.button_cancel.setDefault(True)
        self.button_cancel.setAutoDefault(True)

        dialog_size = QSize(300, 90)

        # helper variable values
        action_title = {const.UPGRADE: _("Upgrade package"),
                        const.DOWNGRADE: _("Downgrade package"),
                        const.REMOVE: _("Remove package"),
                        const.INSTALL: _("Install package")}

        # Versions might have duplicates from different builds
        versions = sort_versions(list(set(versions)), reverse=True)

        # FIXME: There is a bug, a package installed by anaconda has version
        # astropy 0.4 and the linked list 0.4 but the available versions
        # in the json file do not include 0.4 but 0.4rc1... so...
        # temporal fix is to check if inside list otherwise show full list
        if action == const.UPGRADE:
            if version in versions:
                index = versions.index(version)
                versions = versions[:index]
            else:
                versions = versions
        elif action == const.DOWNGRADE:
            if version in versions:
                index = versions.index(version)
                versions = versions[index+1:]
            else:
                versions = versions
        elif action == const.REMOVE:
            versions = [version]
            self.combobox_version.setEnabled(False)

        if len(versions) == 1:
            if action == const.REMOVE:
                labeltext = _('Package version to remove:')
            else:
                labeltext = _('Package version available:')
            self.label_version.setText(versions[0])
            self.widget_version = self.label_version
        else:
            labeltext = _("Select package version:")
            self.combobox_version.addItems(versions)
            self.widget_version = self.combobox_version

        self.label.setText(labeltext)
        self.label_version.setAlignment(Qt.AlignLeft)
        self.table_dependencies = QWidget(self)

        self._layout = QGridLayout()
        self._layout.addWidget(self.label, 0, 0, Qt.AlignVCenter |
                               Qt.AlignLeft)
        self._layout.addWidget(self.widget_version, 0, 1, Qt.AlignVCenter |
                               Qt.AlignRight)

        self.widgets = [self.checkbox, self.button_ok, self.widget_version,
                        self.table_dependencies]
        row_index = 1

        # Create a Table
        if action in [const.INSTALL, const.UPGRADE, const.DOWNGRADE]:
            table = QTableView(self)
            dialog_size = QSize(dialog_size.width() + 40, 300)
            self.table_dependencies = table
            row_index = 1
            self._layout.addItem(QSpacerItem(10, 5), row_index, 0)
            self._layout.addWidget(self.checkbox, row_index + 1, 0, 1, 2)
            self.checkbox.setChecked(True)
            self._changed_version(versions[0])

            table.setSelectionBehavior(QAbstractItemView.SelectRows)
            table.verticalHeader().hide()
            table.horizontalHeader().hide()
            table.setAlternatingRowColors(True)
            table.setShowGrid(False)
            table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            table.horizontalHeader().setStretchLastSection(True)

        self._layout.addWidget(self.table_dependencies, row_index + 2, 0, 1, 2,
                               Qt.AlignHCenter)
        self._layout.addItem(QSpacerItem(10, 5), row_index + 3, 0)
        self._layout.addWidget(self.bbox, row_index + 6, 0, 1, 2,
                               Qt.AlignHCenter)

        title = "{0}: {1}".format(action_title[action], name)
        self.setLayout(self._layout)
        self.setMinimumSize(dialog_size)
        self.setFixedSize(dialog_size)
        self.setWindowTitle(title)
        self.setModal(True)

        # signals and slots
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.close)
        self.combobox_version.currentIndexChanged.connect(
            self._changed_version)
        self.checkbox.stateChanged.connect(self._changed_checkbox)

    def _changed_version(self, version, dependencies=True):
        """ """
        self._set_gui_disabled(True)
        install_dependencies = (self.checkbox.checkState() == 2)
        self._version_text = to_text_string(version)
        self._get_dependencies(install_dependencies)

    def _get_dependencies(self, dependencies=True):
        """ """
        name = [self._name + '=' + self._version_text]

        # Temporal fix
        env_name = self._env
        if env_name != 'root':
            env_name = osp.basename(env_name)
        self._conda_process.dependencies(name=env_name, pkgs=name,
                                         dep=dependencies)

    def _changed_checkbox(self, state):
        """ """
        if state:
            self._changed_version(self._version_text)
        else:
            self._changed_version(self._version_text, dependencies=False)

    def _on_process_finished(self, boo):
        """ """
        if self.isVisible():
            dic = self._conda_process.output
            self.dependencies_dic = dic
            self._set_dependencies_table()
            self._set_gui_disabled(False)

    def _set_dependencies_table(self):
        """ """
        table = self.table_dependencies
        dic = self.dependencies_dic
        table.setModel(CondaDependenciesModel(self, dic))
        table.resizeColumnsToContents()
        table.resizeColumnToContents(1)

    def _set_gui_disabled(self, value):
        """ """
        if value:
            table = self.table_dependencies
            table.setModel(CondaDependenciesModel(self, {}))
            table.resizeColumnsToContents()
            table.setDisabled(True)
        else:
            table = self.table_dependencies
            table.setDisabled(False)

        for widget in self.widgets:
            widget.setDisabled(value)
Ejemplo n.º 6
0
class ItemPropertyDialog(QDialog):
    def __init__(self, jsonitem: JsonItem, parent=None):
        super().__init__(parent)

        assert jsonitem is not None
        self.item = jsonitem

        # name
        self.nameLabel = QLabel(self.tr("name:"))
        self.nameLineEdit = QLineEdit(self.item.name or "")
        self.nameLabel.setBuddy(self.nameLineEdit)

        # unit
        self.unitLabel = QLabel(self.tr("unit:"))
        self.unitLineEdit = QLineEdit(self.item.unit or "")
        self.unitLabel.setBuddy(self.unitLineEdit)

        # type
        self.typeLabel = QLabel(self.tr("type:"))
        self.typeComboBox = QComboBox()
        self.typeComboBox.addItems([k for k, t in VALUETYPES])
        self.typeComboBox.setCurrentIndex(
            self.typeComboBox.findText(self.item.type))
        self.typeComboBox.currentIndexChanged.connect(self.data_changed)
        self.typeLabel.setBuddy(self.typeComboBox)

        # decimals
        self.decimalsLabel = QLabel(self.tr("decimals:"))
        self.decimalsSpinBox = QSpinBox()
        self.decimalsSpinBox.setRange(0, 10)
        self.decimalsSpinBox.setValue(self.item.decimals or 0)
        self.decimalsLabel.setBuddy(self.decimalsSpinBox)
        self.decimalsSpinBox.valueChanged.connect(self.data_changed)
        self.last_decimals = self.decimalsSpinBox.value()

        # min
        self.minLabel = QLabel(self.tr("minimum:"))
        self.minSpinBox =QDoubleSpinBox()
        self.minSpinBox.setRange(-sys.maxsize, sys.maxsize)
        self.minLabel.setBuddy(self.minSpinBox)
        self.minSpinBox.setValue(self.item.min or 0.0)

        # max
        self.maxLabel = QLabel(self.tr("maximum:"))
        self.maxSpinBox = QDoubleSpinBox()
        self.maxSpinBox.setRange(-sys.maxsize, sys.maxsize)
        self.maxSpinBox.setValue(self.item.max or 100.0)

        # numerator
        self.scalefactorLabel = QLabel(self.tr("scalefactor:"))
        self.scalefactorSpinBox = NoZerosDoubleSpinBox()
        self.scalefactorSpinBox.setRange(-sys.maxsize, sys.maxsize)
        self.scalefactorSpinBox.setButtonSymbols(QSpinBox.NoButtons)
        self.scalefactorSpinBox.setDecimals(10)
        self.scalefactorSpinBox.setValue(self.item.scalefactor or 1)
        self.scalefactorLabel.setBuddy(self.scalefactorSpinBox)

        # readonly
        self.readonlyCheckBox = QCheckBox(self.tr("readonly"))
        self.readonlyCheckBox.setChecked(Qt.Checked if self.item.readonly
                                         else Qt.Unchecked)
        self.readonlyCheckBox.stateChanged.connect(self.data_changed)

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

        # layout
        layout = QGridLayout()
        layout.addWidget(self.nameLabel, 0, 0)
        layout.addWidget(self.nameLineEdit, 0, 1)
        layout.addWidget(self.unitLabel, 1, 0)
        layout.addWidget(self.unitLineEdit, 1, 1)
        layout.addWidget(self.typeLabel, 2, 0)
        layout.addWidget(self.typeComboBox, 2, 1)
        layout.addWidget(self.decimalsLabel, 3, 0)
        layout.addWidget(self.decimalsSpinBox, 3, 1)
        layout.addWidget(self.minLabel, 4, 0)
        layout.addWidget(self.minSpinBox, 4, 1)
        layout.addWidget(self.maxLabel, 5, 0)
        layout.addWidget(self.maxSpinBox, 5, 1)
        layout.addWidget(self.scalefactorLabel, 6, 0)
        layout.addWidget(self.scalefactorSpinBox, 6, 1)
        layout.addWidget(self.readonlyCheckBox, 7, 0, 1, 2)
        layout.addWidget(self.buttons, 8, 0, 1, 2)
        self.setLayout(layout)

        # misc
        self.setWindowTitle("Edit JsonItem '%s'" % self.item.key)
        self.data_changed()

    def accept(self):
        self.item.name = self.nameLineEdit.text()
        self.item.unit = self.unitLineEdit.text()
        self.item.decimals = self.decimalsSpinBox.value()
        self.item.min = self.minSpinBox.value()
        self.item.max = self.maxSpinBox.value()
        self.item.scalefactor = self.scalefactorSpinBox.value()
        self.item.readonly = self.readonlyCheckBox.checkState() == Qt.Checked
        self.item.type = self.typeComboBox.currentText()
        return super().accept()

    def data_changed(self):
        type_numeric = self.typeComboBox.currentText() not in ('bool', 'str')
        type_int = self.typeComboBox.currentText() == 'int'
        readonly  = self.readonlyCheckBox.checkState() == Qt.Checked

        # not used properties invisible
        self.decimalsSpinBox.setVisible(type_numeric)
        self.decimalsLabel.setVisible(type_numeric)

        self.scalefactorSpinBox.setVisible(type_numeric)
        self.scalefactorLabel.setVisible(type_numeric)

        self.minSpinBox.setVisible(type_numeric and not readonly)
        self.minLabel.setVisible(type_numeric and not readonly)

        self.maxSpinBox.setVisible(type_numeric and not readonly)
        self.maxLabel.setVisible(type_numeric and not readonly)

        self.unitLineEdit.setVisible(type_numeric)
        self.unitLabel.setVisible(type_numeric)

        # no decimals for int
        self.minSpinBox.setDecimals(self.decimalsSpinBox.value())
        self.maxSpinBox.setDecimals(self.decimalsSpinBox.value())

        if type_int:
            delta = self.decimalsSpinBox.value() - self.last_decimals
            self.scalefactorSpinBox.setValue(
                self.scalefactorSpinBox.value() / 10**delta
            )

        self.last_decimals = self.decimalsSpinBox.value()
Ejemplo n.º 7
0
class EFMDialog(QDialog):
    """A dialog to set up EFM calculation"""
    def __init__(self, appdata: CnaData, centralwidget):
        QDialog.__init__(self)
        self.setWindowTitle("Elementary Flux Mode Computation")

        self.appdata = appdata
        self.centralwidget = centralwidget
        self.eng = appdata.engine
        self.out = io.StringIO()
        self.err = io.StringIO()

        self.layout = QVBoxLayout()

        l1 = QHBoxLayout()
        self.constraints = QCheckBox("consider 0 in current scenario as off")
        self.constraints.setCheckState(Qt.Checked)
        l1.addWidget(self.constraints)
        self.layout.addItem(l1)

        l2 = QHBoxLayout()
        self.flux_bounds = QGroupBox(
            "use flux bounds to calculate elementary flux vectors")
        self.flux_bounds.setCheckable(True)
        self.flux_bounds.setChecked(False)

        vbox = QVBoxLayout()
        label = QLabel("Threshold for bounds to be unconstrained")
        vbox.addWidget(label)
        self.threshold = QLineEdit("100")
        validator = QIntValidator()
        validator.setBottom(0)
        self.threshold.setValidator(validator)
        vbox.addWidget(self.threshold)
        self.flux_bounds.setLayout(vbox)
        l2.addWidget(self.flux_bounds)
        self.layout.addItem(l2)

        l3 = QHBoxLayout()
        self.check_reversibility = QCheckBox("check reversibility")
        self.check_reversibility.setCheckState(Qt.Checked)
        l3.addWidget(self.check_reversibility)
        self.layout.addItem(l3)

        l4 = QHBoxLayout()
        self.convex_basis = QCheckBox("only convex basis")
        l4.addWidget(self.convex_basis)
        self.layout.addItem(l4)

        l5 = QHBoxLayout()
        self.isozymes = QCheckBox("consider isozymes only once")
        l5.addWidget(self.isozymes)
        self.layout.addItem(l5)

        # TODO: choose solver

        l7 = QHBoxLayout()
        self.rational_numbers = QCheckBox("use rational numbers")
        l7.addWidget(self.rational_numbers)
        self.layout.addItem(l7)

        lx = QHBoxLayout()
        self.button = QPushButton("Compute")
        self.cancel = QPushButton("Close")
        lx.addWidget(self.button)
        lx.addWidget(self.cancel)
        self.layout.addItem(lx)

        self.setLayout(self.layout)

        # Connecting the signal
        self.cancel.clicked.connect(self.reject)
        self.button.clicked.connect(self.compute)

    def compute(self):

        # create CobraModel for matlab
        self.appdata.create_cobra_model()
        legacy.read_cnapy_model(self.eng)

        # get some data
        reac_id = self.eng.get_reacID()

        # setting parameters
        a = self.eng.eval("constraints = {};",
                          nargout=0,
                          stdout=self.out,
                          stderr=self.err)
        scenario = {}
        if self.constraints.checkState(
        ) == Qt.Checked or self.flux_bounds.isChecked():
            onoff_str = ""
            for r in reac_id:
                if r in self.appdata.project.scen_values.keys():
                    (vl, vu) = self.appdata.project.scen_values[r]
                    if vl == vu:
                        if vl > 0:
                            onoff_str = onoff_str + " NaN"  # efmtool does not support 1
                        elif vl == 0:
                            scenario[r] = (0, 0)
                            onoff_str = onoff_str + " 0"
                        else:
                            onoff_str = onoff_str + " NaN"
                            print("WARN: negative value in scenario")
                    else:
                        onoff_str = onoff_str + " NaN"
                        print("WARN: not fixed value in scenario")
                else:
                    onoff_str = onoff_str + " NaN"

            onoff_str = "reaconoff = [" + onoff_str + "];"
            a = self.eng.eval(onoff_str,
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)

            a = self.eng.eval("constraints.reaconoff = reaconoff;",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)

        if self.flux_bounds.isChecked():
            threshold = float(self.threshold.text())
            lb_str = ""
            ub_str = ""
            for r in reac_id:
                c_reaction = self.appdata.project.cobra_py_model.reactions.get_by_id(
                    r)
                if r in self.appdata.project.scen_values:
                    (vl, vu) = self.appdata.project.scen_values[r]
                else:
                    vl = c_reaction.lower_bound
                    vu = c_reaction.upper_bound
                if vl <= -threshold:
                    vl = "NaN"
                if vu >= threshold:
                    vu = "NaN"
                if vl == 0 and vu == 0:  # already in reaconoff, can be skipped here
                    vl = "NaN"
                    vu = "NaN"
                lb_str = lb_str + " " + str(vl)
                ub_str = ub_str + " " + str(vu)

            lb_str = "lb = [" + lb_str + "];"
            a = self.eng.eval(lb_str,
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)
            a = self.eng.eval("constraints.lb = lb;",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)

            ub_str = "ub = [" + ub_str + "];"
            a = self.eng.eval(ub_str,
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)
            a = self.eng.eval("constraints.ub = ub;",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)

        # TODO set solver 4 = EFMTool 3 = MetaTool, 1 = cna Mex file, 0 = cna functions
        a = self.eng.eval("solver = 4;",
                          nargout=0,
                          stdout=self.out,
                          stderr=self.err)

        if self.check_reversibility.checkState() == Qt.Checked:
            a = self.eng.eval("irrev_flag = 1;",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)
        else:
            a = self.eng.eval("irrev_flag = 0;",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)

        # convex basis computation is only possible with METATOOL solver=3
        if self.convex_basis.checkState() == Qt.Checked:
            a = self.eng.eval("conv_basis_flag = 1; solver = 3;",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)
        else:
            a = self.eng.eval("conv_basis_flag = 0;",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)

        if self.isozymes.checkState() == Qt.Checked:
            a = self.eng.eval("iso_flag = 1;",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)
        else:
            a = self.eng.eval("iso_flag = 0;",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)

        # default we have no macromolecules and display is et to ALL
        a = self.eng.eval("c_macro=[]; display= 'ALL';",
                          nargout=0,
                          stdout=self.out,
                          stderr=self.err)

        if self.rational_numbers.checkState() == Qt.Checked:
            a = self.eng.eval(
                "efmtool_options = {'arithmetic', 'fractional'};",
                nargout=0,
                stdout=self.out,
                stderr=self.err)
        else:
            a = self.eng.eval("efmtool_options = {};",
                              nargout=0,
                              stdout=self.out,
                              stderr=self.err)

        if self.appdata.is_matlab_set():
            try:
                a = self.eng.eval(
                    "[ems, irrev_ems, ems_idx, ray] = CNAcomputeEFM(cnap, constraints,solver,irrev_flag,conv_basis_flag,iso_flag,c_macro,display,efmtool_options);",
                    nargout=0)

            except Exception:
                output = io.StringIO()
                traceback.print_exc(file=output)
                exstr = output.getvalue()
                print(exstr)
                QMessageBox.warning(
                    self, 'Unknown exception occured!',
                    exstr + '\nPlease report the problem to:\n\
                                    \nhttps://github.com/cnapy-org/CNApy/issues'
                )
                return
            else:
                ems = self.eng.workspace['ems']
                idx = self.eng.workspace['ems_idx']
                irreversible = numpy.squeeze(self.eng.workspace['irrev_ems'])
                unbounded = numpy.squeeze(self.eng.workspace['ray'])
                ems = numpy.array(ems)
                self.result2ui(ems, idx, reac_id, irreversible, unbounded,
                               scenario)

                self.accept()
        elif self.appdata.is_octave_ready():
            a = self.eng.eval(
                "[ems, irrev_ems, ems_idx, ray] = CNAcomputeEFM(cnap, constraints,solver,irrev_flag,conv_basis_flag,iso_flag,c_macro,display,efmtool_options);",
                nargout=0)

            ems = self.eng.pull('ems')
            idx = self.eng.pull('ems_idx')
            irreversible = numpy.squeeze(self.eng.pull('irrev_ems'))
            unbounded = numpy.squeeze(self.eng.pull('ray'))

            self.result2ui(ems, idx, reac_id, irreversible, unbounded,
                           scenario)

    def result2ui(self, ems, idx, reac_id, irreversible, unbounded, scenario):
        if len(ems) == 0:
            QMessageBox.information(
                self, 'No modes',
                'Modes have not been calculated or do not exist.')
        else:
            self.appdata.project.modes = FluxVectorContainer(
                ems, [reac_id[int(i) - 1] for i in idx[0]], irreversible,
                unbounded)
            self.centralwidget.mode_navigator.current = 0
            self.centralwidget.mode_navigator.scenario = scenario
            self.centralwidget.mode_navigator.title.setText("Mode Navigation")
            self.centralwidget.update_mode()
Ejemplo n.º 8
0
class SliceViewerDataView(QWidget):
    """The view for the data portion of the sliceviewer"""
    def __init__(self, presenter, dims_info, can_normalise, parent=None):
        super().__init__(parent)

        self.presenter = presenter

        self.image = None
        self.line_plots = False
        self.can_normalise = can_normalise
        self.nonortho_tr = None
        self.ws_type = dims_info[0]['type']

        # Dimension widget
        self.dimensions_layout = QGridLayout()
        self.dimensions = DimensionWidget(dims_info, parent=self)
        self.dimensions.dimensionsChanged.connect(
            self.presenter.dimensions_changed)
        self.dimensions.valueChanged.connect(self.presenter.slicepoint_changed)
        self.dimensions_layout.addWidget(self.dimensions, 1, 0, 1, 1)

        self.colorbar_layout = QVBoxLayout()
        self.colorbar_layout.setContentsMargins(0, 0, 0, 0)
        self.colorbar_layout.setSpacing(0)

        self.image_info_widget = ImageInfoWidget(self.ws_type, self)
        self.track_cursor = QCheckBox("Track Cursor", self)
        self.track_cursor.setToolTip(
            "Update the image readout table when the cursor is over the plot. "
            "If unticked the table will update only when the plot is clicked")
        if self.ws_type == 'MDE':
            self.colorbar_layout.addWidget(self.image_info_widget,
                                           alignment=Qt.AlignCenter)
            self.colorbar_layout.addWidget(self.track_cursor)
        else:
            self.dimensions_layout.setHorizontalSpacing(10)
            self.dimensions_layout.addWidget(self.track_cursor, 0, 1,
                                             Qt.AlignRight)
            self.dimensions_layout.addWidget(self.image_info_widget, 1, 1)
        self.track_cursor.setChecked(True)

        # normalization options
        if can_normalise:
            self.norm_label = QLabel("Normalization")
            self.colorbar_layout.addWidget(self.norm_label)
            self.norm_opts = QComboBox()
            self.norm_opts.addItems(["None", "By bin width"])
            self.norm_opts.setToolTip("Normalization options")
            self.colorbar_layout.addWidget(self.norm_opts)

        # MPL figure + colorbar
        self.fig = Figure()
        self.ax = None
        self.axx, self.axy = None, None
        self.image = None
        self._grid_on = False
        self.fig.set_facecolor(self.palette().window().color().getRgbF())
        self.canvas = SliceViewerCanvas(self.fig)
        self.canvas.mpl_connect('motion_notify_event', self.mouse_move)
        self.canvas.mpl_connect('axes_leave_event', self.mouse_outside_image)
        self.canvas.mpl_connect('button_press_event', self.mouse_click)
        self.canvas.mpl_connect('button_release_event', self.mouse_release)

        self.colorbar_label = QLabel("Colormap")
        self.colorbar_layout.addWidget(self.colorbar_label)
        self.colorbar = ColorbarWidget(self)
        self.colorbar_layout.addWidget(self.colorbar)
        self.colorbar.colorbarChanged.connect(self.update_data_clim)
        self.colorbar.colorbarChanged.connect(self.update_line_plot_limits)
        # make width larger to fit image readout table
        if self.ws_type == 'MDE':
            self.colorbar.setMaximumWidth(155)

        # MPL toolbar
        self.toolbar_layout = QHBoxLayout()
        self.mpl_toolbar = SliceViewerNavigationToolbar(
            self.canvas, self, False)
        self.mpl_toolbar.gridClicked.connect(self.toggle_grid)
        self.mpl_toolbar.linePlotsClicked.connect(self.on_line_plots_toggle)
        self.mpl_toolbar.homeClicked.connect(self.on_home_clicked)
        self.mpl_toolbar.plotOptionsChanged.connect(
            self.colorbar.mappable_changed)
        self.mpl_toolbar.nonOrthogonalClicked.connect(
            self.on_non_orthogonal_axes_toggle)
        self.mpl_toolbar.zoomPanFinished.connect(self.on_data_limits_changed)
        self.toolbar_layout.addWidget(self.mpl_toolbar)

        # layout
        layout = QGridLayout(self)
        layout.setSpacing(1)
        layout.addLayout(self.dimensions_layout, 0, 0, 1, 2)
        layout.addLayout(self.toolbar_layout, 1, 0, 1, 2)
        layout.addWidget(self.canvas, 2, 0, 1, 1)
        layout.addLayout(self.colorbar_layout, 1, 1, 2, 1)
        layout.setRowStretch(2, 1)

    @property
    def grid_on(self):
        return self._grid_on

    @property
    def nonorthogonal_mode(self):
        return self.nonortho_tr is not None

    def create_axes_orthogonal(self, redraw_on_zoom=False):
        """Create a standard set of orthogonal axes
        :param redraw_on_zoom: If True then when scroll zooming the canvas is redrawn immediately
        """
        self.clear_figure()
        self.nonortho_tr = None
        self.ax = self.fig.add_subplot(111, projection='mantid')
        self.enable_zoom_on_mouse_scroll(redraw_on_zoom)
        if self.grid_on:
            self.ax.grid(self.grid_on)
        if self.line_plots:
            self.add_line_plots()

        self.plot_MDH = self.plot_MDH_orthogonal

        self.canvas.draw_idle()

    def create_axes_nonorthogonal(self, transform):
        self.clear_figure()
        self.set_nonorthogonal_transform(transform)
        self.ax = CurveLinearSubPlot(self.fig,
                                     1,
                                     1,
                                     1,
                                     grid_helper=GridHelperCurveLinear(
                                         (self.nonortho_tr, transform.inv_tr)))
        # don't redraw on zoom as the data is rebinned and has to be redrawn again anyway
        self.enable_zoom_on_mouse_scroll(redraw=False)
        self.set_grid_on()
        self.fig.add_subplot(self.ax)
        self.plot_MDH = self.plot_MDH_nonorthogonal

        self.canvas.draw_idle()

    def enable_zoom_on_mouse_scroll(self, redraw):
        """Enable zoom on scroll the mouse wheel for the created axes
        :param redraw: Pass through to redraw option in enable_zoom_on_scroll
        """
        self.canvas.enable_zoom_on_scroll(self.ax,
                                          redraw=redraw,
                                          toolbar=self.mpl_toolbar,
                                          callback=self.on_data_limits_changed)

    def add_line_plots(self):
        """Assuming line plots are currently disabled, enable them on the current figure
        The image axes must have been created first.
        """
        if self.line_plots:
            return

        self.line_plots = True
        image_axes = self.ax
        if image_axes is None:
            return

        # Create a new GridSpec and reposition the existing image Axes
        gs = gridspec.GridSpec(2,
                               2,
                               width_ratios=[1, 4],
                               height_ratios=[4, 1],
                               wspace=0.0,
                               hspace=0.0)
        image_axes.set_position(gs[1].get_position(self.fig))
        set_artist_property(image_axes.get_xticklabels(), visible=False)
        set_artist_property(image_axes.get_yticklabels(), visible=False)
        self.axx = self.fig.add_subplot(gs[3], sharex=image_axes)
        self.axx.yaxis.tick_right()
        self.axy = self.fig.add_subplot(gs[0], sharey=image_axes)
        self.axy.xaxis.tick_top()
        self.update_line_plot_labels()
        self.mpl_toolbar.update()  # sync list of axes in navstack
        self.canvas.draw_idle()

    def remove_line_plots(self):
        """Assuming line plots are currently enabled, remove them from the current figure
        """
        if not self.line_plots:
            return

        self.line_plots = False
        image_axes = self.ax
        if image_axes is None:
            return

        self.delete_line_plot_lines()
        all_axes = self.fig.axes
        # The order is defined by the order of the add_subplot calls so we always want to remove
        # the last two Axes. Do it backwards to cope with the container size change
        all_axes[2].remove()
        all_axes[1].remove()

        gs = gridspec.GridSpec(1, 1)
        image_axes.set_position(gs[0].get_position(self.fig))
        image_axes.xaxis.tick_bottom()
        image_axes.yaxis.tick_left()
        self.axx, self.axy = None, None

        self.mpl_toolbar.update()  # sync list of axes in navstack
        self.canvas.draw_idle()

    def plot_MDH_orthogonal(self, ws, **kwargs):
        """
        clears the plot and creates a new one using a MDHistoWorkspace
        """
        self.clear_image()
        self.image = self.ax.imshow(ws,
                                    origin='lower',
                                    aspect='auto',
                                    transpose=self.dimensions.transpose,
                                    norm=self.colorbar.get_norm(),
                                    **kwargs)
        # ensure the axes data limits are updated to match the
        # image. For example if the axes were zoomed and the
        # swap dimensions was clicked we need to restore the
        # appropriate extents to see the image in the correct place
        extent = self.image.get_extent()
        self.ax.set_xlim(extent[0], extent[1])
        self.ax.set_ylim(extent[2], extent[3])

        self.draw_plot()

    def plot_MDH_nonorthogonal(self, ws, **kwargs):
        self.clear_image()
        self.image = pcolormesh_nonorthogonal(
            self.ax,
            ws,
            self.nonortho_tr,
            transpose=self.dimensions.transpose,
            norm=self.colorbar.get_norm(),
            **kwargs)
        # swapping dimensions in nonorthogonal mode currently resets back to the
        # full data limits as the whole axes has been recreated so we don't have
        # access to the original limits
        # pcolormesh clears any grid that was previously visible
        if self.grid_on:
            self.ax.grid(self.grid_on)
        self.draw_plot()

    def plot_matrix(self, ws, **kwargs):
        """
        clears the plot and creates a new one using a MatrixWorkspace keeping
        the axes limits that have already been set
        """
        # ensure view is correct if zoomed in while swapping dimensions
        # compute required extent and just have resampling imshow deal with it
        old_extent = None
        if self.image is not None:
            old_extent = self.image.get_extent()
            if self.image.transpose != self.dimensions.transpose:
                e1, e2, e3, e4 = old_extent
                old_extent = e3, e4, e1, e2

        self.clear_image()
        self.image = imshow_sampling(self.ax,
                                     ws,
                                     origin='lower',
                                     aspect='auto',
                                     interpolation='none',
                                     transpose=self.dimensions.transpose,
                                     norm=self.colorbar.get_norm(),
                                     extent=old_extent,
                                     **kwargs)

        self.draw_plot()

    def clear_image(self):
        """Removes any image from the axes"""
        if self.image is not None:
            if self.line_plots:
                self.delete_line_plot_lines()
            self.image_info_widget.updateTable(DBLMAX, DBLMAX, DBLMAX)
            self.image.remove()
            self.image = None

    def clear_figure(self):
        """Removes everything from the figure"""
        if self.line_plots:
            self.delete_line_plot_lines()
            self.axx, self.axy = None, None
        self.image = None
        self.canvas.disable_zoom_on_scroll()
        self.fig.clf()
        self.ax = None

    def draw_plot(self):
        self.ax.set_title('')
        self.colorbar.set_mappable(self.image)
        self.colorbar.update_clim()
        self.mpl_toolbar.update()  # clear nav stack
        self.delete_line_plot_lines()
        self.update_line_plot_labels()
        self.canvas.draw_idle()

    def select_zoom(self):
        """Select the zoom control on the toolbar"""
        self.mpl_toolbar.zoom()

    def update_plot_data(self, data):
        """
        This just updates the plot data without creating a new plot. The extents
        can change if the data has been rebinned
        """
        if self.nonortho_tr:
            self.image.set_array(data.T.ravel())
        else:
            self.image.set_data(data.T)
        self.colorbar.update_clim()

    def on_home_clicked(self):
        """Reset the view to encompass all of the data"""
        self.presenter.show_all_data_requested()

    def on_line_plots_toggle(self, state):
        self.presenter.line_plots(state)

    def on_non_orthogonal_axes_toggle(self, state):
        """
        Switch state of the non-orthognal axes on/off
        """
        self.presenter.nonorthogonal_axes(state)

    def on_data_limits_changed(self):
        """
        React to when the data limits have changed
        """
        self.presenter.data_limits_changed()

    def enable_lineplots_button(self):
        """
        Enables line plots functionality
        """
        self.mpl_toolbar.set_action_enabled(ToolItemText.LINEPLOTS, True)

    def disable_lineplots_button(self):
        """
        Disabled line plots functionality
        """
        self.mpl_toolbar.set_action_enabled(ToolItemText.LINEPLOTS, False)

    def enable_peaks_button(self):
        """
        Enables line plots functionality
        """
        self.mpl_toolbar.set_action_enabled(ToolItemText.OVERLAYPEAKS, True)

    def disable_peaks_button(self):
        """
        Disables line plots functionality
        """
        self.mpl_toolbar.set_action_enabled(ToolItemText.OVERLAYPEAKS, False)

    def enable_nonorthogonal_axes_button(self):
        """
        Enables access to non-orthogonal axes functionality
        """
        self.mpl_toolbar.set_action_enabled(ToolItemText.NONORTHOGONAL_AXES,
                                            True)

    def disable_nonorthogonal_axes_button(self):
        """
        Disables non-orthorognal axes functionality
        """
        self.mpl_toolbar.set_action_enabled(ToolItemText.NONORTHOGONAL_AXES,
                                            state=False)

    def delete_line_plot_lines(self):
        try:  # clear old plots
            try:
                self.xfig.remove()
                self.yfig.remove()
            except ValueError:
                pass
            del self.xfig
            del self.yfig
        except AttributeError:
            pass

    def get_axes_limits(self):
        """
        Return the limits of the image axes or None if no image yet exists
        """
        if self.image is None:
            return None
        else:
            return self.ax.get_xlim(), self.ax.get_ylim()

    def set_axes_limits(self, xlim, ylim):
        """
        Set the view limits on the image axes to the given extents
        :param xlim: 2-tuple of (xmin, xmax)
        :param ylim: 2-tuple of (ymin, ymax)
        """
        self.ax.set_xlim(xlim)
        self.ax.set_ylim(ylim)

    def set_grid_on(self):
        """
        If not visible sets the grid visibility
        """
        if not self._grid_on:
            self._grid_on = True
            self.mpl_toolbar.set_action_checked(ToolItemText.GRID,
                                                state=self._grid_on)

    def set_nonorthogonal_transform(self, transform):
        """
        Set the transform for nonorthogonal axes mode
        :param transform: An object with a tr method to transform from nonorthognal
                          coordinates to display coordinates
        """
        self.nonortho_tr = transform.tr

    def toggle_grid(self, state):
        """
        Toggle the visibility of the grid on the axes
        """
        self._grid_on = state
        self.ax.grid(self._grid_on)
        self.canvas.draw_idle()

    def mouse_move(self, event):
        if event.inaxes == self.ax:
            signal = self.update_image_data(event.xdata, event.ydata,
                                            self.line_plots)
            if self.track_cursor.checkState() == Qt.Checked:
                self.update_image_table_widget(event.xdata, event.ydata,
                                               signal)

    def mouse_outside_image(self, _):
        """
        Indicates that the mouse have moved outside of an axes.
        We clear the line plots so that it is not confusing what they mean.
        """
        if self.line_plots:
            self.delete_line_plot_lines()
            self.canvas.draw_idle()

    def mouse_click(self, event):
        if self.track_cursor.checkState() == Qt.Unchecked \
                and event.inaxes == self.ax and event.button == 1:
            signal = self.update_image_data(event.xdata, event.ydata)
            self.update_image_table_widget(event.xdata, event.ydata, signal)

    def mouse_release(self, event):
        if event.button == 3 and event.inaxes == self.ax:
            self.on_home_clicked()

    def update_image_table_widget(self, xdata, ydata, signal):
        if signal is not None:
            if self.dimensions.transpose and self.ws_type == "MATRIX":
                self.image_info_widget.updateTable(ydata, xdata, signal)
            else:
                self.image_info_widget.updateTable(xdata, ydata, signal)

    def plot_x_line(self, x, y):
        try:
            self.xfig.set_data(x, y)
        except (AttributeError, IndexError):
            self.axx.clear()
            self.xfig = self.axx.plot(x, y, scalex=False)[0]
            self.update_line_plot_labels()
            self.update_line_plot_limits()
        self.canvas.draw_idle()

    def plot_y_line(self, x, y):
        try:
            self.yfig.set_data(y, x)
        except (AttributeError, IndexError):
            self.axy.clear()
            self.yfig = self.axy.plot(y, x, scaley=False)[0]
            self.update_line_plot_labels()
            self.update_line_plot_limits()
        self.canvas.draw_idle()

    def update_data_clim(self):
        self.image.set_clim(self.colorbar.colorbar.mappable.get_clim())
        self.canvas.draw_idle()

    def update_line_plot_limits(self):
        try:  # set line plot intensity axes to match colorbar limits
            self.axx.set_ylim(self.colorbar.cmin_value,
                              self.colorbar.cmax_value)
            self.axy.set_xlim(self.colorbar.cmin_value,
                              self.colorbar.cmax_value)
        except AttributeError:
            pass

    def update_line_plot_labels(self):
        try:  # ensure plot labels are in sync with main axes
            self.axx.set_xlabel(self.ax.get_xlabel())
            self.axy.set_ylabel(self.ax.get_ylabel())
        except AttributeError:
            pass

    def update_image_data(self, x, y, update_line_plot=False):
        xmin, xmax, ymin, ymax = self.image.get_extent()
        arr = self.image.get_array()
        data_extent = Bbox([[ymin, xmin], [ymax, xmax]])
        array_extent = Bbox([[0, 0], arr.shape[:2]])
        trans = BboxTransform(boxin=data_extent, boxout=array_extent)
        point = trans.transform_point([y, x])
        if any(np.isnan(point)):
            return
        i, j = point.astype(int)

        if update_line_plot:
            if 0 <= i < arr.shape[0]:
                self.plot_x_line(np.linspace(xmin, xmax, arr.shape[1]),
                                 arr[i, :])
            if 0 <= j < arr.shape[1]:
                self.plot_y_line(np.linspace(ymin, ymax, arr.shape[0]), arr[:,
                                                                            j])

        # Clip the coordinates at array bounds
        if not (0 <= i < arr.shape[0]) or not (0 <= j < arr.shape[1]):
            return None
        else:
            return arr[i, j]

    def set_normalization(self, ws, **kwargs):
        normalize_by_bin_width, _ = get_normalize_by_bin_width(
            ws, self.ax, **kwargs)
        is_normalized = normalize_by_bin_width or ws.isDistribution()
        if is_normalized:
            self.presenter.normalization = mantid.api.MDNormalization.VolumeNormalization
            self.norm_opts.setCurrentIndex(1)
        else:
            self.presenter.normalization = mantid.api.MDNormalization.NoNormalization
            self.norm_opts.setCurrentIndex(0)
Ejemplo n.º 9
0
class CondaPackageActionDialog(QDialog):
    """ """
    def __init__(self, parent, prefix, name, action, version, versions,
                 packages_sizes, active_channels):
        super(CondaPackageActionDialog, self).__init__(parent)
        self._parent = parent
        self._prefix = prefix
        self._version_text = None
        self._name = name
        self._dependencies_dic = {}
        self._active_channels = active_channels
        self._packages_sizes = packages_sizes
        self.api = ManagerAPI()

        # Widgets
        self.label = QLabel(self)
        self.combobox_version = QComboBox()
        self.label_version = QLabel(self)
        self.widget_version = None
        self.table_dependencies = None

        self.checkbox = QCheckBox(_('Install dependencies (recommended)'))
        self.bbox = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)

        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        self.button_cancel.setDefault(True)
        self.button_cancel.setAutoDefault(True)

        dialog_size = QSize(300, 90)

        # Helper variable values
        action_title = {
            C.ACTION_UPGRADE: _("Upgrade package"),
            C.ACTION_DOWNGRADE: _("Downgrade package"),
            C.ACTION_REMOVE: _("Remove package"),
            C.ACTION_INSTALL: _("Install package")
        }

        # FIXME: There is a bug, a package installed by anaconda has version
        # astropy 0.4 and the linked list 0.4 but the available versions
        # in the json file do not include 0.4 but 0.4rc1... so...
        # temporal fix is to check if inside list otherwise show full list
        if action == C.ACTION_UPGRADE:
            if version in versions:
                index = versions.index(version)
                combo_versions = versions[index + 1:]
            else:
                versions = versions
        elif action == C.ACTION_DOWNGRADE:
            if version in versions:
                index = versions.index(version)
                combo_versions = versions[:index]
            else:
                versions = versions
        elif action == C.ACTION_REMOVE:
            combo_versions = [version]
            self.combobox_version.setEnabled(False)
        elif action == C.ACTION_INSTALL:
            combo_versions = versions

        # Reverse order for combobox
        combo_versions = list(reversed(combo_versions))

        if len(versions) == 1:
            if action == C.ACTION_REMOVE:
                labeltext = _('Package version to remove:')
            else:
                labeltext = _('Package version available:')
            self.label_version.setText(combo_versions[0])
            self.widget_version = self.label_version
        else:
            labeltext = _("Select package version:")
            self.combobox_version.addItems(combo_versions)
            self.widget_version = self.combobox_version

        self.label.setText(labeltext)
        self.label_version.setAlignment(Qt.AlignLeft)
        self.table_dependencies = QWidget(self)

        layout = QVBoxLayout()
        version_layout = QHBoxLayout()
        version_layout.addWidget(self.label)
        version_layout.addStretch()
        version_layout.addWidget(self.widget_version)
        layout.addLayout(version_layout)

        self.widgets = [
            self.checkbox, self.button_ok, self.widget_version,
            self.table_dependencies
        ]

        # Create a Table
        if action in [C.ACTION_INSTALL, C.ACTION_UPGRADE, C.ACTION_DOWNGRADE]:
            table = QTableView(self)
            dialog_size = QSize(dialog_size.width() + 40, 300)
            self.table_dependencies = table
            layout.addWidget(self.checkbox)
            self.checkbox.setChecked(True)
            self._changed_version(versions[0])

            table.setSelectionBehavior(QAbstractItemView.SelectRows)
            table.verticalHeader().hide()
            table.horizontalHeader().hide()
            table.setAlternatingRowColors(True)
            table.setShowGrid(False)
            table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            table.horizontalHeader().setStretchLastSection(True)

        layout.addWidget(self.table_dependencies)
        layout.addWidget(self.bbox)

        title = "{0}: {1}".format(action_title[action], name)
        self.setLayout(layout)
        self.setMinimumSize(dialog_size)
        self.setFixedSize(dialog_size)
        self.setWindowTitle(title)
        self.setModal(True)

        # Signals and slots
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.close)
        self.combobox_version.currentIndexChanged.connect(
            self._changed_version)
        self.checkbox.stateChanged.connect(self._changed_checkbox)

    def _changed_version(self, version, dependencies=True):
        """ """
        self._set_gui_disabled(True)
        version = self.combobox_version.currentText()
        install_dependencies = (self.checkbox.checkState() == Qt.Checked)
        self._version_text = to_text_string(version)
        self._get_dependencies(install_dependencies)

    def _get_dependencies(self, dependencies=True):
        """ """
        package_name = [self._name + '=' + self._version_text]

        worker = self.api.conda_dependencies(prefix=self._prefix,
                                             pkgs=package_name,
                                             dep=dependencies,
                                             channels=self._active_channels)
        worker.sig_finished.connect(self._on_process_finished)

    def _changed_checkbox(self, state):
        """ """
        if state:
            self._changed_version(self._version_text)
        else:
            self._changed_version(self._version_text, dependencies=False)

    def _on_process_finished(self, worker, output, error):
        """ """
        if self.isVisible():
            dic = output
            self.dependencies_dic = dic
            self._set_dependencies_table()
            self._set_gui_disabled(False)

    def _set_dependencies_table(self):
        """ """
        table = self.table_dependencies
        dic = self.dependencies_dic
        table.setModel(CondaDependenciesModel(self, dic, self._packages_sizes))
        table.resizeColumnsToContents()
        table.resizeRowsToContents()

    def _set_gui_disabled(self, value):
        """ """
        if value:
            table = self.table_dependencies
            table.setModel(CondaDependenciesModel(self, {}))
            table.resizeColumnsToContents()
            table.setDisabled(True)
        else:
            table = self.table_dependencies
            table.setDisabled(False)

        for widget in self.widgets:
            widget.setDisabled(value)

    def reject(self):
        self.api.conda_terminate()
        super(CondaPackageActionDialog, self).reject()
Ejemplo n.º 10
0
class BONormEdit(SiriusMainWindow):
    """Widget to perform optics adjust in normalized configurations."""

    normConfigChanged = Signal(float, dict)

    def __init__(self, parent=None, prefix='', ramp_config=None,
                 norm_config=None, time=None, energy=None,
                 magnets=dict(), conn_sofb=None,
                 tunecorr_configname=None, chromcorr_configname=None):
        """Initialize object."""
        super().__init__(parent)
        self.setWindowTitle('Edit Normalized Configuration')
        self.setObjectName('BOApp')
        self.prefix = prefix
        self.ramp_config = ramp_config
        self.norm_config = _dcopy(norm_config)
        self.time = time
        self.energy = energy

        self._aux_magnets = magnets
        self._conn_sofb = conn_sofb
        self._tunecorr = BOTuneCorr(tunecorr_configname)
        self._chromcorr = BOChromCorr(chromcorr_configname)

        self._reference = _dcopy(norm_config)
        self._currChrom = self._estimateChrom(use_ref=True)
        self._deltas = {
            'kicks': dict(),
            'factorH': 0.0,
            'factorV': 0.0,
            'tuneX': 0.0,
            'tuneY': 0.0,
            'chromX': self._currChrom[0],
            'chromY': self._currChrom[1],
        }
        self._setupUi()
        self._setupMenu()
        self.verifySync()

    # ---------- setup/build layout ----------

    def _setupUi(self):
        self.label_description = QLabel(
            '<h2>'+self.norm_config['label']+'</h2>', self)
        self.label_description.setAlignment(Qt.AlignCenter)
        self.label_time = QLabel('<h2>T = '+str(self.time)+'ms</h2>', self)
        self.label_time.setAlignment(Qt.AlignCenter)

        self.strengths = self._setupStrengthWidget()
        self.orbit = self._setupOrbitWidget()
        self.tune = self._setupTuneWidget()
        self.chrom = self._setupChromWidget()

        self.bt_apply = QPushButton(qta.icon('fa5s.angle-right'), '', self)
        self.bt_apply.setToolTip('Apply Changes to Machine')
        self.bt_apply.setStyleSheet('icon-size: 30px 30px;')
        self.bt_apply.clicked.connect(self._updateRampConfig)

        cw = QWidget()
        lay = QGridLayout()
        lay.setVerticalSpacing(10)
        lay.setHorizontalSpacing(10)
        lay.addWidget(self.label_description, 0, 0, 1, 2)
        lay.addWidget(self.label_time, 1, 0, 1, 2)
        lay.addWidget(self.strengths, 2, 0, 4, 1)
        lay.addWidget(self.orbit, 2, 1)
        lay.addWidget(self.tune, 3, 1)
        lay.addWidget(self.chrom, 4, 1)
        lay.addWidget(self.bt_apply, 5, 1)
        lay.setColumnStretch(0, 2)
        lay.setColumnStretch(1, 2)
        lay.setRowStretch(0, 2)
        lay.setRowStretch(1, 2)
        lay.setRowStretch(2, 8)
        lay.setRowStretch(3, 8)
        lay.setRowStretch(4, 8)
        lay.setRowStretch(5, 1)
        cw.setLayout(lay)

        cw.setStyleSheet("""
            QGroupBox::title{
                subcontrol-origin: margin;
                subcontrol-position: top center;
                padding: 0 2px 0 2px;}""")
        cw.setFocusPolicy(Qt.StrongFocus)
        self.setCentralWidget(cw)

    def _setupMenu(self):
        self.menubar = QMenuBar(self)
        self.layout().setMenuBar(self.menubar)
        self.menu = self.menubar.addMenu('Options')
        self.act_saveas = self.menu.addAction('Save as...')
        self.act_saveas.triggered.connect(self._showSaveAsPopup)

        self._undo_stack = QUndoStack(self)
        self.act_undo = self._undo_stack.createUndoAction(self, 'Undo')
        self.act_undo.setShortcut(QKeySequence.Undo)
        self.menu.addAction(self.act_undo)
        self.act_redo = self._undo_stack.createRedoAction(self, 'Redo')
        self.act_redo.setShortcut(QKeySequence.Redo)
        self.menu.addAction(self.act_redo)

    def _setupStrengthWidget(self):
        scrollarea = QScrollArea()
        self.nconfig_data = QWidget()
        flay_configdata = QFormLayout()
        psnames = self._get_PSNames()
        self._map_psnames2wigdets = dict()
        for ps in psnames:
            ps = SiriusPVName(ps)
            if ps in ramp.BoosterRamp.PSNAME_DIPOLES:
                ps_value = QLabel(str(self.norm_config[ps])+' GeV', self)
                flay_configdata.addRow(QLabel(ps + ': ', self), ps_value)
            else:
                ps_value = QDoubleSpinBoxPlus(self.nconfig_data)
                ps_value.setDecimals(6)
                ps_value.setMinimum(-10000)
                ps_value.setMaximum(10000)
                ps_value.setValue(self.norm_config[ps])
                ps_value.valueChanged.connect(self._handleStrenghtsSet)

                if ps.dev in {'QD', 'QF', 'QS'}:
                    unit_txt = '1/m'
                elif ps.dev in {'SD', 'SF'}:
                    unit_txt = '1/m²'
                else:
                    unit_txt = 'urad'
                label_unit = QLabel(unit_txt, self)
                label_unit.setStyleSheet("min-width:2.5em; max-width:2.5em;")
                hb = QHBoxLayout()
                hb.addWidget(ps_value)
                hb.addWidget(label_unit)

                flay_configdata.addRow(QLabel(ps + ': ', self), hb)

            ps_value.setObjectName(ps)
            ps_value.setStyleSheet("min-height:1.29em; max-height:1.29em;")
            self._map_psnames2wigdets[ps] = ps_value

        self.nconfig_data.setObjectName('data')
        self.nconfig_data.setStyleSheet("""
            #data{background-color: transparent;}""")
        self.nconfig_data.setLayout(flay_configdata)
        scrollarea.setWidget(self.nconfig_data)

        self.cb_checklims = QCheckBox('Set limits according to energy', self)
        self.cb_checklims.setChecked(False)
        self.cb_checklims.stateChanged.connect(self._handleStrengtsLimits)

        self.bt_graph = QPushButton(qta.icon('mdi.chart-line'), '', self)
        self.bt_graph.clicked.connect(self._show_kicks_graph)

        gbox = QGroupBox()
        gbox.setObjectName('strengths')
        gbox.setStyleSheet('#strengths{min-width:20em;}')
        glay = QGridLayout()
        glay.addWidget(scrollarea, 0, 0, 1, 2)
        glay.addWidget(self.cb_checklims, 1, 0, alignment=Qt.AlignLeft)
        glay.addWidget(self.bt_graph, 1, 1, alignment=Qt.AlignRight)
        gbox.setLayout(glay)
        return gbox

    def _setupOrbitWidget(self):
        self.bt_get_kicks = QPushButton('Get Kicks from SOFB', self)
        self.bt_get_kicks.clicked.connect(self._handleGetKicksFromSOFB)

        label_correctH = QLabel('Correct H', self,
                                alignment=Qt.AlignRight | Qt.AlignVCenter)
        self.sb_correctH = QDoubleSpinBoxPlus(self)
        self.sb_correctH.setValue(self._deltas['factorH'])
        self.sb_correctH.setDecimals(1)
        self.sb_correctH.setMinimum(-10000)
        self.sb_correctH.setMaximum(10000)
        self.sb_correctH.setSingleStep(0.1)
        self.sb_correctH.setObjectName('factorH')
        self.sb_correctH.editingFinished.connect(self._handleCorrFactorsSet)
        labelH = QLabel('%', self)

        label_correctV = QLabel('Correct V', self,
                                alignment=Qt.AlignRight | Qt.AlignVCenter)
        self.sb_correctV = QDoubleSpinBoxPlus(self)
        self.sb_correctV.setValue(self._deltas['factorV'])
        self.sb_correctV.setDecimals(1)
        self.sb_correctV.setMinimum(-10000)
        self.sb_correctV.setMaximum(10000)
        self.sb_correctV.setSingleStep(0.1)
        self.sb_correctV.setObjectName('factorV')
        self.sb_correctV.editingFinished.connect(self._handleCorrFactorsSet)
        labelV = QLabel('%', self)

        self.bt_update_ref_orbit = QPushButton('Update reference', self)
        self.bt_update_ref_orbit.clicked.connect(
            _part(self._updateReference, 'corrs'))

        gbox = QGroupBox('Orbit', self)
        lay = QGridLayout()
        lay.addWidget(self.bt_get_kicks, 0, 0, 1, 4)
        lay.addWidget(label_correctH, 1, 0)
        lay.addWidget(self.sb_correctH, 1, 2)
        lay.addWidget(labelH, 1, 3)
        lay.addWidget(label_correctV, 2, 0)
        lay.addWidget(self.sb_correctV, 2, 2)
        lay.addWidget(labelV, 2, 3)
        lay.addWidget(self.bt_update_ref_orbit, 3, 2, 1, 2)
        lay.setColumnStretch(0, 16)
        lay.setColumnStretch(1, 1)
        lay.setColumnStretch(2, 14)
        lay.setColumnStretch(3, 2)
        gbox.setLayout(lay)
        return gbox

    def _setupTuneWidget(self):
        for cord in ['X', 'Y']:
            setattr(self, 'label_deltaTune'+cord,
                    QLabel('Δν<sub>'+cord+'</sub>: '))
            lab = getattr(self, 'label_deltaTune'+cord)
            lab.setStyleSheet("min-width:1.55em; max-width:1.55em;")

            setattr(self, 'sb_deltaTune'+cord, QDoubleSpinBoxPlus(self))
            sb = getattr(self, 'sb_deltaTune'+cord)
            sb.setDecimals(6)
            sb.setMinimum(-5)
            sb.setMaximum(5)
            sb.setSingleStep(0.0001)
            sb.setObjectName('tune'+cord)
            sb.editingFinished.connect(self._handleDeltaTuneSet)

        label_KL = QLabel('<h4>ΔKL [1/m]</h4>', self)
        label_KL.setStyleSheet("""min-height:1.55em; max-height:1.55em;
                                  qproperty-alignment: AlignCenter;""")
        self.l_deltaKLQF = QLabel('', self)
        self.l_deltaKLQD = QLabel('', self)

        self.bt_update_ref_deltaKL = QPushButton('Update reference', self)
        self.bt_update_ref_deltaKL.clicked.connect(
            _part(self._updateReference, 'quads'))

        gbox = QGroupBox('Tune', self)
        lay = QGridLayout()
        lay.addWidget(self.label_deltaTuneX, 1, 0)
        lay.addWidget(self.sb_deltaTuneX, 1, 1)
        lay.addWidget(self.label_deltaTuneY, 1, 3)
        lay.addWidget(self.sb_deltaTuneY, 1, 4)
        lay.addWidget(label_KL, 3, 0, 1, 5)
        lay.addWidget(QLabel('QF: '), 4, 0)
        lay.addWidget(self.l_deltaKLQF, 4, 1)
        lay.addWidget(QLabel('QD: '), 4, 3)
        lay.addWidget(self.l_deltaKLQD, 4, 4)
        lay.addWidget(self.bt_update_ref_deltaKL, 6, 3, 1, 2)
        lay.setVerticalSpacing(6)
        lay.setColumnStretch(0, 2)
        lay.setColumnStretch(1, 4)
        lay.setColumnStretch(2, 1)
        lay.setColumnStretch(3, 2)
        lay.setColumnStretch(4, 4)
        lay.setRowStretch(0, 1)
        lay.setRowStretch(1, 2)
        lay.setRowStretch(2, 1)
        lay.setRowStretch(3, 2)
        lay.setRowStretch(4, 2)
        lay.setRowStretch(5, 1)
        lay.setRowStretch(6, 2)
        gbox.setLayout(lay)
        return gbox

    def _setupChromWidget(self):
        for cord in ['X', 'Y']:
            setattr(self, 'label_Chrom'+cord,
                    QLabel('ξ<sub>'+cord+'</sub>: '))
            lab = getattr(self, 'label_Chrom'+cord)
            lab.setStyleSheet("min-width:1.55em; max-width:1.55em;")

            setattr(self, 'sb_Chrom'+cord, QDoubleSpinBoxPlus(self))
            sb = getattr(self, 'sb_Chrom'+cord)
            sb.setDecimals(6)
            sb.setMinimum(-5)
            sb.setMaximum(5)
            sb.setSingleStep(0.0001)
            sb.setObjectName('chrom'+cord)
            sb.setValue(self._deltas['chrom'+cord])
            sb.editingFinished.connect(self._handleChromSet)

        label_SL = QLabel('<h4>ΔSL [1/m<sup>2</sup>]</h4>', self)
        label_SL.setStyleSheet("""min-height:1.55em; max-height:1.55em;
                                  qproperty-alignment: AlignCenter;""")
        self.l_deltaSLSF = QLabel('', self)
        self.l_deltaSLSD = QLabel('', self)

        self.bt_update_ref_deltaSL = QPushButton('Update reference', self)
        self.bt_update_ref_deltaSL.clicked.connect(
            _part(self._updateReference, 'sexts'))

        gbox = QGroupBox('Chromaticity', self)
        lay = QGridLayout()
        lay.addWidget(self.label_ChromX, 1, 0)
        lay.addWidget(self.sb_ChromX, 1, 1)
        lay.addWidget(self.label_ChromY, 1, 3)
        lay.addWidget(self.sb_ChromY, 1, 4)
        lay.addWidget(label_SL, 3, 0, 1, 5)
        lay.addWidget(QLabel('SF: '), 4, 0)
        lay.addWidget(self.l_deltaSLSF, 4, 1)
        lay.addWidget(QLabel('SD: '), 4, 3)
        lay.addWidget(self.l_deltaSLSD, 4, 4)
        lay.addWidget(self.bt_update_ref_deltaSL, 6, 3, 1, 2)
        lay.setVerticalSpacing(6)
        lay.setColumnStretch(0, 2)
        lay.setColumnStretch(1, 4)
        lay.setColumnStretch(2, 1)
        lay.setColumnStretch(3, 2)
        lay.setColumnStretch(4, 4)
        lay.setRowStretch(0, 1)
        lay.setRowStretch(1, 2)
        lay.setRowStretch(2, 1)
        lay.setRowStretch(3, 2)
        lay.setRowStretch(4, 2)
        lay.setRowStretch(5, 1)
        lay.setRowStretch(6, 2)
        gbox.setLayout(lay)
        return gbox

    # ---------- server communication ----------

    def _save(self, name):
        try:
            nconf = ramp.BoosterNormalized()
            nconf.value = self.norm_config
            nconf.save(new_name=name)
        except _ConfigDBException as err:
            QMessageBox.critical(self, 'Error', str(err), QMessageBox.Ok)

    def _showSaveAsPopup(self):
        self._saveAsPopup = _SaveConfigDialog('bo_normalized', self)
        self._saveAsPopup.configname.connect(self._save)
        self._saveAsPopup.open()

    def verifySync(self):
        if self.ramp_config is None:
            return
        if not self.ramp_config.verify_ps_normalized_synchronized(
                self.time, value=self.norm_config):
            self.label_time.setStyleSheet('color: red;')
            self.label_description.setStyleSheet('color: red;')
            self.setToolTip("There are unsaved changes")
        else:
            self.label_time.setStyleSheet('color: black;')
            self.label_description.setStyleSheet('color: black;')
            self.setToolTip("")

    # ---------- strengths ----------

    def _handleStrenghtsSet(self, new_value):
        psname = self.sender().objectName()
        self._stack_command(
            self.sender(), self.norm_config[psname], new_value,
            message='set '+psname+' strength to {}'.format(new_value))
        self.norm_config[psname] = new_value
        self.verifySync()

    def _handleStrengtsLimits(self, state):
        psnames = list(self.norm_config.keys())
        psnames.remove('BO-Fam:PS-B-1')
        psnames.remove('BO-Fam:PS-B-2')
        psnames.remove('label')
        if state:
            for ps in psnames:
                ps_value = self.nconfig_data.findChild(
                    QDoubleSpinBoxPlus, name=ps)
                ma = _MASearch.conv_psname_2_psmaname(ps)
                aux = self._aux_magnets[ma]
                currs = (aux.current_min, aux.current_max)
                lims = aux.conv_current_2_strength(
                    currents=currs, strengths_dipole=self.energy)
                ps_value.setMinimum(min(lims))
                ps_value.setMaximum(max(lims))
        else:
            for ps in psnames:
                ps_value = self.nconfig_data.findChild(
                    QDoubleSpinBoxPlus, name=ps)
                ps_value.setMinimum(-10000)
                ps_value.setMaximum(10000)

    def _updateStrenghtsWidget(self, pstype):
        psnames = self._get_PSNames(pstype)
        wid2change = psnames if psnames else list(self.norm_config.keys())
        for wid in wid2change:
            value = self.norm_config[wid]
            self._map_psnames2wigdets[wid].setValue(value)

    # ---------- orbit ----------

    def _updateCorrKicks(self):
        for psname, dkick in self._deltas['kicks'].items():
            corr_factor = self._deltas['factorV'] if 'CV' in psname \
                else self._deltas['factorH']
            corr_factor /= 100
            self.norm_config[psname] = self._reference[psname] + \
                dkick*corr_factor

    def _handleGetKicksFromSOFB(self):
        if not self._conn_sofb.connected:
            QMessageBox.warning(
                self, 'Not Connected',
                'There are not connected PVs!', QMessageBox.Ok)
            return
        dkicks = self._conn_sofb.get_deltakicks()

        if not dkicks:
            QMessageBox.warning(
                self, 'Could not get kicks',
                'Could not get kicks from SOFB!', QMessageBox.Ok)
            return

        self._deltas['kicks'] = dkicks
        self._updateCorrKicks()
        self._updateStrenghtsWidget('corrs')
        self.verifySync()

    def _handleCorrFactorsSet(self):
        widget = self.sender()
        factor = widget.objectName()
        dim = ' vertical ' if factor == 'factorV' else ' horizantal '
        new_value = widget.value()
        self._stack_command(
            widget, self._deltas[factor], new_value,
            message='set'+dim+'orbit correction factor to {}'.format(
                    new_value))
        self._deltas[factor] = new_value

        self._updateCorrKicks()
        self._updateStrenghtsWidget('corrs')
        self.verifySync()

    def _resetOrbitChanges(self):
        self._deltas['kicks'] = dict()
        self._deltas['factorH'] = 0.0
        self._deltas['factorV'] = 0.0
        self.sb_correctH.setValue(0.0)
        self.sb_correctV.setValue(0.0)

    # ---------- tune ----------

    def _handleDeltaTuneSet(self):
        widget = self.sender()
        tune = widget.objectName()
        dim = ' vertical ' if tune == 'tuneY' else ' horizantal '
        new_value = widget.value()
        self._stack_command(
            widget, self._deltas[tune], new_value,
            message='set'+dim+'delta tune to {}'.format(
                    new_value))
        self._deltas[tune] = new_value

        self._updateDeltaKL()

    def _updateDeltaKL(self):
        self._deltaKL = self._tunecorr.calculate_deltaKL(
            [self._deltas['tuneX'], self._deltas['tuneY']])
        self.l_deltaKLQF.setText('{: 4f}'.format(self._deltaKL[0]))
        self.l_deltaKLQD.setText('{: 4f}'.format(self._deltaKL[1]))

        self.norm_config['BO-Fam:PS-QF'] = \
            self._reference['BO-Fam:PS-QF'] + self._deltaKL[0]
        self.norm_config['BO-Fam:PS-QD'] = \
            self._reference['BO-Fam:PS-QD'] + self._deltaKL[1]

        self._updateStrenghtsWidget('quads')
        self.verifySync()

    def _resetTuneChanges(self):
        self.sb_deltaTuneX.setValue(0)
        self.sb_deltaTuneY.setValue(0)
        self._deltaKL = [0.0, 0.0]
        self.l_deltaKLQF.setText('{: 6f}'.format(self._deltaKL[0]))
        self.l_deltaKLQD.setText('{: 6f}'.format(self._deltaKL[1]))

    # ---------- chromaticity ----------

    def _estimateChrom(self, use_ref=False):
        nom_SL = self._chromcorr.nominal_intstrengths.flatten()
        if use_ref:
            curr_SL = _np.array([self._reference['BO-Fam:PS-SF'],
                                 self._reference['BO-Fam:PS-SD']])
        else:
            curr_SL = _np.array([self.norm_config['BO-Fam:PS-SF'],
                                 self.norm_config['BO-Fam:PS-SD']])
        delta_SL = curr_SL - nom_SL
        return self._chromcorr.calculate_Chrom(delta_SL)

    def _handleChromSet(self):
        widget = self.sender()
        chrom = widget.objectName()
        dim = ' vertical ' if chrom == 'chromY' else ' horizantal '
        new_value = widget.value()
        self._stack_command(
            widget, self._deltas[chrom], new_value,
            message='set'+dim+'chromaticity to {}'.format(
                    new_value))
        self._deltas[chrom] = new_value

        self._updateDeltaSL()

    def _updateDeltaSL(self):
        desired_Chrom = _np.array([self._deltas['chromX'],
                                   self._deltas['chromY']])
        deltas = desired_Chrom - self._currChrom
        self._deltaSL = self._chromcorr.calculate_deltaSL(
            [deltas[0], deltas[1]])
        self.l_deltaSLSF.setText('{: 4f}'.format(self._deltaSL[0]))
        self.l_deltaSLSD.setText('{: 4f}'.format(self._deltaSL[1]))

        self.norm_config['BO-Fam:PS-SF'] = \
            self._reference['BO-Fam:PS-SF'] + self._deltaSL[0]
        self.norm_config['BO-Fam:PS-SD'] = \
            self._reference['BO-Fam:PS-SD'] + self._deltaSL[1]

        self._updateStrenghtsWidget('sexts')
        self.verifySync()

    def _resetChromChanges(self):
        self._currChrom = self._estimateChrom(use_ref=True)
        self.sb_ChromX.setValue(self._currChrom[0])
        self.sb_ChromY.setValue(self._currChrom[1])
        self._deltaSL = [0.0, 0.0]
        self.l_deltaSLSF.setText('{: 6f}'.format(self._deltaSL[0]))
        self.l_deltaSLSD.setText('{: 6f}'.format(self._deltaSL[1]))

    # ---------- update methods ----------

    def _updateReference(self, pstype):
        psnames = self._get_PSNames(pstype)
        for ps in psnames:
            self._reference[ps] = self.norm_config[ps]

        if pstype == 'corrs':
            self._resetOrbitChanges()
        elif pstype == 'quads':
            self._resetTuneChanges()
        elif pstype == 'sexts':
            self._resetChromChanges()
        else:
            self._resetOrbitChanges()
            self._resetTuneChanges()
            self._resetChromChanges()

        self.verifySync()

    def _updateRampConfig(self):
        if self.norm_config is not None:
            self.normConfigChanged.emit(self.time, _dcopy(self.norm_config))

    def updateTime(self, time):
        """Update norm config time."""
        self.time = time
        self.label_time.setText('<h2>T = '+str(time)+'ms</h2>')
        self.energy = self.ramp_config.ps_waveform_interp_energy(time)
        self._handleStrengtsLimits(self.cb_checklims.checkState())
        self.verifySync()

    def updateLabel(self, label):
        """Update norm config label."""
        self.norm_config['label'] = label
        self.label_description.setText('<h2>'+label+'</h2>')
        self.verifySync()

    @Slot(str, str)
    def updateSettings(self, tunecorr_configname, chromcorr_configname):
        self._tunecorr = BOTuneCorr(tunecorr_configname)
        self._chromcorr = BOChromCorr(chromcorr_configname)
        self._updateDeltaKL()
        self._estimateChrom(use_ref=True)
        self._updateDeltaSL()

    # ---------- handle undo redo stack ----------

    def _stack_command(self, widget, old_value, new_value, message):
        global _flag_stack_next_command, _flag_stacking
        if _flag_stack_next_command and (old_value != new_value):
            _flag_stacking = True
            command = _UndoRedoSpinbox(widget, old_value, new_value, message)
            self._undo_stack.push(command)
        else:
            _flag_stack_next_command = True

    # ---------- helper methods ----------

    def _get_PSNames(self, pstype=None):
        psnames = list()
        if pstype == 'corrs':
            psnames = _PSSearch.get_psnames({'sec': 'BO', 'dev': 'C(V|H)'})
        elif pstype == 'quads':
            psnames = ['BO-Fam:PS-QF', 'BO-Fam:PS-QD']
        elif pstype == 'sexts':
            psnames = ['BO-Fam:PS-SF', 'BO-Fam:PS-SD']
        else:
            psnames = _PSSearch.get_psnames({'sec': 'BO', 'sub': 'Fam'})
            psnames.extend(_PSSearch.get_psnames({'sec': 'BO', 'dev': 'QS'}))
            psnames.extend(_PSSearch.get_psnames({'sec': 'BO', 'dev': 'CH'}))
            psnames.extend(_PSSearch.get_psnames({'sec': 'BO', 'dev': 'CV'}))
        return psnames

    def _show_kicks_graph(self):
        strenghts_dict = _dcopy(self.norm_config)
        strenghts_dict.pop('label')
        graph = _ShowCorrectorKicks(self, self.time, strenghts_dict)
        graph.show()
Ejemplo n.º 11
0
class FirstSplash(DialogBase):
    """
    Startup splash to display the first time that Navigator runs.
    """
    def __init__(self, parent=None, analytics=True):
        super(FirstSplash, self).__init__()

        text = """
        Thanks for installing Anaconda!

        Anaconda Navigator helps you easily start important Python applications
        and manage the packages in your local Anaconda installation. It also
        connects you to online resources for learning and engaging with the
        Python, SciPy, and PyData community.

        To help us improve Anaconda Navigator, fix bugs, and make it even easier
        for everyone to use Python, we gather anonymized usage information,
        just like most web browsers and mobile apps.

        To opt out of this, please uncheck below (You can always change this
        setting in the Preferences menu).
        """

        # Widgets
        self.button_ok = QPushButton('Ok')
        self.button_ok_dont_show = QPushButton("Ok, and don't show again")
        self.buttonbox = QDialogButtonBox(Qt.Horizontal)
        self.checkbox_track = QCheckBox("Yes, I'd like to help improve "
                                        "Anaconda.")
        self.label_about = QLabel(text)
        self.label_icon = QLabel()

        # Widget setup
        self.buttonbox.addButton(self.button_ok, QDialogButtonBox.ActionRole)
        self.buttonbox.addButton(self.button_ok_dont_show,
                                 QDialogButtonBox.ActionRole)
        self.checkbox_track.setChecked(analytics)
        self.checkbox_track.setChecked(
            CONF.get('main', 'provide_analytics', True))
        self.frame_title_bar.hide()
        self.label_icon.setPixmap(QPixmap(ANACONDA_NAVIGATOR_LOGO))

        # Layouts
        layout = QVBoxLayout()
        layout.addWidget(self.label_icon, 0, Qt.AlignCenter)
        layout.addWidget(self.label_about)
        layout.addWidget(self.checkbox_track, 0, Qt.AlignCenter)
        layout.addSpacing(20)
        layout.addWidget(self.buttonbox)
        self.setLayout(layout)

        # Signals
        self.button_ok.clicked.connect(lambda: self.accept(show_startup=True))
        self.button_ok_dont_show.clicked.connect(
            lambda: self.accept(show_startup=False))

    def accept(self, show_startup):
        """
        Qt override.
        """
        CONF.set('main', 'provide_analytics',
                 self.checkbox_track.checkState() == Qt.Checked)
        CONF.set('main', 'show_startup', show_startup)
        DialogBase.accept(self)

    def reject(self):
        """
        Qt override.

        Force user to select one of the two options bellow and disalow
        canceling the dialog (pressing escape)
        """
        pass
Ejemplo n.º 12
0
class CondaPackageActionDialog(QDialog):
    """ """

    def __init__(self, parent, prefix, name, action, version, versions, packages_sizes, active_channels):
        super(CondaPackageActionDialog, self).__init__(parent)
        self._parent = parent
        self._prefix = prefix
        self._version_text = None
        self._name = name
        self._dependencies_dic = {}
        self._active_channels = active_channels
        self._packages_sizes = packages_sizes
        self.api = ManagerAPI()

        # Widgets
        self.label = QLabel(self)
        self.combobox_version = QComboBox()
        self.label_version = QLabel(self)
        self.widget_version = None
        self.table_dependencies = None

        self.checkbox = QCheckBox(_("Install dependencies (recommended)"))
        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)

        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        self.button_cancel.setDefault(True)
        self.button_cancel.setAutoDefault(True)

        dialog_size = QSize(300, 90)

        # Helper variable values
        action_title = {
            C.ACTION_UPGRADE: _("Upgrade package"),
            C.ACTION_DOWNGRADE: _("Downgrade package"),
            C.ACTION_REMOVE: _("Remove package"),
            C.ACTION_INSTALL: _("Install package"),
        }

        # FIXME: There is a bug, a package installed by anaconda has version
        # astropy 0.4 and the linked list 0.4 but the available versions
        # in the json file do not include 0.4 but 0.4rc1... so...
        # temporal fix is to check if inside list otherwise show full list
        if action == C.ACTION_UPGRADE:
            if version in versions:
                index = versions.index(version)
                combo_versions = versions[index + 1 :]
            else:
                versions = versions
        elif action == C.ACTION_DOWNGRADE:
            if version in versions:
                index = versions.index(version)
                combo_versions = versions[:index]
            else:
                versions = versions
        elif action == C.ACTION_REMOVE:
            combo_versions = [version]
            self.combobox_version.setEnabled(False)
        elif action == C.ACTION_INSTALL:
            combo_versions = versions

        # Reverse order for combobox
        combo_versions = list(reversed(combo_versions))

        if len(versions) == 1:
            if action == C.ACTION_REMOVE:
                labeltext = _("Package version to remove:")
            else:
                labeltext = _("Package version available:")
            self.label_version.setText(combo_versions[0])
            self.widget_version = self.label_version
        else:
            labeltext = _("Select package version:")
            self.combobox_version.addItems(combo_versions)
            self.widget_version = self.combobox_version

        self.label.setText(labeltext)
        self.label_version.setAlignment(Qt.AlignLeft)
        self.table_dependencies = QWidget(self)

        layout = QVBoxLayout()
        version_layout = QHBoxLayout()
        version_layout.addWidget(self.label)
        version_layout.addStretch()
        version_layout.addWidget(self.widget_version)
        layout.addLayout(version_layout)

        self.widgets = [self.checkbox, self.button_ok, self.widget_version, self.table_dependencies]

        # Create a Table
        if action in [C.ACTION_INSTALL, C.ACTION_UPGRADE, C.ACTION_DOWNGRADE]:
            table = QTableView(self)
            dialog_size = QSize(dialog_size.width() + 40, 300)
            self.table_dependencies = table
            layout.addWidget(self.checkbox)
            self.checkbox.setChecked(True)
            self._changed_version(versions[0])

            table.setSelectionBehavior(QAbstractItemView.SelectRows)
            table.verticalHeader().hide()
            table.horizontalHeader().hide()
            table.setAlternatingRowColors(True)
            table.setShowGrid(False)
            table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            table.horizontalHeader().setStretchLastSection(True)

        layout.addWidget(self.table_dependencies)
        layout.addWidget(self.bbox)

        title = "{0}: {1}".format(action_title[action], name)
        self.setLayout(layout)
        self.setMinimumSize(dialog_size)
        self.setFixedSize(dialog_size)
        self.setWindowTitle(title)
        self.setModal(True)

        # Signals and slots
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.close)
        self.combobox_version.currentIndexChanged.connect(self._changed_version)
        self.checkbox.stateChanged.connect(self._changed_checkbox)

    def _changed_version(self, version, dependencies=True):
        """ """
        self._set_gui_disabled(True)
        version = self.combobox_version.currentText()
        install_dependencies = self.checkbox.checkState() == Qt.Checked
        self._version_text = to_text_string(version)
        self._get_dependencies(install_dependencies)

    def _get_dependencies(self, dependencies=True):
        """ """
        package_name = [self._name + "=" + self._version_text]

        worker = self.api.conda_dependencies(
            prefix=self._prefix, pkgs=package_name, dep=dependencies, channels=self._active_channels
        )
        worker.sig_finished.connect(self._on_process_finished)

    def _changed_checkbox(self, state):
        """ """
        if state:
            self._changed_version(self._version_text)
        else:
            self._changed_version(self._version_text, dependencies=False)

    def _on_process_finished(self, worker, output, error):
        """ """
        if self.isVisible():
            dic = output
            self.dependencies_dic = dic
            self._set_dependencies_table()
            self._set_gui_disabled(False)

    def _set_dependencies_table(self):
        """ """
        table = self.table_dependencies
        dic = self.dependencies_dic
        table.setModel(CondaDependenciesModel(self, dic, self._packages_sizes))
        table.resizeColumnsToContents()
        table.resizeRowsToContents()

    def _set_gui_disabled(self, value):
        """ """
        if value:
            table = self.table_dependencies
            table.setModel(CondaDependenciesModel(self, {}))
            table.resizeColumnsToContents()
            table.setDisabled(True)
        else:
            table = self.table_dependencies
            table.setDisabled(False)

        for widget in self.widgets:
            widget.setDisabled(value)

    def reject(self):
        self.api.conda_terminate()
        super(CondaPackageActionDialog, self).reject()
Ejemplo n.º 13
0
class DCCTMonitor(QWidget):
    """DCCT data monitoring."""
    def __init__(self, parent=None, prefix='', device=''):
        """Initialize object."""
        super().__init__(parent)
        self.prefix = prefix
        self.device = SiriusPVName(device)
        self.use_raw = self.device.sec == 'BO'
        self.dcct_prefix = self.device.substitute(prefix=prefix)

        self.acqmode_channel = SignalChannel(
            self.dcct_prefix.substitute(propty='MeasMode-Sel'))
        self.acqmode_channel.new_value_signal[int].connect(self.updateParams)
        self.normalnrsamp_channel = SignalChannel(
            self.dcct_prefix.substitute(propty='SampleCnt-RB'))
        self.normalnrsamp_channel.new_value_signal[int].connect(
            self.updateParams)
        self.fastnrsamp_channel = SignalChannel(
            self.dcct_prefix.substitute(propty='FastSampleCnt-RB'))
        self.fastnrsamp_channel.new_value_signal[int].connect(
            self.updateParams)
        self._acq_mode = None
        self._acq_normalnrsamp = None
        self._acq_fastnrsamp = None

        self._downsampling = 1
        self._smooth_method = 'Average'
        self._smooth_nracq = 1
        self._smooth_buffer = list()

        self._setupUi()

    def _setupUi(self):
        self.currhist = self._setupTimeHistory()
        self.currhist.setVisible(not self.use_raw)
        self.rawreads = self._setupRawReadings()
        self.rawreads.setVisible(self.use_raw)

        self.pb_vis = QPushButton(self)
        self.pb_vis.setStyleSheet(
            'QPushButton{min-width: 0.8em; max-width: 0.8em;}')
        self.menu_vis = QMenu()
        self.switch_act = self.menu_vis.addAction('Switch to ' + (
            'Time History' if self.use_raw else 'Raw Readings'))
        self.switch_act.triggered.connect(self._handle_data_visualization)
        self.pb_vis.setMenu(self.menu_vis)

        self.setStyleSheet("""
            .QLabel{max-height:1.5em;}
            PyDMWaveformPlot, PyDMTimePlot{min-width:30em; min-height:20em;}
        """)

        lay = QGridLayout(self)
        lay.setContentsMargins(0, 0, 0, 0)
        lay.setHorizontalSpacing(0)
        lay.addWidget(self.pb_vis, 0, 0, alignment=Qt.AlignTop | Qt.AlignLeft)
        lay.addWidget(self.currhist, 0, 1)
        lay.addWidget(self.rawreads, 0, 1)

    def _setupTimeHistory(self):
        self.label_currhist = QLabel('<h3>Current History</h3>',
                                     self,
                                     alignment=Qt.AlignCenter)

        self.timegraph = SiriusTimePlot(self)
        self.timegraph.timeSpan = 600
        channel = self.dcct_prefix.substitute(propty='Current-Mon')
        self.timegraph.addYChannel(y_channel=channel,
                                   name='Current History',
                                   color='blue',
                                   lineWidth=1,
                                   lineStyle=Qt.SolidLine)
        self.timegraph.autoRangeX = True
        self.timegraph.autoRangeY = True
        self.timegraph.backgroundColor = QColor(255, 255, 255)
        self.timegraph.showLegend = False
        self.timegraph.showXGrid = True
        self.timegraph.showYGrid = True
        self.timegraph.plotItem.showButtons()
        self.timecurve = self.timegraph.curveAtIndex(0)

        wid = QWidget()
        lay = QGridLayout(wid)
        lay.setAlignment(Qt.AlignTop)
        lay.setRowStretch(0, 1)
        lay.setRowStretch(1, 9)
        lay.addWidget(self.label_currhist, 0, 0)
        lay.addWidget(self.timegraph, 1, 0)
        return wid

    def _setupRawReadings(self):
        self.label_waveread = QLabel('<h3>Current Raw Readings</h3>',
                                     self,
                                     alignment=Qt.AlignCenter)

        self.wavegraph = PyDMWaveformPlot(self)
        self.wavegraph.setLabels(left='Current [mA]', bottom='Index')
        channel = 'FAKE:Readings'
        self.rawreadings_channel = SignalChannel(
            self.dcct_prefix.substitute(propty='RawReadings-Mon'))
        self.rawreadings_channel.new_value_signal[np.ndarray].connect(
            self._updateRawBuffer)
        self.wavegraph.addChannel(y_channel=channel,
                                  name='Current Raw Readings',
                                  color='blue',
                                  lineWidth=2,
                                  lineStyle=Qt.SolidLine)
        self.wavegraph.autoRangeX = True
        self.wavegraph.autoRangeY = True
        self.wavegraph.backgroundColor = QColor(255, 255, 255)
        self.wavegraph.showLegend = False
        self.wavegraph.showXGrid = True
        self.wavegraph.showYGrid = True
        self.wavegraph.plotItem.showButtons()
        self.wavecurve = self.wavegraph.curveAtIndex(0)

        wid = QWidget()
        lay = QGridLayout(wid)
        lay.setAlignment(Qt.AlignTop)
        lay.setRowStretch(0, 1)
        lay.setRowStretch(1, 9)
        lay.addWidget(self.label_waveread, 0, 0)
        lay.addWidget(self.wavegraph, 1, 0)

        # Smoothing
        evgname = SiriusPVName(_LLTimeSearch.get_evg_name())
        self._evnt_dly = SignalChannel(
            evgname.substitute(prefix=self.prefix,
                               propty='Dig' + self.device.sec + 'Delay-RB'))
        self._evnt_dly.new_value_signal[float].connect(self.updateRawXAxis)
        self._trig_dly = SignalChannel(
            self.dcct_prefix.substitute(dis='TI', propty='Delay-RB'))
        self._trig_dly.new_value_signal[float].connect(self.updateRawXAxis)
        self._smpl_cnt = SignalChannel(
            self.dcct_prefix.substitute(propty='FastSampleCnt-RB'))
        self._smpl_cnt.new_value_signal[float].connect(self.updateRawXAxis)
        self._meas_per = SignalChannel(
            self.dcct_prefix.substitute(propty='FastMeasPeriod-RB'))
        self._meas_per.new_value_signal[float].connect(self.updateRawXAxis)

        self.cb_timeaxis = QCheckBox('Use time axis', self)
        self.cb_timeaxis.setChecked(True)
        self.cb_timeaxis.stateChanged.connect(self.updateRawXAxis)
        self.cb_timeaxis.setLayoutDirection(Qt.RightToLeft)
        lay.addWidget(self.cb_timeaxis, 2, 0, alignment=Qt.AlignLeft)
        lay.setRowStretch(2, 1)

        l_smoothmethod = QLabel('Method: ', self)
        self.cb_smoothmethod = QComboBox(self)
        self.cb_smoothmethod.addItems(['Average', 'Median'])
        self.cb_smoothmethod.currentTextChanged.connect(
            self.setRawSmoothMethod)

        l_smoothnracq = QLabel('Nr.Acqs.: ', self)
        self.sb_smoothnracq = QSpinBoxPlus(self)
        self.sb_smoothnracq.setValue(1)
        self.sb_smoothnracq.valueChanged.connect(self.setRawSmoothNrAcq)

        l_smoothbuff = QLabel('Buffer Size: ', self)
        l_smoothbuff.setSizePolicy(QSzPly.Minimum, QSzPly.Preferred)
        self.label_buffsize = QLabel('', self)
        self.label_buffsize.setStyleSheet('min-width:3em; max-width:3em;')
        self.pb_resetbuff = QPushButton(qta.icon('mdi.delete-empty'), '', self)
        self.pb_resetbuff.setToolTip('Reset buffer')
        self.pb_resetbuff.setObjectName('resetbuff')
        self.pb_resetbuff.setStyleSheet(
            "#resetbuff{min-width:25px; max-width:25px; icon-size:20px;}")
        self.pb_resetbuff.clicked.connect(self.resetRawBuffer)
        hlay_buff = QHBoxLayout()
        hlay_buff.addWidget(self.label_buffsize)
        hlay_buff.addWidget(self.pb_resetbuff)

        l_down = QLabel('Downsampling: ', self)
        self.sb_down = QSpinBoxPlus(self)
        self.sb_down.setValue(1)
        self.sb_down.valueChanged.connect(self.setRawDownsampling)

        gbox_smooth = QGroupBox('Smoothing of Readings')
        glay_smooth = QGridLayout(gbox_smooth)
        glay_smooth.addWidget(l_smoothmethod, 0, 0)
        glay_smooth.addWidget(self.cb_smoothmethod, 0, 1)
        glay_smooth.addWidget(l_smoothnracq, 1, 0)
        glay_smooth.addWidget(self.sb_smoothnracq, 1, 1)
        glay_smooth.addWidget(QLabel(''), 0, 2)
        glay_smooth.addWidget(l_smoothbuff, 0, 3)
        glay_smooth.addLayout(hlay_buff, 0, 4, 1, 2)
        glay_smooth.addWidget(l_down, 1, 3)
        glay_smooth.addWidget(self.sb_down, 1, 4, 1, 2)
        glay_smooth.setColumnStretch(0, 10)
        glay_smooth.setColumnStretch(1, 10)
        glay_smooth.setColumnStretch(2, 2)
        glay_smooth.setColumnStretch(3, 10)
        glay_smooth.setColumnStretch(4, 5)
        glay_smooth.setColumnStretch(5, 5)
        lay.addWidget(gbox_smooth, 3, 0)
        lay.setRowStretch(3, 3)
        gbox_smooth.setStyleSheet("""
            .QLabel{
                qproperty-alignment: 'AlignVCenter | AlignRight';}
            QPushButton{
                min-width:3em; max-width:3em;}""")

        return wid

    def _updateRawBuffer(self, raw):
        if raw is None:
            return
        samp = self._acq_fastnrsamp \
            if self._acq_mode == _DCCTc.MeasModeSel.Fast \
            else self._acq_normalnrsamp
        if not samp:
            return
        samp -= samp % self._downsampling
        if samp < 1:
            return
        data = raw[:samp]

        self._smooth_buffer.append(data)
        if len(self._smooth_buffer) > self._smooth_nracq:
            self._smooth_buffer.pop(0)

        self._updateRawCurve()

    def _updateRawCurve(self):
        buff = np.array(self._smooth_buffer, dtype=float)
        self.label_buffsize.setText(str(self.smoothBufferSize))

        if not len(buff):
            return
        if len(buff) > 1:
            if self._smooth_method == 'Average':
                fdata = np.mean(buff, axis=0)
            elif self._smooth_method == 'Median':
                fdata = np.median(buff, axis=0)
        else:
            fdata = buff[0]

        down = self._downsampling
        if down > 1:
            fdata = np.mean(fdata.reshape(-1, down), axis=1)

        self.wavecurve.receiveYWaveform(fdata)
        self.wavecurve.redrawCurve()

    def setRawDownsampling(self, new_value):
        """Update number of samples to use in downsampling."""
        self._downsampling = new_value
        self.resetRawBuffer()

    def setRawSmoothMethod(self, new_method):
        """Update method to perform raw readings smoothing."""
        self._smooth_method = new_method
        self._updateRawCurve()

    def setRawSmoothNrAcq(self, new_value):
        """Update number of samples to use in smoothing."""
        self._smooth_nracq = new_value
        exc = len(self._smooth_buffer) - self._smooth_nracq
        if exc > 0:
            for i in range(exc):
                self._smooth_buffer.pop(0)

    @property
    def smoothBufferSize(self):
        """Smoothing buffer length."""
        return len(self._smooth_buffer)

    def resetRawBuffer(self):
        """Reset smoothing buffer."""
        self._smooth_buffer = list()
        self._updateRawCurve()

    def updateParams(self, new_value):
        """Handle control visualization according to mode."""
        address = self.sender().address
        if 'Mode' in address:
            self._acq_mode = new_value
        elif 'Fast' in address:
            self._acq_fastnrsamp = new_value
        else:
            self._acq_normalnrsamp = new_value
        self.resetRawBuffer()

    def updateRawXAxis(self):
        """Update X axis of waveform graph."""
        smpl = self._smpl_cnt.getvalue()
        if self.cb_timeaxis.checkState():
            evnt = self._evnt_dly.getvalue()
            trig = self._trig_dly.getvalue()
            peri = self._meas_per.getvalue()

            if any([val is None for val in [evnt, trig, smpl, peri]]):
                return

            init = (evnt + trig) / 1e3
            endt = init + peri * 1e3

            xdata = np.linspace(init, endt, smpl)
            xlabel = 'Time [ms]'
        else:
            xdata = np.arange(0, smpl)
            xlabel = 'Index'
        self.wavegraph.setLabels(bottom=xlabel)
        self.wavecurve.receiveXWaveform(xdata)

    def _handle_data_visualization(self):
        show_raw = 'Raw' in self.sender().text()
        self.sender().setText('Switch to ' +
                              ('Time History' if show_raw else 'Raw Readings'))
        self.currhist.setVisible(not show_raw)
        self.rawreads.setVisible(show_raw)