Esempio n. 1
0
class ImportAsWidget(QWidget):

    def __init__(self, parent, sourceWidget: QLineEdit):
        super().__init__(parent)

        self.sourceWidget = sourceWidget
        self.shouldImport = QCheckBox(_("Import As"))
        self.shouldImport.setCheckState(Qt.Checked)
        self.shouldImport.stateChanged.connect(self.activateName)

        self.nameEdit = ImportNameEdit(self)
        sourceWidget.textChanged.connect(self.syncText)

        self.layout = QHBoxLayout(self)
        self.layout.addWidget(self.shouldImport)
        self.layout.addWidget(self.nameEdit)
        self.layout.setContentsMargins(0, 0, 0, 0)

        # https://forum.qt.io/topic/87226/synchronize-2-qlineedit

    def syncText(self, name):
        if self.shouldImport.isChecked() and self.nameEdit.synced:
            self.nameEdit.setText(name)

    def activateName(self, state):
        if state:
            self.nameEdit.setReadOnly(False)
            self.nameEdit.setEnabled(True)
        else:
            self.nameEdit.setReadOnly(True)
            self.nameEdit.setEnabled(False)
class DxfOutputDialog(OutputDialog):
    """Dialog for DXF format."""
    format_name = "DXF"
    format_icon = "dxf.png"
    assembly_description = "The sketch of the parts will include in the file."
    frame_description = "There is only wire frame will be generated."

    def __init__(self, *args):
        """Type name: "DXF module"."""
        super(DxfOutputDialog, self).__init__(*args)
        # DXF version option
        version_label = QLabel("DXF version:", self)
        self.version_option = QComboBox(self)
        self.version_option.addItems(
            sorted((f"{name} - {DXF_VERSIONS_MAP[name]}"
                    for name in DXF_VERSIONS),
                   key=lambda v: v.split()[-1]))
        self.version_option.setCurrentIndex(self.version_option.count() - 1)
        self.version_option.setSizePolicy(QSizePolicy.Expanding,
                                          QSizePolicy.Preferred)
        layout = QHBoxLayout()
        layout.addWidget(version_label)
        layout.addWidget(self.version_option)
        self.main_layout.insertLayout(3, layout)
        # Parts interval
        self.use_interval = QCheckBox("Parts interval:", self)
        self.use_interval.setCheckState(Qt.Checked)
        self.use_interval.setSizePolicy(QSizePolicy.Fixed,
                                        QSizePolicy.Preferred)
        self.interval_option = QDoubleSpinBox(self)
        self.interval_option.setValue(10)
        self.use_interval.stateChanged.connect(self.interval_option.setEnabled)
        layout = QHBoxLayout()
        layout.addWidget(self.use_interval)
        layout.addWidget(self.interval_option)
        layout.addItem(
            QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Preferred))
        self.assembly_layout.insertLayout(2, layout)

    def do(self, dir_str: QDir) -> bool:
        """Output types:

        + Boundary
        + Frame
        """
        file_name = dir_str.filePath(_get_name(self.filename_edit) + '.dxf')
        if isfile(file_name) and self.warn_radio.isChecked():
            self.exist_warning(file_name)
            return False
        version = self.version_option.currentText().split()[0]
        if self.frame_radio.isChecked():
            # Frame
            dxf_frame(self.vpoints, self.v_to_slvs, version, file_name)
        elif self.assembly_radio.isChecked():
            # Boundary
            dxf_boundary(
                self.vpoints, self.link_radius.value(),
                self.interval_option.value()
                if self.use_interval.isChecked() else 0., version, file_name)
        return True
Esempio n. 3
0
    def __init__(self, theme='dark', emphasized=False):
        super().__init__(None)
        self.setProperty('emphasized', emphasized)
        self.setStyleSheet(template(raw_stylesheet, **palettes[theme]))
        lay = QVBoxLayout()
        self.setLayout(lay)
        lay.addWidget(QPushButton('push button'))
        box = QComboBox()
        box.addItems(['a', 'b', 'c', 'cd'])
        lay.addWidget(box)
        lay.addWidget(QFontComboBox())

        hbox = QHBoxLayout()
        chk = QCheckBox('tristate')
        chk.setToolTip('I am a tooltip')
        chk.setTristate(True)
        chk.setCheckState(Qt.PartiallyChecked)
        chk3 = QCheckBox('checked')
        chk3.setChecked(True)
        hbox.addWidget(QCheckBox('unchecked'))
        hbox.addWidget(chk)
        hbox.addWidget(chk3)
        lay.addLayout(hbox)

        lay.addWidget(TabDemo(emphasized=emphasized))

        sld = QSlider(Qt.Horizontal)
        sld.setValue(50)
        lay.addWidget(sld)
        scroll = QScrollBar(Qt.Horizontal)
        scroll.setValue(50)
        lay.addWidget(scroll)
        lay.addWidget(QHRangeSlider(parent=self))
        text = QTextEdit()
        text.setMaximumHeight(100)
        text.setHtml(blurb)
        lay.addWidget(text)
        lay.addWidget(QTimeEdit())
        edit = QLineEdit()
        edit.setPlaceholderText('LineEdit placeholder...')
        lay.addWidget(edit)
        lay.addWidget(QLabel('label'))
        prog = QProgressBar()
        prog.setValue(50)
        lay.addWidget(prog)
        groupBox = QGroupBox("Exclusive Radio Buttons")
        radio1 = QRadioButton("&Radio button 1")
        radio2 = QRadioButton("R&adio button 2")
        radio3 = QRadioButton("Ra&dio button 3")
        radio1.setChecked(True)
        hbox = QHBoxLayout()
        hbox.addWidget(radio1)
        hbox.addWidget(radio2)
        hbox.addWidget(radio3)
        hbox.addStretch(1)
        groupBox.setLayout(hbox)
        lay.addWidget(groupBox)
Esempio n. 4
0
    def add_new_row(self, _metadata, row=0):

        self.main_window.postprocessing_ui.table.insertRow(row)

        _layout = QHBoxLayout()
        _widget = QCheckBox()
        _widget.setEnabled(True)
        _layout.addWidget(_widget)
        _layout.addStretch()
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)

        _widget.stateChanged.connect(lambda state=0, row=row:
                                     self.parent.table_select_state_changed(state, row))
        self.main_window_postprocessing_ui.table.setCellWidget(row, 0, _new_widget)

        _item = QTableWidgetItem(_metadata['name'])
        self.main_window_postprocessing_ui.table.setItem(row, 1, _item)

        _item = QTableWidgetItem(_metadata['runs'])
        self.main_window_postprocessing_ui.table.setItem(row, 2, _item)

        if not _metadata['sample_formula']:
            _item = QTableWidgetItem(_metadata['sample_formula'])
            self.main_window_postprocessing_ui.table.setItem(row, 3, _item)

        if not _metadata['mass_density']:
            _item = QTableWidgetItem(_metadata['mass_density'])
            self.main_window_postprocessing_ui.table.setItem(row, 4, _item)

        if not _metadata['radius']:
            _item = QTableWidgetItem(_metadata['radius'])
            self.main_window_postprocessing_ui.table.setItem(row, 5, _item)

        if not _metadata['packing_fraction']:
            _item = QTableWidgetItem(_metadata['packing_fraction'])
            self.main_window_postprocessing_ui.table.setItem(row, 6, _item)

        _widget = QComboBox()
        _widget.addItem("cylindrical")
        _widget.addItem("spherical")
        if _metadata['sample_shape'] == 'spherical':
            _widget.setCurrentIndex(1)
        self.main_window_postprocessing_ui.table.setCellWidget(row, 7, _widget)

        _layout = QHBoxLayout()
        _widget = QCheckBox()
        if _metadata['do_abs_correction'] == 'go':
            _widget.setCheckState(Qt.Checked)
        _widget.setStyleSheet("border:  2px; solid-black")
        _widget.setEnabled(True)
        _layout.addStretch()
        _layout.addWidget(_widget)
        _layout.addStretch()
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)
        self.main_window_postprocessing_ui.table.setCellWidget(row, 8, _new_widget)
Esempio n. 5
0
    def add_new_row(self, _metadata, row=0):

        self.parent.ui.table.insertRow(row)

        _layout = QHBoxLayout()
        _widget = QCheckBox()
        _widget.setEnabled(True)
        _layout.addWidget(_widget)
        _layout.addStretch()
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)

        _widget.stateChanged.connect(lambda state=0, row=row: self.parent.
                                     table_select_state_changed(state, row))
        self.parent.ui.table.setCellWidget(row, 0, _new_widget)

        _item = QTableWidgetItem(_metadata['name'])
        self.parent.ui.table.setItem(row, 1, _item)

        _item = QTableWidgetItem(_metadata['runs'])
        self.parent.ui.table.setItem(row, 2, _item)

        if not _metadata['sample_formula']:
            _item = QTableWidgetItem(_metadata['sample_formula'])
            self.parent.ui.table.setItem(row, 3, _item)

        if not _metadata['mass_density']:
            _item = QTableWidgetItem(_metadata['mass_density'])
            self.parent.ui.table.setItem(row, 4, _item)

        if not _metadata['radius']:
            _item = QTableWidgetItem(_metadata['radius'])
            self.parent.ui.table.setItem(row, 5, _item)

        if not _metadata['packing_fraction']:
            _item = QTableWidgetItem(_metadata['packing_fraction'])
            self.parent.ui.table.setItem(row, 6, _item)

        _widget = QComboBox()
        _widget.addItem("cylindrical")
        _widget.addItem("spherical")
        if _metadata['sample_shape'] == 'spherical':
            _widget.setCurrentIndex(1)
        self.parent.ui.table.setCellWidget(row, 7, _widget)

        _layout = QHBoxLayout()
        _widget = QCheckBox()
        if _metadata['do_abs_correction'] == 'go':
            _widget.setCheckState(Qt.Checked)
        _widget.setStyleSheet("border:  2px; solid-black")
        _widget.setEnabled(True)
        _layout.addStretch()
        _layout.addWidget(_widget)
        _layout.addStretch()
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)
        self.parent.ui.table.setCellWidget(row, 8, _new_widget)
Esempio n. 6
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()
Esempio n. 7
0
    def createTopLeftGroupBox(self):
        self.topLeftGroupBox = QGroupBox("Group 1")

        radioButton1 = QRadioButton("Radio button 1")
        radioButton2 = QRadioButton("Radio button 2")
        radioButton3 = QRadioButton("Radio button 3")
        radioButton1.setChecked(True)

        checkBox = QCheckBox("Tri-state check box")
        checkBox.setTristate(True)
        checkBox.setCheckState(Qt.PartiallyChecked)

        layout = QVBoxLayout()
        layout.addWidget(radioButton1)
        layout.addWidget(radioButton2)
        layout.addWidget(radioButton3)
        layout.addWidget(checkBox)
        layout.addStretch(1)
        self.topLeftGroupBox.setLayout(layout)
