示例#1
0
 def setHeaderIcon(self):
     """Updates header icons to match data enabled state"""
     if np.all(self._data.enabled):
         self.header_icon = path_for('checked.png')
     elif np.any(self._data.enabled):
         self.header_icon = path_for('intermediate.png')
     else:
         self.header_icon = path_for('unchecked.png')
     self.headerDataChanged.emit(QtCore.Qt.Horizontal, 3, 3)
示例#2
0
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.parent_model = parent.presenter.model
        self.parent.scenes.switchToSampleScene()

        layout = QtWidgets.QHBoxLayout()
        self.list_widget = QtWidgets.QListWidget()
        self.list_widget.setAlternatingRowColors(True)
        self.list_widget.setSelectionMode(
            QtWidgets.QAbstractItemView.ExtendedSelection)
        self.list_widget.setMinimumHeight(300)
        self.list_widget.setSpacing(2)
        self.list_widget.itemSelectionChanged.connect(self.onMultiSelection)
        self.updateSampleList()

        layout.addWidget(self.list_widget)

        button_layout = QtWidgets.QVBoxLayout()
        self.delete_button = create_tool_button(
            icon_path=path_for('cross.png'),
            style_name='ToolButton',
            tooltip='Delete Sample',
            status_tip='Remove selected sample from project')
        self.delete_button.clicked.connect(self.removeSamples)
        button_layout.addWidget(self.delete_button)

        self.merge_button = create_tool_button(
            icon_path=path_for('merge.png'),
            style_name='ToolButton',
            tooltip='Merge Samples',
            status_tip=
            'Combine vertices of selected samples to form single sample')
        self.merge_button.clicked.connect(self.mergeSamples)
        button_layout.addWidget(self.merge_button)

        self.priority_button = create_tool_button(
            icon_path=path_for('check.png'),
            style_name='ToolButton',
            tooltip='Set Main Sample',
            status_tip='Set selected sample as main sample')
        self.priority_button.clicked.connect(self.changeMainSample)
        button_layout.addWidget(self.priority_button)

        layout.addSpacing(10)
        layout.addLayout(button_layout)

        main_layout = QtWidgets.QVBoxLayout()
        main_layout.addLayout(layout)
        main_layout.addStretch(1)
        self.setLayout(main_layout)

        self.parent_model.sample_changed.connect(self.updateSampleList)
        self.title = 'Samples'
        self.setMinimumWidth(450)
示例#3
0
 def updateSampleList(self):
     """Updates the sample keys in the list widget"""
     self.list_widget.clear()
     samples = self.parent_model.sample.keys()
     if samples:
         self.list_widget.addItems(samples)
         self.list_widget.item(0).setIcon(QtGui.QIcon(
             path_for('check.png')))
示例#4
0
    def createPositionerForm(self):
        """Creates the form inputs for the detector positioner"""
        title = FormTitle('Detector Position')
        self.main_layout.addWidget(title)
        self.position_form_group = FormGroup(FormGroup.Layout.Grid)

        for index, link in enumerate(self.detector.positioner.links):
            if link.type == Link.Type.Revolute:
                unit = 'degrees'
                offset = math.degrees(link.set_point)
                lower_limit = math.degrees(link.lower_limit)
                upper_limit = math.degrees(link.upper_limit)
            else:
                unit = 'mm'
                offset = link.set_point
                lower_limit = link.lower_limit
                upper_limit = link.upper_limit

            pretty_label = link.name.replace('_', ' ').title()
            control = FormControl(pretty_label,
                                  offset,
                                  desc=unit,
                                  required=True,
                                  number=True)
            control.form_lineedit.setDisabled(link.locked)
            if not link.ignore_limits:
                control.range(lower_limit, upper_limit)

            limits_button = create_tool_button(
                tooltip='Disable Joint Limits',
                style_name='MidToolButton',
                icon_path=path_for('limit.png'),
                checkable=True,
                status_tip=f'Ignore joint limits of {pretty_label}',
                checked=link.ignore_limits)
            limits_button.clicked.connect(self.ignoreJointLimits)
            limits_button.setProperty('link_index', index)

            control.extra = [limits_button]
            self.position_form_group.addControl(control)
            self.position_form_group.group_validation.connect(
                self.formValidation)

        self.main_layout.addWidget(self.position_form_group)
        button_layout = QtWidgets.QHBoxLayout()
        self.move_detector_button = QtWidgets.QPushButton('Move Detector')
        self.move_detector_button.clicked.connect(
            self.moveDetectorsButtonClicked)
        button_layout.addWidget(self.move_detector_button)
        button_layout.addStretch(1)
        self.main_layout.addLayout(button_layout)
