Beispiel #1
0
class plotScroller:
    def update_val(self, proc):
        d=str(self.scl.value())
        self.v.setText(d)
        if proc != None:
            proc(self.scl.value())
        
    def __init__(self, master, text, geo, proc=None, lim=(0,100,1)):
        self.scl=QScrollBar(Qt.Horizontal, master)
        self.scl.resize(geo[2]-50,geo[3])
        self.scl.move(geo[0]+50,geo[1])
        self.scl.setMinimum(lim[0])
        self.scl.setMaximum(lim[1])
        self.scl.setSingleStep(lim[2])
        self.scl.valueChanged.connect(lambda: self.update_val(proc))
        
        q=QLabel(master)
        q.move(geo[0],geo[1]+10)
        q.resize(50,20)
        q.setText(text)
        
        self.v=QLabel(master)
        self.v.move(geo[2]+10,geo[1]+10)
        self.v.resize(50,20)
        self.v.setText(str(self.scl.value()))
    
    def setValue(self, v):
        self.scl.setValue(v)
Beispiel #2
0
class ObjMotorWidgetUI(QWidget):
    
#    waveforms_generated = pyqtSignal(object, object, list, int)
#    SignalForContourScanning = pyqtSignal(int, int, int, np.ndarray, np.ndarray)
#    MessageBack = pyqtSignal(str)
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
#        os.chdir('./')# Set directory to current folder.
        self.setFont(QFont("Arial"))
        
#        self.setMinimumSize(1350,900)
        self.setWindowTitle("ObjMotorWidget")
        self.layout = QGridLayout(self)
        self.connect_status = False
        #**************************************************************************************************************************************
        #--------------------------------------------------------------------------------------------------------------------------------------
        #-----------------------------------------------------------GUI for Objective Motor----------------------------------------------------
        #--------------------------------------------------------------------------------------------------------------------------------------          
        #**************************************************************************************************************************************
        
        # Movement based on relative positions.
        self.ObjMotorcontrolContainer = QGroupBox("Objective motor control")
        self.ObjMotorcontrolContainer.setStyleSheet("QGroupBox {\
                                font: bold;\
                                border: 1px solid silver;\
                                border-radius: 6px;\
                                margin-top: 12px;\
                                color:Navy; \
                                background-color: #FFFAFA}\
                                QGroupBox::title{subcontrol-origin: margin;\
                                                 left: 7px;\
                                                 padding: 5px 5px 5px 5px;}")
        self.ObjMotorcontrolLayout = QGridLayout()
        
        self.ObjMotor_connect = StylishQT.connectButton()
        self.ObjMotor_connect.setFixedWidth(70)
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_connect, 0, 0)
        self.ObjMotor_connect.clicked.connect(lambda: self.ConnectMotor())     
        self.ObjMotor_connect.setGraphicsEffect(QGraphicsDropShadowEffect(blurRadius=3, xOffset=2, yOffset=2))
        
        self.ObjMotor_disconnect = StylishQT.disconnectButton()
        self.ObjMotor_disconnect.setFixedWidth(70)
        self.ObjMotor_disconnect.setGraphicsEffect(QGraphicsDropShadowEffect(blurRadius=3, xOffset=2, yOffset=2))
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_disconnect, 0, 1)
        
        self.ObjMotor_disconnect.clicked.connect(lambda: self.DisconnectMotor()) 
        self.ObjMotor_disconnect.setEnabled(False)
        
        self.ObjMotor_upwards = QPushButton("↑")
        self.ObjMotor_upwards.setStyleSheet("QPushButton {color:white;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}"
                                            "QPushButton:pressed {color:red;background-color: white; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}"
                                            "QPushButton:hover:!pressed {color:gray;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}")        
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_upwards, 2, 2)
        self.ObjMotor_upwards.clicked.connect(lambda: self.MovingMotorThread("Motor_move_upwards"))