Esempio n. 8
0
class ImportNamesDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(
            self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.setWindowTitle('Import Names')
        self.treeview = parent
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.importSelected = QCheckBox(_("Import selected"), self)
        self.importSelected.setCheckState(Qt.Checked)
        self.importChildren = QCheckBox(_("Import children"), self)
        self.importChildren.setCheckState(Qt.Checked)
        self.replaceExisting = QCheckBox(_("Replace existing names"), self)
        self.replaceExisting.setCheckState(Qt.Checked)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(self.importSelected)
        mainLayout.addWidget(self.importChildren)
        mainLayout.addWidget(self.replaceExisting)
        mainLayout.addWidget(self.buttonBox)
        self.setLayout(mainLayout)

    def accept(self) -> None:
        reply = {
            'accepted': True,
            'import_selected': self.importSelected.isChecked(),
            'import_children': self.importChildren.isChecked(),
            'replace_existing': self.replaceExisting.isChecked()
        }
        self.treeview.reply = reply
        super().accept()

    def reject(self) -> None:
        self.treeview.reply = {'accepted': False}
        super().reject()
Esempio n. 9
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()
Esempio n. 10
0
class WorkflowWidget(QWidget):
    sigAddFunction = Signal(object)
    sigRunWorkflow = Signal()

    # TODO -- emit Workflow from sigRunWorkflow

    def __init__(self,
                 workflowview: QAbstractItemView,
                 operation_filter: Callable[[OperationPlugin], bool] = None,
                 workflows: Dict[Workflow, str] = None):
        super(WorkflowWidget, self).__init__()

        self.operation_filter = operation_filter
        self.view = workflowview

        self.autorun_checkbox = QCheckBox("Run Automatically")
        self.autorun_checkbox.setCheckState(Qt.Unchecked)
        self.autorun_checkbox.stateChanged.connect(self._autorun_state_changed)
        self.run_button = QPushButton("Run Workflow")
        self.run_button.clicked.connect(self.sigRunWorkflow.emit)
        self.view.model().workflow.attach(self._autorun)
        # TODO -- actually hook up the auto run OR dependent class needs to connect (see SAXSGUIPlugin)

        self.toolbar = QToolBar()
        self.addfunctionmenu = QToolButton()
        self.addfunctionmenu.setIcon(QIcon(path("icons/addfunction.png")))
        self.addfunctionmenu.setText("Add Function")
        self.addfunctionmenu.setToolTip("Add Operation")
        self.addfunctionmenu.setWhatsThis(
            "This button can be used to add a new operation to the end of a workflow. "
            "A menu to select operations will be populated based on the installed "
            "operations' categories.")
        # Defer menu population to once the plugins have been loaded; otherwise, the menu may not contain anything
        # if this widget is init'd before all plugins have been loaded.
        self.functionmenu = QMenu()
        self.functionmenu.aboutToShow.connect(self.populateFunctionMenu)
        self.addfunctionmenu.setMenu(self.functionmenu)
        self.addfunctionmenu.setPopupMode(QToolButton.InstantPopup)

        self.workflows = WorkflowDict(workflows or {})

        self.workflow_menu = QMenu()
        self.workflow_menu.aboutToShow.connect(self.populateWorkflowMenu)
        self.workflow_selector = QToolButton()
        self.workflow_selector.setIcon(QIcon(path("icons/bookshelf.png")))
        self.workflow_selector.setText("Select Workflow")
        self.workflow_selector.setToolTip("Workflow Library")
        self.workflow_selector.setWhatsThis(
            "This button allows switching between any stored workflows. "
            "(Stored workflows are typically defined programmatically "
            "in a GUI Plugin's modules.)")
        self.workflow_selector.setMenu(self.workflow_menu)
        self.workflow_selector.setPopupMode(QToolButton.InstantPopup)
        self.toolbar.addWidget(self.workflow_selector)

        self.toolbar.addWidget(self.addfunctionmenu)
        # self.toolbar.addAction(QIcon(path('icons/up.png')), 'Move Up')
        # self.toolbar.addAction(QIcon(path('icons/down.png')), 'Move Down')
        action = self.toolbar.addAction(QIcon(path("icons/save.png")),
                                        "Export Workflow")
        action.setEnabled(False)  # FIXME: implement export workflow feature
        action = self.toolbar.addAction(QIcon(path("icons/folder.png")),
                                        "Import Workflow")
        action.setEnabled(False)  # FIXME: implement import workflow feature

        action = self.toolbar.addAction(QIcon(path("icons/trash.png")),
                                        "Delete Operation",
                                        self.deleteOperation)
        action.setWhatsThis("This button removes the currently selected operation from the workflow. "\
                            "(The currently selected operation is highlighted. "\
                            "An operation is selected when its text is clicked in the workflow editor.")

        v = QVBoxLayout()
        v.addWidget(self.view)
        h = QHBoxLayout()
        h.addWidget(self.autorun_checkbox)
        h.addWidget(self.run_button)
        v.addLayout(h)
        v.addWidget(self.toolbar)
        v.setContentsMargins(0, 0, 0, 0)
        self.setLayout(v)

    def _autorun_state_changed(self, state):
        if state == Qt.Checked:
            self.run_button.setDisabled(True)
        else:
            self.run_button.setDisabled(False)

    def _autorun(self):
        if self.autorun_checkbox.isChecked():
            self.sigRunWorkflow.emit()

    def populateFunctionMenu(self):
        self.functionmenu.clear()
        sortingDict = MenuDict()
        operations = pluginmanager.get_plugins_of_type("OperationPlugin")
        if self.operation_filter is not None:
            operations = filter(self.operation_filter, operations)
        for operation in operations:

            categories = operation.categories
            if not categories:
                categories = [("Uncategorized", )
                              ]  # put found operations into a default category

            for categories_tuple in categories:
                if isinstance(categories_tuple, str):
                    categories_tuple = (categories_tuple, )
                submenu = sortingDict
                categories_list = list(categories_tuple)
                while categories_list:
                    category = categories_list.pop(0)
                    submenu = submenu[category]

                submenu['___'].append(operation)

        self._mkMenu(sortingDict)

    def populateWorkflowMenu(self):
        self.workflow_menu.clear()
        for workflow, workflow_name in self.workflows.items():
            self.workflow_menu.addAction(workflow_name,
                                         partial(self.setWorkflow, workflow))

    def _mkMenu(self, sorting_dict, menu=None):
        if menu is None:
            menu = self.functionmenu
            menu.clear()

        for key in sorting_dict:
            if key == '___':
                menu.addSeparator()
                for operation in sorting_dict['___']:
                    menu.addAction(
                        operation.name,
                        partial(self.addOperation,
                                operation,
                                autoconnectall=True))
            else:
                submenu = QMenu(title=key, parent=menu)
                menu.addMenu(submenu)
                self._mkMenu(sorting_dict[key], submenu)

    def setWorkflow(self, workflow: Workflow):
        self.view.model().workflow = workflow

    def addWorkflow(self, workflow: Workflow, name: str = None):
        if name is None:
            name = workflow.name
        if name in self.workflows:
            raise ValueError(
                f'A workflow already exists in this editor with the name "{name}"'
            )
        self.workflows[name] = workflow

    def removeWorkflow(self, workflow):
        for name, match_workflow in self.workflows.items():
            if workflow == match_workflow:
                del self.workflows[name]

    def addOperation(self, operation: OperationPlugin, autoconnectall=True):
        self.view.model().workflow.add_operation(operation())
        if autoconnectall:
            self.view.model().workflow.auto_connect_all()
        print("selected new row:", self.view.model().rowCount() - 1)
        self.view.setCurrentIndex(self.view.model().index(
            self.view.model().rowCount() - 1, 0))

    def deleteOperation(self):
        index = self.view.currentIndex()
        operation = self.view.model().workflow.operations[index.row()]
        self.view.model().workflow.remove_operation(operation)
        self.view.setCurrentIndex(QModelIndex())
Esempio n. 11
0
class FindReplace(QWidget):
    """Find widget"""
    STYLE = {False: "background-color:rgb(255, 175, 90);",
             True: ""}
    visibility_changed = Signal(bool)
    
    def __init__(self, parent, enable_replace=False):
        QWidget.__init__(self, parent)
        self.enable_replace = enable_replace
        self.editor = None
        self.is_code_editor = None
        
        glayout = QGridLayout()
        glayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(glayout)
        
        self.close_button = create_toolbutton(self, triggered=self.hide,
                                      icon=ima.icon('DialogCloseButton'))
        glayout.addWidget(self.close_button, 0, 0)
        
        # Find layout
        self.search_text = PatternComboBox(self, tip=_("Search string"),
                                           adjust_to_minimum=False)
        self.search_text.valid.connect(
                     lambda state:
                     self.find(changed=False, forward=True, rehighlight=False))
        self.search_text.lineEdit().textEdited.connect(
                                                     self.text_has_been_edited)
        
        self.previous_button = create_toolbutton(self,
                                             triggered=self.find_previous,
                                             icon=ima.icon('ArrowUp'))
        self.next_button = create_toolbutton(self,
                                             triggered=self.find_next,
                                             icon=ima.icon('ArrowDown'))
        self.next_button.clicked.connect(self.update_search_combo)
        self.previous_button.clicked.connect(self.update_search_combo)

        self.re_button = create_toolbutton(self, icon=ima.icon('advanced'),
                                           tip=_("Regular expression"))
        self.re_button.setCheckable(True)
        self.re_button.toggled.connect(lambda state: self.find())
        
        self.case_button = create_toolbutton(self,
                                             icon=get_icon("upper_lower.png"),
                                             tip=_("Case Sensitive"))
        self.case_button.setCheckable(True)
        self.case_button.toggled.connect(lambda state: self.find())
                     
        self.words_button = create_toolbutton(self,
                                              icon=get_icon("whole_words.png"),
                                              tip=_("Whole words"))
        self.words_button.setCheckable(True)
        self.words_button.toggled.connect(lambda state: self.find())
                     
        self.highlight_button = create_toolbutton(self,
                                              icon=get_icon("highlight.png"),
                                              tip=_("Highlight matches"))
        self.highlight_button.setCheckable(True)
        self.highlight_button.toggled.connect(self.toggle_highlighting)

        hlayout = QHBoxLayout()
        self.widgets = [self.close_button, self.search_text,
                        self.previous_button, self.next_button,
                        self.re_button, self.case_button, self.words_button,
                        self.highlight_button]
        for widget in self.widgets[1:]:
            hlayout.addWidget(widget)
        glayout.addLayout(hlayout, 0, 1)

        # Replace layout
        replace_with = QLabel(_("Replace with:"))
        self.replace_text = PatternComboBox(self, adjust_to_minimum=False,
                                            tip=_('Replace string'))
        
        self.replace_button = create_toolbutton(self,
                                     text=_('Replace/find'),
                                     icon=ima.icon('DialogApplyButton'),
                                     triggered=self.replace_find,
                                     text_beside_icon=True)
        self.replace_button.clicked.connect(self.update_replace_combo)
        self.replace_button.clicked.connect(self.update_search_combo)
        
        self.all_check = QCheckBox(_("Replace all"))
        
        self.replace_layout = QHBoxLayout()
        widgets = [replace_with, self.replace_text, self.replace_button,
                   self.all_check]
        for widget in widgets:
            self.replace_layout.addWidget(widget)
        glayout.addLayout(self.replace_layout, 1, 1)
        self.widgets.extend(widgets)
        self.replace_widgets = widgets
        self.hide_replace()
        
        self.search_text.setTabOrder(self.search_text, self.replace_text)
        
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        
        self.shortcuts = self.create_shortcuts(parent)
        
        self.highlight_timer = QTimer(self)
        self.highlight_timer.setSingleShot(True)
        self.highlight_timer.setInterval(1000)
        self.highlight_timer.timeout.connect(self.highlight_matches)
        
    def create_shortcuts(self, parent):
        """Create shortcuts for this widget"""
        # Configurable
        findnext = config_shortcut(self.find_next, context='_',
                                   name='Find next', parent=parent)
        findprev = config_shortcut(self.find_previous, context='_',
                                   name='Find previous', parent=parent)
        togglefind = config_shortcut(self.show, context='_',
                                     name='Find text', parent=parent)
        togglereplace = config_shortcut(self.toggle_replace_widgets,
                                        context='_', name='Replace text',
                                        parent=parent)
        # Fixed
        fixed_shortcut("Escape", self, self.hide)

        return [findnext, findprev, togglefind, togglereplace]

    def get_shortcut_data(self):
        """
        Returns shortcut data, a list of tuples (shortcut, text, default)
        shortcut (QShortcut or QAction instance)
        text (string): action/shortcut description
        default (string): default key sequence
        """
        return [sc.data for sc in self.shortcuts]
        
    def update_search_combo(self):
        self.search_text.lineEdit().returnPressed.emit()
        
    def update_replace_combo(self):
        self.replace_text.lineEdit().returnPressed.emit()
    
    def toggle_replace_widgets(self):
        if self.enable_replace:
            # Toggle replace widgets
            if self.replace_widgets[0].isVisible():
                self.hide_replace()
                self.hide()
            else:
                self.show_replace()
                self.replace_text.setFocus()

    @Slot(bool)
    def toggle_highlighting(self, state):
        """Toggle the 'highlight all results' feature"""
        if self.editor is not None:
            if state:
                self.highlight_matches()
            else:
                self.clear_matches()
        
    def show(self):
        """Overrides Qt Method"""
        QWidget.show(self)
        self.visibility_changed.emit(True)
        if self.editor is not None:
            text = self.editor.get_selected_text()

            # If no text is highlighted for search, use whatever word is under the cursor
            if not text:
                cursor = self.editor.textCursor()
                cursor.select(QTextCursor.WordUnderCursor)
                text = to_text_string(cursor.selectedText())

            # Now that text value is sorted out, use it for the search
            if text:
                self.search_text.setEditText(text)
                self.search_text.lineEdit().selectAll()
                self.refresh()
            else:
                self.search_text.lineEdit().selectAll()
            self.search_text.setFocus()

    @Slot()
    def hide(self):
        """Overrides Qt Method"""
        for widget in self.replace_widgets:
            widget.hide()
        QWidget.hide(self)
        self.visibility_changed.emit(False)
        if self.editor is not None:
            self.editor.setFocus()
            self.clear_matches()
        
    def show_replace(self):
        """Show replace widgets"""
        self.show()
        for widget in self.replace_widgets:
            widget.show()
            
    def hide_replace(self):
        """Hide replace widgets"""
        for widget in self.replace_widgets:
            widget.hide()
        
    def refresh(self):
        """Refresh widget"""
        if self.isHidden():
            if self.editor is not None:
                self.clear_matches()
            return
        state = self.editor is not None
        for widget in self.widgets:
            widget.setEnabled(state)
        if state:
            self.find()
            
    def set_editor(self, editor, refresh=True):
        """
        Set associated editor/web page:
            codeeditor.base.TextEditBaseWidget
            browser.WebView
        """
        self.editor = editor
        # Note: This is necessary to test widgets/editor.py
        # in Qt builds that don't have web widgets
        try:
            from qtpy.QtWebEngineWidgets import QWebEngineView
        except ImportError:
            QWebEngineView = type(None)
        self.words_button.setVisible(not isinstance(editor, QWebEngineView))
        self.re_button.setVisible(not isinstance(editor, QWebEngineView))
        from spyderlib.widgets.sourcecode.codeeditor import CodeEditor
        self.is_code_editor = isinstance(editor, CodeEditor)
        self.highlight_button.setVisible(self.is_code_editor)
        if refresh:
            self.refresh()
        if self.isHidden() and editor is not None:
            self.clear_matches()

    @Slot()
    def find_next(self):
        """Find next occurrence"""
        state = self.find(changed=False, forward=True, rehighlight=False)
        self.editor.setFocus()
        self.search_text.add_current_text()
        return state

    @Slot()
    def find_previous(self):
        """Find previous occurrence"""
        state = self.find(changed=False, forward=False, rehighlight=False)
        self.editor.setFocus()
        return state

    def text_has_been_edited(self, text):
        """Find text has been edited (this slot won't be triggered when 
        setting the search pattern combo box text programmatically"""
        self.find(changed=True, forward=True, start_highlight_timer=True)
        
    def highlight_matches(self):
        """Highlight found results"""
        if self.is_code_editor and self.highlight_button.isChecked():
            text = self.search_text.currentText()
            words = self.words_button.isChecked()
            regexp = self.re_button.isChecked()
            self.editor.highlight_found_results(text, words=words,
                                                regexp=regexp)
                                                
    def clear_matches(self):
        """Clear all highlighted matches"""
        if self.is_code_editor:
            self.editor.clear_found_results()
        
    def find(self, changed=True, forward=True,
             rehighlight=True, start_highlight_timer=False):
        """Call the find function"""
        text = self.search_text.currentText()
        if len(text) == 0:
            self.search_text.lineEdit().setStyleSheet("")
            return None
        else:
            case = self.case_button.isChecked()
            words = self.words_button.isChecked()
            regexp = self.re_button.isChecked()
            found = self.editor.find_text(text, changed, forward, case=case,
                                          words=words, regexp=regexp)
            self.search_text.lineEdit().setStyleSheet(self.STYLE[found])
            if self.is_code_editor and found:
                if rehighlight or not self.editor.found_results:
                    self.highlight_timer.stop()
                    if start_highlight_timer:
                        self.highlight_timer.start()
                    else:
                        self.highlight_matches()
            else:
                self.clear_matches()
            return found

    @Slot()
    def replace_find(self):
        """Replace and find"""
        if (self.editor is not None):
            replace_text = to_text_string(self.replace_text.currentText())
            search_text = to_text_string(self.search_text.currentText())
            pattern = search_text if self.re_button.isChecked() else None
            case = self.case_button.isChecked()
            first = True
            cursor = None
            while True:
                if first:
                    # First found
                    seltxt = to_text_string(self.editor.get_selected_text())
                    cmptxt1 = search_text if case else search_text.lower()
                    cmptxt2 = seltxt if case else seltxt.lower()
                    if self.editor.has_selected_text() and cmptxt1 == cmptxt2:
                        # Text was already found, do nothing
                        pass
                    else:
                        if not self.find(changed=False, forward=True,
                                         rehighlight=False):
                            break
                    first = False
                    wrapped = False
                    position = self.editor.get_position('cursor')
                    position0 = position
                    cursor = self.editor.textCursor()
                    cursor.beginEditBlock()
                else:
                    position1 = self.editor.get_position('cursor')
                    if is_position_inf(position1,
                                       position0 + len(replace_text) -
                                       len(search_text) + 1):
                        # Identify wrapping even when the replace string
                        # includes part of the search string
                        wrapped = True
                    if wrapped:
                        if position1 == position or \
                           is_position_sup(position1, position):
                            # Avoid infinite loop: replace string includes
                            # part of the search string
                            break
                    if position1 == position0:
                        # Avoid infinite loop: single found occurrence
                        break
                    position0 = position1
                if pattern is None:
                    cursor.removeSelectedText()
                    cursor.insertText(replace_text)
                else:
                    seltxt = to_text_string(cursor.selectedText())
                    cursor.removeSelectedText()
                    cursor.insertText(re.sub(pattern, replace_text, seltxt))
                if self.find_next():
                    found_cursor = self.editor.textCursor()
                    cursor.setPosition(found_cursor.selectionStart(),
                                       QTextCursor.MoveAnchor)
                    cursor.setPosition(found_cursor.selectionEnd(),
                                       QTextCursor.KeepAnchor)
                else:
                    break
                if not self.all_check.isChecked():
                    break
            self.all_check.setCheckState(Qt.Unchecked)
            if cursor is not None:
                cursor.endEditBlock()
Esempio n. 12
0
class QtLabelsControls(QtLayerControls):
    """Qt view and controls for the napari Labels layer.

    Parameters
    ----------
    layer : napari.layers.Labels
        An instance of a napari Labels layer.

    Attributes
    ----------
    button_group : qtpy.QtWidgets.QButtonGroup
        Button group of labels layer modes: PAN_ZOOM, PICKER, PAINT, ERASE, or
        FILL.
    colormapUpdate : qtpy.QtWidgets.QPushButton
        Button to update colormap of label layer.
    contigCheckBox : qtpy.QtWidgets.QCheckBox
        Checkbox to control if label layer is contiguous.
    fill_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select FILL mode on Labels layer.
    grid_layout : qtpy.QtWidgets.QGridLayout
        Layout of Qt widget controls for the layer.
    layer : napari.layers.Labels
        An instance of a napari Labels layer.
    ndimSpinBox : qtpy.QtWidgets.QSpinBox
        Spinbox to control the number of editable dimensions of label layer.
    paint_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select PAINT mode on Labels layer.
    panzoom_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select PAN_ZOOM mode on Labels layer.
    pick_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select PICKER mode on Labels layer.
    erase_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select ERASE mode on Labels layer.
    selectionSpinBox : superqt.QLargeIntSpinBox
        Widget to select a specific label by its index.
        N.B. cannot represent labels > 2**53.

    Raises
    ------
    ValueError
        Raise error if label mode is not PAN_ZOOM, PICKER, PAINT, ERASE, or
        FILL.
    """
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.mode.connect(self._on_mode_change)
        self.layer.events._ndisplay.connect(self._on_ndisplay_change)
        self.layer.events.rendering.connect(self._on_rendering_change)
        self.layer.events.selected_label.connect(
            self._on_selected_label_change)
        self.layer.events.brush_size.connect(self._on_brush_size_change)
        self.layer.events.contiguous.connect(self._on_contiguous_change)
        self.layer.events.n_edit_dimensions.connect(
            self._on_n_edit_dimensions_change)
        self.layer.events.contour.connect(self._on_contour_change)
        self.layer.events.editable.connect(self._on_editable_change)
        self.layer.events.preserve_labels.connect(
            self._on_preserve_labels_change)
        self.layer.events.color_mode.connect(self._on_color_mode_change)

        # selection spinbox
        self.selectionSpinBox = QLargeIntSpinBox()
        dtype_lims = get_dtype_limits(get_dtype(layer))
        self.selectionSpinBox.setRange(*dtype_lims)
        self.selectionSpinBox.setKeyboardTracking(False)
        self.selectionSpinBox.valueChanged.connect(self.changeSelection)
        self.selectionSpinBox.setAlignment(Qt.AlignCenter)
        self._on_selected_label_change()

        self.maskSelectionCheckBox = QCheckBox()
        self.maskSelectionCheckBox.setCheckState(Qt.CheckState.Unchecked)
        self.maskSelectionCheckBox.stateChanged.connect(self.maskSelection)

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(1)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        sld.valueChanged.connect(self.changeSize)
        self.brushSizeSlider = sld
        self._on_brush_size_change()

        contig_cb = QCheckBox()
        contig_cb.setToolTip(trans._('contiguous editing'))
        contig_cb.stateChanged.connect(self.change_contig)
        self.contigCheckBox = contig_cb
        self._on_contiguous_change()

        ndim_sb = QSpinBox()
        self.ndimSpinBox = ndim_sb
        ndim_sb.setToolTip(trans._('number of dimensions for label editing'))
        ndim_sb.valueChanged.connect(self.change_n_edit_dim)
        ndim_sb.setMinimum(2)
        ndim_sb.setMaximum(self.layer.ndim)
        ndim_sb.setSingleStep(1)
        ndim_sb.setAlignment(Qt.AlignCenter)
        self._on_n_edit_dimensions_change()

        self.contourSpinBox = QLargeIntSpinBox()
        self.contourSpinBox.setRange(*dtype_lims)
        self.contourSpinBox.setToolTip(trans._('display contours of labels'))
        self.contourSpinBox.valueChanged.connect(self.change_contour)
        self.contourSpinBox.setKeyboardTracking(False)
        self.contourSpinBox.setAlignment(Qt.AlignCenter)
        self._on_contour_change()

        preserve_labels_cb = QCheckBox()
        preserve_labels_cb.setToolTip(
            trans._('preserve existing labels while painting'))
        preserve_labels_cb.stateChanged.connect(self.change_preserve_labels)
        self.preserveLabelsCheckBox = preserve_labels_cb
        self._on_preserve_labels_change()

        selectedColorCheckbox = QCheckBox()
        selectedColorCheckbox.setToolTip(
            trans._("Display only selected label"))
        selectedColorCheckbox.stateChanged.connect(self.toggle_selected_mode)
        self.selectedColorCheckbox = selectedColorCheckbox

        # shuffle colormap button
        self.colormapUpdate = QtModePushButton(
            None,
            'shuffle',
            slot=self.changeColor,
            tooltip=trans._('shuffle colors'),
        )

        self.panzoom_button = QtModeRadioButton(
            layer,
            'zoom',
            Mode.PAN_ZOOM,
            checked=True,
        )
        action_manager.bind_button('napari:activate_label_pan_zoom_mode',
                                   self.panzoom_button)

        self.pick_button = QtModeRadioButton(layer, 'picker', Mode.PICK)
        action_manager.bind_button('napari:activate_label_picker_mode',
                                   self.pick_button)

        self.paint_button = QtModeRadioButton(layer, 'paint', Mode.PAINT)
        action_manager.bind_button('napari:activate_paint_mode',
                                   self.paint_button)

        self.fill_button = QtModeRadioButton(
            layer,
            'fill',
            Mode.FILL,
        )
        action_manager.bind_button(
            'napari:activate_fill_mode',
            self.fill_button,
            extra_tooltip_text=trans._(
                "Toggle with {shortcut}",
                shortcut=Shortcut("Control"),
            ),
        )

        self.erase_button = QtModeRadioButton(
            layer,
            'erase',
            Mode.ERASE,
        )
        action_manager.bind_button(
            'napari:activate_label_erase_mode',
            self.erase_button,
            extra_tooltip_text=trans._(
                "Toggle with {shortcut}",
                shortcut=Shortcut("Alt"),
            ),
        )

        # don't bind with action manager as this would remove "Toggle with {shortcut}"

        self.button_group = QButtonGroup(self)
        self.button_group.addButton(self.panzoom_button)
        self.button_group.addButton(self.paint_button)
        self.button_group.addButton(self.pick_button)
        self.button_group.addButton(self.fill_button)
        self.button_group.addButton(self.erase_button)
        self._on_editable_change()

        button_row = QHBoxLayout()
        button_row.addStretch(1)
        button_row.addWidget(self.colormapUpdate)
        button_row.addWidget(self.erase_button)
        button_row.addWidget(self.paint_button)
        button_row.addWidget(self.fill_button)
        button_row.addWidget(self.pick_button)
        button_row.addWidget(self.panzoom_button)
        button_row.setSpacing(4)
        button_row.setContentsMargins(0, 0, 0, 5)

        renderComboBox = QComboBox(self)
        rendering_options = [i.value for i in LabelsRendering]
        renderComboBox.addItems(rendering_options)
        index = renderComboBox.findText(self.layer.rendering,
                                        Qt.MatchFixedString)
        renderComboBox.setCurrentIndex(index)
        renderComboBox.activated[str].connect(self.changeRendering)
        self.renderComboBox = renderComboBox
        self.renderLabel = QLabel(trans._('rendering:'))
        self._on_ndisplay_change()

        color_mode_comboBox = QComboBox(self)
        for index, (data,
                    text) in enumerate(LABEL_COLOR_MODE_TRANSLATIONS.items()):
            data = data.value
            color_mode_comboBox.addItem(text, data)

            if self.layer.color_mode == data:
                color_mode_comboBox.setCurrentIndex(index)

        color_mode_comboBox.activated.connect(self.change_color_mode)
        self.colorModeComboBox = color_mode_comboBox
        self._on_color_mode_change()

        color_layout = QHBoxLayout()
        self.colorBox = QtColorBox(layer)
        color_layout.addWidget(self.colorBox)
        color_layout.addWidget(self.selectionSpinBox)

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addLayout(button_row, 0, 0, 1, 4)
        self.grid_layout.addWidget(QLabel(trans._('label:')), 1, 0, 1, 1)
        self.grid_layout.addWidget(self.maskSelectionCheckBox, 1, 1, 1, 1)
        self.grid_layout.addLayout(color_layout, 1, 2, 1, 2)
        self.grid_layout.addWidget(QLabel(trans._('opacity:')), 2, 0, 1, 1)
        self.grid_layout.addWidget(self.opacitySlider, 2, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('brush size:')), 3, 0, 1, 1)
        self.grid_layout.addWidget(self.brushSizeSlider, 3, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('blending:')), 5, 0, 1, 1)
        self.grid_layout.addWidget(self.blendComboBox, 5, 1, 1, 3)
        self.grid_layout.addWidget(self.renderLabel, 6, 0, 1, 1)
        self.grid_layout.addWidget(self.renderComboBox, 6, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('color mode:')), 7, 0, 1, 1)
        self.grid_layout.addWidget(self.colorModeComboBox, 7, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('contour:')), 8, 0, 1, 1)
        self.grid_layout.addWidget(self.contourSpinBox, 8, 1, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('n edit dim:')), 9, 0, 1, 1)
        self.grid_layout.addWidget(self.ndimSpinBox, 9, 1, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('contiguous:')), 10, 0, 1, 1)
        self.grid_layout.addWidget(self.contigCheckBox, 10, 1, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('preserve\nlabels:')), 11, 0,
                                   1, 2)
        self.grid_layout.addWidget(self.preserveLabelsCheckBox, 11, 1, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('show\nselected:')), 11, 2,
                                   1, 1)
        self.grid_layout.addWidget(self.selectedColorCheckbox, 11, 3, 1, 1)
        self.grid_layout.setRowStretch(12, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)

    def _on_mode_change(self, event):
        """Receive layer model mode change event and update checkbox ticks.

        Parameters
        ----------
        event : napari.utils.event.Event
            The napari event that triggered this method.

        Raises
        ------
        ValueError
            Raise error if event.mode is not PAN_ZOOM, PICK, PAINT, ERASE, or
            FILL
        """
        mode = event.mode
        if mode == Mode.PAN_ZOOM:
            self.panzoom_button.setChecked(True)
        elif mode == Mode.PICK:
            self.pick_button.setChecked(True)
        elif mode == Mode.PAINT:
            self.paint_button.setChecked(True)
        elif mode == Mode.FILL:
            self.fill_button.setChecked(True)
        elif mode == Mode.ERASE:
            self.erase_button.setChecked(True)
        elif mode == Mode.TRANSFORM:
            pass
        else:
            raise ValueError(trans._("Mode not recognized"))

    def changeRendering(self, text):
        """Change rendering mode for image display.

        Parameters
        ----------
        text : str
            Rendering mode used by vispy.
            Selects a preset rendering mode in vispy that determines how
            volume is displayed:
            * translucent: voxel colors are blended along the view ray until
              the result is opaque.
            * iso_categorical: isosurface for categorical data (e.g., labels).
              Cast a ray until a value greater than zero is encountered. At that
              location, lighning calculations are performed to give the visual
              appearance of a surface.
        """
        self.layer.rendering = text

    def changeColor(self):
        """Change colormap of the label layer."""
        self.layer.new_colormap()

    def maskSelection(self, state):
        """Mask the selected label

        Parameters
        ----------
        state : int
            State of the checkbox.
        """
        if state == Qt.CheckState.Unchecked:
            self.selectionSpinBox.setMaskLineEdit(False)
        if state == Qt.CheckState.Checked:
            self.selectionSpinBox.setMaskLineEdit(True)

    def changeSelection(self, value):
        """Change currently selected label.

        Parameters
        ----------
        value : int
            Index of label to select.
        """
        self.layer.selected_label = value
        self.selectionSpinBox.clearFocus()
        self.setFocus()

    def toggle_selected_mode(self, state):
        if state == Qt.Checked:
            self.layer.show_selected_label = True
        else:
            self.layer.show_selected_label = False

    def changeSize(self, value):
        """Change paint brush size.

        Parameters
        ----------
        value : float
            Size of the paint brush.
        """
        self.layer.brush_size = value

    def change_contig(self, state):
        """Toggle contiguous state of label layer.

        Parameters
        ----------
        state : QCheckBox
            Checkbox indicating if labels are contiguous.
        """
        if state == Qt.Checked:
            self.layer.contiguous = True
        else:
            self.layer.contiguous = False

    def change_n_edit_dim(self, value):
        """Change the number of editable dimensions of label layer.

        Parameters
        ----------
        value : int
            The number of editable dimensions to set.
        """
        self.layer.n_edit_dimensions = value
        self.ndimSpinBox.clearFocus()
        self.setFocus()

    def change_contour(self, value):
        """Change contour thickness.

        Parameters
        ----------
        value : int
            Thickness of contour.
        """
        self.layer.contour = value
        self.contourSpinBox.clearFocus()
        self.setFocus()

    def change_preserve_labels(self, state):
        """Toggle preserve_labels state of label layer.

        Parameters
        ----------
        state : QCheckBox
            Checkbox indicating if overwriting label is enabled.
        """
        self.layer.preserve_labels = state == Qt.Checked

    def change_color_mode(self):
        """Change color mode of label layer"""
        self.layer.color_mode = self.colorModeComboBox.currentData()

    def _on_contour_change(self):
        """Receive layer model contour value change event and update spinbox."""
        with self.layer.events.contour.blocker():
            value = self.layer.contour
            self.contourSpinBox.setValue(value)

    def _on_selected_label_change(self):
        """Receive layer model label selection change event and update spinbox."""
        with self.layer.events.selected_label.blocker():
            value = self.layer.selected_label
            self.selectionSpinBox.setValue(value)

    def _on_brush_size_change(self):
        """Receive layer model brush size change event and update the slider."""
        with self.layer.events.brush_size.blocker():
            value = self.layer.brush_size
            value = np.maximum(1, int(value))
            if value > self.brushSizeSlider.maximum():
                self.brushSizeSlider.setMaximum(int(value))
            self.brushSizeSlider.setValue(value)

    def _on_n_edit_dimensions_change(self):
        """Receive layer model n-dim mode change event and update the checkbox."""
        with self.layer.events.n_edit_dimensions.blocker():
            value = self.layer.n_edit_dimensions
            self.ndimSpinBox.setValue(int(value))

    def _on_contiguous_change(self):
        """Receive layer model contiguous change event and update the checkbox."""
        with self.layer.events.contiguous.blocker():
            self.contigCheckBox.setChecked(self.layer.contiguous)

    def _on_preserve_labels_change(self):
        """Receive layer model preserve_labels event and update the checkbox."""
        with self.layer.events.preserve_labels.blocker():
            self.preserveLabelsCheckBox.setChecked(self.layer.preserve_labels)

    def _on_color_mode_change(self):
        """Receive layer model color."""
        with self.layer.events.color_mode.blocker():
            self.colorModeComboBox.setCurrentIndex(
                self.colorModeComboBox.findData(self.layer.color_mode))

    def _on_editable_change(self):
        """Receive layer model editable change event & enable/disable buttons."""
        # In 3D mode, we need to disable all buttons other than picking
        # (only picking works in 3D)
        widget_list = [
            'pick_button',
            'fill_button',
            'paint_button',
            'erase_button',
        ]
        widgets_to_toggle = {
            (2, True): widget_list,
            (2, False): widget_list,
            (3, True): widget_list,
            (3, False): widget_list,
        }

        disable_with_opacity(
            self,
            widgets_to_toggle[(self.layer._ndisplay, self.layer.editable)],
            self.layer.editable,
        )

    def _on_rendering_change(self):
        """Receive layer model rendering change event and update dropdown menu."""
        with self.layer.events.rendering.blocker():
            index = self.renderComboBox.findText(self.layer.rendering,
                                                 Qt.MatchFixedString)
            self.renderComboBox.setCurrentIndex(index)

    def _on_ndisplay_change(self):
        """Toggle between 2D and 3D visualization modes."""
        if self.layer._ndisplay == 2:
            self.renderComboBox.hide()
            self.renderLabel.hide()
        else:
            self.renderComboBox.show()
            self.renderLabel.show()

        self._on_editable_change()

    def deleteLater(self):
        disconnect_events(self.layer.events, self.colorBox)
        super().deleteLater()
