Beispiel #1
0
 def make_pbox(self, p, r, s, n):
     pbox = SuperSpinBox(r, s, n)
     pbox.display(1)
     label = QtWidgets.QLabel(p + ': ')
     label.setFixedWidth(30)
     label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
     pbox.setFixedWidth(80)
     pbox.setFixedHeight(20)
     return p, pbox
class MSQClient(QtWidgets.QWidget):
    """ Widget for Msquared server control """
    msquared_servername = None
    msquared_devicename = None
    wlm_servername = None

    update_time1 = 2500  # [ms]
    update_time2 = 5000  # [ms]
    lock_update_time = 2500  # [ms]
    is_on_OneShot = False

    frequency_units = ['THz', 'GHz']
    wavelength_units = ['nm', 'um']

    etalon_range = (0, 100)  # Etalon tuner
    etalon_units = [(0, '%')]
    etalon_digits = 2
    etalon_max = 196

    resonator_range = (0, 100)  # Resonator tuner
    resonator_units = [(0, '%')]
    resonator_digits = 4
    resonator_max = 196

    fineresonator_range = (0, 100)  # Resonator Fine tuner
    fineresonator_units = [(0, '%')]
    fineresonator_digits = 2

    PD_range = (0, 100)
    PD_units = [(0, 'V')]
    PD_digits = 4

    xy_range = (0, 100)  # X, Y tuner
    xy_units = [(0, '%')]
    xy_digits = 2

    wl_range = (696, 877)  # Rough wavelength
    wl_units = [(0, 'nm')]
    wl_digits = 1

    spinbox_height = 30
    spinbox_width = 80
    update_id = np.random.randint(0, 2**31 - 1)

    def __init__(self, reactor, cxn, msquared_servername, msquared_devicename,
                 wlm_servername, parent):
        super(MSQClient, self).__init__()
        try:
            self.reactor = reactor
            self.cxn = cxn
            self.msquared_servername = msquared_servername
            self.msquared_devicename = msquared_devicename
            self.wlm_servername = wlm_servername
            self.parent = parent
            self.connect()
        except Exception as e:
            print(e)
            traceback.print_exc()

    @inlineCallbacks
    def connect(self):
        if self.cxn == None:
            self.cxn = connection()
            yield self.cxn.connect()
        self.populate()
        yield self.connectWidgets()

    def populate(self):
        self.nameLabel = ClickableLabel('<b> MSquared Laser Control </b>')

        self.statusLabel = ClickableLabel('<b> MSquared Status: </b>')
        self.statusText = QtWidgets.QLineEdit()
        self.statusText.setReadOnly(True)
        self.statusText.setAlignment(QtCore.Qt.AlignCenter)
        self.statusText.setFixedHeight(40)
        self.statusText.setFont(QtGui.QFont('Arial', 10))

        self.wlmLabel = ClickableLabel('<b> HF Wavemeter: </b>')
        self.wlmText = QtWidgets.QLineEdit()
        self.wlmText.setReadOnly(True)
        self.wlmText.setAlignment(QtCore.Qt.AlignCenter)
        self.wlmText.setFixedHeight(40)
        self.wlmText.setFont(QtGui.QFont('Arial', 10))

        self.lockButton = QtWidgets.QPushButton()
        self.lockButton.setCheckable(True)
        self.lockButton.setFixedHeight(40)
        self.lockButton.setFixedWidth(120)

        self.oneshotButton = QtWidgets.QPushButton()
        self.oneshotButton.setFixedHeight(40)
        self.oneshotButton.setFixedWidth(120)
        self.oneshotButton.setText('One Shot Alignment')

        self.manualButton = QtWidgets.QPushButton()
        self.manualButton.setFixedHeight(40)
        self.manualButton.setFixedWidth(120)
        self.manualButton.setText('Manual Alignment')

        self.EtalonTunerLabel = ClickableLabel('Etalon Tuner: ')
        self.EtalonTunerBox = SuperSpinBox(self.etalon_range,
                                           self.etalon_units,
                                           self.etalon_digits)
        self.EtalonTunerBox.setFixedHeight(self.spinbox_height)
        self.EtalonTunerBox.setFixedWidth(self.spinbox_width)

        self.ResonatorTunerLabel = ClickableLabel('Resonator Tuner: ')
        self.ResonatorTunerBox = SuperSpinBox(self.resonator_range,
                                              self.resonator_units,
                                              self.resonator_digits)
        self.ResonatorTunerBox.setFixedHeight(self.spinbox_height)
        self.ResonatorTunerBox.setFixedWidth(self.spinbox_width)

        self.ResonatorFineTunerLabel = ClickableLabel(
            'Resonator Fine \n Tuner:')
        self.ResonatorFineTunerLabel.setAlignment(QtCore.Qt.AlignRight
                                                  | QtCore.Qt.AlignVCenter)
        self.ResonatorFineTunerBox = SuperSpinBox(self.fineresonator_range,
                                                  self.fineresonator_units,
                                                  self.fineresonator_digits)
        self.ResonatorFineTunerBox.setFixedHeight(self.spinbox_height)
        self.ResonatorFineTunerBox.setFixedWidth(self.spinbox_width)

        self.XLabel = ClickableLabel('X Tuner: ')
        self.XBox = SuperSpinBox(self.xy_range, self.xy_units, self.xy_digits)
        self.XBox.setFixedHeight(self.spinbox_height)
        self.XBox.setFixedWidth(self.spinbox_width)

        self.YLabel = ClickableLabel('Y Tuner: ')
        self.YBox = SuperSpinBox(self.xy_range, self.xy_units, self.xy_digits)
        self.YBox.setFixedHeight(self.spinbox_height)
        self.YBox.setFixedWidth(self.spinbox_width)

        self.wavelengthLabel = ClickableLabel(
            'Preset wavelength: \n (rough tune)')
        self.wavelengthLabel.setAlignment(QtCore.Qt.AlignRight
                                          | QtCore.Qt.AlignVCenter)
        self.wavelengthBox = SuperSpinBox(self.wl_range, self.wl_units,
                                          self.wl_digits)
        self.wavelengthBox.setFixedHeight(self.spinbox_height)
        self.wavelengthBox.setFixedWidth(self.spinbox_width)

        self.EtalonPDLabel = ClickableLabel('Etalon PD DC:')
        self.EtalonPDLabel.setAlignment(QtCore.Qt.AlignRight
                                        | QtCore.Qt.AlignVCenter)
        self.EtalonPDBox = SuperSpinBox(self.PD_range, self.PD_units,
                                        self.PD_digits)
        self.EtalonPDBox.setFixedHeight(self.spinbox_height)
        self.EtalonPDBox.setFixedWidth(self.spinbox_width)
        self.EtalonPDBox.setReadOnly(True)

        self.OutputPDLabel = ClickableLabel('Output PD:')
        self.OutputPDLabel.setAlignment(QtCore.Qt.AlignRight
                                        | QtCore.Qt.AlignVCenter)
        self.OutputPDBox = SuperSpinBox(self.PD_range, self.PD_units,
                                        self.PD_digits)
        self.OutputPDBox.setFixedHeight(self.spinbox_height)
        self.OutputPDBox.setFixedWidth(self.spinbox_width)
        self.OutputPDBox.setReadOnly(True)

        self.layout = QtWidgets.QGridLayout()
        self.layout.addWidget(self.nameLabel, 1, 0, 1, 6,
                              QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.statusLabel, 2, 0, 2, 1,
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.statusText, 2, 1, 2, 5)
        self.layout.addWidget(self.wlmLabel, 4, 0, 2, 1, QtCore.Qt.AlignRight)
        self.layout.addWidget(self.wlmText, 4, 1, 2, 5)
        self.layout.addWidget(self.lockButton, 6, 0, 2, 2,
                              QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.oneshotButton, 6, 2, 2, 2,
                              QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.manualButton, 6, 4, 2, 2,
                              QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.EtalonTunerLabel, 8, 0, 2, 1,
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.EtalonTunerBox, 8, 1, 2, 2,
                              QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.XLabel, 8, 3, 2, 1, QtCore.Qt.AlignRight)
        self.layout.addWidget(self.XBox, 8, 4, 2, 2, QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.ResonatorTunerLabel, 10, 0, 2, 1,
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.ResonatorTunerBox, 10, 1, 2, 2,
                              QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.YLabel, 10, 3, 2, 1, QtCore.Qt.AlignRight)
        self.layout.addWidget(self.YBox, 10, 4, 2, 2, QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.ResonatorFineTunerLabel, 12, 0, 2, 1,
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.ResonatorFineTunerBox, 12, 1, 2, 2,
                              QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.wavelengthLabel, 12, 3, 2, 1,
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.wavelengthBox, 12, 4, 2, 2,
                              QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.EtalonPDLabel, 14, 0, 2, 1,
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.EtalonPDBox, 14, 1, 2, 2,
                              QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.OutputPDLabel, 14, 3, 2, 1,
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.OutputPDBox, 14, 4, 2, 2,
                              QtCore.Qt.AlignLeft)

        self.layout.setContentsMargins(5, 5, 5, 5)
        self.layout.setSpacing(5)
        self.setLayout(self.layout)
        self.setFixedSize(450, 450)

    @inlineCallbacks
    def connectWidgets(self):
        self.msquared_server = yield self.cxn.get_server(
            self.msquared_servername)
        yield self.msquared_server.signal__update(self.update_id)
        yield self.msquared_server.addListener(listener=self.receive_update,
                                               source=None,
                                               ID=self.update_id)
        self.wlm_server = yield self.cxn.get_server(self.wlm_servername)
        self.nameLabel.clicked.connect(self.onNameLabelClick)
        self.wlmLabel.clicked.connect(self.getWLM)
        self.lockButton.released.connect(self.onLockButton)
        self.oneshotButton.released.connect(self.onOneShotButton)
        self.manualButton.released.connect(self.onManualButton)
        self.XBox.returnPressed.connect(self.onX)
        self.YBox.returnPressed.connect(self.onY)
        self.wavelengthBox.returnPressed.connect(self.onWavelength)
        self.EtalonPDLabel.clicked.connect(self.getEtalonPD)
        self.OutputPDLabel.clicked.connect(self.getOutputPD)

        self.timer1 = QtCore.QTimer(self)
        self.timer1.timeout.connect(self.timer_task1)
        self.timer1.start(self.update_time1)

        self.timer2 = QtCore.QTimer(self)
        self.timer2.timeout.connect(self.timer_task2)
        self.timer2.start(self.update_time2)

        self.lock_timer = QtCore.QTimer(self)
        self.lock_timer.timeout.connect(self.lock_timer_task)

        self.getAll()

    def receive_update(self, c, signal_json):
        signal = json.loads(signal_json)
        message = signal.get('alignment_x_auto')
        if message is not None:
            value = message[self.msquared_devicename]
            self.displayX(value)
        message = signal.get('alignment_y_auto')
        if message is not None:
            value = message[self.msquared_devicename]
            self.displayY(value)

    def disable_when_wlm_lock(self, state):
        self.lockButton.setDisabled(state)
        self.EtalonTunerBox.setDisabled(state)
        self.wavelengthBox.setDisabled(state)

        resonator_state = not bool(state ^ self.lockButton.isChecked())
        self.ResonatorTunerBox.setDisabled(resonator_state)
        self.ResonatorFineTunerBox.setDisabled(resonator_state)

    def onNameLabelClick(self):
        self.getAll()

    def timer_task1(self):
        if self.lockButton.isChecked():
            self.getLockState()
        if self.parent.LockClient.lockButton.isChecked():
            self.lock_timer.start(self.lock_update_time)
        else:
            self.lock_timer.stop()

    def timer_task2(self):
        if self.is_on_OneShot:
            self.getOneShotState()
            self.getOutputPD()
            self.getEtalonPD()

    def lock_timer_task(self):
        self.getWLM()
        self.getResonatorTuner()
        self.getEtalonPD()
        self.getOutputPD()

    def getAll(self):
        self.getLockState()
        self.getEtalonTuner()
        self.getResonatorTuner()
        self.getX()
        self.getY()
        self.getWavelength()
        self.getWLM()
        self.getEtalonPD()
        self.getOutputPD()

    def onLockButton(self):
        lock_state = self.lockButton.isChecked()
        self.setLockState(lock_state)

    @inlineCallbacks
    def setLockState(self, lock_state):
        if lock_state:
            request_json = json.dumps({self.msquared_devicename: True})
        else:
            request_json = json.dumps({self.msquared_devicename: False})
        yield self.msquared_server.etalon_lock(request_json)
        self.displayLockState(lock_state)

    @inlineCallbacks
    def getLockState(self):
        request_json = json.dumps({self.msquared_devicename: None})
        response_json = yield self.msquared_server.etalon_lock(request_json)
        response = json.loads(response_json)
        message = response[self.msquared_devicename]
        if message == True:
            lock_state = True
        elif message == False:
            lock_state = False
        else:
            lock_state = False
            self.statusText.setText(message)
            request_json = json.dumps({self.msquared_devicename: False})
            yield self.msquared_server.etalon_lock(request_json)
        self.displayLockState(lock_state)

    def displayLockState(self, lock_state):
        if lock_state == True:
            self.lockButton.setChecked(1)
            self.lockButton.setText('Remove Etalon Lock')
            self.statusText.setText('Etalon lock ON')
            self.ResonatorTunerBox.setDisabled(False)
            self.ResonatorFineTunerBox.setDisabled(False)
        else:
            self.lockButton.setChecked(0)
            self.lockButton.setText('Apply Etalon Lock')
            self.statusText.setText('Etalon lock OFF')
            self.ResonatorTunerBox.setDisabled(True)
            self.ResonatorFineTunerBox.setDisabled(True)
        self.parent.toggle_lock()

    @inlineCallbacks
    def onOneShotButton(self):
        if not self.is_on_OneShot:
            self.is_on_OneShot = True
            mode = 4  # 4 for One Shot
            request_json = json.dumps({self.msquared_devicename: mode})
            yield self.msquared_server.beam_alignment(request_json)
            self.statusText.setText('One Shot Alignment Started...')
            self.oneshotButton.setDisabled(True)
            self.manualButton.setEnabled(True)
            self.XBox.setDisabled(True)
            self.YBox.setDisabled(True)
        else:
            pass

    @inlineCallbacks
    def getOneShotState(self):
        if self.is_on_OneShot:
            request_json = json.dumps({self.msquared_devicename: None})
            response_json = yield self.msquared_server.beam_alignment(
                request_json)
            status = json.loads(response_json).get(self.msquared_devicename)
            if status == True:
                self.is_on_OneShot = False
                self.statusText.setText('One Shot Alignment Completed')
                self.oneshotButton.setDisabled(False)
                self.XBox.setDisabled(False)
                self.YBox.setDisabled(False)
            else:
                pass
        else:
            pass

    @inlineCallbacks
    def onNewEtalonTuner(self):
        value = self.EtalonTunerBox.value()
        request_json = json.dumps({self.msquared_devicename: value})
        yield self.msquared_server.etalon_tune(request_json)
        self.displayEtalonTuner(value)

    @inlineCallbacks
    def getEtalonTuner(self):
        request_json = json.dumps({self.msquared_devicename: None})
        response_json = yield self.msquared_server.etalon_tune(request_json)
        response = json.loads(response_json)
        value = response.get(self.msquared_devicename)
        value_percentage = value / self.etalon_max * 100
        self.displayEtalonTuner(value_percentage)

    def displayEtalonTuner(self, value):
        self.EtalonTunerBox.display(value)

    @inlineCallbacks
    def onNewResonatorTuner(self):
        value = self.ResonatorTunerBox.value()
        request_json = json.dumps({self.msquared_devicename: value})
        yield self.msquared_server.resonator_tune(request_json)
        self.displayResonatorTuner(value)

    @inlineCallbacks
    def getResonatorTuner(self):
        request_json = json.dumps({self.msquared_devicename: None})
        response_json = yield self.msquared_server.resonator_tune(request_json)
        response = json.loads(response_json)
        value = response.get(self.msquared_devicename)
        value_percentage = value / self.resonator_max * 100
        self.displayResonatorTuner(value_percentage)

    def displayResonatorTuner(self, value):
        self.ResonatorTunerBox.display(value)

    @inlineCallbacks
    def onManualButton(self):
        self.is_on_OneShot = False
        self.oneshotButton.setDisabled(False)
        self.XBox.setDisabled(False)
        self.YBox.setDisabled(False)
        mode = 1  # 1 for Manual
        request_json = json.dumps({self.msquared_devicename: mode})
        yield self.msquared_server.beam_alignment(request_json)

    @inlineCallbacks
    def onX(self):
        value = self.XBox.value()
        request_json = json.dumps({self.msquared_devicename: value})
        yield self.msquared_server.alignment_x(request_json)
        self.displayX(value)

    @inlineCallbacks
    def getX(self):
        request_json = json.dumps({self.msquared_devicename: None})
        response_json = yield self.msquared_server.alignment_x(request_json)
        response = json.loads(response_json)
        value = response.get(self.msquared_devicename)
        self.displayX(value)

    def displayX(self, value):
        self.XBox.display(value)

    @inlineCallbacks
    def onY(self):
        value = self.YBox.value()
        request_json = json.dumps({self.msquared_devicename: value})
        yield self.msquared_server.alignment_y(request_json)
        self.displayY(value)

    @inlineCallbacks
    def getY(self):
        request_json = json.dumps({self.msquared_devicename: None})
        response_json = yield self.msquared_server.alignment_y(request_json)
        response = json.loads(response_json)
        value = response.get(self.msquared_devicename)
        self.displayY(value)

    def displayY(self, value):
        self.YBox.display(value)

    @inlineCallbacks
    def onWavelength(self):
        value = self.wavelengthBox.value()
        request_json = json.dumps({self.msquared_devicename: value})
        yield self.msquared_server.wavelength(request_json)
        self.displayWavelength(value)

    @inlineCallbacks
    def getWavelength(self):
        request_json = json.dumps({self.msquared_devicename: None})
        response_json = yield self.msquared_server.wavelength(request_json)
        response = json.loads(response_json)
        value = response.get(self.msquared_devicename)
        self.displayWavelength(value)

    def displayWavelength(self, value):
        self.wavelengthBox.display(value)

    @inlineCallbacks
    def getWLM(self):
        units = self.parent.PIDClient.unitsBox.currentText()
        channel = self.parent.PIDClient.channelBox.currentText()
        if units in self.frequency_units:
            value = yield self.wlm_server.get_frequency(int(channel))
        elif units in self.wavelength_units:
            value = yield self.wlm_server.get_wavelength(int(channel))
        self.displayWLM(value, units)

    def displayWLM(self, value, units):
        self.wlmText.setText('{} {}'.format(value, units))

    @inlineCallbacks
    def getEtalonPD(self):
        request_json = json.dumps({self.msquared_devicename: None})
        response_json = yield self.msquared_server.etalon_pd(request_json)
        response = json.loads(response_json)
        value = response.get(self.msquared_devicename)
        self.displayEtalonPD(value)

    def displayEtalonPD(self, value):
        self.EtalonPDBox.display(value)

    @inlineCallbacks
    def getOutputPD(self):
        request_json = json.dumps({self.msquared_devicename: None})
        response_json = yield self.msquared_server.output_pd(request_json)
        response = json.loads(response_json)
        value = response.get(self.msquared_devicename)
        self.displayOutputPD(value)

    def displayOutputPD(self, value):
        self.OutputPDBox.display(value)

    def closeEvent(self, x):
        pass