#        self.ObjMotor_upwards.setShortcut('w')
        
        self.ObjMotor_down = QPushButton("↓")
        self.ObjMotor_down.setStyleSheet("QPushButton {color:white;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}"
                                            "QPushButton:pressed {color:red;background-color: white; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}"
                                            "QPushButton:hover:!pressed {color:gray;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}")        
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_down, 3, 2)
        self.ObjMotor_down.clicked.connect(lambda: self.MovingMotorThread("Motor_move_downwards"))
#        self.stage_down.setShortcut('s')
        
        self.ObjMotor_target = QDoubleSpinBox(self)
        self.ObjMotor_target.setMinimum(-10000)
        self.ObjMotor_target.setMaximum(10000)
        self.ObjMotor_target.setDecimals(6)
#        self.ObjMotor_target.setValue(3.45)
        self.ObjMotor_target.setSingleStep(0.001)        
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_target, 1, 1)
        self.ObjMotorcontrolLayout.addWidget(QLabel("Target:"), 1, 0)
        
        self.ObjMotor_current_pos_Label = QLabel("Current position: ")
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_current_pos_Label, 2, 0, 1, 2)
        
        self.ObjMotor_goto = QPushButton()
        self.ObjMotor_goto.setIcon(QIcon('./Icons/move_coord.png')) 
        self.ObjMotor_goto.setToolTip("Move to absolute position")
        self.ObjMotor_goto.setStyleSheet("QPushButton {color:white;background-color: #CCFFFF;}"
                                      "QPushButton:hover:!pressed {color:white;background-color: #FFE5CC;}")
        self.ObjMotor_goto.setFixedWidth(35)
        self.ObjMotor_goto.setFixedHeight(35)
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_goto, 1, 2)
        self.ObjMotor_goto.clicked.connect(lambda: self.MovingMotorThread("Motor_move_target"))
        
        self.ObjMotor_step = QDoubleSpinBox(self)
        self.ObjMotor_step.setMinimum(-10000)
        self.ObjMotor_step.setMaximum(10000)
        self.ObjMotor_step.setDecimals(6)
        self.ObjMotor_step.setValue(0.003)
        self.ObjMotor_step.setSingleStep(0.001)        
        self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_step, 3, 1)
        self.ObjMotorcontrolLayout.addWidget(QLabel("Step: "), 3, 0)  
        
        self.FocusSlider = QScrollBar(Qt.Horizontal)
        self.FocusSlider.setMinimum(2500000)
        self.FocusSlider.setMaximum(4500000)
#        self.FocusSlider.setTickPosition(QSlider.TicksBothSides)
#        self.FocusSlider.setTickInterval(1000000)
        self.FocusSlider.setStyleSheet('color:white; background: lightblue')
        self.FocusSlider.setSingleStep(10000)
#        self.line640 = QLineEdit(self)
#        self.line640.setFixedWidth(60)
#        self.FocusSlider.sliderReleased.connect(lambda:self.updatelinevalue(640))
        self.FocusSlider.valueChanged.connect(lambda:self.MovingMotorThread("Motor_move_slider"))
        self.FocusSlider.setTracking(False)
#        self.line640.returnPressed.connect(lambda:self.updatesider(640))
        self.ObjMotorcontrolLayout.addWidget(self.FocusSlider, 4, 0, 1, 3)
        
        self.ObjMotorcontrolContainer.setLayout(self.ObjMotorcontrolLayout)
        self.ObjMotorcontrolContainer.setMaximumHeight(300)
        self.layout.addWidget(self.ObjMotorcontrolContainer, 4, 0)          
        
        #**************************************************************************************************************************************
        #--------------------------------------------------------------------------------------------------------------------------------------
        #-----------------------------------------------------------Fucs for Motor movement----------------------------------------------------
        #--------------------------------------------------------------------------------------------------------------------------------------          
        #**************************************************************************************************************************************         
    def ConnectMotor(self):
        self.ObjMotorcontrolContainer.setEnabled(False)
        self.ObjMotor_disconnect.setEnabled(True)
        self.ObjMotor_connect.setEnabled(False)
        
        self.device_instance = ConnectObj_Thread()
        self.device_instance.start()
        self.device_instance.finished.connect(self.getmotorhandle)

    def getmotorhandle(self):
        self.pi_device_instance = self.device_instance.getInstance()
        print('Objective motor connected.')
        self.connect_status = True