Esempio n. 13
0
class WorkflowWidget(QWidget):
    sigAddFunction = Signal(object)
    sigRunWorkflow = Signal(object)

    # TODO -- emit Workflow from sigRunWorkflow

    def __init__(self, workflowview: QAbstractItemView):
        super(WorkflowWidget, self).__init__()

        self.view = workflowview

        self.autorun_checkbox = QCheckBox("Run Automatically")
        self.autorun_checkbox.setCheckState(Qt.Unchecked)
        self.autorun_checkbox.stateChanged.connect(self._autorun_state_changed)
        self.run_button = QPushButton("Run Workflow")
        self.run_button.clicked.connect(self.sigRunWorkflow.emit)
        # TODO -- actually hook up the auto run OR dependent class needs to connect (see SAXSGUIPlugin)

        self.toolbar = QToolBar()
        self.addfunctionmenu = QToolButton()
        self.addfunctionmenu.setIcon(QIcon(path("icons/addfunction.png")))
        self.addfunctionmenu.setText("Add Function")
        # Defer menu population to once the plugins have been loaded; otherwise, the menu may not contain anything
        # if this widget is init'd before all plugins have been loaded.
        self.functionmenu = QMenu()
        self.functionmenu.aboutToShow.connect(self.populateFunctionMenu)
        self.addfunctionmenu.setMenu(self.functionmenu)
        self.addfunctionmenu.setPopupMode(QToolButton.InstantPopup)
        self.toolbar.addWidget(self.addfunctionmenu)
        # self.toolbar.addAction(QIcon(path('icons/up.png')), 'Move Up')
        # self.toolbar.addAction(QIcon(path('icons/down.png')), 'Move Down')
        self.toolbar.addAction(QIcon(path("icons/folder.png")),
                               "Load Workflow")
        self.toolbar.addAction(QIcon(path("icons/trash.png")),
                               "Delete Operation", self.deleteOperation)

        v = QVBoxLayout()
        v.addWidget(self.view)
        h = QHBoxLayout()
        h.addWidget(self.autorun_checkbox)
        h.addWidget(self.run_button)
        v.addLayout(h)
        v.addWidget(self.toolbar)
        v.setContentsMargins(0, 0, 0, 0)
        self.setLayout(v)

    def _autorun_state_changed(self, state):
        if state == Qt.Checked:
            self.run_button.setDisabled(True)
        else:
            self.run_button.setDisabled(False)

    def _run_workflow(self, _):
        self._workflow

    def populateFunctionMenu(self):
        self.functionmenu.clear()
        sortingDict = {}
        for plugin in pluginmanager.get_plugins_of_type("OperationPlugin"):
            typeOfOperationPlugin = plugin.categories
            # TODO : should OperationPlugin be responsible for initializing categories
            # to some placeholder value (instead of [])?
            if typeOfOperationPlugin == []:
                typeOfOperationPlugin = "uncategorized"  # put found operations into a default category
            if not typeOfOperationPlugin in sortingDict.keys():
                sortingDict[typeOfOperationPlugin] = []
            sortingDict[typeOfOperationPlugin].append(plugin)
        for key in sortingDict.keys():
            self.functionmenu.addSeparator()
            self.functionmenu.addAction(key)
            self.functionmenu.addSeparator()
            for plugin in sortingDict[key]:
                self.functionmenu.addAction(
                    plugin.name,
                    partial(self.addOperation, plugin, autoconnectall=True))

    def addOperation(self, operation: OperationPlugin, autoconnectall=True):
        self.view.model().workflow.add_operation(operation())
        if autoconnectall:
            self.view.model().workflow.auto_connect_all()
        print("selected new row:", self.view.model().rowCount() - 1)
        self.view.setCurrentIndex(self.view.model().index(
            self.view.model().rowCount() - 1, 0))

    def deleteOperation(self):
        for index in self.view.selectedIndexes():
            operation = self.view.model().workflow.operations[index.row()]
            self.view.model().workflow.remove_operation(operation)
