Skip to content

Commit

Permalink
Merge pull request #51 from ralph-group/mn455_reading
Browse files Browse the repository at this point in the history
Remove support for old PyVisa versions.
  • Loading branch information
minhhaiphys committed Aug 29, 2016
2 parents 5960b9c + 6dd8670 commit ade4c5b
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 113 deletions.
4 changes: 2 additions & 2 deletions docs/about/authors.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
Authors
=======

PyMeasure was started in 2013 by Colin Jermain and Graham Rowlands at Cornell University, when it became appearent that both were working on similar Python packages for scientific measurements. PyMeasure combined these efforts and continues to gain valuable contributions from other scientists who are interested in advancing measurement software.
PyMeasure was started in 2013 by Colin Jermain and Graham Rowlands at Cornell University, when it became apparent that both were working on similar Python packages for scientific measurements. PyMeasure combined these efforts and continues to gain valuable contributions from other scientists who are interested in advancing measurement software.

The following developers have contributed to the PyMeasure package:

| Colin Jermain
| Graham Rowlands
| Minh-Hai Nguyen
| Guen Prawiro-Atmodjo
|
|
4 changes: 2 additions & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ python gui.py

The following examples simulate data using a random number generator, so they do not require an instrument to be connected. They show off the basic structure for setting up your measurement.

1. [gui.py](Basic/gui.py) - A graphical user interface example with live-plotting and full features.
1. [gui.py](Basic/gui.py) - A graphical user interface example with live-plotting and full features.
2. [script_plotter.py](Basic/script.py) - A command line example, which also has a live-plot.
3. [script.py](Basic/script.py) - A simple command line example.
4. [gui_custom_inputs.py](Basic/gui_custom_inputs.py) - An extension of [gui.py](Basic/gui.py), which uses a [custom Qt Creator file](Basic/gui_custom_inputs.ui) for the inputs.
Expand All @@ -28,7 +28,7 @@ There are two examples of for measuring current-voltage (IV) characteristics, wh

## Notebook Experiments