#        self.normalOutputWritten('Objective motor connected.'+'\n')
        
        self.ObjCurrentPos = self.pi_device_instance.pidevice.qPOS(self.pi_device_instance.pidevice.axes)
        self.ObjMotor_current_pos_Label.setText("Current position: {:.4f}".format(self.ObjCurrentPos['1'])) # Axis here is a string.
        self.ObjMotor_target.setValue(self.ObjCurrentPos['1'])
        
        decimal_places = len(str(self.ObjCurrentPos['1']).split('.')[1])
        print(int(self.ObjCurrentPos['1']*(10**decimal_places)))
        self.FocusSlider.setValue(int(self.ObjCurrentPos['1']*(10**6)))
        self.ObjMotorcontrolContainer.setEnabled(True)
        
    def MovingMotorThread(self, target):
        if target == "Motor_move_target":
            MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('Target',))
            MoveMotorThread.start()
        elif target == "Motor_move_upwards":
            MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('UP',))
            MoveMotorThread.start()            
        elif target == "Motor_move_downwards":
            MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('DOWN',))
            MoveMotorThread.start()  
        elif target == "Motor_move_slider":
            MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('Slider',))
            MoveMotorThread.start()          
        
    def MoveMotor(self, direction):
        if direction == "Target":
            pos = PIMotor.move(self.pi_device_instance.pidevice, self.ObjMotor_target.value())
        elif direction == "UP":
            self.MotorStep = self.ObjMotor_step.value()
            pos = PIMotor.move(self.pi_device_instance.pidevice, (self.ObjCurrentPos['1'] + self.MotorStep))
        elif direction == "DOWN":
            self.MotorStep = self.ObjMotor_step.value()
            pos = PIMotor.move(self.pi_device_instance.pidevice, (self.ObjCurrentPos['1'] - self.MotorStep))
        elif direction == "Slider":
            pos = PIMotor.move(self.pi_device_instance.pidevice, self.FocusSlider.value()/1000000)
            
        self.ObjCurrentPos = self.pi_device_instance.pidevice.qPOS(self.pi_device_instance.pidevice.axes)
        self.ObjMotor_current_pos_Label.setText("Current position: {:.4f}".format(self.ObjCurrentPos['1'])) # Axis here is a string.
        self.ObjMotor_target.setValue(self.ObjCurrentPos['1'])  
        
        # decimal_places = len(str(self.ObjCurrentPos['1']).split('.')[1])
        self.FocusSlider.setValue(int(self.ObjCurrentPos['1']*(10**6)))
      
    def DisconnectMotor(self):
        self.ObjMotor_connect.setEnabled(True)
        self.ObjMotor_disconnect.setEnabled(False)
        
        PIMotor.CloseMotorConnection(self.pi_device_instance.pidevice)
        print('Disconnected')
        self.connect_status = False
#        self.normalOutputWritten('Objective motor disconnected.'+'\n')
        
    def closeEvent(self, event):
        # ## Because the software combines both PyQt and PyQtGraph, using the
        # ## closeEvent() from PyQt will cause a segmentation fault. Calling 
        # ## also the exit() from PyQtGraph solves this problem. 
        # pg.exit()
        if self.connect_status == True:
            self.DisconnectMotor()
            
        QtWidgets.QApplication.quit()
        event.accept()
