Skip to content

Commit

Permalink
Updates to documentation, more to come
Browse files Browse the repository at this point in the history
  • Loading branch information
pbnjeff89 committed Sep 9, 2018
1 parent 2e43d8c commit 5857148
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 102 deletions.
82 changes: 29 additions & 53 deletions labdrivers/oxford/itc503.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
"""Module containing a class to interface with an Oxford Instruments ITC 503.
Note: Our (Mason Group) laboratory does not have a working motorized needle
valve, so the gas functions are not totally useful. However, if
it somehow is fixed or if someone not from the group decides to use
this module, then it may be of use.
This module requires a National Instruments VISA driver, which can be found at
https://www.ni.com/visa/
Attributes:
resource_manager: the pyvisa resource manager which provides the visa
objects used for communicating over the GPIB interface
logger: a python logger object
Classes:
itc503: a class for interfacing with a ITC 503 temperature controller
"""
import logging

import visa
Expand All @@ -36,25 +15,23 @@


class Itc503:
"""
Module to connect to an ITC 503.
Modes supported: GPIB
:param gpib_addr: GPIB address of the ITC 503
"""

def __init__(self, gpib_addr=24):
"""Instantiate an Itc503 object.
:param gpib_addr: GPIB address of the ITC 503
"""
self._visa_resource = resource_manager.open_resource("GPIB::%d" % gpib_addr)
self._visa_resource.read_termination = '\r'

def setControl(self, unlocked=1, remote=1):
"""Set the LOCAL / REMOTE control state of the ITC 503
0 - Local & Locked (default state)
1 - Remote & Locked
2 - Local & Unlocked
3 - Remote & Unlocked
:param unlocked: 0 to lock, 1 to unlock
:param remote: 0 for local, 1 for remote
:param unlocked (int): 0 to lock, 1 to unlock
:param remote (int): 0 for local, 1 for remote
:return: None
"""
state_bit = str(remote) + str(unlocked)
Expand All @@ -64,11 +41,8 @@ def setControl(self, unlocked=1, remote=1):

def setTemperature(self, temperature=0.010):
"""Change the temperature set point.
Args:
temperature(float): temperature to move to in Kelvin.
Default: 0.010 K (10 mK) for default no heating
above base temperature for any system.
:param temperature (float): Temperature set point in Kelvin (default: 0.010)
"""
assert type(temperature) in [int, float], 'argument must be a number'

Expand All @@ -77,19 +51,22 @@ def setTemperature(self, temperature=0.010):

def getValue(self, variable=0):
"""Read the variable defined by the index.
There are values 11-13 but generally useless for
general use. These are omitted.
0: SET TEMPERATURE 6: HEATER O/P (as V)
1: SENSOR 1 TEMPERATURE 7: GAS FLOW O/P (a.u.)
2: SENSOR 2 TEMPERATURE 8: PROPORTIONAL BAND
3: SENSOR 3 TEMPERATURE 9: INTEGRAL ACTION TIME
4: TEMPERATURE ERROR 10: DERIVATIVE ACTION TIME
5: HEATER O/P (as %)
Args:
variable: Index of variable to read.
The possible inputs are::
0: SET TEMPERATURE
1: SENSOR 1 TEMPERATURE
2: SENSOR 2 TEMPERATURE
3: SENSOR 3 TEMPERATURE
4: TEMPERATURE ERROR
5: HEATER O/P (as %)
6: HEATER O/P (as V)
7: GAS FLOW O/P (a.u.)
8: PROPORTIONAL BAND
9: INTEGRAL ACTION TIME
10: DERIVATIVE ACTION TIME
:param variable (int): Index of variable to read.
"""
assert type(variable) == int, 'Argument must be an integer.'
assert variable in range(0,11), 'Argument is not a valid number.'
Expand All @@ -102,9 +79,8 @@ def getValue(self, variable=0):

def setProportional(self, prop=0):
"""Sets the proportional band.
Args:
prop: Proportional band, in steps of 0.0001K.
:param prop (float): Proportional band, in steps of 0.0001K.
"""
self._visa_resource.write('$P{}'.format(prop))
return None
Expand Down
73 changes: 44 additions & 29 deletions labdrivers/oxford/mercuryips.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,37 @@


class MercuryIps:
PORT_NO = 7020

# Magnet class

class Magnet:
"""
Constructor for a magnet along a certain axis.
:param axis: The axis for the magnet, given by ['GRPX'|'GRPY'|'GRPZ']
:type axis: string
:param mode: Connection, given by ['ip'|'visa']
:type mode: string
:param resource_name: VISA resource name of the MercuryIPS
:type resource_name: string
:param ip_address: IP address of the MercuryIPS
:type ip_address: string
:param port: Port number of the Mercury iPS
:type port: integer
:param timeout: Time to wait for a response from the MercuryIPS before throwing an error.
:type timeout: float
:param bytes_to_read: Amount of information to read from a response
:type bytes_to_read: integer
"""