class WorkflowWidget(QWidget):
    sigAddFunction = Signal(object)
    sigRunWorkflow = Signal()

    # TODO -- emit Workflow from sigRunWorkflow

    def __init__(self,
                 workflowview: QAbstractItemView,
                 operation_filter: Callable[[OperationPlugin], bool] = None):
        super(WorkflowWidget, self).__init__()

        self.operation_filter = operation_filter
        self.view = workflowview

        self.autorun_checkbox = QCheckBox("Run Automatically")
        self.autorun_checkbox.setCheckState(Qt.Unchecked)
        self.autorun_checkbox.stateChanged.connect(self._autorun_state_changed)
        self.run_button = QPushButton("Run Workflow")
        self.run_button.clicked.connect(self.sigRunWorkflow.emit)
        self.view.model().workflow.attach(self._autorun)
        # TODO -- actually hook up the auto run OR dependent class needs to connect (see SAXSGUIPlugin)

        self.toolbar = QToolBar()
        self.addfunctionmenu = QToolButton()
        self.addfunctionmenu.setIcon(QIcon(path("icons/addfunction.png")))
        self.addfunctionmenu.setText("Add Function")
        # Defer menu population to once the plugins have been loaded; otherwise, the menu may not contain anything
        # if this widget is init'd before all plugins have been loaded.
        self.functionmenu = QMenu()
        self.functionmenu.aboutToShow.connect(self.populateFunctionMenu)
        self.addfunctionmenu.setMenu(self.functionmenu)
        self.addfunctionmenu.setPopupMode(QToolButton.InstantPopup)
        self.toolbar.addWidget(self.addfunctionmenu)
        # self.toolbar.addAction(QIcon(path('icons/up.png')), 'Move Up')
        # self.toolbar.addAction(QIcon(path('icons/down.png')), 'Move Down')
        self.toolbar.addAction(QIcon(path("icons/folder.png")),
                               "Load Workflow")
        self.toolbar.addAction(QIcon(path("icons/trash.png")),
                               "Delete Operation", self.deleteOperation)

        v = QVBoxLayout()
        v.addWidget(self.view)
        h = QHBoxLayout()
        h.addWidget(self.autorun_checkbox)
        h.addWidget(self.run_button)
        v.addLayout(h)
        v.addWidget(self.toolbar)
        v.setContentsMargins(0, 0, 0, 0)
        self.setLayout(v)

    def _autorun_state_changed(self, state):
        if state == Qt.Checked:
            self.run_button.setDisabled(True)
        else:
            self.run_button.setDisabled(False)

    def _autorun(self):
        if self.autorun_checkbox.isChecked():
            self.sigRunWorkflow.emit()

    def populateFunctionMenu(self):
        self.functionmenu.clear()
        sortingDict = MenuDict()
        operations = pluginmanager.get_plugins_of_type("OperationPlugin")
        if self.operation_filter is not None:
            operations = filter(self.operation_filter, operations)
        for operation in operations:

            categories = operation.categories
            if not categories:
                categories = [("Uncategorized", )
                              ]  # put found operations into a default category

            for categories_tuple in categories:
                if isinstance(categories_tuple, str):
                    categories_tuple = (categories_tuple, )
                submenu = sortingDict
                categories_list = list(categories_tuple)
                while categories_list:
                    category = categories_list.pop(0)
                    submenu = submenu[category]

                submenu['___'].append(operation)

        self._mkMenu(sortingDict)

    def _mkMenu(self, sorting_dict, menu=None):
        if menu is None:
            menu = self.functionmenu
            menu.clear()

        for key in sorting_dict:
            if key == '___':
                menu.addSeparator()
                for operation in sorting_dict['___']:
                    menu.addAction(
                        operation.name,
                        partial(self.addOperation,
                                operation,
                                autoconnectall=True))
            else:
                submenu = QMenu(title=key, parent=menu)
                menu.addMenu(submenu)
                self._mkMenu(sorting_dict[key], submenu)

    def addOperation(self, operation: OperationPlugin, autoconnectall=True):
        self.view.model().workflow.add_operation(operation())
        if autoconnectall:
            self.view.model().workflow.auto_connect_all()
        print("selected new row:", self.view.model().rowCount() - 1)
        self.view.setCurrentIndex(self.view.model().index(
            self.view.model().rowCount() - 1, 0))

    def deleteOperation(self):
        index = self.view.currentIndex()
        operation = self.view.model().workflow.operations[index.row()]
        self.view.model().workflow.remove_operation(operation)
        self.view.setCurrentIndex(QModelIndex())
Esempio n. 15
0
class WriteModelDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(
            self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.setWindowTitle('Write Model')
        self.treeview = parent
        self.setAttribute(Qt.WA_DeleteOnClose)

        fixed_dir_layout = QHBoxLayout()
        browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self)
        browse_btn.setToolTip(_("Select model directory"))
        browse_btn.clicked.connect(self.select_directory)
        self.wd_edit = QLineEdit()
        fixed_dir_layout.addWidget(self.wd_edit)
        fixed_dir_layout.addWidget(browse_btn)
        fixed_dir_layout.setContentsMargins(0, 0, 0, 0)

        namelabel = QLabel(_("Folder Name"))
        self.nameEdit = QLineEdit(self)

        self.backupCheck = QCheckBox(_("Back up old folder"))
        self.backupCheck.setCheckState(Qt.Checked)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        mainLayout = QGridLayout(self)
        mainLayout.addLayout(fixed_dir_layout, 0, 0, 1, 2)
        mainLayout.addWidget(namelabel, 1, 0)
        mainLayout.addWidget(self.nameEdit, 1, 1)
        mainLayout.addWidget(self.backupCheck, 2, 0, 1, 2)
        mainLayout.addWidget(self.buttonBox, 3, 0, 1, 2)
        # mainLayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(mainLayout)

    def accept(self) -> None:
        reply = {
            'accepted': True,
            'directory': self.wd_edit.text(),
            'name': self.nameEdit.text(),
            'backup': self.backupCheck.isChecked()
        }
        self.treeview.reply = reply
        super().accept()

    def reject(self) -> None:
        self.treeview.reply = {'accepted': False}
        super().reject()

    def select_directory(self):
        """Select directory"""
        basedir = to_text_string(self.wd_edit.text())
        if not os.path.isdir(basedir):
            basedir = getcwd_or_home()
        directory = getexistingdirectory(self, _("Select directory"), basedir)
        if directory:
            self.wd_edit.setText(directory)
Esempio n. 16
0
    def populate_gui(self):
        _contain_parsed = self.contain_parsed
        for _row, _entry in enumerate(_contain_parsed):

            if _entry == ['']:
                continue

            self.parent.ui.table.insertRow(_row)

            # select
            _layout = QHBoxLayout()
            _widget = QCheckBox()
            _widget.setEnabled(True)
            _layout.addWidget(_widget)
            _layout.addStretch()
            _new_widget = QWidget()
            _new_widget.setLayout(_layout)

            _widget.stateChanged.connect(
                lambda state=0, row=_row: self.parent.
                table_select_state_changed(state, row))
            self.parent.ui.table.setCellWidget(_row, 0, _new_widget)

            # name
            _item = QTableWidgetItem(_entry[1])
            self.parent.ui.table.setItem(_row, 1, _item)

            # runs
            _item = QTableWidgetItem(_entry[2])
            self.parent.ui.table.setItem(_row, 2, _item)

            # Sample formula
            if _entry[3]:
                _item = QTableWidgetItem(_entry[3])
            else:
                _item = QTableWidgetItem("")
            self.parent.ui.table.setItem(_row, 3, _item)

            # mass density
            if _entry[4]:
                _item = QTableWidgetItem(_entry[4])
            else:
                _item = QTableWidgetItem("")
            self.parent.ui.table.setItem(_row, 4, _item)

            # radius
            if _entry[5]:
                _item = QTableWidgetItem(_entry[5])
            else:
                _item = QTableWidgetItem("")
            self.parent.ui.table.setItem(_row, 5, _item)

            # packing fraction
            if _entry[6]:
                _item = QTableWidgetItem(_entry[6])
            else:
                _item = QTableWidgetItem("")
            self.parent.ui.table.setItem(_row, 6, _item)

            # sample shape
            _widget = QComboBox()
            _widget.addItem("cylindrical")
            _widget.addItem("spherical")
            if _entry[7] == "spherical":
                _widget.setCurrentIndex(1)
            self.parent.ui.table.setCellWidget(_row, 7, _widget)

            # do abs corr
            _layout = QHBoxLayout()
            _widget = QCheckBox()
            if _entry[8] == "True":
                _widget.setCheckState(Qt.Checked)
            _widget.setStyleSheet("border:  2px; solid-black")
            _widget.setEnabled(True)
            _layout.addStretch()
            _layout.addWidget(_widget)
            _layout.addStretch()
            _new_widget = QWidget()
            _new_widget.setLayout(_layout)
            self.parent.ui.table.setCellWidget(_row, 8, _new_widget)

        for _row, _entry in enumerate(_contain_parsed):

            if _entry == ['']:
                continue

            # select
            _widget = self.parent.ui.table.cellWidget(_row, 0).children()[1]
            if _entry[0] == "True":
                _widget.setChecked(True)