Beispiel #3
0
class PIDClient(QtWidgets.QWidget):
    
    wlm_lock_servername = None
    
    units = None
    units_list = ['nm', 'GHz']
    
    channel_list = ['1', '2', '3', '4']
    
    gain_range = (0, 100)
    gain_units = [(0, '')]
    gain_digits = 2
    
    setpoint_range = (0, 1e15)
    setpoint_units = [(0, '')]
    setpoint_digits = 6
    
    offset_range = (0, 100)  # Resonator offset
    offset_units = [(0, '%')]
    offset_digits = 4
    
    spinbox_height = 30
    spinbox_width = 80
    
    config_directory = 'C:\\LabRad\\SrA\\msquared_wlm_lock'
    
    def __init__(self, reactor, cxn, wlm_lock_servername, parent):
        super(PIDClient, self).__init__(None)
        try:
            self.reactor = reactor
            self.cxn = cxn
            self.wlm_lock_servername = wlm_lock_servername
            self.parent = parent
            self.connect()
        except Exception as e:
            print(e)
            traceback.print_exc()            
    
    @inlineCallbacks
    def connect(self):
        if self.cxn == None:
            self.cxn = connection()
            yield self.cxn.connect()
        self.populate()
        yield self.connectWidgets()
    
    def populate(self):
        self.nameLabel =  ClickableLabel('<b> PID Settings </b>')
        
        self.loadButton = QtWidgets.QPushButton()
        self.loadButton.setText('Load Settings')
        self.loadButton.setFixedHeight(40)
        self.loadButton.setFixedWidth(100)
        self.saveButton = QtWidgets.QPushButton()
        self.saveButton.setText('Save Settings')
        self.saveButton.setFixedHeight(40)
        self.saveButton.setFixedWidth(self.spinbox_width*1.5)
        
        self.setpointLabel = ClickableLabel('Set point: ')
        self.setpointBox = SuperSpinBox(self.setpoint_range, self.setpoint_units,
                                        self.setpoint_digits)
        self.setpointBox.setFixedHeight(self.spinbox_height)
        self.setpointBox.setFixedWidth(self.spinbox_width*1.5)
    
        self.offsetLabel = ClickableLabel('Offset: ')
        self.offsetBox = SuperSpinBox(self.offset_range, self.offset_units,
                                        self.offset_digits)
        self.offsetBox.setFixedHeight(self.spinbox_height)
        self.offsetBox.setFixedWidth(self.spinbox_width*1.5)
        
        self.unitsLabel = ClickableLabel('<b> Setpoint Units: </b>')
        self.unitsBox = QtWidgets.QComboBox()
        self.unitsBox.addItems(self.units_list)
        
        self.channelLabel = ClickableLabel('<b> WLM Channel: </b>')
        self.channelBox = QtWidgets.QComboBox()
        self.channelBox.addItems(self.channel_list)
        
        self.OverallGainLabel = ClickableLabel('Overall Gain: ')
        self.OverallGainBox = SuperSpinBox(self.gain_range, self.gain_units,
                                        4)
        self.OverallGainBox.setFixedHeight(self.spinbox_height)
        self.OverallGainBox.setFixedWidth(self.spinbox_width)
        self.PGainLabel = ClickableLabel('P Gain: ')
        self.PGainBox = SuperSpinBox(self.gain_range, self.gain_units,
                                        self.gain_digits)
        self.PGainBox.setFixedHeight(self.spinbox_height)
        self.PGainBox.setFixedWidth(self.spinbox_width)
        self.IGainLabel = ClickableLabel('I Gain: ')
        self.IGainBox = SuperSpinBox(self.gain_range, self.gain_units,
                                        self.gain_digits)
        self.IGainBox.setFixedHeight(self.spinbox_height)
        self.IGainBox.setFixedWidth(self.spinbox_width)
        self.DGainLabel = ClickableLabel('D Gain: ')
        self.DGainBox = SuperSpinBox(self.gain_range, self.gain_units,
                                        self.gain_digits)
        self.DGainBox.setFixedHeight(self.spinbox_height)
        self.DGainBox.setFixedWidth(self.spinbox_width)
        
        
        self.layout = QtWidgets.QGridLayout()
        self.layout.addWidget(self.nameLabel, 1, 0, 3, 1, 
                              QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.loadButton, 1, 1, 3, 2, 
                              QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.saveButton, 1, 3, 3, 2, 
                              QtCore.Qt.AlignHCenter)
        
        self.layout.addWidget(self.setpointLabel, 4, 0, 3, 1, 
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.setpointBox, 4, 1, 3, 3, 
                              QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.offsetLabel, 7, 0, 3, 1, 
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.offsetBox, 7, 1, 3, 3, 
                              QtCore.Qt.AlignLeft)
        
        self.layout.addWidget(self.unitsLabel, 4, 3, 2, 2,
                              QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.unitsBox, 6, 3, 2, 2,
                              QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.channelLabel, 8, 3, 2, 2,
                              QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.channelBox, 10, 3, 2, 2,
                              QtCore.Qt.AlignHCenter)
        
        self.layout.addWidget(self.OverallGainLabel, 10, 0, 3, 1, 
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.OverallGainBox, 10, 1, 3, 1,
                              QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.PGainLabel, 13, 0, 3, 1, 
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.PGainBox, 13, 1, 3, 1,
                              QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.IGainLabel, 16, 0, 3, 1, 
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.IGainBox, 16, 1, 3, 1,
                              QtCore.Qt.AlignLeft)
        self.layout.addWidget(self.DGainLabel, 19, 0, 3, 1, 
                              QtCore.Qt.AlignRight)
        self.layout.addWidget(self.DGainBox, 19, 1, 3, 1,
                              QtCore.Qt.AlignLeft)
        
        self.layout.setContentsMargins(5, 5, 5, 5)
        self.layout.setSpacing(10)
        self.setLayout(self.layout)
        self.setFixedSize(400, 300)

    # def updateParameters(self, parameter_values):
    #     self.parameter_values = parameter_values
    #     self.displaySequence(self.sequence)
    
    @inlineCallbacks
    def connectWidgets(self):
        self.wlm_lock_server = yield self.cxn.get_server(self.wlm_lock_servername)
        
        self.nameLabel.clicked.connect(self.getAll)
        self.loadButton.clicked.connect(self.browseLoad)
        self.saveButton.clicked.connect(self.browseSave)
        self.setpointBox.returnPressed.connect(self.onNewPIDsetpoint)
        self.offsetBox.returnPressed.connect(self.onNewPIDoffset)
        self.OverallGainBox.returnPressed.connect(self.onNewPIDparams)
        self.PGainBox.returnPressed.connect(self.onNewPIDparams)
        self.IGainBox.returnPressed.connect(self.onNewPIDparams)
        self.DGainBox.returnPressed.connect(self.onNewPIDparams)
        self.unitsBox.currentIndexChanged.connect(self.onUnitsChange)
        self.channelBox.currentIndexChanged.connect(self.onChannelChange)
        
        self.getAll()
    
    def disconnectWidgets(self):
        try:
            self.nameLabel.disconnect()
            self.loadButton.disconnect()
            self.saveButton.disconnect()
            self.setpointBox.disconnect()
            self.offsetBox.disconnect()
            self.OverallGainBox.disconnect()
            self.PGainBox.disconnect()
            self.IGainBox.disconnect()
            self.DGainBox.disconnect()
            self.unitsBox.disconnect()
            self.channelBox.disconnect()
        except:
            pass
    
    def disableAll(self):
        self.loadButton.setDisabled(True)
        self.saveButton.setDisabled(True)
        self.setpointBox.setDisabled(True)
        self.offsetBox.setDisabled(True)
        self.OverallGainBox.setDisabled(True)
        self.PGainBox.setDisabled(True)
        self.IGainBox.setDisabled(True)
        self.DGainBox.setDisabled(True)
        self.unitsBox.setDisabled(True)
        self.channelBox.setDisabled(True)
        self.disconnectWidgets()

    def enableAll(self):
        self.loadButton.setDisabled(False)
        self.saveButton.setDisabled(False)
        self.setpointBox.setDisabled(False)
        self.offsetBox.setDisabled(False)
        self.OverallGainBox.setDisabled(False)
        self.PGainBox.setDisabled(False)
        self.IGainBox.setDisabled(False)
        self.DGainBox.setDisabled(False)
        self.unitsBox.setDisabled(False)
        self.channelBox.setDisabled(False)
        self.connectWidgets()
    
    def getAll(self):
        self.getPID()
        self.getWLM()
    
    def disable_when_wlm_lock(self, state):
        self.unitsBox.setDisabled(state)
        self.channelBox.setDisabled(state)
        self.setpointBox.setDisabled(state)
        self.offsetBox.setDisabled(state)
        self.loadButton.setDisabled(state)
    
    @inlineCallbacks
    def loadSettingsFromServer(self):
        current_settings_json = yield self.wlm_lock_server.load_current_settings()
        current_settings = json.loads(current_settings_json)
        self.displaySettings(current_settings)

    def browseLoad(self):
        # timestr = time.strftime(self.time_format)
        directory = self.config_directory
        if not os.path.exists(directory):
            directory = self.config_directory.split('{}')[0]
        filepath = QtWidgets.QFileDialog().getOpenFileName(directory=directory)[0]  # Added [0]
        if filepath:
            self.loadConfig(filepath)
    
    def loadConfig(self, filepath):
        with open(filepath, 'r') as infile:
            settings = json.load(infile)
        self.displaySettings(settings)       
        
    def browseSave(self):
        directory = self.config_directory
        if not os.path.exists(directory):
            directory = self.config_directory.split('{}')[0]
        filepath = QtWidgets.QFileDialog().getSaveFileName(directory=directory)[0]
        if filepath:
            self.saveConfig(filepath)
    
    @inlineCallbacks
    def saveConfig(self, filepath):
        current_settings_json = yield self.wlm_lock_server.load_current_settings()
        with open(filepath, 'w') as f:
            f.write(current_settings_json)

    def displaySettings(self, settings):
        pid_settings = settings['pid']
        wlm_settings = settings['wlm']
        
        setpoint = pid_settings['setpoint']
        offset = pid_settings['offset']
        overall_gain = pid_settings['overall_gain']
        prop_gain = pid_settings['prop_gain']
        int_gain = pid_settings['int_gain']
        diff_gain = pid_settings['diff_gain']
        
        units = wlm_settings['units']
        channel = wlm_settings['channel']
        
        self.displayPIDsetpoint(setpoint)
        self.displayPIDoffset(offset)
        self.displayPIDparams(overall_gain, prop_gain, int_gain, diff_gain)
        self.displayUnits(units)
        self.displayChannel(channel)    


    def getPID(self):
        self.getPIDsetpoint()
        self.getPIDoffset()
        self.getPIDparams()
    
    @inlineCallbacks
    def getPIDsetpoint(self):
        setpoint = yield self.wlm_lock_server.get_setpoint()
        self.displayPIDsetpoint(setpoint)
        
    @inlineCallbacks
    def getPIDoffset(self):
        offset = yield self.wlm_lock_server.get_offset()
        self.displayPIDoffset(offset)
    
    @inlineCallbacks
    def getPIDparams(self):
        overall_gain = yield self.wlm_lock_server.get_gain()
        prop_gain = yield self.wlm_lock_server.get_prop_gain()
        int_gain = yield self.wlm_lock_server.get_int_gain()
        diff_gain = yield self.wlm_lock_server.get_diff_gain()
        self.displayPIDparams(overall_gain, prop_gain, int_gain, diff_gain)
    
    def displayPIDsetpoint(self, setpoint):
        self.setpointBox.display(setpoint)

    def displayPIDoffset(self, offset):
        self.offsetBox.display(offset)
        
    def displayPIDparams(self, overall_gain, prop_gain, int_gain, diff_gain):
        self.OverallGainBox.display(overall_gain)
        self.PGainBox.display(prop_gain)
        self.IGainBox.display(int_gain)
        self.DGainBox.display(diff_gain)
    
    def onNewPIDsetpoint(self):
        setpoint = self.setpointBox.value()
        self.setPIDsetpoint(setpoint)

    def onNewPIDoffset(self):
        offset = self.offsetBox.value()
        self.setPIDoffset(offset)
    
    def onNewPIDparams(self):
        overall_gain = self.OverallGainBox.value()
        prop_gain = self.PGainBox.value()
        int_gain = self.IGainBox.value()
        diff_gain = self.DGainBox.value()
        self.setPIDparams(overall_gain, prop_gain, int_gain, diff_gain)

    @inlineCallbacks
    def setPIDsetpoint(self, setpoint):
        yield self.wlm_lock_server.set_setpoint(setpoint)
        self.displayPIDsetpoint(setpoint)
        
    @inlineCallbacks
    def setPIDoffset(self, offset):
        yield self.wlm_lock_server.set_offset(offset)
        self.displayPIDoffset(offset)
        
    @inlineCallbacks
    def setPIDparams(self, overall_gain, prop_gain, int_gain, diff_gain):
        yield self.wlm_lock_server.set_gain(overall_gain)
        yield self.wlm_lock_server.set_prop_gain(prop_gain)
        yield self.wlm_lock_server.set_int_gain(int_gain)
        yield self.wlm_lock_server.set_diff_gain(diff_gain)
        self.displayPIDparams(overall_gain, prop_gain, int_gain, diff_gain)
    
    def getWLM(self):
        self.getUnits()
        self.getChannel() 
        
    def onUnitsChange(self):
        value = self.unitsBox.currentText()
        self.setUnits(value)
    
    @inlineCallbacks
    def setUnits(self, value):
        yield self.wlm_lock_server.set_units(value)
    
    @inlineCallbacks
    def getUnits(self):
        units = yield self.wlm_lock_server.get_units()
        self.displayUnits(units)
    
    def displayUnits(self, units):
        index = self.unitsBox.findText(units, QtCore.Qt.MatchFixedString)
        if index >= 0:
            self.unitsBox.setCurrentIndex(index)
    
    def onChannelChange(self):
        value = self.channelBox.currentText()
        self.setChannel(int(value))

    @inlineCallbacks
    def setChannel(self, value):
        yield self.wlm_lock_server.set_channel(value)
        
    @inlineCallbacks
    def getChannel(self):
        channel = yield self.wlm_lock_server.get_channel()
        self.displayChannel(channel)
        
    def displayChannel(self, channel):
        index = self.channelBox.findText(str(channel), QtCore.Qt.MatchFixedString)
        if index >= 0:
            self.channelBox.setCurrentIndex(index)
    
    def closeEvent(self, x):
        # super(WLMLockControllerClient, self).closeEvent(x)
        # self.PIDClient.wlm_lock_server.remove_etalon_lock(10) # TODO: Remove Etalon Lock when exit
        try:
            self.reactor.stop()
            x.accept()
        except:
            pass