def __init__(self, axis, mode='ip', resource_name=None, ip_address=None, timeout=10.0,
def __init__(self, axis, mode='ip', resource_name=None, ip_address=None, port=7020, timeout=10.0,
bytes_to_read=2048):
"""
Constructor for a magnet along a certain axis.
:param axis: The axis for the magnet, given by ['GRPX'|'GRPY'|'GRPZ']
:param mode: Connection, given by ['ip'|'visa']
:param resource_name: VISA resource name of the MercuryIPS
:param ip_address: IP address of the MercuryIPS
:param timeout: Time to wait for a response from the MercuryIPS before throwing an error.
:param bytes_to_read: Amount of information to read from a response
"""
self.axis = axis

self.mode = mode
self.resource_name = resource_name
self.resource_manager = visa.ResourceManager()
self.ip_address = ip_address
self.port = port
self.timeout = timeout
self.bytes_to_read = bytes_to_read

Expand All @@ -39,10 +46,11 @@ def query_ip(self, command):
"""Sends a query to the MercuryIPS via ethernet.
:param command: The command, which should be in the NOUN + VERB format
:return: The MercuryIPS response
:type command: string
:returns str: The MercuryIPS response
"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((self.ip_address, MercuryIps.PORT_NO))
s.connect((self.ip_address, self.port))
s.settimeout(self.timeout)
s.sendall(command.encode())
response = s.recv(self.bytes_to_read).decode()
Expand All @@ -53,7 +61,8 @@ def query_visa(self, command):
"""Sends a query to the MercuryIPS via VISA.
:param command: The command, which should be in the NOUN + VERB format
:return: The MercuryIPS response
:type command: string
:returns str: The MercuryIPS response
"""
instr = self.resource_manager.open_resource(self.resource_name)
response = instr.query(command)
Expand All @@ -66,9 +75,10 @@ def extract_value(response, noun, unit):
"""Finds the value that is contained within the response to a previously sent query.
:param response: The response from a query.
:type response: string
:param noun: The part of the query that refers to the NOUN (refer to MercuryIPS documentation).
:param unit: The measurement unit (e.g. K for Kelvin, T for Tesla).
:return: A floating-point value of the response, but without units.
:returns float: The value of the response, but without units.
"""
expected_response = 'STAT:' + noun + ':'
value = float(response.replace(expected_response, '').strip('\n').replace(unit, ''))
Expand All @@ -79,7 +89,7 @@ def extract_value(response, noun, unit):

@property
def field_setpoint(self):
"""The magnetic field setpoint in Tesla along the magnet axis."""
"""The magnetic field set point in Tesla"""
noun = 'DEV:' + self.axis + ':PSU:SIG:FSET'
command = 'READ:' + noun + '\n'
response = MercuryIps.Magnet.QUERY_AND_RECEIVE[self.mode](self, command)
Expand Down Expand Up @@ -117,7 +127,7 @@ def field_ramp_rate(self, value):

@property
def current_setpoint(self):
"""The setpoint of the current for a magnet in Amperes."""
"""The set point of the current for a magnet in Amperes."""
noun = 'DEV:' + self.axis + ':PSU:SIG:CSET'
command = 'READ:' + noun + '\n'
response = MercuryIps.Magnet.QUERY_AND_RECEIVE[self.mode](self, command)
Expand Down Expand Up @@ -151,6 +161,7 @@ def current_ramp_rate(self, value):

@property
def magnetic_field(self):
"""Gets the magnetic field."""
noun = 'DEV:' + self.axis + ':PSU:SIG:FLD'
command = 'READ:' + noun + '\n'
response = MercuryIps.Magnet.QUERY_AND_RECEIVE[self.mode](self, command)
Expand Down Expand Up @@ -218,14 +229,18 @@ def clamped(self):

def __init__(self, mode='ip',
resource_name=None,
ip_address=None, timeout=10.0, bytes_to_read=2048):
ip_address=None, port=7020, timeout=10.0, bytes_to_read=2048):
"""
Parameters:
:param mode: ['ip'|'visa']
:param resource_name: VISA resource name of the Mercury iPS
:param ip_address: IP address of the Mercury iPS
:param str mode: The connection to the iPS, either 'ip' or 'visa'
:param str resource_name: VISA resource name of the Mercury iPS
:param str ip_address: IP address of the Mercury iPS
:param port: Port number of the Mercury iPS
:type port: integer
:param timeout: Time in seconds to wait for command acknowledgment
:type timeout: float
:param bytes_to_read: Number of bytes to read from query
:type bytes_to_read: integer
"""
supported_modes = ('ip', 'visa')

Expand All @@ -234,12 +249,12 @@ def __init__(self, mode='ip',
else:
raise RuntimeError('Mode is not currently supported.')

self.x_magnet = MercuryIps.Magnet('GRPX', mode=mode, resource_name=resource_name,
ip_address=ip_address, timeout=timeout, bytes_to_read=bytes_to_read)
self.y_magnet = MercuryIps.Magnet('GRPY', mode=mode, resource_name=resource_name,
ip_address=ip_address, timeout=timeout, bytes_to_read=bytes_to_read)
self.z_magnet = MercuryIps.Magnet('GRPZ', mode=mode, resource_name=resource_name,
ip_address=ip_address, timeout=timeout, bytes_to_read=bytes_to_read)
self.x_magnet = MercuryIps.Magnet('GRPX', mode=mode, resource_name=resource_name, ip_address=ip_address,
port=7020, timeout=timeout, bytes_to_read=bytes_to_read)
self.y_magnet = MercuryIps.Magnet('GRPY', mode=mode, resource_name=resource_name, ip_address=ip_address,
port=7020, timeout=timeout, bytes_to_read=bytes_to_read)
self.z_magnet = MercuryIps.Magnet('GRPZ', mode=mode, resource_name=resource_name, ip_address=ip_address,
port=7020, timeout=timeout, bytes_to_read=bytes_to_read)

def circle_sweep(self, field_radius, number_points):
pass
33 changes: 13 additions & 20 deletions labdrivers/oxford/triton200.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,19 @@


class Triton200:
"""
Create an instance of the Triton200 class.
RUO2_CHANNEL = '5'
CERNOX_CHANNEL = '6'
Supported modes: IP
VALID_CHANNELS = (CERNOX_CHANNEL, RUO2_CHANNEL)

HEATER_RANGE = ['0.316', '1', '3.16', '10', '31.6', '100']
:param str ip_address: The IP address of the Triton 200.
:param int port_number: The associated port number of the Triton 200 (default: 33576)
:param int timeout: How long to wait for a response (default: 10000)
:param int bytes_to_read: How many bytes to accept from the response (default: 2048)
"""

def __init__(self, ip_address, port_number=33576, timeout=10000, bytes_to_read=2048):
"""
Constructor for the Triton200 class.
:param ip_address: The IP address of the Triton 200.
:param port_number: The associated port number of the Triton 200.
(default: 33576, as per the Triton 200 manual)
:param timeout: How long to wait for a response. (default: 10000)
:param bytes_to_read: How many bytes to accept from the response.
(defualt: 2048)
"""

self._address = (str(ip_address), int(port_number))
self._timeout = timeout
self._bytes_to_read = bytes_to_read
Expand All @@ -34,7 +28,7 @@ def __init__(self, ip_address, port_number=33576, timeout=10000, bytes_to_read=2
@property
def temperature_channel(self):
"""
:return: The temperature channel, either the cernox (5) or the RuO2 (6)
:returns str: The temperature channel, either the cernox (5) or the RuO2 (6)
"""
return self._temperature_channel

Expand All @@ -58,9 +52,7 @@ def temperature_setpoint(self, value):

@property
def temperature(self):
"""
:return: The temperature reading from the current temperature channel.
"""
"""The temperature reading from the current temperature channel."""
noun = 'DEV:T' + str(self.temperature_channel) + ':TEMP:SIG:TEMP'
command = 'READ:' + noun + '\r\n'
response = self.query_and_receive(command)
Expand All @@ -72,6 +64,7 @@ def update_heater(self):
Associates the heater with the current temperature channel and changes the heater current to
preset values given the temperature set point.
"""
heater_range = ['0.316', '1', '3.16', '10', '31.6', '100']
command = 'SET:DEV:T' + str(self.temperature_channel) + ':TEMP:LOOP:HTR:H' + str(self._heater_channel) + '\r\n'
response = self.query_and_receive(command)

Expand All @@ -83,7 +76,7 @@ def update_heater(self):
+ (self.temperature_setpoint > 0.300)
+ (self.temperature_setpoint > 1.000)
+ (self.temperature_setpoint > 1.500))
heater_current = Triton200.HEATER_RANGE[heater_index]
heater_current = heater_range[heater_index]

command = 'SET:DEV:T' + str(self.temperature_channel) + ':TEMP:LOOP:RANGE:' + heater_current + '\r\n'
response = self.query_and_receive(command)
Expand Down

0 comments on commit 5857148

Please sign in to comment.