0

Based on a previous question, I was thinking on a security mechanism: I want to be able to uncheck the groupbox trigbox (which has the trigger settings) when I close the connection to the intrument (via the 'Close' button).

My updated code is as follows:

# -*- coding: utf-8 -*-

"""
Driver for devices from Stanford Research Systems
contains:
- DG645
File name: stanford_research_systems.py
Python version: 3.7

This script reuses code from 

https://github.com/Galvant/InstrumentKit/blob/master/instruments/srs/srsdg645.py

by Reto Trappisch and Steven Casagrande



"""
from typing import Tuple, Union
import socket
import time
from termcolor import colored, cprint
import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc


class DG645:
    """ Driver for delay generators """

    DEFAULTS = {
        'outputBNC': {
            "T0":0,
            "AB":1,
            "CD":2,
            "EF":3,
            "GH":4
        },
        'channel': {
            "T0":0,
            "T1":1,
            "A":2,
            "B":3,
            "C":4,
            "D":5,
            "E":6,
            "F":7 ,
            "G":8,
            "H":9
        },
        'write_termination': '\n',
        'read_termination': '\r\n',
    }


    def __init__(self, tcp: str, port: int, timeout: float = 0.010):
        """
        Arguments:
        tcp - IP address of device
        port - port of device
        timeout - time in seconds before recv() gives a timeout error
        """
        self.tcp = tcp
        self.port = port
        self._device = None
        self.timeout = timeout

    def initialize(self):
        """Connect to the device."""
        self._device = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._device.settimeout(self.timeout)
        self._device.connect((self.tcp, self.port))
        time.sleep(0.2)
        print_blue_on_white = lambda x: cprint(x, 'blue', 'on_white')
        print_blue_on_white(f'=======================\n Connection Sucessful! \n=======================\n{self.idn}')
#        time.sleep(0.3)
#        print_blue_on_white(f'MAC Address is \n{self.emac}')

    def close(self):
        """Closing connection with the device"""
        print_red_on_white = lambda x: cprint(x, 'red', 'on_white')
        print_red_on_white(f'{self.idn}\n===================\n Connection closed \n===================')
        self._device.close()


    def write(self, cmd: str) -> None:
        """Send command to device"""
        # Add write termination character and encode
        termination_char = self.DEFAULTS['write_termination']
        cmd += termination_char
        cmd = cmd.encode()
        # Send command
        self._device.send(cmd)

    def query(self, cmd: str) -> str:
        """Send a request to the device and return its respons."""
        self.write(cmd)
        respons = self._device.recv(256)
        respons = respons.decode()
        # Strip off read termination character
        return respons.rstrip()

    @property
    def idn(self) -> str:
        """ Get identification of device. """
        idn = self.query('*IDN?')
        return idn

    def set_delay(self, channel: Union[int, str], delay: float, reference: Union[int, str] = "T0"):
        """Set the delay of a certain channel with respect to a reference.
        Arguments:
        channel -- str/int corresponding to a channel (see self.DEFAULTS)
        delay -- float, with time in seconds
        reference -- defaults to 'T0'
        """
        if isinstance(channel, str):
            channel = self.DEFAULTS['channel'][channel]

        if isinstance(reference, str):
            reference = self.DEFAULTS['channel'][reference]

        cmd = f'DLAY {channel}, {reference}, {delay}'
        self.write(cmd)
        #wait for 100 ms, this is the time it will take to write the command
        time.sleep(0.1)

    def get_delay(self, channel: Union[int, str]) -> Tuple[int, float]:
        """Request the delay of a certain channel
        Arguments:
            channel -- str/int corresponding to a channel (see self.DEFAULTS)
        Returns -- (int, float) | reference channel, delay in seconds.
        """

        if isinstance(channel, str):
            channel = self.DEFAULTS['channel'][channel]
        cmd = f'DLAY? {channel}'
        respons = self.query(cmd).split(',')
        reference = int(respons[0])
        delay = float(respons[1])
        return reference, delay

    def get_output_level(self, channel: Union[int, str]) -> float:
        """Request output amplitude of a channel
        Arguments:
        channel -- str/int corresponding to a channel (see self.DEFAULTS)
        Returns --float, the amplitude in Volts
        """
        if isinstance(channel, str):
            channel = self.DEFAULTS['outputBNC'][channel]
        cmd = f'LAMP? {channel}'
        respons = self.query(cmd)
        return float(respons)

    def emac(self) -> str:
        "Get MAC address of device"
        emac = self.query('*EMAC?')
        return emac



class MainWindow(qtw.QWidget) :
    
    def setDelay(self):
#        channel = self.entChan.text()
        channel = self.ChanComboBox.currentText()
        timing = self.entTiming.text()