Esempio n. 17
0
class WndLoadQuantitativeCalibration(SecondaryWindow):

    signal_quantitative_calibration_changed = Signal()

    def __init__(self, *, gpc, gui_vars):
        super().__init__()

        # Global processing classes
        self.gpc = gpc
        # Global GUI variables (used for control of GUI state)
        self.gui_vars = gui_vars

        self.initialize()

    def initialize(self):
        self.table_header_display_names = False

        self.setWindowTitle("PyXRF: Load Quantitative Calibration")
        self.setMinimumWidth(750)
        self.setMinimumHeight(400)
        self.resize(750, 600)

        self.pb_load_calib = QPushButton("Load Calibration ...")
        self.pb_load_calib.clicked.connect(self.pb_load_calib_clicked)

        self._changes_exist = False
        self._auto_update = True
        self.cb_auto_update = QCheckBox("Auto")
        self.cb_auto_update.setCheckState(
            Qt.Checked if self._auto_update else Qt.Unchecked)
        self.cb_auto_update.stateChanged.connect(
            self.cb_auto_update_state_changed)

        self.pb_update_plots = QPushButton("Update Plots")
        self.pb_update_plots.clicked.connect(self.pb_update_plots_clicked)

        self.grp_current_scan = QGroupBox(
            "Parameters of Currently Processed Scan")

        self._distance_to_sample = 0.0
        self.le_distance_to_sample = LineEditExtended()
        le_dist_validator = QDoubleValidator()
        le_dist_validator.setBottom(0)
        self.le_distance_to_sample.setValidator(le_dist_validator)
        self._set_distance_to_sample()
        self.le_distance_to_sample.editingFinished.connect(
            self.le_distance_to_sample_editing_finished)
        self.le_distance_to_sample.focusOut.connect(
            self.le_distance_to_sample_focus_out)

        hbox = QHBoxLayout()
        hbox.addWidget(QLabel("Distance-to-sample:"))
        hbox.addWidget(self.le_distance_to_sample)
        hbox.addStretch(1)
        self.grp_current_scan.setLayout(hbox)

        self.eline_rb_exclusive = [
        ]  # Holds the list of groups of exclusive radio buttons
        self._setup_tab_widget()

        vbox = QVBoxLayout()

        hbox = QHBoxLayout()
        hbox.addWidget(self.pb_load_calib)
        hbox.addStretch(1)
        hbox.addWidget(self.cb_auto_update)
        hbox.addWidget(self.pb_update_plots)
        vbox.addLayout(hbox)

        vbox.addWidget(self.tab_widget)

        vbox.addWidget(self.grp_current_scan)

        self.setLayout(vbox)

        # Display data
        self.update_all_data()

        self._set_tooltips()

    def _setup_tab_widget(self):

        self.tab_widget = QTabWidget()
        self.loaded_standards = QWidget()
        # self.display_loaded_standards()
        self.scroll = QScrollArea()
        self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scroll.setWidget(self.loaded_standards)
        self.tab_widget.addTab(self.scroll, "Loaded Standards")

        self.combo_set_table_header = QComboBox()
        self.combo_set_table_header.addItems(
            ["Standard Serial #", "Standard Name"])
        self.combo_set_table_header.currentIndexChanged.connect(
            self.combo_set_table_header_index_changed)

        vbox = QVBoxLayout()
        vbox.addSpacing(5)
        hbox = QHBoxLayout()
        hbox.addWidget(QLabel("Display in table header:"))
        hbox.addWidget(self.combo_set_table_header)
        hbox.addStretch(1)
        vbox.addLayout(hbox)
        self.table = QTableWidget()
        self.table.verticalHeader().hide()
        self.table.setSelectionMode(QTableWidget.NoSelection)
        self.table.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        self.table.horizontalHeader().setMinimumSectionSize(150)
        vbox.addWidget(self.table)

        self.table.setStyleSheet("QTableWidget::item{color: black;}")

        frame = QFrame()
        vbox.setContentsMargins(0, 0, 0, 0)
        frame.setLayout(vbox)

        self.tab_widget.addTab(frame, "Selected Emission Lines")

    def display_loaded_standards(self):
        calib_data = self.gpc.get_quant_calibration_data()
        calib_settings = self.gpc.get_quant_calibration_settings()

        # Create the new widget (this deletes the old widget)
        self.loaded_standards = QWidget()
        self.loaded_standards.setMinimumWidth(700)

        # Also delete references to all components
        self.frames_calib_data = []
        self.pbs_view = []
        self.pbs_remove = []

        # All 'View' buttons are added to the group in order to be connected to the same slot
        self.group_view = QButtonGroup()
        self.group_view.setExclusive(False)
        self.group_view.buttonClicked.connect(self.pb_view_clicked)
        # The same for the 'Remove' buttons
        self.group_remove = QButtonGroup()
        self.group_remove.setExclusive(False)
        self.group_remove.buttonClicked.connect(self.pb_remove_clicked)

        vbox = QVBoxLayout()

        class _LabelBlack(QLabel):
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)
                self.setStyleSheet("color: black")

        for cdata, csettings in zip(calib_data, calib_settings):
            frame = QFrame()
            frame.setFrameStyle(QFrame.StyledPanel)
            frame.setStyleSheet(
                get_background_css((200, 255, 200), widget="QFrame"))

            _vbox = QVBoxLayout()

            name = cdata["name"]  # Standard name (can be arbitrary string
            # If name is long, then print it in a separate line
            _name_is_long = len(name) > 30

            pb_view = QPushButton("View ...")
            self.group_view.addButton(pb_view)
            pb_remove = QPushButton("Remove")
            self.group_remove.addButton(pb_remove)

            # Row 1: serial, name
            serial = cdata["serial"]
            _hbox = QHBoxLayout()
            _hbox.addWidget(_LabelBlack(f"<b>Standard</b> #{serial}"))
            if not _name_is_long:
                _hbox.addWidget(_LabelBlack(f"'{name}'"))
            _hbox.addStretch(1)
            _hbox.addWidget(pb_view)
            _hbox.addWidget(pb_remove)
            _vbox.addLayout(_hbox)

            # Optional row
            if _name_is_long:
                # Wrap name if it is extemely long
                name = textwrap.fill(name, width=80)
                _hbox = QHBoxLayout()
                _hbox.addWidget(_LabelBlack("<b>Name:</b> "), 0, Qt.AlignTop)
                _hbox.addWidget(_LabelBlack(name), 0, Qt.AlignTop)
                _hbox.addStretch(1)
                _vbox.addLayout(_hbox)

            # Row 2: description
            description = textwrap.fill(cdata["description"], width=80)
            _hbox = QHBoxLayout()
            _hbox.addWidget(_LabelBlack("<b>Description:</b>"), 0, Qt.AlignTop)
            _hbox.addWidget(_LabelBlack(f"{description}"), 0, Qt.AlignTop)
            _hbox.addStretch(1)
            _vbox.addLayout(_hbox)

            # Row 3:
            incident_energy = cdata["incident_energy"]
            scaler = cdata["scaler_name"]
            detector_channel = cdata["detector_channel"]
            distance_to_sample = cdata["distance_to_sample"]
            _hbox = QHBoxLayout()
            _hbox.addWidget(
                _LabelBlack(f"<b>Incident energy, keV:</b> {incident_energy}"))
            _hbox.addWidget(_LabelBlack(f"  <b>Scaler:</b> {scaler}"))
            _hbox.addWidget(
                _LabelBlack(f"  <b>Detector channel:</b> {detector_channel}"))
            _hbox.addWidget(
                _LabelBlack(
                    f"  <b>Distance-to-sample:</b> {distance_to_sample}"))
            _hbox.addStretch(1)
            _vbox.addLayout(_hbox)

            # Row 4: file name
            fln = textwrap.fill(csettings["file_path"], width=80)
            _hbox = QHBoxLayout()
            _hbox.addWidget(_LabelBlack("<b>Source file:</b>"), 0, Qt.AlignTop)
            _hbox.addWidget(_LabelBlack(fln), 0, Qt.AlignTop)
            _hbox.addStretch(1)
            _vbox.addLayout(_hbox)

            frame.setLayout(_vbox)

            # Now the group box is added to the upper level layout
            vbox.addWidget(frame)
            vbox.addSpacing(5)
            self.frames_calib_data.append(frame)
            self.pbs_view.append(pb_view)
            self.pbs_remove.append(pb_remove)

        # Add the layout to the widget
        self.loaded_standards.setLayout(vbox)
        # ... and put the widget inside the scroll area. This will update the
        # contents of the scroll area.
        self.scroll.setWidget(self.loaded_standards)

    def display_table_header(self):
        calib_data = self.gpc.get_quant_calibration_data()
        header_by_name = self.table_header_display_names

        tbl_labels = ["Lines"]
        for n, cdata in enumerate(calib_data):
            if header_by_name:
                txt = cdata["name"]
            else:
                txt = cdata["serial"]
            txt = textwrap.fill(txt, width=20)
            tbl_labels.append(txt)

        self.table.setHorizontalHeaderLabels(tbl_labels)

    def display_standard_selection_table(self):
        calib_data = self.gpc.get_quant_calibration_data()
        self._quant_file_paths = self.gpc.get_quant_calibration_file_path_list(
        )

        brightness = 220
        table_colors = [(255, brightness, brightness),
                        (brightness, 255, brightness)]

        # Disconnect all radio button signals before clearing the table
        for bgroup in self.eline_rb_exclusive:
            bgroup.buttonToggled.disconnect(self.rb_selection_toggled)

        # This list will hold radio button groups for horizontal rows
        #   Those are exclusive groups. They are not going to be
        #   used directly, but they must be kept alive in order
        #   for the radiobuttons to work properly. Most of the groups
        #   will contain only 1 radiobutton, which will always remain checked.
        self.eline_rb_exclusive = []
        # The following list will contain the list of radio buttons for each
        #   row. If there is no radiobutton in a position, then the element is
        #   set to None.
        # N rows: the number of emission lines, N cols: the number of standards
        self.eline_rb_lists = []

        self.table.clear()

        if not calib_data:
            self.table.setRowCount(0)
            self.table.setColumnCount(0)
        else:
            # Create the sorted list of available element lines
            line_set = set()
            for cdata in calib_data:
                ks = list(cdata["element_lines"].keys())
                line_set.update(list(ks))
            self.eline_list = list(line_set)
            self.eline_list.sort()

            for n in range(len(self.eline_list)):
                self.eline_rb_exclusive.append(QButtonGroup())
                self.eline_rb_lists.append([None] * len(calib_data))

            self.table.setColumnCount(len(calib_data) + 1)
            self.table.setRowCount(len(self.eline_list))
            self.display_table_header()

            for n, eline in enumerate(self.eline_list):

                rgb = table_colors[n % 2]

                item = QTableWidgetItem(eline)
                item.setTextAlignment(Qt.AlignCenter)
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                item.setBackground(QBrush(QColor(*rgb)))
                self.table.setItem(n, 0, item)

                for ns, cdata in enumerate(calib_data):
                    q_file_path = self._quant_file_paths[
                        ns]  # Used to identify standard
                    if eline in cdata["element_lines"]:
                        rb = QRadioButton()
                        if self.gpc.get_quant_calibration_is_eline_selected(
                                eline, q_file_path):
                            rb.setChecked(True)

                        rb.setStyleSheet("color: black")

                        self.eline_rb_lists[n][ns] = rb
                        # self.eline_rb_by_standard[ns].addButton(rb)
                        self.eline_rb_exclusive[n].addButton(rb)

                        item = QWidget()
                        item_hbox = QHBoxLayout(item)
                        item_hbox.addWidget(rb)
                        item_hbox.setAlignment(Qt.AlignCenter)
                        item_hbox.setContentsMargins(0, 0, 0, 0)

                        item.setStyleSheet(get_background_css(rgb))

                        # Generate tooltip
                        density = cdata["element_lines"][eline]["density"]
                        fluorescence = cdata["element_lines"][eline][
                            "fluorescence"]
                        ttip = f"Fluorescence (F): {fluorescence:12g}\nDensity (D): {density:12g}\n"
                        # Avoid very small values of density (probably zero)
                        if abs(density) > 1e-30:
                            ttip += f"F/D: {fluorescence/density:12g}"

                        item.setToolTip(ttip)

                        self.table.setCellWidget(n, ns + 1, item)
                    else:
                        # There is no radio button, but we still need to fill the cell
                        item = QTableWidgetItem("")
                        item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                        item.setBackground(QBrush(QColor(*rgb)))
                        self.table.setItem(n, ns + 1, item)

            # Now the table is set (specifically radio buttons).
            # So we can connect the button groups with the event processing function
            for bgroup in self.eline_rb_exclusive:
                bgroup.buttonToggled.connect(self.rb_selection_toggled)

    @Slot()
    def update_all_data(self):
        self.display_loaded_standards()
        self.display_standard_selection_table()
        self._set_distance_to_sample()

    def _set_distance_to_sample(self):
        """Set 'le_distance_to_sample` without updating maps"""
        distance_to_sample = self.gpc.get_quant_calibration_distance_to_sample(
        )
        if distance_to_sample is None:
            distance_to_sample = 0.0
        self._distance_to_sample = distance_to_sample
        self._set_le_distance_to_sample(distance_to_sample)

    def _set_tooltips(self):
        set_tooltip(self.pb_load_calib,
                    "Load <b>calibration data</b> from JSON file.")
        set_tooltip(
            self.cb_auto_update,
            "Automatically <b>update the plots</b> when changes are made. "
            "If unchecked, then button <b>Update Plots</b> must be pressed "
            "to update the plots. Automatic update is often undesirable "
            "when large maps are displayed and multiple changes to parameters "
            "are made.",
        )
        set_tooltip(
            self.pb_update_plots,
            "<b>Update plots</b> based on currently selected parameters.")
        set_tooltip(
            self.le_distance_to_sample,
            "Distance between <b>the sample and the detector</b>. The ratio between of the distances "
            "during calibration and measurement is used to scale computed concentrations. "
            "If distance-to-sample is 0 for calibration or measurement, then no scaling is performed.",
        )
        set_tooltip(
            self.combo_set_table_header,
            "Use <b>Serial Number</b> or <b>Name</b> of the calibration standard in the header of the table",
        )
        set_tooltip(
            self.table,
            "Use Radio Buttons to select the <b>source of calibration data</b> for each emission line. "
            "This feature is needed if multiple loaded calibration files have data on the same "
            "emission line.",
        )

    def update_widget_state(self, condition=None):
        # Update the state of the menu bar
        state = not self.gui_vars["gui_state"]["running_computations"]
        self.setEnabled(state)

        # Hide the window if required by the program state
        state_xrf_map_exists = self.gui_vars["gui_state"][
            "state_xrf_map_exists"]
        if not state_xrf_map_exists:
            self.hide()

        if condition == "tooltips":
            self._set_tooltips()

    def cb_auto_update_state_changed(self, state):
        self._auto_update = state
        self.pb_update_plots.setEnabled(not state)
        # If changes were made, apply the changes while switching to 'auto' mode
        if state and self._changes_exist:
            self._update_maps_auto()

    def pb_update_plots_clicked(self):
        self._update_maps()

    def pb_load_calib_clicked(self):
        current_dir = self.gpc.get_current_working_directory()
        file_name = QFileDialog.getOpenFileName(
            self, "Select File with Quantitative Calibration Data",
            current_dir, "JSON (*.json);; All (*)")
        file_name = file_name[0]
        if file_name:
            try:
                logger.debug(
                    f"Loading quantitative calibration from file: '{file_name}'"
                )
                self.gpc.load_quantitative_calibration_data(file_name)
                self.update_all_data()
                self._update_maps_auto()
            except Exception:
                msg = "The selected JSON file has incorrect format. Select a different file."
                msgbox = QMessageBox(QMessageBox.Critical,
                                     "Data Loading Error",
                                     msg,
                                     QMessageBox.Ok,
                                     parent=self)
                msgbox.exec()

    def pb_view_clicked(self, button):
        try:
            n_standard = self.pbs_view.index(button)
            calib_settings = self.gpc.get_quant_calibration_settings()
            file_path = calib_settings[n_standard]["file_path"]
            calib_preview = self.gpc.get_quant_calibration_text_preview(
                file_path)
            dlg = DialogViewCalibStandard(None,
                                          file_path=file_path,
                                          calib_preview=calib_preview)
            dlg.exec()
        except ValueError:
            logger.error(
                "'View' button was pressed, but not found in the list of buttons"
            )

    def pb_remove_clicked(self, button):
        try:
            n_standard = self.pbs_remove.index(button)
            calib_settings = self.gpc.get_quant_calibration_settings()
            file_path = calib_settings[n_standard]["file_path"]
            self.gpc.quant_calibration_remove_entry(file_path)
            self.update_all_data()
            self._update_maps_auto()
        except ValueError:
            logger.error(
                "'Remove' button was pressed, but not found in the list of buttons"
            )

    def rb_selection_toggled(self, button, checked):
        if checked:
            # Find the button in 2D list 'self.eline_rb_lists'
            button_found = False
            for nr, rb_list in enumerate(self.eline_rb_lists):
                try:
                    nc = rb_list.index(button)
                    button_found = True
                    break
                except ValueError:
                    pass

            if button_found:
                eline = self.eline_list[nr]
                n_standard = nc
                file_path = self._quant_file_paths[n_standard]
                self.gpc.set_quant_calibration_select_eline(eline, file_path)
                self._update_maps_auto()
            else:
                # This should never happen
                logger.error(
                    "Selection radio button was pressed, but not found in the list"
                )

    def combo_set_table_header_index_changed(self, index):
        self.table_header_display_names = bool(index)
        self.display_table_header()

    def le_distance_to_sample_editing_finished(self):
        distance_to_sample = float(self.le_distance_to_sample.text())
        if distance_to_sample != self._distance_to_sample:
            self._distance_to_sample = distance_to_sample
            self.gpc.set_quant_calibration_distance_to_sample(
                distance_to_sample)
            self._update_maps_auto()

    def le_distance_to_sample_focus_out(self):
        try:
            float(self.le_distance_to_sample.text())
        except ValueError:
            # If the text can not be interpreted to float, then replace the text with the old value
            self._set_le_distance_to_sample(self._distance_to_sample)

    def _set_le_distance_to_sample(self, distance_to_sample):
        self.le_distance_to_sample.setText(f"{distance_to_sample:.12g}")

    def _update_maps_auto(self):
        """Update maps only if 'auto' update is ON. Used as a 'filter'
        to prevent extra plot updates."""
        self._changes_exist = True
        if self._auto_update:
            self._update_maps()

    def _update_maps(self):
        """Upload the selections (limit table) and update plot"""
        self._changes_exist = False
        self._redraw_maps()
        # Emit signal only after the maps are redrawn. This should change
        #   ranges in the respective controls for the plots
        self.signal_quantitative_calibration_changed.emit()

    def _redraw_maps(self):
        # We don't emit any signals here, but we don't really need to.
        logger.debug("Redrawing RGB XRF Maps")
        self.gpc.compute_map_ranges()
        self.gpc.redraw_maps()
        self.gpc.compute_rgb_map_ranges()
        self.gpc.redraw_rgb_maps()