示例#5
0
    def createPositionerForm(self):
        """Creates the form inputs for the jaw positioner"""
        title = FormTitle(f'{self.instrument.jaws.name} Position')
        self.main_layout.addWidget(title)
        self.position_form_group = FormGroup(FormGroup.Layout.Grid)

        for index in self.instrument.jaws.positioner.order:
            link = self.instrument.jaws.positioner.links[index]
            if link.type == Link.Type.Revolute:
                unit = 'degrees'
                offset = math.degrees(link.set_point)
                lower_limit = math.degrees(link.lower_limit)
                upper_limit = math.degrees(link.upper_limit)
            else:
                unit = 'mm'
                offset = link.set_point
                lower_limit = link.lower_limit
                upper_limit = link.upper_limit

            control = FormControl(link.name.title(),
                                  offset,
                                  desc=unit,
                                  required=True,
                                  number=True)
            control.form_lineedit.setDisabled(link.locked)
            if not link.ignore_limits:
                control.range(lower_limit, upper_limit)

            limits_button = create_tool_button(
                tooltip='Disable Joint Limits',
                style_name='MidToolButton',
                icon_path=path_for('limit.png'),
                checkable=True,
                status_tip=f'Ignore joint limits of {link.name}',
                checked=link.ignore_limits)
            limits_button.clicked.connect(self.ignoreJointLimits)
            limits_button.setProperty('link_index', index)

            control.extra = [limits_button]
            self.position_form_group.addControl(control)
            self.position_form_group.group_validation.connect(
                self.formValidation)

        self.main_layout.addWidget(self.position_form_group)
        button_layout = QtWidgets.QHBoxLayout()
        self.move_jaws_button = QtWidgets.QPushButton('Move Jaws')
        self.move_jaws_button.clicked.connect(self.moveJawsButtonClicked)
        button_layout.addWidget(self.move_jaws_button)
        button_layout.addStretch(1)
        self.main_layout.addLayout(button_layout)
示例#6
0
    def __init__(self):
        super().__init__()

        self.filename = ''
        self.saved_text = ''
        self.initialized = False
        self.file_watcher = QtCore.QFileSystemWatcher()
        self.file_watcher.directoryChanged.connect(
            lambda: self.lazyInstrumentUpdate())
        self.controls = Controls(self)

        self.main_splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
        self.setCentralWidget(self.main_splitter)

        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
        self.splitter.setChildrenCollapsible(False)
        self.main_splitter.addWidget(self.splitter)
        self.main_splitter.setStretchFactor(0, 2)

        self.message = QtWidgets.QTextEdit('')
        self.message.setReadOnly(True)
        self.message.setFontFamily('courier')
        self.message.setStyleSheet(
            'QTextEdit {background-color: white; color: red; font-size: 12px; '
            'padding-left: 10px; background-position: top left}')
        self.message.setMinimumHeight(100)
        self.main_splitter.addWidget(self.message)

        self.gl_widget = OpenGLRenderer(self)
        self.gl_widget.custom_error_handler = self.sceneSizeErrorHandler
        self.scene = SceneManager(self, self.gl_widget, False)
        self.scene.changeVisibility(Attributes.Beam, True)
        self.animate_instrument.connect(self.scene.animateInstrument)

        self.editor = Editor(self)
        self.editor.textChanged.connect(self.lazyInstrumentUpdate)
        self.splitter.addWidget(self.gl_widget)
        self.splitter.addWidget(self.editor)

        self.setMinimumSize(1024, 800)
        self.setTitle()
        self.setWindowIcon(QtGui.QIcon(path_for('editor-logo.png')))

        self.initActions()
        self.initMenus()
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.useWorker)
        self.worker = InstrumentWorker(self)