#        reference = self.entRef.text()
        reference = self.RefComboBox.currentText()
        if channel and timing:
            dg.set_delay(channel, timing, reference)
    #        print(dg.set_delay)

    def __init__(self) :
        """MainWindow constructor"""
        super().__init__()
        
        self.setWindowTitle("SRS DG645 Setting Box")
 
        ##########################
        # Main UI code goes here #
        ##########################
   
        layout = qtw.QVBoxLayout()
        self.setLayout(layout)     
        
        groupbox = qtw.QGroupBox(
            'I/O Status',
            checkable=True,
            checked=True,
            alignment=qtc.Qt.AlignHCenter,
            flat=True)        


        groupbox.setLayout(qtw.QHBoxLayout())
        groupbox.layout().addWidget(qtw.QPushButton('Initialize', clicked = dg.initialize))
        groupbox.layout().addWidget(qtw.QPushButton('Close', clicked = dg.close))
        layout.addWidget(groupbox)
        
   

        self.WtrTrigBut = qtw.QPushButton(
            'Write Values',
            clicked=self.setDelay
        )
        
        self.WtrTrigBut.clicked.connect(
            lambda: dg.set_delay(ChanComboBox.currentText(),
            self.entTiming.text(),
            RefComboBox.currentText())
        )


        
        trigbox = qtw.QGroupBox(
            'Channel, Reference and Delay',
            checkable=True,
            checked=False,
            alignment=qtc.Qt.AlignHCenter,
            flat=True) 
        trigbox.setLayout(qtw.QVBoxLayout())
        
        
        ChanComboBox = qtw.QComboBox(
            self,
            editable=True,
            insertPolicy=qtw.QComboBox.InsertAtTop,
        )
        
        ChanComboBox.addItem('T0')
        ChanComboBox.addItem('T1')
        ChanComboBox.addItem('A')
        ChanComboBox.addItem('B')
        ChanComboBox.addItem('C')
        ChanComboBox.addItem('D')
        ChanComboBox.addItem('E')
        ChanComboBox.addItem('F')
        ChanComboBox.addItem('G')
        ChanComboBox.addItem('H')
 



        
        self.labRef = qtw.QLabel('Reference')
        
        RefComboBox = qtw.QComboBox(
            self,
            editable=True,
            insertPolicy=qtw.QComboBox.InsertAtTop,
        )
        
        RefComboBox.addItem('T0')
        RefComboBox.addItem('T1')
        RefComboBox.addItem('A')
        RefComboBox.addItem('B')
        RefComboBox.addItem('C')
        RefComboBox.addItem('D')
        RefComboBox.addItem('E')
        RefComboBox.addItem('F')
        RefComboBox.addItem('G')
        RefComboBox.addItem('H')
        

        trigbox.layout().addWidget(qtw.QLabel('Channel'))
        trigbox.layout().addWidget(ChanComboBox)
        trigbox.layout().addWidget(qtw.QLabel('Reference'))
        trigbox.layout().addWidget(RefComboBox)


        self.labTiming = qtw.QLabel('Timing')
        self.entTiming = qtw.QLineEdit()
        
#        self.layout().addWidget(self.labChan)
#        self.layout().addWidget(ChanComboBox)
#        trigbox.layout().addWidget(self.labRef)
#        trigbox.layout().addWidget(RefComboBox)

        trigbox.layout().addWidget(self.labTiming)
        trigbox.layout().addWidget(self.entTiming)

        trigbox.layout().addWidget(self.WtrTrigBut)

        layout.addWidget(trigbox)
        

        
        
        
        ##########################
        # End of UI code Section #
        ##########################
        self.show()



if __name__ == '__main__':
    dg = DG645('169.254.74.114', 5025)
    app = qtw.QApplication(sys.argv)
    mw = MainWindow()
    sys.exit(app.exec())  
musicamante
  • 41,230
  • 6
  • 33
  • 58
Strelok
  • 189
  • 9
  • 2
    The concept is still the same: don't connect directly to the function that closes the connection, but create a function that unchecks the group box *and* calls the close function. Note that in order to access the group box, you should make it an instance attribute: `self.trigbox = qtw.QGroupBox(...)`. Consider that you're often doing the same "mistake", which is to create objects without persistent references; while the parenthood of Qt widgets ensures that they don't get deleted due to garbage collection, you should create instance attributes for widgets that you need to access afterwards. – musicamante Aug 27 '21 at 15:44
  • 1
    Other suggestions: 1. similarly to what written above, there's little benefit in continuously calling `layout()`: just create the layout as a local variable and use that to add widgets; 2. use [`addItems([...])`](https://doc.qt.io/qt-5/qcombobox.html#addItems) instead of multiple `addItem()`; 3. only classes and constants should be capitalized, while variable, attribute and function names should always start with a lowercase letter; 4. for future reference, always provide a [mre] (it should be *both* minimal *and* reproducible): your code has lot of parts that are unnecessary for the question. – musicamante Aug 27 '21 at 15:55

0 Answers0