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()
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()
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()
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
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)
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()
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()
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)
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()
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()
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
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()
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)