示例#7
0
    def createPositionerWidget(self, positioner, add_base_button=False):
        """Creates the form widget for the given positioner

        :param positioner: serial manipulator
        :type positioner: SerialManipulator
        :param add_base_button: indicates base button should be shown
        :type add_base_button: bool
        :return: positioner widget
        :rtype: QtWidgets.QWidget
        """
        widget = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        title = FormTitle(positioner.name)
        layout.addWidget(title)
        if add_base_button:
            base_button = create_tool_button(tooltip='Change Base Matrix',
                                             style_name='MidToolButton')

            import_base_action = QtWidgets.QAction('Import Base Matrix', self)
            import_base_action.setStatusTip(
                f'Import base transformation matrix for {positioner.name}')
            import_base_action.triggered.connect(
                lambda ignore, n=positioner.name: self.importPositionerBase(n))

            compute_base_action = QtWidgets.QAction('Calculate Base Matrix',
                                                    self)
            compute_base_action.setStatusTip(
                f'Calculate base transformation matrix for {positioner.name}')
            compute_base_action.triggered.connect(
                lambda ignore, n=positioner.name: self.computePositionerBase(n
                                                                             ))

            export_base_action = QtWidgets.QAction('Export Base Matrix', self)
            export_base_action.setStatusTip(
                f'Export base transformation matrix for {positioner.name}')
            export_base_action.triggered.connect(
                lambda ignore, n=positioner.name: self.exportPositionerBase(n))

            base_button.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup)
            base_button.addActions(
                [import_base_action, compute_base_action, export_base_action])
            base_button.setDefaultAction(import_base_action)
            base_button.setIcon(QtGui.QIcon(path_for('base.png')))
            title.addHeaderControl(base_button)

            reset_button = create_tool_button(
                tooltip='Reset Base Matrix',
                style_name='MidToolButton',
                status_tip=
                f'Reset base transformation matrix of {positioner.name}',
                icon_path=path_for('refresh.png'),
                hide=True)
            reset_button.clicked.connect(
                lambda ignore, n=positioner.name: self.resetPositionerBase(n))
            title.addHeaderControl(reset_button)
            reset_button.setVisible(
                positioner.base is not positioner.default_base)
            self.base_reset_buttons[positioner.name] = reset_button

        form_group = FormGroup(FormGroup.Layout.Grid)
        order_offset = len(self.positioner_form_controls)
        for index in positioner.order:
            link = positioner.links[index]
            if link.type == Link.Type.Revolute:
                unit = 'degrees'
                offset = math.degrees(link.set_point)
                lower_limit = math.degrees(link.lower_limit)
                upper_limit = math.degrees(link.upper_limit)
            else:
                unit = 'mm'
                offset = link.set_point
                lower_limit = link.lower_limit
                upper_limit = link.upper_limit

            control = FormControl(link.name.title(),
                                  offset,
                                  desc=unit,
                                  required=True,
                                  number=True)
            control.form_lineedit.setDisabled(link.locked)
            if not link.ignore_limits:
                control.range(lower_limit, upper_limit)

            lock_button = create_tool_button(
                tooltip='Lock Joint',
                style_name='MidToolButton',
                status_tip=f'Lock {link.name} joint in {positioner.name}',
                icon_path=path_for('lock.png'),
                checkable=True,
                checked=link.locked)
            lock_button.clicked.connect(self.lockJoint)
            lock_button.setProperty('link_index', index + order_offset)

            limits_button = create_tool_button(
                tooltip='Disable Joint Limits',
                style_name='MidToolButton',
                status_tip=f'Ignore joint limits of {link.name}',
                icon_path=path_for('limit.png'),
                checkable=True,
                checked=link.ignore_limits)
            limits_button.clicked.connect(self.ignoreJointLimits)
            limits_button.setProperty('link_index', index + order_offset)

            control.extra = [lock_button, limits_button]
            form_group.addControl(control)

            form_group.group_validation.connect(self.formValidation)
            self.positioner_form_controls.append(control)

        layout.addWidget(form_group)
        widget.setLayout(layout)
        self.positioner_forms.append(form_group)

        return widget