Esempio n. 18
0
    def populate_gui(self):
        _contain_parsed = self.contain_parsed
        for _row, _entry in enumerate(_contain_parsed):

            if _entry == ['']:
                continue

            self.parent.ui.table.insertRow(_row)

            # select
            _layout = QHBoxLayout()
            _widget = QCheckBox()
            _widget.setEnabled(True)
            _layout.addWidget(_widget)
            _layout.addStretch()
            _new_widget = QWidget()
            _new_widget.setLayout(_layout)

            _widget.stateChanged.connect(lambda state=0, row=_row:
                                         self.parent.table_select_state_changed(state, row))
            self.parent.ui.table.setCellWidget(_row, 0, _new_widget)

            # name
            _item = QTableWidgetItem(_entry[1])
            self.parent.ui.table.setItem(_row, 1, _item)

            # runs
            _item = QTableWidgetItem(_entry[2])
            self.parent.ui.table.setItem(_row, 2, _item)

            # Sample formula
            if _entry[3]:
                _item = QTableWidgetItem(_entry[3])
            else:
                _item = QTableWidgetItem("")
            self.parent.ui.table.setItem(_row, 3, _item)

            # mass density
            if _entry[4]:
                _item = QTableWidgetItem(_entry[4])
            else:
                _item = QTableWidgetItem("")
            self.parent.ui.table.setItem(_row, 4, _item)

            # radius
            if _entry[5]:
                _item = QTableWidgetItem(_entry[5])
            else:
                _item = QTableWidgetItem("")
            self.parent.ui.table.setItem(_row, 5, _item)

            # packing fraction
            if _entry[6]:
                _item = QTableWidgetItem(_entry[6])
            else:
                _item = QTableWidgetItem("")
            self.parent.ui.table.setItem(_row, 6, _item)

            # sample shape
            _widget = QComboBox()
            _widget.addItem("cylindrical")
            _widget.addItem("spherical")
            if _entry[7] == "spherical":
                _widget.setCurrentIndex(1)
            self.parent.ui.table.setCellWidget(_row, 7, _widget)

            # do abs corr
            _layout = QHBoxLayout()
            _widget = QCheckBox()
            if _entry[8] == "True":
                _widget.setCheckState(Qt.Checked)
            _widget.setStyleSheet("border:  2px; solid-black")
            _widget.setEnabled(True)
            _layout.addStretch()
            _layout.addWidget(_widget)
            _layout.addStretch()
            _new_widget = QWidget()
            _new_widget.setLayout(_layout)
            self.parent.ui.table.setCellWidget(_row, 8, _new_widget)

        for _row, _entry in enumerate(_contain_parsed):

            if _entry == ['']:
                continue

            # select
            _widget = self.parent.ui.table.cellWidget(_row, 0).children()[1]
            if _entry[0] == "True":
                _widget.setChecked(True)