Beispiel #3
0
class Slider(QWidget):
    def __init__(self, parent, name):
        super().__init__(parent)
        self.name = name
        self.layout = QHBoxLayout(self)
        self.setLayout(self.layout)

        self.slider = QScrollBar(self)
        self.spin_box = QDoubleSpinBox(self)
        self.spin_box.setMaximumWidth(70)
        self.layout.addWidget(self.slider)
        self.layout.addWidget(self.spin_box)

        self.slider.setOrientation(QtCore.Qt.Horizontal)
        self.slider.setPageStep(1)

        self._slider_mult = 1

        self._spin_val = QtPropertyVar(self.spin_box, 'value')
        self._slider_val = QtPropertyVar(self.slider, 'value')

        self._var = None
        self.set_from_value = None

        self._step = None
        self._min = None
        self._max = None

        self.var = Var(name='var')

    def _uses_integer(self):
        return isinstance(self._slider_mult, int)

    @reactive
    def _set_all_to(self, value):
        #print("set all to ", value)
        if self._min is not None and self._max is not None and self._min > self._max:
            set_if_inequal(self._var, None)
            return

        if self._uses_integer() and value is not None:
            value = int(round(value))
        set_if_inequal(self._slider_val, value * self._slider_mult)
        set_if_inequal(self._spin_val, value)
        set_if_inequal(self._var, value)

    @property
    def var(self):
        return self._var

    @var.setter
    def var(self, var):
        with ScopedName(name=self.name):
            self._var = var if var is not None else Var(name='var')
            self.set_from_value = volatile(self._set_all_to(self._var))

    def set_params(self, min, max, step=1):
        self._step = step
        self._min = min
        self._max = max

        if isinstance(min, float) or isinstance(max, float) or isinstance(
                step, float):
            self._slider_mult = 1.0 / step
            self.spin_box.setDecimals(int(ceil(-log10(step))))
        else:
            self._slider_mult = 1
            self.spin_box.setDecimals(0)
        self.slider.setRange(int(min * self._slider_mult),
                             int(max * self._slider_mult))
        self.slider.setSingleStep(int(step * self._slider_mult))
        self.spin_box.setRange(min, max)
        self.spin_box.setSingleStep(step)
        with ScopedName(name=self.name):
            self.refs = [
                volatile(self._set_all_to(self._spin_val)),
                volatile(self._set_all_to(self._slider_val /
                                          self._slider_mult))
            ]

        val = unwrap_def(self._var, None)

        self.fix_value(max, min, val)

    def fix_value(self, max, min, val):
        if min > max:
            new_val = None
        elif val is None:
            new_val = min
        elif val > max:
            new_val = max
        elif val < min:
            new_val = min
        else:
            return

        set_if_inequal(self._var, new_val)

    def dump_state(self):
        return dict(
            #            min=self._min,
            #            max=self._max,
            #            step=self._step,
            value=unwrap(self._var))

    def load_state(self, state: dict):
        #        self.set_params(state['min'], state['max'], state['step'])
        value = state['value']
        if self._uses_integer() and value is not None:
            value = int(round(value))

        self._var.set(value)