示例#8
0
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.parent_model = parent.presenter.model
        self.parent.scenes.switchToSampleScene()

        self.main_layout = QtWidgets.QVBoxLayout()
        layout = QtWidgets.QHBoxLayout()
        layout.addWidget(QtWidgets.QLabel('Alignment:'))
        self.alignment_combobox = QtWidgets.QComboBox()
        self.alignment_combobox.setView(QtWidgets.QListView())
        self.alignment_combobox.activated.connect(self.onComboBoxActivated)
        layout.addWidget(self.alignment_combobox, 4)
        layout.addSpacing(10)

        self.detector_combobox = QtWidgets.QComboBox()
        self.detector_combobox.setView(QtWidgets.QListView())
        self.detector_combobox.addItems(
            list(self.parent_model.instrument.detectors.keys()))
        self.detector_combobox.activated.connect(self.onComboBoxActivated)
        if len(self.parent_model.instrument.detectors) > 1:
            layout.addWidget(QtWidgets.QLabel('Detector:'))
            layout.addWidget(self.detector_combobox, 4)
            size = self.detector_combobox.iconSize()
            self.detector_combobox.setItemIcon(
                0,
                create_icon(settings.value(settings.Key.Vector_1_Colour),
                            size))
            self.detector_combobox.setItemIcon(
                1,
                create_icon(settings.value(settings.Key.Vector_2_Colour),
                            size))

        self.delete_vector_action = QtWidgets.QAction("Delete Vectors", self)
        self.delete_vector_action.triggered.connect(self.deleteVectors)
        self.delete_vector_action.setStatusTip(
            'Remove (zero) selected vectors or all vectors in current alignment'
        )

        self.delete_alignment_action = QtWidgets.QAction(
            "Delete Alignment", self)
        self.delete_alignment_action.triggered.connect(self.deleteAlignment)
        self.delete_alignment_action.setStatusTip(
            'Remove selected vector alignment')
        delete_menu = QtWidgets.QMenu()
        delete_menu.addAction(self.delete_vector_action)
        delete_menu.addAction(self.delete_alignment_action)

        self.delete_alignment_button = create_tool_button(
            icon_path=path_for('cross.png'),
            style_name='ToolButton',
            status_tip='Remove measurement vectors or alignments')
        self.delete_alignment_button.setPopupMode(
            QtWidgets.QToolButton.InstantPopup)
        self.delete_alignment_button.setMenu(delete_menu)

        layout.addStretch(1)
        layout.addWidget(self.delete_alignment_button)
        layout.setAlignment(self.delete_alignment_button,
                            QtCore.Qt.AlignBottom)
        self.main_layout.addLayout(layout, 0)

        self.table = QtWidgets.QTableWidget()
        self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels(['X', 'Y', 'Z'])
        self.table.setAlternatingRowColors(True)
        self.table.setMinimumHeight(300)
        self.table.setMaximumHeight(500)
        self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.table.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.Stretch)
        self.table.horizontalHeader().setMinimumSectionSize(40)
        self.table.horizontalHeader().setDefaultSectionSize(40)
        self.updateWidget()
        self.main_layout.addWidget(self.table, 20)
        self.main_layout.addStretch(1)

        self.setLayout(self.main_layout)

        self.title = 'Measurement Vectors'
        self.setMinimumWidth(450)
        self.parent_model.measurement_vectors_changed.connect(
            self.updateWidget)
        self.parent.scenes.rendered_alignment_changed.connect(
            self.updateWidget)
示例#9
0
    def __init__(self, point_type, parent):
        super().__init__(parent)
        self.parent = parent
        self.parent_model = parent.presenter.model
        self.parent.scenes.switchToSampleScene()
        self.point_type = point_type
        self.attribute = Attributes.Fiducials if point_type == PointType.Fiducial else Attributes.Measurements

        self.selected = None

        layout = QtWidgets.QHBoxLayout()
        self.table_view = QtWidgets.QTableView()
        self.table_model = PointModel(self.points.copy())
        self.table_model.edit_completed.connect(self.editPoints)
        self.table_view.setItemDelegate(LimitTextDelegate())
        self.table_view.horizontalHeader().sectionClicked.connect(
            self.table_model.toggleCheckState)
        self.table_view.setModel(self.table_model)
        self.table_view.setSelectionBehavior(
            QtWidgets.QAbstractItemView.SelectRows)
        self.table_view.setAlternatingRowColors(True)
        self.table_view.setMinimumHeight(300)
        self.table_view.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.Stretch)
        self.table_view.horizontalHeader().setSectionResizeMode(
            3, QtWidgets.QHeaderView.Fixed)
        self.table_view.horizontalHeader().setMinimumSectionSize(40)
        self.table_view.horizontalHeader().setDefaultSectionSize(40)

        layout.addWidget(self.table_view)

        button_layout = QtWidgets.QVBoxLayout()
        self.delete_button = create_tool_button(
            icon_path=path_for('cross.png'),
            style_name='ToolButton',
            tooltip='Delete Points',
            status_tip='Remove selected points from project')
        self.delete_button.clicked.connect(self.deletePoints)
        button_layout.addWidget(self.delete_button)

        self.move_up_button = create_tool_button(
            icon_path=path_for('arrow-up.png'),
            style_name='ToolButton',
            tooltip='Move Point Index Up',
            status_tip='Swap point index with previous point')
        self.move_up_button.clicked.connect(lambda: self.movePoint(-1))
        button_layout.addWidget(self.move_up_button)

        self.move_down_button = create_tool_button(
            icon_path=path_for('arrow-down.png'),
            style_name='ToolButton',
            tooltip='Move Point Index Down',
            status_tip='Swap point index with next point')
        self.move_down_button.clicked.connect(lambda: self.movePoint(1))
        button_layout.addWidget(self.move_down_button)

        layout.addSpacing(10)
        layout.addLayout(button_layout)
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addLayout(layout)
        self.main_layout.addStretch(1)

        self.setLayout(self.main_layout)

        self.title = f'{self.point_type.value} Points'
        self.setMinimumWidth(450)
        self.table_view.selectionModel().selectionChanged.connect(
            self.onMultiSelection)
        if self.point_type == PointType.Fiducial:
            self.parent_model.fiducials_changed.connect(self.updateTable)
        elif self.point_type == PointType.Measurement:
            self.parent_model.measurement_points_changed.connect(
                self.updateTable)