Esempio n. 19
0
    def insert_row(self, row=-1,
                   title='',
                   sample_runs='',
                   sample_mass_density='N/A',
                   sample_chemical_formula='N/A',
                   packing_fraction='N/A',
                   align_and_focus_args={},
                   sample_placzek_arguments={},
                   normalization_placzek_arguments={}):
        self.table_ui.insertRow(row)
        self.set_row_height(row, COLUMN_DEFAULT_HEIGHT)

        _list_ui_to_unlock = [self.table_ui]

        _dimension_widgets = {'label': None, 'value': 'N/A', 'units': None}
        _full_dimension_widgets = {'radius': copy.deepcopy(_dimension_widgets),
                                   'radius2': copy.deepcopy(_dimension_widgets),
                                   'height': copy.deepcopy(_dimension_widgets)}
        _text_button = {'text': None, 'button': None}
        _mass_density_options = {'value': "N/A",
                                 "selected": False}
        _mass_density_infos = {'number_density': copy.deepcopy(_mass_density_options),
                               'mass_density': copy.deepcopy(_mass_density_options),
                               'mass': copy.deepcopy(_mass_density_options),
                               'molecular_mass': np.NaN,
                               'total_number_of_atoms': np.NaN,
                               }
        _material_infos = {'mantid_format': None,
                           'addie_format': None}
        _mass_density_infos['mass_density']["selected"] = True

        _master_table_row_ui = {'active': None,
                                'title': None,
                                'sample': {'runs': None,
                                           'background': {'runs': None,
                                                          'background': None,
                                                          },
                                           'material': copy.deepcopy(_text_button),
                                           'material_infos': copy.deepcopy(_material_infos),
                                           'mass_density': copy.deepcopy(_text_button),
                                           'mass_density_infos': copy.deepcopy(_mass_density_infos),
                                           'packing_fraction': None,
                                           'geometry': copy.deepcopy(_full_dimension_widgets),
                                           'shape': None,
                                           'abs_correction': None,
                                           'mult_scat_correction': None,
                                           'inelastic_correction': None,
                                           'placzek_button': None,
                                           'placzek_infos': None,
                                           },
                                'normalization': {'runs': None,
                                                  'background': {'runs': None,
                                                                 'background': None,
                                                                 },
                                                  'material': copy.deepcopy(_text_button),
                                                  'material_infos': copy.deepcopy(_material_infos),
                                                  'mass_density': copy.deepcopy(_text_button),
                                                  'mass_density_infos': copy.deepcopy(_mass_density_infos),
                                                  'packing_fraction': None,
                                                  'geometry': copy.deepcopy(_full_dimension_widgets),
                                                  'shape': None,
                                                  'abs_correction': None,
                                                  'mult_scat_correction': None,
                                                  'inelastic_correction': None,
                                                  'placzek_button': None,
                                                  'placzek_infos': None,
                                                  },
                                'align_and_focus_args_button': None,
                                'align_and_focus_args_infos': {},
                                }

        random_key = self.generate_random_key()
        self.key = random_key

        # block main table events
        self.table_ui.blockSignals(True)

        # column 0 (active or not checkBox)
        _layout = QHBoxLayout()
        _widget = QCheckBox()
        _widget.setCheckState(QtCore.Qt.Checked)
        _widget.setEnabled(True)
        _master_table_row_ui['active'] = _widget
        _spacer = QSpacerItem(40, 20,
                              QSizePolicy.Expanding,
                              QSizePolicy.Minimum)
        _layout.addItem(_spacer)
        _layout.addWidget(_widget)
        _spacer = QSpacerItem(40, 20,
                              QSizePolicy.Expanding,
                              QSizePolicy.Minimum)
        _layout.addItem(_spacer)
        _layout.addStretch()
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)
        _widget.stateChanged.connect(lambda state=0, key=random_key:
                                     self.main_window.master_table_select_state_changed(state, key))
        column = 0
        self.table_ui.setCellWidget(row, column, _new_widget)

        # sample

        column += 1
        # column 1 - title
        _item = QTableWidgetItem(title)
        _master_table_row_ui['title'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 2 - sample runs
        column += 1
        _item = QTableWidgetItem(sample_runs)
        _master_table_row_ui['sample']['runs'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 3 - background runs
        column += 1
        _item = QTableWidgetItem("")
        _master_table_row_ui['sample']['background']['runs'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 4 - background background
        column += 1
        _item = QTableWidgetItem("")
        _master_table_row_ui['sample']['background']['background'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 5 - material (chemical formula)
        column += 1
        clean_sample_chemical_formula = format_chemical_formula_equation(sample_chemical_formula)
        _material_text = QLineEdit(clean_sample_chemical_formula)
        _material_text = QLabel(clean_sample_chemical_formula)
        _material_button = QPushButton("...")
        _material_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _material_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _material_button.pressed.connect(lambda key=random_key:
                                         self.main_window.master_table_sample_material_button_pressed(key))

        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_material_text)
        _verti_layout.addWidget(_material_button)
        _material_widget = QWidget()
        _material_widget.setLayout(_verti_layout)
        self.table_ui.setCellWidget(row, column, _material_widget)
        _master_table_row_ui['sample']['material']['text'] = _material_text
        _master_table_row_ui['sample']['material']['button'] = _material_button

        # column 6 - mass density
        column += 1
        _mass_text = QLineEdit(sample_mass_density)
        _mass_text.returnPressed.connect(lambda key=random_key:
                                         self.main_window.master_table_sample_mass_density_line_edit_entered(key))

        _mass_units = QLabel("g/cc")
        _top_widget = QWidget()
        _top_layout = QHBoxLayout()
        _top_layout.addWidget(_mass_text)
        _top_layout.addWidget(_mass_units)
        _top_widget.setLayout(_top_layout)
        _mass_button = QPushButton("...")
        _mass_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _mass_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _mass_button.pressed.connect(lambda key=random_key:
                                     self.main_window.master_table_sample_mass_density_button_pressed(key))
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_top_widget)
        _verti_layout.addWidget(_mass_button)
        _mass_widget = QWidget()
        _mass_widget.setLayout(_verti_layout)
        self.table_ui.setCellWidget(row, column, _mass_widget)
        _master_table_row_ui['sample']['mass_density']['text'] = _mass_text
        _master_table_row_ui['sample']['mass_density']['button'] = _mass_button

        # column 7 - packing fraction
        column += 1
        if packing_fraction == "N/A":
            packing_fraction = "{}".format(self.main_window.packing_fraction)
        _item = QTableWidgetItem(packing_fraction)
        _master_table_row_ui['sample']['packing_fraction'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 8 - shape (cylindrical or spherical)
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _shape_default_index = 0
        _widget.currentIndexChanged.connect(lambda index=_shape_default_index,
                                            key=random_key:
                                            self.main_window.master_table_sample_shape_changed(index, key))
        _list_ui_to_unlock.append(_widget)
        _widget.blockSignals(True)
        _widget.addItem("cylindrical")
        _widget.addItem("spherical")
        _widget.addItem("hollow cylinder")
        _master_table_row_ui['sample']['shape'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 9 - dimensions
        column += 1

        # layout 1
        _grid_layout = QGridLayout()

        _label1 = QLabel("Radius:")
        _grid_layout.addWidget(_label1, 1, 0)
        _value1 = QLabel("N/A")
        _grid_layout.addWidget(_value1, 1, 1)
        _dim1 = QLabel("cm")
        _grid_layout.addWidget(_dim1, 1, 2)

        _label2 = QLabel("Radius:")
        _label2.setVisible(False)
        _grid_layout.addWidget(_label2, 2, 0)
        _value2 = QLabel("N/A")
        _value2.setVisible(False)
        _grid_layout.addWidget(_value2, 2, 1)
        _dim2 = QLabel("cm")
        _dim2.setVisible(False)
        _grid_layout.addWidget(_dim2, 2, 2)

        _label3 = QLabel("Height:")
        _grid_layout.addWidget(_label3, 3, 0)
        _value3 = QLabel("N/A")
        _grid_layout.addWidget(_value3, 3, 1)
        _dim3 = QLabel("cm")
        _grid_layout.addWidget(_dim3, 3, 2)

        _master_table_row_ui['sample']['geometry']['radius']['value'] = _value1
        _master_table_row_ui['sample']['geometry']['radius2']['value'] = _value2
        _master_table_row_ui['sample']['geometry']['height']['value'] = _value3

        _master_table_row_ui['sample']['geometry']['radius']['label'] = _label1
        _master_table_row_ui['sample']['geometry']['radius2']['label'] = _label2
        _master_table_row_ui['sample']['geometry']['height']['label'] = _label3

        _master_table_row_ui['sample']['geometry']['radius']['units'] = _dim1
        _master_table_row_ui['sample']['geometry']['radius2']['units'] = _dim2
        _master_table_row_ui['sample']['geometry']['height']['units'] = _dim3

        _geometry_widget = QWidget()
        _geometry_widget.setLayout(_grid_layout)

        _set_dimensions_button = QPushButton("...")
        _set_dimensions_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _set_dimensions_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_geometry_widget)
        _verti_layout.addWidget(_set_dimensions_button)
        _verti_widget = QWidget()
        _verti_widget.setLayout(_verti_layout)

        _set_dimensions_button.pressed.connect(lambda key=random_key:
                                               self.main_window.master_table_sample_dimensions_setter_button_pressed(key))

        self.table_ui.setCellWidget(row, column, _verti_widget)

        # column 10 - abs. correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _shape_default_value = 0
        list_abs_correction = self.get_absorption_correction_list(shape=_shape_default_value)
        _widget.currentIndexChanged.connect(lambda value=list_abs_correction[0],
                                            key = random_key:
                                            self.main_window.master_table_sample_abs_correction_changed(value, key))
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        for _item in list_abs_correction:
            _widget.addItem(_item)
        _master_table_row_ui['sample']['abs_correction'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 11 - multi. scattering correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        list_multi_scat_correction = self.get_multi_scat_correction_list(shape=_shape_default_value)
        _widget.currentIndexChanged.connect(lambda value=list_multi_scat_correction[0],
                                            key=random_key:
                                            self.main_window.master_table_sample_multi_scattering_correction_changed(value, key))
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        for _item in list_multi_scat_correction:
            _widget.addItem(_item)
        _master_table_row_ui['sample']['mult_scat_correction'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 12 - inelastic correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget1 = QComboBox()
        _widget1.setMinimumHeight(20)
        list_inelastic_correction = self.get_inelastic_scattering_list(shape=_shape_default_value)
        for _item in list_inelastic_correction:
            _widget1.addItem(_item)
        _master_table_row_ui['sample']['inelastic_correction'] = _widget1
        _button = QPushButton("...")
        _button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _button.pressed.connect(lambda key=random_key:
                                self.main_window.master_table_sample_placzek_button_pressed(key))
        _master_table_row_ui['sample']['placzek_button'] = _button
        _button.setVisible(False)
        _master_table_row_ui['sample']['placzek_button'] = _button
        _layout.addWidget(_widget1)
        _layout.addWidget(_button)
        _widget = QWidget()
        _widget.setLayout(_layout)
        _default_value = 'None'
        _widget1.currentIndexChanged.connect(lambda value=_default_value,
                                             key=random_key:
                                             self.main_window.master_table_sample_inelastic_correction_changed(value, key))
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        self.table_ui.setCellWidget(row, column, _widget)

        # save default placzek settings
        _sample_formated_placzek_default = self.formated_placzek_default(sample_placzek_arguments)
        _master_table_row_ui['sample']['placzek_infos'] = _sample_formated_placzek_default

        ## normalization

        # column 13 - sample runs
        column += 1
        _item = QTableWidgetItem("")
        self.table_ui.setItem(row, column, _item)

        # column 14 - background runs
        column += 1
        _item = QTableWidgetItem("")
        self.table_ui.setItem(row, column, _item)

        # column 15 - background background
        column += 1
        _item = QTableWidgetItem("")
        self.table_ui.setItem(row, column, _item)

        # column 16 - material (chemical formula)
        column += 1
        #_material_text = QLineEdit("")
        _material_text = QLabel("N/A")
        _material_button = QPushButton("...")
        _material_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _material_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _material_button.pressed.connect(lambda key=random_key:
                                         self.main_window.master_table_normalization_material_button_pressed(key))
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_material_text)
        _verti_layout.addWidget(_material_button)
        _material_widget = QWidget()
        _material_widget.setLayout(_verti_layout)
        self.table_ui.setCellWidget(row, column, _material_widget)
        _master_table_row_ui['normalization']['material']['text'] = _material_text
        _master_table_row_ui['normalization']['material']['button'] = _material_button

        # column 17 - mass density
        column += 1
        _mass_text = QLineEdit("N/A")
        _mass_text.returnPressed.connect(lambda key=random_key:
                                         self.main_window.master_table_normalization_mass_density_line_edit_entered(key))
        _mass_units = QLabel("g/cc")
        _top_widget = QWidget()
        _top_layout = QHBoxLayout()
        _top_layout.addWidget(_mass_text)
        _top_layout.addWidget(_mass_units)
        _top_widget.setLayout(_top_layout)
        _mass_button = QPushButton("...")
        _mass_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _mass_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _mass_button.pressed.connect(lambda key=random_key:
                                     self.main_window.master_table_normalization_mass_density_button_pressed(key))
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_top_widget)
        _verti_layout.addWidget(_mass_button)
        _mass_widget = QWidget()
        _mass_widget.setLayout(_verti_layout)
        self.table_ui.setCellWidget(row, column, _mass_widget)
        _master_table_row_ui['normalization']['mass_density']['text'] = _mass_text
        _master_table_row_ui['normalization']['mass_density']['button'] = _mass_button

        # column 18 - packing fraction
        column += 1
        _item = QTableWidgetItem("")
        self.table_ui.setItem(row, column, _item)

        # column 19 - shape (cylindrical or spherical)
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _widget.currentIndexChanged.connect(lambda value=_shape_default_value,
                                            key=random_key:
                                            self.main_window.master_table_normalization_shape_changed(value, key))
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        _widget.addItem("cylindrical")
        _widget.addItem("spherical")
        _widget.addItem("hollow cylinder")
        _master_table_row_ui['normalization']['shape'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 20 - dimensions
        column += 1

        # layout 1
        _grid_layout = QGridLayout()

        _label1 = QLabel("Radius:")
        _grid_layout.addWidget(_label1, 1, 0)
        _value1 = QLabel("N/A")
        _grid_layout.addWidget(_value1, 1, 1)
        _dim1 = QLabel("cm")
        _grid_layout.addWidget(_dim1, 1, 2)

        _label2 = QLabel("Radius:")
        _label2.setVisible(False)
        _grid_layout.addWidget(_label2, 2, 0)
        _value2 = QLabel("N/A")
        _value2.setVisible(False)
        _grid_layout.addWidget(_value2, 2, 1)
        _dim2 = QLabel("cm")
        _dim2.setVisible(False)
        _grid_layout.addWidget(_dim2, 2, 2)

        _label3 = QLabel("Height:")
        _grid_layout.addWidget(_label3, 3, 0)
        _value3 = QLabel("N/A")
        _grid_layout.addWidget(_value3, 3, 1)
        _dim3 = QLabel("cm")
        _grid_layout.addWidget(_dim3, 3, 2)

        _master_table_row_ui['normalization']['geometry']['radius']['value'] = _value1
        _master_table_row_ui['normalization']['geometry']['radius2']['value'] = _value2
        _master_table_row_ui['normalization']['geometry']['height']['value'] = _value3

        _master_table_row_ui['normalization']['geometry']['radius']['label'] = _label1
        _master_table_row_ui['normalization']['geometry']['radius2']['label'] = _label2
        _master_table_row_ui['normalization']['geometry']['height']['label'] = _label3

        _master_table_row_ui['normalization']['geometry']['radius']['units'] = _dim1
        _master_table_row_ui['normalization']['geometry']['radius2']['units'] = _dim2
        _master_table_row_ui['normalization']['geometry']['height']['units'] = _dim3

        _geometry_widget = QWidget()
        _geometry_widget.setLayout(_grid_layout)

        _set_dimensions_button = QPushButton("...")
        _set_dimensions_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _set_dimensions_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_geometry_widget)
        _verti_layout.addWidget(_set_dimensions_button)
        _verti_widget = QWidget()
        _verti_widget.setLayout(_verti_layout)

        _set_dimensions_button.pressed.connect(lambda key=random_key:
                                               self.main_window.master_table_normalization_dimensions_setter_button_pressed(key))  # noqa

        self.table_ui.setCellWidget(row, column, _verti_widget)

        # column 21 - abs. correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _widget.currentIndexChanged.connect(lambda value=list_abs_correction[0],
                                            key=random_key:
                                            self.main_window.master_table_normalization_abs_correction_changed(value, key))  # noqa
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        for _item in list_abs_correction:
            _widget.addItem(_item)
        _widget.setCurrentIndex(0)
        _master_table_row_ui['normalization']['abs_correction'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 24 - multi. scattering correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _widget.currentIndexChanged.connect(lambda value=list_multi_scat_correction[0],
                                            key=random_key:
                                            self.main_window.master_table_normalization_multi_scattering_correction_changed(value, key))  # noqa
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        for _item in list_multi_scat_correction:
            _widget.addItem(_item)
        _widget.setCurrentIndex(0)
        _master_table_row_ui['normalization']['mult_scat_correction'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 22 - inelastic correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget1 = QComboBox()
        _widget1.setMinimumHeight(20)
        list_inelastic_correction = self.get_inelastic_scattering_list(shape=_shape_default_value)
        for _item in list_inelastic_correction:
            _widget1.addItem(_item)
        _widget1.setCurrentIndex(0)
        _master_table_row_ui['normalization']['inelastic_correction'] = _widget1
        _button = QPushButton("...")
        _button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _button.pressed.connect(lambda key=random_key:
                                self.main_window.master_table_normalization_placzek_button_pressed(key))
        _master_table_row_ui['normalization']['placzek_button'] = _button
        _button.setVisible(False)
        _layout.addWidget(_widget1)
        _layout.addWidget(_button)
        _widget = QWidget()
        _widget.setLayout(_layout)
        _default_value = 'None'
        _widget1.currentIndexChanged.connect( lambda value=_default_value,
                                              key=random_key:
                                              self.main_window.master_table_normalization_inelastic_correction_changed(value, key))  # noqa
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        self.table_ui.setCellWidget(row, column, _widget)

        # automatically populate placzek infos with default values
        _norm_formated_placzek_default = self.formated_placzek_default(normalization_placzek_arguments)
        _master_table_row_ui['normalization']['placzek_infos'] = _norm_formated_placzek_default

        # column 23 - key/value pair
        column += 1
        _layout = QHBoxLayout()
        _spacer_kv1 = QSpacerItem(40, 20,
                                  QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        _layout.addItem(_spacer_kv1)
        _button = QPushButton("...")
        _layout.addWidget(_button)
        _button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _button.pressed.connect(lambda key=random_key:
                                self.main_window.master_table_keyvalue_button_pressed(key))
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _new_widget)
        _master_table_row_ui['align_and_focus_args_button'] = _button
        _spacer_kv2 = QSpacerItem(40, 20,
                                  QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        _layout.addItem(_spacer_kv2)
        _layout.addStretch()
        _master_table_row_ui['align_and_focus_args_infos'] = align_and_focus_args

        ## recap

        self.main_window.master_table_list_ui[random_key] = _master_table_row_ui
        self.unlock_signals_ui(list_ui=_list_ui_to_unlock)
        self.main_window.check_status_of_right_click_buttons()
Esempio n. 20
0
    def insert_row(self,
                   row=-1,
                   title='',
                   sample_runs='',
                   sample_mass_density='N/A',
                   sample_chemical_formula='N/A',
                   packing_fraction='N/A',
                   align_and_focus_args={},
                   sample_placzek_arguments={},
                   normalization_placzek_arguments={}):
        self.table_ui.insertRow(row)
        self.set_row_height(row, COLUMN_DEFAULT_HEIGHT)

        _list_ui_to_unlock = [self.table_ui]

        _dimension_widgets = {'label': None, 'value': 'N/A', 'units': None}
        _full_dimension_widgets = {
            'radius': copy.deepcopy(_dimension_widgets),
            'radius2': copy.deepcopy(_dimension_widgets),
            'height': copy.deepcopy(_dimension_widgets)
        }
        _text_button = {'text': None, 'button': None}
        _mass_density_options = {'value': "N/A", "selected": False}
        _mass_density_infos = {
            'number_density': copy.deepcopy(_mass_density_options),
            'mass_density': copy.deepcopy(_mass_density_options),
            'mass': copy.deepcopy(_mass_density_options),
            'molecular_mass': np.NaN,
            'total_number_of_atoms': np.NaN,
        }
        _material_infos = {'mantid_format': None, 'addie_format': None}
        _mass_density_infos['mass_density']["selected"] = True

        _master_table_row_ui = {
            'active': None,
            'title': None,
            'sample': {
                'runs': None,
                'background': {
                    'runs': None,
                    'background': None,
                },
                'material': copy.deepcopy(_text_button),
                'material_infos': copy.deepcopy(_material_infos),
                'mass_density': copy.deepcopy(_text_button),
                'mass_density_infos': copy.deepcopy(_mass_density_infos),
                'packing_fraction': None,
                'geometry': copy.deepcopy(_full_dimension_widgets),
                'shape': None,
                'abs_correction': None,
                'mult_scat_correction': None,
                'inelastic_correction': None,
                'placzek_button': None,
                'placzek_infos': None,
            },
            'normalization': {
                'runs': None,
                'background': {
                    'runs': None,
                    'background': None,
                },
                'material': copy.deepcopy(_text_button),
                'material_infos': copy.deepcopy(_material_infos),
                'mass_density': copy.deepcopy(_text_button),
                'mass_density_infos': copy.deepcopy(_mass_density_infos),
                'packing_fraction': None,
                'geometry': copy.deepcopy(_full_dimension_widgets),
                'shape': None,
                'abs_correction': None,
                'mult_scat_correction': None,
                'inelastic_correction': None,
                'placzek_button': None,
                'placzek_infos': None,
            },
            'align_and_focus_args_button': None,
            'align_and_focus_args_infos': {},
            'align_and_focus_args_use_global': True,
        }

        random_key = self.generate_random_key()
        self.key = random_key

        # block main table events
        self.table_ui.blockSignals(True)

        # column 0 (active or not checkBox)
        _layout = QHBoxLayout()
        _widget = QCheckBox()
        _widget.setCheckState(QtCore.Qt.Checked)
        _widget.setEnabled(True)
        _master_table_row_ui['active'] = _widget
        _spacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                              QSizePolicy.Minimum)
        _layout.addItem(_spacer)
        _layout.addWidget(_widget)
        _spacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                              QSizePolicy.Minimum)
        _layout.addItem(_spacer)
        _layout.addStretch()
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)
        _widget.stateChanged.connect(
            lambda state=0, key=random_key: self.main_window.
            master_table_select_state_changed(state, key))
        column = 0
        self.table_ui.setCellWidget(row, column, _new_widget)

        # sample

        column += 1
        # column 1 - title
        _item = QTableWidgetItem(title)
        _master_table_row_ui['title'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 2 - sample runs
        column += 1
        _item = QTableWidgetItem(sample_runs)
        _master_table_row_ui['sample']['runs'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 3 - background runs
        column += 1
        _item = QTableWidgetItem("")
        _master_table_row_ui['sample']['background']['runs'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 4 - background background
        column += 1
        _item = QTableWidgetItem("")
        _master_table_row_ui['sample']['background']['background'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 5 - material (chemical formula)
        column += 1
        clean_sample_chemical_formula = format_chemical_formula_equation(
            sample_chemical_formula)
        _material_text = QLineEdit(clean_sample_chemical_formula)
        _material_text = QLabel(clean_sample_chemical_formula)
        _material_button = QPushButton("...")
        _material_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _material_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _material_button.pressed.connect(
            lambda key=random_key: self.main_window.
            master_table_sample_material_button_pressed(key))

        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_material_text)
        _verti_layout.addWidget(_material_button)
        _material_widget = QWidget()
        _material_widget.setLayout(_verti_layout)
        self.table_ui.setCellWidget(row, column, _material_widget)
        _master_table_row_ui['sample']['material']['text'] = _material_text
        _master_table_row_ui['sample']['material']['button'] = _material_button

        # column 6 - mass density
        column += 1
        _mass_text = QLineEdit(sample_mass_density)
        _mass_text.returnPressed.connect(
            lambda key=random_key: self.main_window.
            master_table_sample_mass_density_line_edit_entered(key))

        _mass_units = QLabel("g/cc")
        _top_widget = QWidget()
        _top_layout = QHBoxLayout()
        _top_layout.addWidget(_mass_text)
        _top_layout.addWidget(_mass_units)
        _top_widget.setLayout(_top_layout)
        _mass_button = QPushButton("...")
        _mass_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _mass_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _mass_button.pressed.connect(
            lambda key=random_key: self.main_window.
            master_table_sample_mass_density_button_pressed(key))
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_top_widget)
        _verti_layout.addWidget(_mass_button)
        _mass_widget = QWidget()
        _mass_widget.setLayout(_verti_layout)
        self.table_ui.setCellWidget(row, column, _mass_widget)
        _master_table_row_ui['sample']['mass_density']['text'] = _mass_text
        _master_table_row_ui['sample']['mass_density']['button'] = _mass_button

        # column 7 - packing fraction
        column += 1
        if packing_fraction == "N/A":
            packing_fraction = "{}".format(self.main_window.packing_fraction)
        _item = QTableWidgetItem(packing_fraction)
        _master_table_row_ui['sample']['packing_fraction'] = _item
        self.table_ui.setItem(row, column, _item)

        # column 8 - shape (cylinder or sphere)
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _shape_default_index = 0
        _widget.currentIndexChanged.connect(
            lambda index=_shape_default_index, key=random_key: self.main_window
            .master_table_sample_shape_changed(index, key))
        _list_ui_to_unlock.append(_widget)
        _widget.blockSignals(True)
        _widget.addItem("Cylinder")
        _widget.addItem("Sphere")
        _widget.addItem("Hollow Cylinder")
        _master_table_row_ui['sample']['shape'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 9 - dimensions
        column += 1

        # layout 1
        _grid_layout = QGridLayout()

        _label1 = QLabel("Radius:")
        _grid_layout.addWidget(_label1, 1, 0)
        _value1 = QLabel("N/A")
        _grid_layout.addWidget(_value1, 1, 1)
        _dim1 = QLabel("cm")
        _grid_layout.addWidget(_dim1, 1, 2)

        _label2 = QLabel("Radius:")
        _label2.setVisible(False)
        _grid_layout.addWidget(_label2, 2, 0)
        _value2 = QLabel("N/A")
        _value2.setVisible(False)
        _grid_layout.addWidget(_value2, 2, 1)
        _dim2 = QLabel("cm")
        _dim2.setVisible(False)
        _grid_layout.addWidget(_dim2, 2, 2)

        _label3 = QLabel("Height:")
        _grid_layout.addWidget(_label3, 3, 0)
        _value3 = QLabel("N/A")
        _grid_layout.addWidget(_value3, 3, 1)
        _dim3 = QLabel("cm")
        _grid_layout.addWidget(_dim3, 3, 2)

        _master_table_row_ui['sample']['geometry']['radius']['value'] = _value1
        _master_table_row_ui['sample']['geometry']['radius2'][
            'value'] = _value2
        _master_table_row_ui['sample']['geometry']['height']['value'] = _value3

        _master_table_row_ui['sample']['geometry']['radius']['label'] = _label1
        _master_table_row_ui['sample']['geometry']['radius2'][
            'label'] = _label2
        _master_table_row_ui['sample']['geometry']['height']['label'] = _label3

        _master_table_row_ui['sample']['geometry']['radius']['units'] = _dim1
        _master_table_row_ui['sample']['geometry']['radius2']['units'] = _dim2
        _master_table_row_ui['sample']['geometry']['height']['units'] = _dim3

        _geometry_widget = QWidget()
        _geometry_widget.setLayout(_grid_layout)

        _set_dimensions_button = QPushButton("...")
        _set_dimensions_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _set_dimensions_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_geometry_widget)
        _verti_layout.addWidget(_set_dimensions_button)
        _verti_widget = QWidget()
        _verti_widget.setLayout(_verti_layout)

        _set_dimensions_button.pressed.connect(
            lambda key=random_key: self.main_window.
            master_table_sample_dimensions_setter_button_pressed(key))

        self.table_ui.setCellWidget(row, column, _verti_widget)

        # column 10 - abs. correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _shape_default_value = 0
        list_abs_correction = self.get_absorption_correction_list(
            shape=_shape_default_value)
        _widget.currentIndexChanged.connect(
            lambda value=list_abs_correction[0], key=random_key: self.
            main_window.master_table_sample_abs_correction_changed(value, key))
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        for _item in list_abs_correction:
            _widget.addItem(_item)
        _master_table_row_ui['sample']['abs_correction'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 11 - multi. scattering correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        list_multi_scat_correction = self.get_multi_scat_correction_list(
            shape=_shape_default_value)
        _widget.currentIndexChanged.connect(
            lambda value=list_multi_scat_correction[
                0], key=random_key: self.main_window.
            master_table_sample_multi_scattering_correction_changed(
                value, key))
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        for _item in list_multi_scat_correction:
            _widget.addItem(_item)
        _master_table_row_ui['sample']['mult_scat_correction'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 12 - inelastic correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget1 = QComboBox()
        _widget1.setMinimumHeight(20)
        list_inelastic_correction = self.get_inelastic_scattering_list(
            shape=_shape_default_value)
        for _item in list_inelastic_correction:
            _widget1.addItem(_item)
        _master_table_row_ui['sample']['inelastic_correction'] = _widget1
        _button = QPushButton("...")
        _button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _button.pressed.connect(
            lambda key=random_key: self.main_window.
            master_table_sample_placzek_button_pressed(key))
        _master_table_row_ui['sample']['placzek_button'] = _button
        _button.setVisible(False)
        _master_table_row_ui['sample']['placzek_button'] = _button
        _layout.addWidget(_widget1)
        _layout.addWidget(_button)
        _widget = QWidget()
        _widget.setLayout(_layout)
        _default_value = 'None'
        _widget1.currentIndexChanged.connect(
            lambda value=_default_value, key=random_key: self.main_window.
            master_table_sample_inelastic_correction_changed(value, key))
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        self.table_ui.setCellWidget(row, column, _widget)

        # save default placzek settings
        _sample_formated_placzek_default = self.formated_placzek_default(
            sample_placzek_arguments)
        _master_table_row_ui['sample'][
            'placzek_infos'] = _sample_formated_placzek_default

        ## normalization

        # column 13 - sample runs
        column += 1
        _item = QTableWidgetItem("")
        self.table_ui.setItem(row, column, _item)

        # column 14 - background runs
        column += 1
        _item = QTableWidgetItem("")
        self.table_ui.setItem(row, column, _item)

        # column 15 - background background
        column += 1
        _item = QTableWidgetItem("")
        self.table_ui.setItem(row, column, _item)

        # column 16 - material (chemical formula)
        column += 1
        #_material_text = QLineEdit("")
        _material_text = QLabel("N/A")
        _material_button = QPushButton("...")
        _material_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _material_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _material_button.pressed.connect(
            lambda key=random_key: self.main_window.
            master_table_normalization_material_button_pressed(key))
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_material_text)
        _verti_layout.addWidget(_material_button)
        _material_widget = QWidget()
        _material_widget.setLayout(_verti_layout)
        self.table_ui.setCellWidget(row, column, _material_widget)
        _master_table_row_ui['normalization']['material'][
            'text'] = _material_text
        _master_table_row_ui['normalization']['material'][
            'button'] = _material_button

        # column 17 - mass density
        column += 1
        _mass_text = QLineEdit("N/A")
        _mass_text.returnPressed.connect(
            lambda key=random_key: self.main_window.
            master_table_normalization_mass_density_line_edit_entered(key))
        _mass_units = QLabel("g/cc")
        _top_widget = QWidget()
        _top_layout = QHBoxLayout()
        _top_layout.addWidget(_mass_text)
        _top_layout.addWidget(_mass_units)
        _top_widget.setLayout(_top_layout)
        _mass_button = QPushButton("...")
        _mass_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _mass_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _mass_button.pressed.connect(
            lambda key=random_key: self.main_window.
            master_table_normalization_mass_density_button_pressed(key))
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_top_widget)
        _verti_layout.addWidget(_mass_button)
        _mass_widget = QWidget()
        _mass_widget.setLayout(_verti_layout)
        self.table_ui.setCellWidget(row, column, _mass_widget)
        _master_table_row_ui['normalization']['mass_density'][
            'text'] = _mass_text
        _master_table_row_ui['normalization']['mass_density'][
            'button'] = _mass_button

        # column 18 - packing fraction
        column += 1
        _item = QTableWidgetItem("")
        self.table_ui.setItem(row, column, _item)

        # column 19 - shape (cylinder or sphere)
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _widget.currentIndexChanged.connect(
            lambda value=_shape_default_value, key=random_key: self.main_window
            .master_table_normalization_shape_changed(value, key))
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        _widget.addItem("Cylinder")
        _widget.addItem("Sphere")
        _widget.addItem("Hollow Cylinder")
        _master_table_row_ui['normalization']['shape'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 20 - dimensions
        column += 1

        # layout 1
        _grid_layout = QGridLayout()

        _label1 = QLabel("Radius:")
        _grid_layout.addWidget(_label1, 1, 0)
        _value1 = QLabel("N/A")
        _grid_layout.addWidget(_value1, 1, 1)
        _dim1 = QLabel("cm")
        _grid_layout.addWidget(_dim1, 1, 2)

        _label2 = QLabel("Radius:")
        _label2.setVisible(False)
        _grid_layout.addWidget(_label2, 2, 0)
        _value2 = QLabel("N/A")
        _value2.setVisible(False)
        _grid_layout.addWidget(_value2, 2, 1)
        _dim2 = QLabel("cm")
        _dim2.setVisible(False)
        _grid_layout.addWidget(_dim2, 2, 2)

        _label3 = QLabel("Height:")
        _grid_layout.addWidget(_label3, 3, 0)
        _value3 = QLabel("N/A")
        _grid_layout.addWidget(_value3, 3, 1)
        _dim3 = QLabel("cm")
        _grid_layout.addWidget(_dim3, 3, 2)

        _master_table_row_ui['normalization']['geometry']['radius'][
            'value'] = _value1
        _master_table_row_ui['normalization']['geometry']['radius2'][
            'value'] = _value2
        _master_table_row_ui['normalization']['geometry']['height'][
            'value'] = _value3

        _master_table_row_ui['normalization']['geometry']['radius'][
            'label'] = _label1
        _master_table_row_ui['normalization']['geometry']['radius2'][
            'label'] = _label2
        _master_table_row_ui['normalization']['geometry']['height'][
            'label'] = _label3

        _master_table_row_ui['normalization']['geometry']['radius'][
            'units'] = _dim1
        _master_table_row_ui['normalization']['geometry']['radius2'][
            'units'] = _dim2
        _master_table_row_ui['normalization']['geometry']['height'][
            'units'] = _dim3

        _geometry_widget = QWidget()
        _geometry_widget.setLayout(_grid_layout)

        _set_dimensions_button = QPushButton("...")
        _set_dimensions_button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _set_dimensions_button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _verti_layout = QVBoxLayout()
        _verti_layout.addWidget(_geometry_widget)
        _verti_layout.addWidget(_set_dimensions_button)
        _verti_widget = QWidget()
        _verti_widget.setLayout(_verti_layout)

        _set_dimensions_button.pressed.connect(
            lambda key=random_key: self.main_window.
            master_table_normalization_dimensions_setter_button_pressed(
                key))  # noqa

        self.table_ui.setCellWidget(row, column, _verti_widget)

        # column 21 - abs. correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _widget.currentIndexChanged.connect(
            lambda value=list_abs_correction[0], key=random_key: self.
            main_window.master_table_normalization_abs_correction_changed(
                value, key))  # noqa
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        for _item in list_abs_correction:
            _widget.addItem(_item)
        _widget.setCurrentIndex(0)
        _master_table_row_ui['normalization']['abs_correction'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 24 - multi. scattering correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget = QComboBox()
        _widget.currentIndexChanged.connect(
            lambda value=list_multi_scat_correction[
                0], key=random_key: self.main_window.
            master_table_normalization_multi_scattering_correction_changed(
                value, key))  # noqa
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        for _item in list_multi_scat_correction:
            _widget.addItem(_item)
        _widget.setCurrentIndex(0)
        _master_table_row_ui['normalization']['mult_scat_correction'] = _widget
        _layout.addWidget(_widget)
        _w = QWidget()
        _w.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _w)

        # column 22 - inelastic correction
        column += 1
        _layout = QHBoxLayout()
        _layout.setContentsMargins(0, 0, 0, 0)
        _widget1 = QComboBox()
        _widget1.setMinimumHeight(20)
        list_inelastic_correction = self.get_inelastic_scattering_list(
            shape=_shape_default_value)
        for _item in list_inelastic_correction:
            _widget1.addItem(_item)
        _widget1.setCurrentIndex(0)
        _master_table_row_ui['normalization'][
            'inelastic_correction'] = _widget1
        _button = QPushButton("...")
        _button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _button.pressed.connect(
            lambda key=random_key: self.main_window.
            master_table_normalization_placzek_button_pressed(key))
        _master_table_row_ui['normalization']['placzek_button'] = _button
        _button.setVisible(False)
        _layout.addWidget(_widget1)
        _layout.addWidget(_button)
        _widget = QWidget()
        _widget.setLayout(_layout)
        _default_value = 'None'
        _widget1.currentIndexChanged.connect(
            lambda value=_default_value, key=random_key: self.main_window.
            master_table_normalization_inelastic_correction_changed(
                value, key))  # noqa
        _widget.blockSignals(True)
        _list_ui_to_unlock.append(_widget)
        self.table_ui.setCellWidget(row, column, _widget)

        # automatically populate placzek infos with default values
        _norm_formated_placzek_default = self.formated_placzek_default(
            normalization_placzek_arguments)
        _master_table_row_ui['normalization'][
            'placzek_infos'] = _norm_formated_placzek_default

        # column 23 - key/value pair
        column += 1
        _layout = QHBoxLayout()
        _spacer_kv1 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        _layout.addItem(_spacer_kv1)
        _button = QPushButton("...")
        _layout.addWidget(_button)
        _button.setFixedWidth(CONFIG_BUTTON_WIDTH)
        _button.setFixedHeight(CONFIG_BUTTON_HEIGHT)
        _button.pressed.connect(lambda key=random_key: self.main_window.
                                master_table_keyvalue_button_pressed(key))
        _new_widget = QWidget()
        _new_widget.setLayout(_layout)
        self.table_ui.setCellWidget(row, column, _new_widget)
        _master_table_row_ui['align_and_focus_args_button'] = _button
        _spacer_kv2 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        _layout.addItem(_spacer_kv2)
        _layout.addStretch()

        align_and_focus_args = self.add_global_key_value_to_local_key_value(
            align_and_focus_args)
        _master_table_row_ui[
            'align_and_focus_args_infos'] = align_and_focus_args

        # Recap.

        self.main_window.master_table_list_ui[
            random_key] = _master_table_row_ui
        self.unlock_signals_ui(list_ui=_list_ui_to_unlock)
        self.main_window.check_status_of_right_click_buttons()