Besides the interfaces shown in the [Basic examples](#basic), you can also make measurements in Jupyter notebooks. Its recommended that you use caution when using this technique, as the notebooks allow scripts to be executed out of order and they do not provide the same level of performance as the standard interfaces. Despite these caveats, the notebooks can be a flexible method for running custom experiments, where the Procedure needs to be modified often.
Besides the interfaces shown in the [Basic examples](#basic), you can also make measurements in Jupyter notebooks. It is recommended that you use caution when using this technique, as the notebooks allow scripts to be executed out of order and they do not provide the same level of performance as the standard interfaces. Despite these caveats, the notebooks can be a flexible method for running custom experiments, where the Procedure needs to be modified often.

1. [script.ipynb](Notebook Experiments/script.ipynb) - Runs the simulated random number Procedure from [gui.py](Basic/gui.py) in a notebook.
2. [script2.ipynb](Notebook Experiments/script2.ipynb) - Extends [script.ipynb](Notebook Experiments/script.ipynb), using custom configurations and Measureable parameters.
133 changes: 36 additions & 97 deletions pymeasure/adapters/visa.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@
import copy
import logging
log = logging.getLogger(__name__)
#log.addHandler(log.NullHandler())

long = int # Python 3 fix


log.addHandler(logging.NullHandler())

class VISAAdapter(Adapter):
""" Adapter class for the VISA library using PyVISA to communicate
Expand All @@ -42,24 +38,28 @@ class VISAAdapter(Adapter):
:param resource: VISA resource name that identifies the address
:param kwargs: Any valid key-word arguments for constructing a PyVISA instrument
"""
def __new__(cls, resourceName, **kwargs):
""" Choose a parent class based on PyVISA version"""

version = float(visa.__version__)
if version > 1.4:
mode = VISAAdapter17
else:
mode = VISAAdapter14

cls = type(cls.__name__ + '+' + mode.__name__, (cls, mode), {})
return super(VISAAdapter, cls).__new__(cls)

def __init__(self, resourceName, **kwargs):
#Check PyVisa version
version = float(self.version)
if version < 1.7:
raise NotImplementedError("PyVisa {} is no longer supported. Please upgrade to version 1.8 or later.".format(version))

if isinstance(resourceName, (int, long)):
resourceName = "GPIB0::%d::INSTR" % resourceName
super(VISAAdapter, self).__init__(resourceName, **kwargs)
self.resource_name = resourceName

self.manager = visa.ResourceManager()
safeKeywords = ['resource_name', 'timeout', 'term_chars',
'chunk_size', 'lock', 'delay', 'send_end',
'values_format']
kwargsCopy = copy.deepcopy(kwargs)
for key in kwargsCopy:
if key not in safeKeywords:
kwargs.pop(key)
self.connection = self.manager.get_instrument(
resourceName,
**kwargs
)
@property
def version(self):
""" The string of the PyVISA version in use
Expand All @@ -86,84 +86,41 @@ def read(self):
:returns: String ASCII response of the instrument.
"""
return self.connection.read()

def binary_values(self, command, header_bytes=0, dtype=np.float32):
""" Returns a numpy array from a query for binary data
:param command: SCPI command to be sent to the instrument
:param header_bytes: Integer number of bytes to ignore in header
:param dtype: The NumPy data type to format the values with
:returns: NumPy array of values
"""
self.connection.write(command)
binary = self.connection.read_raw()
header, data = binary[:header_bytes], binary[header_bytes:]
return np.fromstring(data, dtype=dtype)


class VISAAdapter14(Adapter):
""" Adapter class for VISA version 1.4. Be inherited by class VISAAdapter.
:param resource: VISA resource name that identifies the address.
:param kwargs: Any valid key-word arguments for constructing a PyVISA instrument.
"""
def __init__(self, resourceName, **kwargs):
self.connection = visa.instrument(resourceName, **kwargs)

def config(self, **kwargs):
""" Reserve for future implementation."""
log.warning("Class method config() not yet implemented! Do nothing.")
pass

def ask(self, command):
""" Writes the command to the instrument and returns the resulting
""" Writes the command to the instrument and returns the resulting
ASCII response
:param command: SCPI command string to be sent to the instrument
:returns: String ASCII response of the instrument
"""
return self.connection.ask(command)
return self.connection.query(command)

def ask_values(self, command):
""" Writes a command to the instrument and returns a list of formatted
values from the result
values from the result. The format of the return is configurated by
self.config().
:param command: SCPI command to be sent to the instrument
:returns: String ASCII response of the instrument
:returns: Formatted response of the instrument.
"""
return self.connection.ask_for_values(command)
return self.connection.query_values(command)

def wait_for_srq(self, timeout=25, delay=0.1):
""" Blocks until a SRQ, and leaves the bit high
def binary_values(self, command, header_bytes=0, dtype=np.float32):
""" Returns a numpy array from a query for binary data
:param timeout: Timeout duration in seconds
:param delay: Time delay between checking SRQ in seconds
:param command: SCPI command to be sent to the instrument
:param header_bytes: Integer number of bytes to ignore in header
:param dtype: The NumPy data type to format the values with
:returns: NumPy array of values
"""
self.connection.wait_for_srq(timeout)


class VISAAdapter17(Adapter):
""" Adapter class for VISA version 1.5 or above. Be inherited by class VISAAdapter.
self.connection.write(command)
binary = self.connection.read_raw()
header, data = binary[:header_bytes], binary[header_bytes:]
return np.fromstring(data, dtype=dtype)

:param resource: VISA resource name that identifies the address.
:param kwargs: Any valid key-word arguments for constructing a PyVISA instrument.
"""
def __init__(self, resourceName, **kwargs):
self.manager = visa.ResourceManager()
safeKeywords = ['resource_name', 'timeout', 'term_chars',
'chunk_size', 'lock', 'delay', 'send_end',
'values_format']
kwargsCopy = copy.deepcopy(kwargs)
for key in kwargsCopy:
if key not in safeKeywords:
kwargs.pop(key)
self.connection = self.manager.get_instrument(
resourceName,
**kwargs
)

def config(self, is_binary = False, datatype = 'str',
container = np.array, converter = 's',
container = np.array, converter = 's',
separator = ',', is_big_endian = False):
""" Configurate the format of data transfer to and from the instrument.
Expand All @@ -181,29 +138,11 @@ def config(self, is_binary = False, datatype = 'str',
self.connection.values_format.separator = separator
self.connection.values_format.is_big_endian = is_big_endian

def ask(self, command):
""" Writes the command to the instrument and returns the resulting
ASCII response
:param command: SCPI command string to be sent to the instrument
:returns: String ASCII response of the instrument
"""
return self.connection.query(command)

def ask_values(self, command):
""" Writes a command to the instrument and returns a list of formatted
values from the result. The format of the return is configurated by
self.config().
:param command: SCPI command to be sent to the instrument
:returns: Formatted response of the instrument.
"""
return self.connection.query_values(command)

def wait_for_srq(self, timeout=25, delay=0.1):
""" Blocks until a SRQ, and leaves the bit high
:param timeout: Timeout duration in seconds
:param delay: Time delay between checking SRQ in seconds
"""
self.connection.wait_for_srq(timeout*1000)
self.connection.wait_for_srq(timeout*1000)
24 changes: 12 additions & 12 deletions pymeasure/experiment/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self, name, default=None, ui_class=None):
self.name = name
self._value = default
self.default = default
self.ui_class = None
self.ui_class = ui_class

@property
def value(self):
Expand Down Expand Up @@ -212,7 +212,7 @@ class VectorParameter(Parameter):
:param ui_class: A Qt class to use for the UI of this parameter
"""
def __init__(self, name, length=3, units=None, **kwargs):
self._length = length
self._length = length
super(VectorParameter, self).__init__(name, **kwargs)
self.units = units

Expand Down Expand Up @@ -295,7 +295,7 @@ def value(self, value):
class PhysicalParameter(VectorParameter):
""" :class: '.VectorParameter' sub-class of 2 dimentions to store a value
and its uncertainty.
:var value: The value of the parameter as a list of 2 floating point numbers
:param name: The parameter name
Expand All @@ -304,21 +304,21 @@ class PhysicalParameter(VectorParameter):
:param default: The default value
:param ui_class: A Qt class to use for the UI of this parameter
"""

def __init__(self, name, uncertaintyType='absolute', **kwargs):
super(PhysicalParameter, self).__init__(name, length=2, **kwargs)
self._utype = ListParameter("uncertainty type",
choices = ['absolute', 'relative', 'percentage'],
default = None)
self._utype.value = uncertaintyType

@property
def value(self):
if self.is_set():
return [float(ve) for ve in self._value]
else:
raise ValueError("Parameter value is not set")

@value.setter
def value(self, value):
# Strip initial and final brackets
Expand All @@ -343,17 +343,17 @@ def value(self, value):
"not be converted to floats." % str(value))
# Uncertainty must be non-negative
self._value[1] = abs(self._value[1])

@property
def uncertainty_type(self):
return self._utype.value

@uncertainty_type.setter
def uncertainty_type(self, uncertaintyType):
oldType = self._utype.value
self._utype.value = uncertaintyType
newType = self._utype.value

if self.is_set():
# Convert uncertainty value to the new type
if (oldType, newType) == ('absolute', 'relative'):
Expand Down Expand Up @@ -382,8 +382,8 @@ def __str__(self):
def __repr__(self):
return "<%s(name=%s,value=%s,units=%s,uncertaintyType=%s)>" % (
self.__class__.__name__, self.name, self._value, self.units, self._utype.value)


class Measurable(object):
""" Encapsulates the information for a measurable experiment parameter
with information about the name, fget function and units if supplied.
Expand Down Expand Up @@ -421,4 +421,4 @@ def value(self):

@value.setter
def value(self, value):
self._value = value
self._value = value

0 comments on commit ade4c5b

Please sign in to comment.