示例#10
0
    def __init__(self, sample, parent):
        super().__init__()

        self.parent = parent

        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.setContentsMargins(0, 0, 0, 0)
        self.vertices = None
        self.initial_plane = None
        self.final_plane_normal = None

        layout = QtWidgets.QHBoxLayout()
        self.table_widget = QtWidgets.QTableWidget()
        self.table_widget.setShowGrid(False)
        self.table_widget.setAlternatingRowColors(True)
        self.table_widget.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        self.table_widget.setColumnCount(3)
        self.table_widget.setFixedHeight(150)
        self.table_widget.verticalHeader().setVisible(False)
        self.table_widget.setHorizontalHeaderLabels(['X', 'Y', 'Z'])
        self.table_widget.setSelectionBehavior(
            QtWidgets.QAbstractItemView.SelectRows)
        self.table_widget.setSelectionMode(
            QtWidgets.QAbstractItemView.ExtendedSelection)
        self.table_widget.selectionModel().selectionChanged.connect(
            self.selection)
        self.table_widget.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.Stretch)
        layout.addWidget(self.table_widget)

        button_layout = QtWidgets.QVBoxLayout()
        self.select_button = create_tool_button(
            icon_path=path_for('select.png'),
            checkable=True,
            checked=True,
            status_tip='Normal scene manipulation with the mouse',
            tooltip='Normal Mode',
            style_name='ToolButton')
        self.select_button.clicked.connect(lambda: self.togglePicking(False))
        button_layout.addWidget(self.select_button)

        self.pick_button = create_tool_button(
            icon_path=path_for('point.png'),
            checkable=True,
            status_tip='Select 3D points that define the plane',
            tooltip='Pick Point Mode',
            style_name='ToolButton')

        self.pick_button.clicked.connect(lambda: self.togglePicking(True))
        button_layout.addWidget(self.pick_button)

        self.delete_button = create_tool_button(
            icon_path=path_for('cross.png'),
            style_name='ToolButton',
            status_tip='Remove selected points from the scene',
            tooltip='Delete Points')
        self.delete_button.clicked.connect(self.removePicks)
        button_layout.addWidget(self.delete_button)

        layout.addSpacing(10)
        layout.addLayout(button_layout)
        self.main_layout.addLayout(layout)
        self.main_layout.addSpacing(10)
        self.main_layout.addWidget(QtWidgets.QLabel('Select Final Plane:'))
        self.plane_combobox = QtWidgets.QComboBox()
        self.plane_combobox.setView(QtWidgets.QListView())
        self.plane_combobox.addItems([p.value for p in PlaneOptions])
        self.plane_combobox.currentTextChanged.connect(self.setPlane)
        self.main_layout.addWidget(self.plane_combobox)
        self.createCustomPlaneBox()
        self.setPlane(self.plane_combobox.currentText())

        button_layout = QtWidgets.QHBoxLayout()
        self.execute_button = QtWidgets.QPushButton('Align Planes')
        self.execute_button.clicked.connect(self.executeButtonClicked)
        button_layout.addWidget(self.execute_button)
        button_layout.addStretch(1)

        self.main_layout.addLayout(button_layout)
        self.main_layout.addStretch(1)

        self.setLayout(self.main_layout)
        self.parent.gl_widget.pick_added.connect(self.addPicks)

        self.selected_sample = sample