debugpythonMinor
Interfacing with instruments using pyvisa
Viewed 0 times
interfacingwithinstrumentsusingpyvisa
Problem
I'm new to Python, and after running through some introductory exercises I wrote a class definition for working with some hardware, specifically a Signal Recovery model 7230 lockin amplifier. In the interests of learning good habits from the beginning, I've tried to write "good code" that is properly documented, follows good practices and so forth.
```
""" Module for interfacing with Signal Recovery 7230 lock-in amplifier.
A substantial ammount is currently not implmented. It will not work with
a lockin which is configured for double demodulation. If you get a lot
of timeouts, that might be why.
It is also currently missing any way to configure the lockin. Use the
web interface. It does read and expose the status bytes, but at the moment
there is no checking of their content.
@author: Jack Barraclough
"""
import pyvisa
class WrongInstrumentError(Exception):
"""The wrong instrument is connected
A connection was successfuly established, and the instrument responded
to a request to identify itself, but the ID recieved was wrong.
Probably the instrument at the given VISA identifier is not the one
you wanted.
"""
pass
class Instrument:
"""Represents a Signal Recovery Model 7230 lock-in amplifier
Note that several instances can be created representing the same
instrument. Be careful.
Instance variables:
pyvisa -- a pyvisa object for the connection, avoid using.
status_byte -- status byte after the last read operation.
overload_byte -- overload byte after the last read operation.
Methods:
read, write -- Read and write strings to/from the instrument.
get_X, get_Y, get_R, get_T -- get measurements from the instrument.
get_noise -- get the estimated measurement noise
"""
def __init__(self,visaName):
""" Connects to the lockin amplifier
Connects to the lockin, and checks that the lockin is present and
correct. An error will be raised if the locki
```
""" Module for interfacing with Signal Recovery 7230 lock-in amplifier.
A substantial ammount is currently not implmented. It will not work with
a lockin which is configured for double demodulation. If you get a lot
of timeouts, that might be why.
It is also currently missing any way to configure the lockin. Use the
web interface. It does read and expose the status bytes, but at the moment
there is no checking of their content.
@author: Jack Barraclough
"""
import pyvisa
class WrongInstrumentError(Exception):
"""The wrong instrument is connected
A connection was successfuly established, and the instrument responded
to a request to identify itself, but the ID recieved was wrong.
Probably the instrument at the given VISA identifier is not the one
you wanted.
"""
pass
class Instrument:
"""Represents a Signal Recovery Model 7230 lock-in amplifier
Note that several instances can be created representing the same
instrument. Be careful.
Instance variables:
pyvisa -- a pyvisa object for the connection, avoid using.
status_byte -- status byte after the last read operation.
overload_byte -- overload byte after the last read operation.
Methods:
read, write -- Read and write strings to/from the instrument.
get_X, get_Y, get_R, get_T -- get measurements from the instrument.
get_noise -- get the estimated measurement noise
"""
def __init__(self,visaName):
""" Connects to the lockin amplifier
Connects to the lockin, and checks that the lockin is present and
correct. An error will be raised if the locki
Solution
Your code so far looks pretty good - well structured, useful docstrings, well done! You mention exceptions; the one occasion you use it seems fine to me.
Per the style guide, e.g.
Rather than including
Now, rather than
Going further, there is a lot of duplication - every single one calls
I admit I don't know much about
and be certain that everything was dealt with on
Per the style guide, e.g.
visaName should be visa_name. Also, rather than commenting pyvisa -- a pyvisa object for the connection, avoid using., it is conventional to prepend the names of attributes that shouldn't be used externally with a single underscore: _pyvisa.Rather than including
@author in your docstring, you could use one of Python's special module attributes:__author__ = 'Jack Barraclough'get methods aren't very Pythonic. Instead, I would suggest you use properties, for example:@property
def R(self):
"""Get R value from the instrument, returns a float"""
self.write('MAG.')
return float(self.read())Now, rather than
instrument.get_R(), you can type simply instrument.R.Going further, there is a lot of duplication - every single one calls
self.write then returns the value from self.read. You could factor this out entirely:class Instrument:
PROPERTIES = {'R': 'MAG.', ...}
def __getattr__(self, attr):
if attr in self.PROPERTIES:
return self._get(self.PROPERTIES[attr])
msg = "{!r} object has no attribute {!r}"
raise AttributeError(msg.format(self.__class__.__name__, attr))
def __setattr__(self, attr, val):
if attr in self.PROPERTIES:
raise AttributeError("can't set attribute")
return super().__setattr__(attr)
def _get(self, value):
self.write(value)
return float(self.read())I admit I don't know much about
pyvisa, but one option to ensure the resource is released would be to make your class a context manager type. Then a user could do e.g. with Instrument(whatever) as inst:
...and be certain that everything was dealt with on
__exit__.Code Snippets
__author__ = 'Jack Barraclough'@property
def R(self):
"""Get R value from the instrument, returns a float"""
self.write('MAG.')
return float(self.read())class Instrument:
PROPERTIES = {'R': 'MAG.', ...}
def __getattr__(self, attr):
if attr in self.PROPERTIES:
return self._get(self.PROPERTIES[attr])
msg = "{!r} object has no attribute {!r}"
raise AttributeError(msg.format(self.__class__.__name__, attr))
def __setattr__(self, attr, val):
if attr in self.PROPERTIES:
raise AttributeError("can't set attribute")
return super().__setattr__(attr)
def _get(self, value):
self.write(value)
return float(self.read())with Instrument(whatever) as inst:
...Context
StackExchange Code Review Q#84087, answer score: 3
Revisions (0)
No revisions yet.