Beispiel #4
0
class MainWindow(MainWindowBase, MainWindowUI):

    VIDEOS = ('front_video_file', 'eyes_video_file')

    def __init__(self, manager, parent=None):
        MainWindowBase.__init__(self, parent)

        self.manager = manager
        self.current_segment = None
        self.current_video = 0
        self.nav_hide_empty = True

        self.setupUi(self)
        self.setupConnections()

    def setupUi(self, parent):
        MainWindowUI.setupUi(self, parent)

        # content area
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.content.setLayout(layout)

        # add video widget
        self.contentWidget = VideoWidget()
        self.content.layout().addWidget(self.contentWidget)

        self.prev_code = 'def f(img):\n    return img'
        self.te_code = PyCodeEdit()
        self.te_code.setPlainText(self.prev_code)
        self.content.layout().addWidget(self.te_code)

        # footer area
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.footer.setLayout(layout)

        self.bar_index = QScrollBar(Qt.Horizontal)
        self.bar_index.setFocusPolicy(Qt.WheelFocus)
        self.bar_index.setMinimum(0)
        self.bar_index.setSingleStep(1)
        self.bar_index.valueChanged.connect(self.indexChanged)
        layout.addWidget(self.bar_index)

        self.info = QLabel()
        layout.addWidget(self.info)

        # construct navigation tree
        self.refreshNavigation()

        # design the view
        self.treeView.header().hide()  # hide header
        self.treeView.expandToDepth(0)  # expand first level

    def setupConnections(self):

        # shortcuts
        self.sc_next = QShortcut(QKeySequence("Right"), self)
        self.sc_next.activated.connect(self.nextImage)

        self.sc_prev = QShortcut(QKeySequence("Left"), self)
        self.sc_prev.activated.connect(self.prevImage)

        self.treeView.doubleClicked.connect(self.navigation_doubleClicked)

        self.pb_video_toggle.clicked.connect(self.toggleVideo)
        self.pb_hide_toggle.clicked.connect(self.toggleHideEmpty)

    def toggleVideo(self):
        self.current_video = (self.current_video + 1) % len(MainWindow.VIDEOS)
        self.setSegment(self.current_segment)

    def toggleHideEmpty(self):
        self.nav_hide_empty = not self.nav_hide_empty
        self.refreshNavigation()

    def refreshNavigation(self):
        items = []
        for project_id in self.manager.getProjectNames():
            project = self.manager.getProject(project_id)
            p_node = NavigationNode(project.info['Name'])
            p_node.obj_data = project
            items.append(p_node)

            for r_id in sorted(p_node.obj_data.getRecordingNames()):
                print(r_id)
                recording = p_node.obj_data.getRecording(r_id)
                print(recording)

                if recording:
                    r_node = NavigationNode(r_id)
                    r_node.obj_data = recording

                    p_node.addChild(r_node)
                    for segment_id in r_node.obj_data.getSegmentIDs():
                        s_node = NavigationNode(segment_id)
                        s_node.obj_data = r_node.obj_data.getSegment(
                            segment_id)
                        r_node.addChild(s_node)

        self.treeView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.treeView.setUniformRowHeights(True)
        self.treeView.setModel(NavigationModel(items))

    def navigation_doubleClicked(self, _):
        item = self.treeView.selectedIndexes()[0]
        obj = item.internalPointer().obj_data

        if hasattr(obj, 'segments') and obj.segments_data:
            obj = obj.segments_data[0]

        if hasattr(obj, 'eyes_video_file'):
            self.setSegment(obj)

    def applyCode(self):
        code = self.te_code.toPlainText()
        if self.prev_code != code:
            try:
                exec(code, globals(), locals())
                self.contentWidget.onImage = locals()['f']
            except Exception as e:
                print(e)

    def prevImage(self):
        self.bar_index.setValue(self.bar_index.value() - 1)

    def nextImage(self):
        self.bar_index.setValue(self.bar_index.value() + 1)

    def setVideo(self, path):
        self.contentWidget.openVideo(path)
        self.bar_index.setMaximum(self.contentWidget.video.length)

    def indexChanged(self, value):
        self.applyCode()
        video = self.contentWidget.video
        video.pos_frame = value
        self.contentWidget.updateImage()

        info_msg = []
        info_msg.append('FPS:   %s' % video.fps)
        info_msg.append('Frame: %d / %d (%.4f)' %
                        (video.pos_frame + 1, video.length, video.pos_msec))

        self.info.setText('\n'.join(info_msg))

    def setSegment(self, segment):
        try:
            self.current_segment = segment
            self.setVideo(
                getattr(self.current_segment,
                        MainWindow.VIDEOS[self.current_video]))
            self.bar_index.setValue(0)
            self.indexChanged(0)
        except:
            pass