Pyexplabsys
Pyexplabsys
Release 1.5
CINF
1 Overview 3
1.1 Project Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Python 3 support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Module Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 User Notes 17
2.1 Setting up logging of your program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2 Activating PyExpLabSys library logging in you program . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3 Using PyExpLabSys drivers outside of PyExpLabSys . . . . . . . . . . . . . . . . . . . . . . . . . 19
4 File parsers 65
4.1 XML based file formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.2 Binary File Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5 Apps 73
5.1 The Bakeout App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6 Hardware Drivers 75
6.1 The bio_logic module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.2 The 4d Systems module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.3 The pfeiffer module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
i
7.5 The brooks_s_protocol module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
7.6 The cpx400dp module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
7.7 The crowcon module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
7.8 The dataq_binary module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
7.9 The dataq_comm module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
7.10 The edwards_agc module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
7.11 The edwards_nxds module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
7.12 The epimax module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
7.13 The freescale_mma7660fc module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
7.14 The fug module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
7.15 The galaxy_3500 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
7.16 The honeywell_6000 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
7.17 The inficon_sqm160 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
7.18 The innova module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
7.19 The intellemetrics_il800 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
7.20 The isotech_ips module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
7.21 The keithley_2700 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
7.22 The keithley_smu module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
7.23 The kjlc_pressure_gauge module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
7.24 The lascar module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
7.25 The mks_925_pirani module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
7.26 The mks_937b module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
7.27 The mks_g_series module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.28 The mks_pi_pc module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.29 The omega_D6400 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.30 The omega_cn7800 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
7.31 The omega_cni module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
7.32 The omegabus module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
7.33 The omron_d6fph module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.34 The pfeiffer_qmg420 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.35 The pfeiffer_qmg422 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.36 The pfeiffer_turbo_pump module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
7.37 The polyscience_4100 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
7.38 The rosemount_nga2000 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
7.39 The scpi module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
7.40 The specs_XRC1000 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
7.41 The specs_iqe11 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
7.42 The srs_sr630 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
7.43 The stahl_hv_400 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
7.44 The stmicroelectronics_ais328dq module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
7.45 The stmicroelectronics_l3g4200d module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
7.46 The tenma module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
7.47 The vivo_technologies module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
7.48 The wpi_al1000 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
7.49 The xgs600 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
ii
10 Indices and tables 165
iii
iv
PyExpLabSys Documentation, Release 1.5
This page serves as documentation for the software activities at CINF. Of interest to the public are hardware drivers
for experimental equipment and data logging clients but the page also contain documentation for setup specific code.
Contents:
Contents 1
PyExpLabSys Documentation, Release 1.5
2 Contents
CHAPTER 1
Overview
This page contains different overviews of the PyExpLabSys archive and can work as an entry point for a new user.
Section Project Overview contains a short explanation of the different components that PyExpLabSys consist of and
the source code and documentation entries that are relevant for that part.
The table in section Module Overview contains an overview of all the modules in PyExpLabSys. The overview consist
of a short description (the first line of the module docstring) and its Python 2/3 support status.
PyExpLabSys strive to support Python version 2.7 and >=3.3. See the section Python 3 support about Python 3
support.
This section will explain how the different components of PyExpLabSys (and its sister project cinfdata) fits together.
The overall structure is illustrated in the overview figure. On the aquisition level, there is a number of machines which
could be e.g. Raspberry Pi’s or laboratory PC’s, which will use different parts of PyExpLabSys depending on its
purpose.
Machine 1 e.g. is used to parse already aquired data from local data files (File parsers) and send that data to the
database (Database Savers). Machine 2 aquires data via an equipment drivers (Drivers) and makes it available to
other machines on the network (Sockets) and uploads it to the database (Database Savers). Like machine 2, machine
3 also aquires data directly (Drivers), but it also makes use of the data that machine 2 makes available (Sockets).
On the server level there is a MySQL servers to which all data is saved and a webserver. The webserver runs a webpage
called “Cinfdata” (source code), which is used for data presentation and light data treatment.
On the user level, users will commonly access the data via the Cinfdata website in a browser on the desktop or on a
smart phone. To get the data locally to do more extensive data treament, it is possible to fetch the data directly from
MySQL server or to use an export function on the website.
In the following, each of these software components will be described in a little more detail.
3
PyExpLabSys Documentation, Release 1.5
Fig. 1.1: Figure illustrating how the different software components (boxes with blue edge) of PyExpLabSys (and
cinfdata) fits together.
1.1.1 Drivers
At this point PyExpLabSys contains a reasonable amount of drivers (46 files, 81 classes May-16) for general purpose
equipment (data cards, temperature readout etc.) and for equipment related specifically to the vacuum lab we work in
(pressure gauge controllers, mass spectrometers etc).
The source code for the drivers are in the drivers folder, in which the file names are either manufacturer and model or
just the manufacturer.
The documentation for the drivers are divided into two sections Hardware Drivers and Hardware Drivers Autogen-
erated Docs Only. The latter is the group for which there is only API documentation auto generated from the source
code and the former are the drivers that has more specific documentation with example usage etc.
PyExpLabSys also contains a small number of parsers for custom file formats. The source code for these are in the
file_parsers folder and the documentation is in the File parsers section.
The database savers are some of the more frequently used classes in PyExpLabSys. Quite simply, they abstract away;
the database layout, the SQL and the queuing of data ofloading (to prevent loosing data in the event of data loss). The
source code for the database savers are in database_saver module in the common sub-package. The documentation is
located at The database_saver module.
4 Chapter 1. Overview
PyExpLabSys Documentation, Release 1.5
1.1.4 Sockets
The sockets are another set of very important and highly used classes in PyExpLabSys. Most of the sockets are socket
servers, which mean that they accept UDP requests and serves (or accepts) data. These are essentially used as network
variables, by either exposing a measurement on the network or accepting input. A final type of socket is the LiveSocket
which is used to live stream data to a live streaming proxy server. Furthermore, all sockets also expose system (health)
information to the network. The code for the sockets are found in the sockets module in the common sub-package.
The documentation is located at The sockets module.
1.1.5 Apps
The apps section contains stand alone programs which can be used directly and not only as service functions of larger
programs. Typically the apps sports text based guis and several apps also have ambitions for graphical guis. Notable
examples of apps are: socket supervisor This very simple app continously probes a port (typically a socket) and reports
back if the socket is running correctly.
Mass Spectrometer Controls a number of Pfeiffer mass spectrometers. The app includes support for an infinite amount
of meta-channels wich is pulled in via sockets.
Picture Logbook A graphical logbook system based on a barcode reader and a camera. The user of the equipment logs
in before use and out after use. A picture of the equipment is acquired at login and logout. Also contains support for
an external screen wich shows the currently logged in user.
Turbo pump controler Logs and controls Pfeiffer turbo pumps. A number of important parameters are shown in a
terminal and the values are also availble as live sockets.
1.1.6 Misc.
Besides from the items listed above PyExpLabSys contains a number of little helpers. The PyExpLabSys.
common.utilities (code, doc) module contains a convenience function to get a logger, that is configured that
way that we prefer, including email notification of anything warning level or above.
We love Python 3. Unfortunately we are not hired to make software, but to keep a lab running. This means that
modules are only ported to Python 3, when it is either convinient or we are touching the code anyway.
6 Chapter 1. Overview
PyExpLabSys Documentation, Release 1.5
• This module contains convinience classes for database logging. The classes implement queues to contain the
data before of loading to the database to ensure against network or server problems.
8 Chapter 1. Overview
PyExpLabSys Documentation, Release 1.5
10 Chapter 1. Overview
PyExpLabSys Documentation, Release 1.5
12 Chapter 1. Overview
PyExpLabSys Documentation, Release 1.5
14 Chapter 1. Overview
PyExpLabSys Documentation, Release 1.5
• NO DESCRIPTION
16 Chapter 1. Overview
CHAPTER 2
User Notes
To set up logging of a program, it is possible to simply follow the standard library documentation. However, since
many of the programs that uses PyExpLabSys are programs that runs for extended periods without monitoring, a more
specific logging setup may be required. E.g. one that makes use of email handlers, so be notified by email in case of
errors or warnings.
For that purpose, PyExpLabSys has the get_logger() function in the utilities module that is a convinience
function to set up a logger with one or more of the commonly used log handlers i.e. a terminal handler, a rotating file
handler and email handlers. This may be used to things up and running in a hurry.
utilities.MAIL_HOST = 'my.mail.host'
utilities.WARNING_EMAIL = 'email-address-to-use-in-case-of-warnings@log.com'
utilities.ERROR_EMAIL = 'email-address-to-use-in-case-of-error@log.com'
PyExpLabSys contains quite a few loggers and exposes a few convinience functions in the utilities mod-
ule for listing and activating them. To get a list of loggers that are relevant for the modules that you have im-
17
PyExpLabSys Documentation, Release 1.5
ported, you can use either the get_library_logger_names() function, which will return you a list or the
print_library_logger_names() function, which prints them out:
from PyExpLabSys.common import sockets
from PyExpLabSys.common.utilities import print_library_logger_names
print_library_logger_names()
To activate a logger use the full path of the logger e.g. PyExpLabSys.common.sockets.DataPullSocket
and remembers that the loggers are configured as a tree, so activating PyExpLabSys.common.sockets will
activate all the loggers in that module and activating PyExpLabSys will activate all PyExpLabSys library loggers.
There are now two ways to activate a logger. One is to configure one from scratch, using the path of the logger and the
same options as in get_logger():
from PyExpLabSys.common import sockets
from PyExpLabSys.common.utilities import activate_library_logging
activate_library_logging(
'PyExpLabSys.common.sockets.DateDataPullSocket',
level='debug',
file_log=True,
file_name='socket_log.txt',
)
This would output all log message at debug level to a file called socket_log.txt.
The other way to activate a library logger is to ask it to enherit all the handlers and levels from an existing logger. This
will send all the library log messages to the same destination:
from PyExpLabSys.common.utilities import get_logger, activate_library_logging
from PyExpLabSys.common import sockets
LOG = get_logger('my_program_name')
LOG.info('My program started')
activate_library_logging(
'PyExpLabSys.common.sockets.DateDataPullSocket',
logger_to_inherit_from=LOG,
)
It is still possible, when inheriting from an existing logger, to set a custom level for the library logger, using the level
argument as in the example above.
All I wanted was a banana, but what I got was a gorilla holding a banana
The quote above, is often used to refer to the fact that it can be difficult to use a component from a “framework”
separate from the framework.
PyExpLabSys is not a framework as such, but there are some common elements that are used across different in
principle independent modules. Specifically, most of the drivers in PyExpLabSys will work just fine outside of Py-
ExpLabSys, with a few very minor modifications, by just copying the file to where the driver is to be used. Most of
the drivers make use of just one other PyExpLabSys module that tie it to the package, the supported_versions
module. The only thing that this module does, is to mark the specific driver as working with Python 2, Python 3 or
both, and make a check at run-time of the Python version and possibly output a warning. It can therefore trivially be
removed. To do this, look to lines of code somewhat like this:
and comment them out. The specific function that is imported and called, will vary depending on which versions is
supported, but that should be fairly simple to figure out.
This section documents the common software components at CINF. These are general purpose modules and classes
that does not fit into the any of the other categories like drivers and parsers.
21
PyExpLabSys Documentation, Release 1.5
measurements_table
str – The measurements tables
xy_values_table
str – The x, y values tables
sql_saver
SqlSaver – The SqlSaver used to save points
insert_measurement_query
str – The query used to insert a measurement
insert_point_query
str – The query used to insert a point
insert_batch_query
str – The query used to insert a batch of points
connection
MySQLdb connection – The database connection used to register new measurements
cursor
MySQLdb cursor – The database cursor used to register new measurements
__init__(measurements_table, xy_values_table, username, password, measurement_specs=None)
Initialize local parameters
Parameters
• measurements_table (str) – The name of the measurements table
• xy_values_table (str) – The name of the xy values table
• username (str) – The database username
• passwork (str) – The database password
• measurement_specs (sequence) – A sequence of measurement_codename,
metadata pairs, see below
measurement_specs is used if you want to initialize all the measurements at __init__ time.
You can also do it later with add_measurement(). The expected value is a sequence of
measurement_codename, metadata e.g:
measurement_specs = [
['M2', {'type': 5, 'timestep': 0.1, 'mass_label': 'M2M'}],
['M28', {'type': 5, 'timestep': 0.1, 'mass_label': 'M2M'}],
['M32', {'type': 5, 'timestep': 0.1, 'mass_label': 'M2M'}],
]
As above, the expected metadata is simply a mapping of column names to column values in the
measurements_table.
Per default, the value will be put into the table as is. If it is necessary to do SQL processing on the value,
to make it fit the column type, then the value must be replaced with a CustomColumn instance, whose
arguments are the value and the format/processing string. The format/processing string must contain a
‘%s’ as a placeholder for the value. It could look like this:
measurement_specs = [
['M2', {'type': 5, 'time': CustomColumn(M2_timestamp, 'FROM_UNIXTIME(%s)
˓→')}],
The most common use for this is the one shown above, where the time column is of type timestamp and
the time value (e.g. in M2_timestamp) is a unix timestamp. The unix timestamp is converted to a SQL
timestamp with the FROM_UNIXTIME SQL function.
Note: The SQL timestamp column understand the datetime.datetime type directly, so if the input
timestamp is already on that form, then there is no need to convert it
add_measurement(codename, metadata)
Add a measurement
This is equivalent to forming the entry in the measurements table with the metadata values and saving the
id of this entry locally for use with add_point().
Parameters
• codename (str) – The codename that this measurement should have
• metadata (dict) – The dictionary that holds the information for the measurements
table. See __init__() for details.
save_point(codename, point)
Save a point for a specific codename
Parameters
• codename (str) – The codename for the measurement to add the point to
• point (sequence) – A sequence of x, y
save_points_batch(codename, x_values, y_values, batchsize=1000)
Save a number points for the same codename in batches
Parameters
• codename (str) – The codename for the measurement to save the points for
• x_values (sequence) – A sequence of x values
• y_values (sequence) – A sequence of y values
• batchsize (int) – The number of points to send in the same batch. Defaults to 1000,
see the warning below before changing it
Warning: The batchsize is ultimately limited by the max package size that the MySQL server will
receive. The default is 1MB. Each point amounts to around 60 bytes in the final query. Rounding this
up to 100, means that the limit is ~10000 points. This means that the default of 1000 should be safe
and that if it is changed by the user, expect problems if exceeding the lower 10000ths.
get_unique_values_from_measurements(column)
Return a set of unique column values from the measurements database
This is commonly used in fileparsers to identify the files already uploaded
Parameters column (str) – The column specification to extract values from. This can be
just a column name e.g. “time”, but it is also allowed to contain SQL processing e.g.
UNIX_TIMESTAMP(time). The value of column will be formatted directly into the query.
start()
Start the DataSetSaver
And the underlying SqlSaver.
stop()
Stop the MeasurementSaver
And shut down the underlying SqlSaver instance nicely.
wait_for_queue_to_empty()
Wait for the query queue in the SqlSaver to empty
This purpose of this method is to avoid usgin too much memory when uploading large amount of data.
class PyExpLabSys.common.database_saver.ContinuousDataSaver(continuous_data_table,
username, pass-
word, measure-
ment_codenames=None)
Bases: object
This class saves data to the database for continuous measurements
Continuous measurements are measurements of a single parameters as a function of datetime. The class can
ONLY be used with the new layout of tables for continous data, where there is only one table per setup, as
apposed to the old layout where there was one table per measurement type per setup. The class sends data to the
hostname and database named in HOSTNAME and DATABASE respectively.
__init__(continuous_data_table, username, password, measurement_codenames=None)
Initialize the continous logger
Parameters
• continuous_data_table (str) – The contunuous data table to log data to
• username (str) – The MySQL username
• password (str) – The password for username in the database
• measurement_codenames (sequence) – A sequence of measurement code-
names that this logger will send data to. These codenames can be given
here, to initialize them at the time of initialization or later by the use of the
add_continuous_measurement() method.
Note: The codenames are the ‘official’ codenames defined in the database for contionuous measurements
NOT codenames that can be userdefined
add_continuous_measurement(codename)
Add a continuous measurement codename to this saver
Parameters codename (str) – Codename for the measurement to add
Note: The codenames are the ‘official’ codenames defined in the database for contionuous measurements
NOT codenames that can be userdefined
save_point_now(codename, value)
Save a value and use now (a call to time.time()) as the timestamp
Parameters
• codename (str) – The measurement codename that this point will be saved under
• value (float) – The value to be logged
Returns The Unixtime used
Return type float
save_point(codename, point)
Save a point
Parameters
• codename (str) – The measurement codename that this point will be saved under
• point (sequence) – The point to be saved, as a sequence of 2 floats: (x, y)
start()
Starts the underlying SqlSaver
stop()
Stop the ContiniousDataSaver
And shut down the underlying SqlSaver instance nicely.
class PyExpLabSys.common.database_saver.SqlSaver(username, password, queue=None)
Bases: threading.Thread
The SqlSaver class administers a queue from which it executes SQL queries
Note: In general queries are added to the queue via the enqueue_query() method. If it is desired to add
elements manually, remember that they must be on the form of a (query, query_args) tuple. (These are
the arguments to the execute method on the cursor object)
queue
Queue.Queue – The queue the queries and qeury arguments are stored in. See note below.
commits
int – The number of commits the saver has performed
commit_time
float – The timespan the last commit took
connection
MySQLdb connection – The MySQLdb database connection
cursor
MySQLdb cursor – The MySQLdb database cursor
__init__(username, password, queue=None)
Initialize local variables
Parameters
• username (str) – The username for the MySQL database
• password (str) – The password for the MySQL database
The logger module contains classes that hide some of all the repeated code associated with sending data to the data
base. The main component is the ContinousLogger class, which is used to send continuously logged data to the
data base.
The ContinuousLogger class is meant to do as much of the manual work related to logging a parameter continu-
ously to the database as possible. The main features are:
• Simple single method usage. After the class is instantiated, a single call to enqueue_point() or
enqueue_point_now() is all that is needed to log a point. No manual database query manipulation is
required.
• Resistent to network or database down time. The class implements a queue for the data, from which points
will only be removed if they are successfully handed of to the data base and while it is not possible to hand the
data of, it will be stored in memory.
Warning: The resilience against network downtime has only been tested for the way it will fail if you disable
the network from the machine it is running on. Different kinds of failures may produce different kinds of failure
modes. If you encounter a failure mode that the class did not recover from you should report it as a bug.
Todo: Write that it uses new style database layout and refer to that section.
Usage Example
If code already exists to retrieve the data (e.g. a driver to interface a piece of equipment with), writing a data logger
can be reduced to as little as the following:
db_logger = ContinuousLogger(table='dateplots_dummy',
username='dummy', password='dummy',
measurement_codenames = ['dummy_sine_one'])
db_logger.start()
import time
from PyExpLabSys.common.loggers import ContinuousLogger
This module contains convinience classes for database logging. The classes implement queues to contain the data
before of loading to the database to ensure against network or server problems.
class PyExpLabSys.common.loggers.NoneResponse
__init__()
PyExpLabSys.common.loggers.NONE_RESPONSE = <PyExpLabSys.common.loggers.NoneResponse instanc
Module variable used to indicate a none response, currently is an instance if NoneResponse
class PyExpLabSys.common.loggers.InterruptableThread(cursor, query)
Bases: threading.Thread
Class to run a MySQL query with a time out
__init__(cursor, query)
run()
Start the thread
Returns
(tuple or NONE_RESPONSE): A tuple of results from the query or NONE_RESPONSE if the query
timed out
stop()
Stop the thread
run()
Start the thread. Must be run before points are added.
enqueue_point_now(codename, value)
Add a point to the queue and use the current time as the time
Parameters
• codename (str) – The measurement codename that this point will be saved under
• value (float) – The value to be logged
Returns The Unixtime used
Return type float
enqueue_point(codename, point)
Add a point to the queue
Parameters
• codename (str) – The measurement codename that this point will be saved under
• point (iterable) – Current point as a list (or tuple) of 2 floats: [x, y]
The DataLogger is a general purpose plotter that is suitable for plotting data sets as they are being gathered. The
data logger uses the qwt backend, though the class QwtPlot, that forms the plot by means of the PyQwt library.
Usage Example
import sys
import time
import random
import numpy as np
from PyQt4 import Qt, QtGui, QtCore
from PyExpLabSys.common.plotters import DataPlotter
class TestApp(QtGui.QWidget):
"""Test Qt application"""
def __init__(self):
super(TestApp, self).__init__()
# Form plotnames
self.plots_l = ['signal1', 'signal2']
self.plots_r = ['aux_signal1']
self.plotter = DataPlotter(
self.plots_l, right_plotlist=self.plots_r, parent=self,
hbox = QtGui.QHBoxLayout()
hbox.addWidget(self.plotter.plot)
self.setLayout(hbox)
self.setGeometry(5, 5, 500, 500)
self.start = time.time()
QtCore.QTimer.singleShot(10, self.main)
def main(self):
"""Simulate gathering one set of points and adding them to plot"""
elapsed = time.time() - self.start
value = (np.sin(elapsed) + 1.1) * 1E-9
self.plotter.add_point('signal1', (elapsed, value))
value = (np.cos(elapsed) + 1.1) * 1E-8
self.plotter.add_point('signal2', (elapsed, value))
value = elapsed + random.random()
self.plotter.add_point('aux_signal1', (elapsed, value))
QtCore.QTimer.singleShot(100, self.main)
def main():
"""Main method"""
app = Qt.QApplication(sys.argv)
testapp = TestApp()
testapp.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
plotters module
This module contains plotters for experimental data gathering applications. It contains a plotter for data sets.
class PyExpLabSys.common.plotters.DataPlotter(left_plotlist, right_plotlist=None,
left_log=False, right_log=False,
auto_update=True, backend=’qwt’,
parent=None, **kwargs)
Bases: object
This class provides a data plotter for continuous data
__init__(left_plotlist, right_plotlist=None, left_log=False, right_log=False, auto_update=True,
backend=’qwt’, parent=None, **kwargs)
Initialize the plotting backend, data and local setting
Parameters
• left_plotlist (iterable with strs) – Codenames for the plots that should go
on the left y-axis
• right_plotlist – Codenames for the plots that should go in the right y-axis
data
Get and set the data
plot
Get the plot
class PyExpLabSys.common.plotters.ContinuousPlotter(left_plotlist, right_plotlist=None,
left_log=False, right_log=False,
timespan=600, preload=60,
auto_update=True, back-
end=’none’, **kwargs)
Bases: object
This class provides a data plotter for continuous data
__init__(left_plotlist, right_plotlist=None, left_log=False, right_log=False, timespan=600,
preload=60, auto_update=True, backend=’none’, **kwargs)
Initialize the plotting backend, data and local setting
Parameters
• left_plotlist (iterable with strs) – Codenames for the plots that should go
on the left y-axis
• right_plotlist – Codenames for the plots that should go in the right y-axis
• left_log (bool) – Left y-axis should be log
• right_log (bool) – Right y-axis should be log
• timespan (int) – Numbers of seconds to show in the plot
• preload (int) – Number of seconds to jump ahead when reaching edge of plot
• auto_update (bool) – Whether all data actions should trigger a update
• backend (str) – The plotting backend to use. Current only option is ‘none’
Kwargs
TODO
add_point_now(plot, value, update=None)
Add a point to a plot using now as the time
Parameters
• plot (str) – The codename for the plot
• value (numpy.float) – The value to add
• update – Whether a update should be performed after adding the point. If set, this value
will over write the auto_update value
Returns plot content or None
add_point(plot, point, update=None)
Add a point to a plot
Parameters
• plot (str) – The codename for the plot
• point (Iterable with unix time and value as two numpy.float) –
The point to add
• update – Whether a update should be performed after adding the point. If set, this value
will over write the auto_update value
Returns plot content or None
update()
Update the plot and possible return the content
data
Get and set the data
plot
Get the plot
plotters_backend_qwt
This module contains plotting backends that use the PyQwt library
class PyExpLabSys.common.plotters_backend_qwt.Colors
Class that gives plot colors
__init__()
get_color()
Return a color
class PyExpLabSys.common.plotters_backend_qwt.QwtPlot(parent, left_plotlist,
right_plotlist=None,
left_log=False,
right_log=False, **kwargs)
Bases: list
Class that represents a Qwt plot
__init__(parent, left_plotlist, right_plotlist=None, left_log=False, right_log=False, **kwargs)
Initialize the plot and local setting
Parameters
• parent (GUI object) – The parent GUI object, then that should be supplied here
• left_plotlist (iterable with strs) – Codenames for the plots that should go
on the left y-axis
• right_plotlist – Codenames for the plots that should go in the right y-axis
• left_log (bool) – Left y-axis should be log
• right_log (bool) – Right y-axis should be log
Kwargs:
Parameters
• title (str) – The title of the plot
• xaxis_label (str) – Label for the x axis
• yaxis_left_label (str) – Label for the left y axis
• yaxis_right_label (str) – Label for the right y axis
• left_labels (iterable with strs) – Labels for the plots on the left y-axis. If
none are given the codenames will be used.
• right_labels (iterable with strs) – Labels for the plots on the right y-axis.
If none are given the codenames will be used.
• legend (str) – Position of the legend. Possible values are: ‘left’, ‘right’, ‘bottom’,
‘top’. If no argument is given, the legend will not be shown.
• left_colors (iterable of strs) – Colors for the left curves (see back-
ground_color for details)
• right_colors (iterable of strs) – Colors for the right curves (see back-
ground_color for details)
• left_thickness (int or iterable of ints) – Line thickness. Either an in-
teger to apply for all left lines or a iterable of integers, one for each line.
• right_thickness (int or iterable of ints) – Line thickness. Either an
integer to apply for all right lines or a iterable of integers, one for each line.
• background_color (str) – The name in a str (as understood by QtGui.QColor(), see
Colors section for possible values) or a string with a hex value e.g. ‘#101010’ that should
be used as the background color.
update(data)
Update the plot with new values and possibly move the xaxis
Parameters data (dict) – The data to plot. Should be a dict, where keys are plot code names
and values are data series as an iterable of (x, y) iterables. E.g. {‘plot1’: [(1, 1), (2, 2)]}
Colors
The data sockets are convenience classes that make it easier to send data back and forth between machines. All the
data sockets are socket servers, i.e. they handle requests, and to interact with them it is necessary to work as a client.
The main purpose of these sockets is to hide the complexity and present a easy-to-use interface while performing e.g.
error checking in the background.
The sockets are divided into push and pull sockets, which are intended to either pull data from or pushing data to.
The main advantages of the pull sockets are:
• Simple usage: After e.g. the DateDataPullSocket or DataPullSocket class is instantiated, a single
call to the set_point method is all that is needed to make a point available via the socket.
• Codename based: After instantiation, the different data slots are referred to by codenames. This makes code
easier to read and help to prevent e.g. indexing errors.
• Timeout safety to prevent serving obsolete data: The class can be instantiated with a timeout for each mea-
surement type. If the available point is too old an error message will be served.
The main advantages of the push socket are:
• Simple usage: If all that is required is to receive data in a variable like manner, both the last and the updated
variable values can be accessed via the DataPushSocket.last and DataPushSocket.updated prop-
erties.
• Flexible: The DataPushSocket offers a lot of functionality around what actions are performed when a data
set is received, including enqueue it or calling a callback function with the data set as an argument.
Table of Contents
3.4.1 Examples
In the following examples it is assumed, that all other code that is needed, such as e.g. an equipment driver, already
exists, and the places where such code is needed, is filled in with dummy code.
Making data available on the network for pulling can be achieved with:
# Create a data socket with timeouts and start the socket server
name = 'Last shot usage data from the giant laser on the moon'
codenames = ['moon_laser_power', 'moon_laser_duration']
moon_socket = DateDataPullSocket(name, codenames, timeouts=[1.0, 0.7])
moon_socket.start()
try:
while True:
power, duration = laser.get_values()
# To set a variable use its codename
moon_socket.set_point_now('moon_laser_power', power)
moon_socket.set_point_now('moon_laser_duration', duration)
except KeyboardInterrupt:
# Stop the socket server
moon_socket.stop()
try:
while True:
now = time.time()
power, duration = driver.get_values()
moon_socket.set_point('moon_laser_power', (now, power))
moon_socket.set_point('moon_laser_duration', (now, duration))
except KeyboardInterrupt:
# Stop the socket server
moon_socket.stop()
A few things to note from the examples. The port number used for the socket is 9000, which is the default for this
type is socket (see Port defaults). The two measurements have been setup to have different timeouts (maximum ages),
which is in seconds by the way, but it could also be set up to be the same, and if it is the same, it can be supplied as just
one float timeouts=0.7 instead of a list of floats. For the sockets, the codenames should be kept relatively short,
but for data safety reasons, they should contain an unambiguous reference to the setup, i.e. the ‘moon_laser’ part.
Client side
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# hostname can something like 'rasppi250', if that happens to be the one
# located on the moon
host_port = ('moon_raspberry_pi', 9000)
With the initialization of the client as above, it is now possible to send the socket different commands and get appro-
priate responses. In the following, the different commands are listed, along with how to send it, receive (and decode)
the reply.
Used to get the name of the socket server, which can be used to make sure that data is being pulled from the correct
location:
command = 'name'
sock.sendto(command, host_port)
data = sock.recv(2048)
at which point the data variable, which contains the reply, will contain the string 'Last shot usage data
from the giant laser on the moon'.
Tip: The ‘wn’ suffix is short for ‘with names’ and is used for all the sockets to indicate that data is sent or received
prefixed with names of the particular data channel
This command is used to get all the latest data encoded as json. It will retrieve all the data as a dictionary where the
keys are the names, encoded as json for transport:
import json
command = 'json_wn'
sock.sendto(command, host_port)
data = json.loads(sock.recv(2048))
at which point the data variable will contain a dict like this one:
It is also possible to decouple the codenames. A possible use case might be to produce a plot of the data. In such a
case, the names are really only needed when setting up the plot, and then afterwards the data should just arrive in the
same order, to add points to the graph. This is exactly what these two command do:
import json
# Sent repeatedly
command = 'json'
sock.sendto(command, host_port)
data = json.loads(sock.recv(2048))
and the data variable would contain a list of points, returned in the same order as the codenames:
[[1414150538.551638, 47.0], [1414150538.551662, 42.0]]
Note: The codename in the command should be substituted with an actual codename
At which point the data variable would contains just a single point as a list:
[1414151366.400581, 47.0]
These commands do exactly the same as their json counterparts, only that the data is not encoded as json, but with
the homemade raw encoding.
Warning: The raw encoding is manually serialized, which is an 100% guarantied error prone approach, so use
the json variant whenever possible. Even Labview® to some extent supports json as of version 2013.
Remember that when receiving data in the raw encoding, it should not be json decoded, so the code to work with these
commands will look like this:
There format if the raw encoding is documented in the API documentation for the PullUDPHandler.handle()
method.
Below are a simple list of each type of raw command and example out:
command = 'raw_wn'
# Output
'moon_laser_power:1414154338.17,47.0;moon_laser_duration:1414154338.17,42.0'
command = 'codenames_raw'
# Output
'moon_laser_power,moon_laser_duration'
command = 'raw'
# Output
'1414154433.4,47.0;1414154433.4,42.0'
command = 'moon_laser_power#raw'
# Output
'1414154485.08,47.0'
To receive data on a machine, the DataPushSocket can be used. To set it up simply to be able to see the last
received data and the updated total data, set it up like this:
After settings this up, the last received data set will be available as a tuple in the DataPushSocket.last property,
where the first value is the Unix timestamp of reception and the second value is a dictionary with the last received
data (all data sent to the DataPushSocket is in dictionary form, see PushUDPHandler.handle() for details).
Alternatively, the DataPushSocket.updated property contains the last value received ever for each key in the
dict (i.e. not only in the last transmission).
Command examples
The socket server understands commands in two formats, a json and a raw encoded one. For details about how to
send commands to a socket server and receive the reply in the two different encodings, see the sections Client side and
Command and data examples from the DateDataPullSocket make data available (network variable) section.
The json commands looks like this:
After the first command the data values in both the DataPushSocket.last and the DataPushSocket.
updated properties are:
After the second command the value in the DataPushSocket.last property is:
{u'number': 42}
The commands can also be raw encoded, in which case the commands above will be:
Upon receipt, the socket server will make a message available on the socket, that contains a status for the receipt and
a copy of the data it has gathered (in simple Python string representation). I will look like this:
If it does not understand the data, e.g. if it is handed badly formatted raw data, it will return an error:
Sending: "raw_wn#number:88"
Will return: "ERROR#The data part 'number:88' did not match the expected format of 3
˓→parts divided by ':'"
Sending: "raw_wn#number:floats:88"
Will return: "ERROR#The data type 'floats' is unknown. Only ['int', 'float', 'bool',
˓→'str'] are allowed"
To receive data and make sure that each and every point is reacted to, it is possible to ask the socket to enqueue the
data. It is set up in the following manner:
As seen above, the queue that holds the data items, is available as the DataPushSocket.queue attribute. Data
can be pulled out by calling get() on the queue. NOTE: The for-loop only gets all the data that was available at the
time of calling qsize(), so if the actions inside the for loop takes time, it is possible that new data will be enqueued
while the for-loop is running, which it will not pull out.
If it is desired to use an existing queue or to set up a queue with other than default settings, the DataPushSocket
can be instantiated with a custom queue.
Command examples
Examples of commands that can be sent are the same as in the code example above, after which the queue would end
up containing the two dictionaries:
With the DataPushSocket it is also possible to ask the socket to call a callback function on data reception:
# Module variables
STATE = 'idle'
STOP = False
def callback_func(data):
"""Callback function for the socket"""
print 'Received: {}'.format(data)
#... do fancy stuff depending on the data, e.g. adjust laser settings
# or fire (may change STATE)
In this examples, the data for the callbacks (and therefore the callbacks themselves) will be queued up and happen
asynchronously. This makes it possible to send a batch of commands without waiting, but there is no monitoring of
whether the queue is filled faster than it can be emptied. It can of course be checked by the user, but if there is a need
for functionality in which the sockets make such checks itself and rejects data if there is too much in queue, then talk
to the development team about it.
Command examples
Command examples this kind of socket will as always be dicts, but in this case will likely have to contain some
information about which action to perform or method to call, but that is entirely up to the user, since that is implemented
by the user in the call back function. Some examples could be:
DataPushSocket, control class and send return values back (callback with return)
class LaserControl(object):
"""Class that controls the giant laser laser on the moon"""
def __init__(self):
self.settings = {'power': 100, 'focus': 100, 'target': None}
self._state = 'idle'
# Start socket
name = 'Laser control, callback socket, for giant laser on the moon'
self.dps = DataPushSocket(name, action='callback_direct',
callback=self.callback)
self.dps.start()
self.stop = False
# Assume one of the methods can set stop
while not self.stop:
# Do continuous stuff on command
time.sleep(1)
self.dps.stop()
This socket would then be sent commands in the form of json encoded dicts from an UDP client in the secret lair.
These dicts could look like:
which would, respectively, make the update_settings method be called with the arguments power=300,
focus=10 and the state method be called with the argument state='active'. NOTE: In this implemen-
tation, it is the responsibility of the caller that the method name exists and that the arguments that are sent have the
correct names. An alternative, but less flexible, way to do the same, would be to make an if-elif-else structure on the
method name and format the arguments in manually:
return out
The complete and running example of both server and client for this example can be downloaded in these two files:
server, client.
Command examples
See the attached files with example code for command examples.
To make for easier configuration on both ends of the network communication, the different kinds of sockets each have
their own default port. They are as follows:
Again, to ease configuration also on the client side, if more than one socket of the same kind is needed on one machine,
then it is recommended to simply add 1 to the port number for each additional socket.
3.4.3 Inheritance
The DateDataPullSocket and DataPullSocket classes inherit common functionality, such as;
• Input checks
• Initialization of DATA
• Methods to start and stop the thread and reset DATA
from the CommonDataPullSocket class, as illustrated in the diagram below.
PyExpLabSys.common.sockets.PullUDPHandler
SocketServer.BaseRequestHandler
PyExpLabSys.common.sockets.PushUDPHandler
PyExpLabSys.common.sockets.PortStillReserved
PyExpLabSys.common.sockets.LiveSocket PyExpLabSys.common.sockets.CallBackThread
PyExpLabSys.common.sockets.DataPullSocket
threading.Thread PyExpLabSys.common.sockets.CommonDataPullSocket
PyExpLabSys.common.sockets.DateDataPullSocket
PyExpLabSys.common.sockets.DataPushSocket
All 4 socket servers understand the status command. This command will return some information about the status
of the machine the socket server is running on and the status of all socket servers running on this machine. The reason
the command returns the status for all the socket servers running on the machine is, that what this command is really
meant for, is to get the status of the system and so it should not be necessary to communicate with several socket
servers to get that.
The data returned is a json encoded dictionary, which looks like this:
{u'socket_server_status':
{u'8000': {u'name': u'my_live_socket',
u'since_last_activity': 0.0009279251098632812,
u'status': u'OK',
u'type': u'live'},
u'9000': {u'name': u'my_socket',
u'since_last_activity': 0.0011229515075683594,
u'status': u'OK',
u'type': u'date'}},
u'system_status':
{u'filesystem_usage': {u'free_bytes': 279182213120,
u'total_bytes': 309502345216},
u'last_apt_cache_change_unixtime': 1413984912.529932,
u'last_git_fetch_unixtime': 1413978995.4109764,
u'load_average': {u'15m': 0.14, u'1m': 0.1, u'5m': 0.15},
u'max_python_mem_usage_bytes': 37552128,
u'number_of_python_threads': 3,
u'uptime': {u'idle_sec': 321665.77,
u'uptime_sec': 190733.39}}}
The socket servers status is broken down into one dictionary for each socket server, indexed by their ports. The status
for the individual socket server comprise of the following items:
name (str) The name of the socket server
since_last_activity (float) The number of seconds since last activity on the socket server
status (str) The status of the socket server. It will return either 'OK' if the last activity was newer than
the activity timeout, or 'INACTIVE' if the last activity was older than the activity timeout or
'DISABLED' is activity monitoring is disabled for the socket server.
type The type of the socket server
System status
The system status items depends on the operating system the socket server is running on.
last_git_fetch_unixtime (float) The Unix timestamp of the last git fetch of the ‘origin’ remote, which
points at the Github archive
max_python_mem_usage_bytes (int) The maximum memory usage of Python in bytes
number_of_python_threads (int) The number of Python threads in use
uptime (dict) Information about system uptime (from /proc/uptime). The value 'uptime_sec'
contains the system uptime in seconds and the value 'idle_sec' contains the idle time in seconds.
NOTE: While the uptime is measured in wall time, the idle time is measured in CPU time, which
means that if the system is multi-core, it will add up idle time for all the cores.
last_apt_cache_change_unixtime (float) The Unix time stamp of the last change to the apt cache, which
should be a fair approximation to the last time the system was updated
load_average(dict) The load average (roughly number of active processes) over the last 1, 5 and 15
minutes (from /proc/loadavg). For a detailed explanation see the /proc/loadavg section from
the proc man-page
filesystem_usage (dict) The number of total and free bytes for the file-system the PyExpLabSys archive
is located on
The sockets module contains various implementations of UDP socket servers (at present 4 in total) for transmission of
data over the network. The different implementations are tailored for a specific purposes, as described below.
In general, there is a distinction in the naming of the different socket server implementation between push socket
servers, that you can push data to, and pull socket servers, that you can pull data from.
Presently the module contains the following socket servers:
• DateDataPullSocket (DateDataPullSocket) This socket server is used to make continuous data (i.e. one-
value data as function of time) available on the network. It identifies different data channels by codenames and
has a timeout functionality to prevent serving old data to the client.
• DataPullSocket (DataPullSocket) This socket is similar to the date data server, but is used to make x, y
type data available on the network. It identifies different data channel by codenames and has timeout function-
ality to prevent serving old data.
• DataPushSocket (DataPushSocket) This socket is used to recieve data from the network. The data is
received in dictionary form and it identifies the data channels by codenames (keys) in the dictionaries. It will
save the last point, and the last value for each codename. It also has the option to, for each received data set,
to put them in a queue (that the user can then empty) or to call a callback function with the received data as en
argument.
• LiveSocket (LiveSocket) This socket is used only for serving data to the live socket server. It also is not
actually a socket server like the others, but it has a similar interface.
Note: The module variable DATA is a dict shared for all socket servers started from this module. It contains all the
data, queues, settings etc. It can be a good place to look if, to get a behind the scenes look at what is happening.
PyExpLabSys.common.sockets.bool_translate(string)
Returns boolean value from strings ‘True’ or ‘False’
PyExpLabSys.common.sockets.socket_server_status()
Returns the status of all socket servers
Returns
Dict with port to status dict mapping. The status dict has the following keys: name, type,
status (with str values) and since_last_activity with float value.
Return type dict
class PyExpLabSys.common.sockets.PullUDPHandler(request, client_address, server)
Bases: SocketServer.BaseRequestHandler
Request handler for the DateDataPullSocket and DateDataPullSocket socket servers. The com-
mands this request handler understands are documented in the handle() method.
handle()
Returns data corresponding to the request
The handler understands the following commands:
COMMANDS
• raw (str): Returns all values on the form x1,y1;x2,y2 in the order the codenames was given to
the DateDataPullSocket.__init__() or DataPullSocket.__init__() method
• json (str): Return all values as a list of points (which in themselves are lists) e.g: [[x1, y1],
[x2, y2]]), contained in a json string. The order is the same as in raw.
• raw_wn (str): (wn = with names) Same as raw but with names, e.g. codenam1:x1,y1;
codename2:x2,y2. The order is the same as in raw.
• json_wn (str): (wn = with names) Return all data as a dict contained in a json string. In the dict
the keys are the codenames.
• codename#raw (str): Return the value for codename on the form x,y
• codename#json (str): Return the value for codename as a list (e.g [x1, y1]) contained in a json
string
Note: Closing the server and deleting the socket server instance is necessary to free up the port for other
usage
poke()
Pokes the socket server to let it know that there is activity
class PyExpLabSys.common.sockets.DataPullSocket(name, codenames, port=9010, de-
fault_x=0.0, default_y=0.0, time-
outs=None, check_activity=True,
activity_timeout=900,
poke_on_set=True)
Bases: PyExpLabSys.common.sockets.CommonDataPullSocket
This class implements a UDP socket server for serving x, y type data. The UDP server uses the
PullUDPHandler class to handle the UDP requests. The commands that can be used with this socket server
are documented in the PullUDPHandler.handle() method.
__init__(name, codenames, port=9010, default_x=0.0, default_y=0.0, timeouts=None,
check_activity=True, activity_timeout=900, poke_on_set=True)
Initializes internal variables and UPD server
For parameter description of name, codenames, port, default_x, default_y, timeouts,
check_activity and activity_timeout see CommonDataPullSocket.__init__().
Parameters poke_on_set (bool) – Whether to poke the socket server when a point is set,
to let it know there is activity
set_point(codename, point, timestamp=None)
Sets the current point for codename
Parameters
• codename (str) – Name for the measurement whose current point should be set
• value (iterable) – Current point as a list or tuple of 2 floats: [x, y]
• timestamp (float) – A unix timestamp that indicates when the point was measured.
If it is not set, it is assumed to be now. This value is used to evaluate if the point is new
enough if timeouts are set.
class PyExpLabSys.common.sockets.DateDataPullSocket(name, codenames, port=9000,
default_x=0.0, de-
fault_y=0.0, timeouts=None,
check_activity=True,
activity_timeout=900,
poke_on_set=True)
Bases: PyExpLabSys.common.sockets.CommonDataPullSocket
This class implements a UDP socket server for serving data as a function of time. The UDP server uses the
PullUDPHandler class to handle the UDP requests. The commands that can be used with this socket server
are documented in the PullUDPHandler.handle() method.
– 'string' in which the string representation of the value the call back returns will be
sent back. NOTE: These string representations may differ between Python 2 and 3, so
do not parse them
run()
Starts the UPD socket server
stop()
Stops the UDP socket server
Note: Closing the server and deleting the SocketServer.UDPServer socket instance is necessary
to free up the port for other usage
queue
Gets the queue, returns None if action is 'store_last' or 'callback_direct'
last
Gets a copy of the last data
Returns
tuple: (last_data_time, last_data) where last_data is the data from the last recep-
tion and last_data_time is the Unix timestamp of that reception. Returns (None, None)
if no data has been recieved.
updated
Gets a copy of the updated total data, returns empty dict if no data has been received yet
Returns
(updated_data_time, updated_data) where updated_data is the total up-
dated data after the last reception and updated_data_time is the Unix timestamp
of that reception. Returns (None, {}) if no data has been recieved.
Return type tuple
set_last_to_none()
Sets the last data point and last data point time to None
clear_updated()
Clears the total updated data and set the time of last update to None
poke()
Pokes the socket server to let it know that there is activity
class PyExpLabSys.common.sockets.CallBackThread(queue, callback)
Bases: threading.Thread
Class to handle the calling back for a DataReceiveSocket
__init__(queue, callback)
Initialize the local variables
Parameters
• queue (Queue.Queue) – The queue that queues up the arguments for the callback
function
• callback (callable) – The callable that will be called when there are items in the
queue
run()
Starts the calling back
stop()
Stops the calling back
exception PyExpLabSys.common.sockets.PortStillReserved
Bases: exceptions.Exception
Custom exception to explain socket server port still reserved even after closing the port
__init__()
class PyExpLabSys.common.sockets.LiveSocket(name, codenames, live_server=None,
no_internal_data_pull_socket=False, inter-
nal_data_pull_socket_port=8000)
Bases: object
This class implements a Live Socket
As of version 2 LiveSocket there are a few new features to note:
1. There is now support for values of any json-able object. The values can of course only be shown in a graph
if they are numbers, but all other types can be shown in a table.
2. There is now support for generic xy data. Simply use set_point() or set_batch() and give it x, y
values.
__init__(name, codenames, live_server=None, no_internal_data_pull_socket=False, inter-
nal_data_pull_socket_port=8000)
Intialize the LiveSocket
Parameters
• name (str) – The name of the socket
• codenames (sequence) – The codenames for the different data channels on this
LiveSocket
• live_server (sequence) – 2 element sequence of hostname and port for
the live server to connect to. Defaults to (Settings.common_liveserver_host, Set-
tings.common_liveserver_host).
• no_internal_data_pull_socket (bool) – Whether to not open an internal Dat-
aPullSocket. Defaults to False. See note below.
• internal_data_pull_socket_port (int) – Port for the internal DataPull-
Socket. Defaults to 8000. See note below.
Note: In general, any socket should also work as a status socket. But since the new design of the live
socket, it no longers runs a UDP server, as would be required for it to work as a status socket. Therefore,
LiveSocket now internally runs a DataPullSocket on port 8000 (that was the old LiveSocket port) to work
as a status socket. With default setting, everything should work as before.
start()
Starts the internal DataPullSocket
stop()
Stop the internal DataPullSocket
set_batch(data)
Set a batch of points now
Parameters data (dict) – Batch of data on the form {codename1: (x1, y1), codename2: (x2,
y2)}. Note, that for the live socket system, the y values need not be data in the form of a
float, it can also be an int, bool or str. This is done to make it possible to also transmit e.g.
equipment status to the live pages.
Note: All data is sent to the live socket proxy and onwards to the web browser clients as batches, so if the
data is on batch form, might as well send it as such and reduce the number of transmissions.
set_batch_now(data)
Set a batch of point now
Parameters data (dict) – A mapping of codenames to values without times or x-values (see
example below)
The format for data is:
set_point_now(codename, value)
Sets the current value for codename using the current time as x
Parameters
• codename (str) – Name for the measurement whose current value should be set
• value (float, int, bool or str) – value
set_point(codename, point)
Sets the current point for codename
Parameters
• codename (str) – Name for the measurement whose current point should be set
• point (list or tuple) – Current value “point” as a list (or tuple) of items, the first
must be a float, the second can be float, int, bool or str
reset(codenames)
Send the reset signal for codenames
Parameters codenames (list) – List of codenames
PyExpLabSys.common.sockets.BAD_CHARS = [u'#', u',', u';', u':', u'&']
The list of characters that are not allowed in code names
PyExpLabSys.common.sockets.UNKNOWN_COMMAND = u'UNKNOWN_COMMMAND'
The string returned if an unknown command is sent to the socket
PyExpLabSys.common.sockets.OLD_DATA = u'OLD_DATA'
The string used to indicate old or obsoleted data
PyExpLabSys.common.sockets.PUSH_ERROR = u'ERROR'
The answer prefix used when a push failed
PyExpLabSys.common.sockets.PUSH_ACK = u'ACK'
The answer prefix used when a push succeds
PyExpLabSys.common.sockets.PUSH_EXCEP = u'EXCEP'
The answer prefix for when a callback or callback value formatting produces an exception
PyExpLabSys.common.sockets.PUSH_RET = u'RET'
The answer prefix for a callback return value
PyExpLabSys.common.sockets.DATA = {}
The variable used to contain all the data.
The format of the DATA variable is the following. The DATA variable is a dict, where each key is an integer port
number and the value is the data for the socket server on that port. The data for each individual socket server is
always a dict, but the contained values will depend on which kind of socket server it is, Examples below.
For a DateDataPullSocket the dict will resemble this example:
{'action': 'store_last',
'activity': {'activity_timeout': 900,
'check_activity': False,
'last_activity': 1413983209.825681},
'last': None,
'last_time': None,
'name': 'my_push_socket',
'type': 'push',
'updated': {},
'updated_time': None}
This module contains convenience functions for quick setup of common tasks.
Table of Contents
The get_logger() function is a convenience function to setup logging output. It will return a named logger, which
can be used inside programs. The function has the ability to setup logging both to a terminal, to a log file, including
setting up log rotation and for sending out email on log message at warning level or above.
To get a named logger that will output logging information to the terminal and send emails on warnings and above, do
the following:
where the name_of_my_logger should be some descriptive name for what the program/script does e.g. “cof-
fee_machine_count_monitor”.
From the returned LOGGER, information can now be logged via the usual .info(), .warning() methods etc.
To turn logging to the terminal of (and only use the other configured logging handlers), set the optional boolean
terminal_log parameter to False.
The email notification on warnings and above is on-by-default and is controlled by the two optional boolean parameters
email_on_warnings and email_on_errors. It will send emails on logged warnings to the warnings list and
on logged errors (and above) to the error list.
The log will be written to the file name_of_my_logger.log. The file name can be changed via the option
file_name, the same way as the maximum log file size and number of saved backups can be changed, as documented
below.
To also make the logger send en email, containing any un-caught exception, do the following:
def main():
pass # All your main code that might raise exceptions
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass # Shut down code here
except Exception:
LOGGER.exception("Main program failed")
# Possibly shut down code here
raise
Note: The argument to LOGGER.exception is a string, just like all other LOGGER methods. All the exception
information, like the traceback, line number etc., is picked up automatically by the logger. Also note, that the raise
will re-raise the caught exception, to make sure that the program fails like it is supposed to. That it is the caught
exception that is re-raised, is implicit when using raise without arguments in an except clause.
Note: In the example there is a seperate except for the KeyboardInterrupt exception, to make it possible to
use keyboard interrupts to shut the program down, without sending an exception email about it.
This module contains a convenience function for easily setting up a logger with the logging module.
This module uses the following settings from the Settings class:
• util_log_warning_email
• util_log_error_email
• util_log_mail_host
• util_log_max_emails_per_period (defaults to 5)
• util_log_email_throttle_time (defaults to 86400s = 1day)
• util_log_backlog_limit (defaults to 250)
Note: All of these settings are at present read from the settings module at import time, so if it is desired
to modify them at run time, it should be done before import
PyExpLabSys.common.utilities.ERROR_EMAIL = 'FYS-list-CINF-FM@fysik.dtu.dk'
The email list error emails are sent to
PyExpLabSys.common.utilities.MAIL_HOST = 'mail.fysik.dtu.dk'
The email host used to send emails on logged warnings and errors
PyExpLabSys.common.utilities.MAX_EMAILS_PER_PERIOD = 5
The maximum number of emails the logger will send in EMAIL_THROTTLE_TIME
PyExpLabSys.common.utilities.EMAIL_THROTTLE_TIME = 86400
The time period that the numbers of emails will be limited within
PyExpLabSys.common.utilities.EMAIL_BACKLOG_LIMIT = 250
The maximum number of messages in the email backlog that will be sent when the next email is let through
PyExpLabSys.common.utilities.get_logger(name, level=u’INFO’, termi-
nal_log=True, file_log=False,
file_name=None, file_max_bytes=1048576,
file_backup_count=1, email_on_warnings=True,
email_on_errors=True)
Setup and return a program logger
This is meant as a logger to be used in a top level program/script. The logger is set up for with terminal, file and
email handlers if requested.
Parameters
• name (str) – The name of the logger, e.g: ‘my_fancy_program’. Passing in an empty
string will return the root logger. See note below.
• level (str) – The level for the logger. Can be either 'DEBUG', 'INFO', 'WARNING',
'ERROR' or 'CRITICAL'. See logging for details. Default is 'INFO'.
• terminal_log (bool) – If True then logging to a terminal will be activated. Default is
True.
• file_log (bool) – If True then logging to a file, with log rotation, will be activated. If
file_name is not given, then name + '.log' will be used. Default is False.
• file_name (str) – Optional file name to log to
• file_max_size (int) – The maximum size of the log file in bytes. The default is
1048576 (1MB), which corresponds to roughly 10000 lines of log per file.
• file_backup_count (int) – The number of backup logs to keep. The default is 1.
• email_on_warnings (bool) – Whether to send an email to the WARNING_EMAIL
email list if a warning is logged. The default is True.
• email_on_error (bool) – Whether to send en email to the ERROR_EMAIL email list
if an error (or any logging level above) is logged. The default is True.
Returns A logger module with the requested setup
Return type logging.Logger
Note: Passing in the empty string as the name, will return the root logger. That means that all other library
loggers will inherit the level and handlers from this logger, which may potentially result in a lot of output. See
activate_library_logging() for a way to activate the library loggers from PyExpLabSys in a more
controlled manner.
PyExpLabSys.common.utilities.get_library_logger_names()
Return all loggers currently configured in PyExpLabSys
PyExpLabSys.common.utilities.print_library_logger_names()
Nicely printout all loggers currently configured in PyExpLabSys
PyExpLabSys.common.utilities.activate_library_logging(logger_name, log-
ger_to_inherit_from=None,
level=None, termi-
nal_log=True, file_log=False,
file_name=None,
file_max_bytes=1048576,
file_backup_count=1,
email_on_warnings=True,
email_on_errors=True)
Activate logging for a PyExpLabSys library logger
Parameters
• logger_name (str) – The name of the logger to activate, as returned by
get_library_logger_names()
• logger_to_inherit_from (logging.Logger) – (Optional) If this is set, the li-
brary logger will simply share the handlers that are present in this logger. The library to be
activated will also inherit the level from this logger, unless level is set, in which case it
will override. In case neither level nor the level on logger_to_inherit_from is
set, the level will not be changed.
• level (str) – (Optional) See docstring for get_logger(). If
logger_to_inherit_from is not set, it will default to ‘info’.
• terminal_log (bool) – See docstring for get_logger()
• file_log (bool) – See docstring for get_logger()
• file_name (str) – See docstring for get_logger()
• file_max_size (int) – See docstring for get_logger()
• file_backup_count (int) – See docstring for get_logger()
• email_on_warnings (bool) – See docstring for get_logger()
• email_on_error (bool) – See docstring for get_logger()
class PyExpLabSys.common.utilities.CustomSMTPHandler(mailhost, fromaddr, toaddrs,
subject, credentials=None, se-
cure=None)
Bases: logging.handlers.SMTPHandler
PyExpLabSys modified SMTP handler
emit(record)
Custom emit that throttles the number of email sent
getSubject(record)
Returns subject with hostname
class PyExpLabSys.common.utilities.CustomSMTPWarningHandler(mailhost, fromaddr,
toaddrs, subject,
credentials=None,
secure=None)
Bases: PyExpLabSys.common.utilities.CustomSMTPHandler
Custom SMTP handler to emit record only if: warning =< level < error
emit(record)
Custom emit that checks if: warning =< level < error
PyExpLabSys.common.utilities.call_spec_string()
Return the argument names and values of the method or function it was called from as a string
Returns
The argument string, e.g: (name=’hello’, codenames=[‘aa’, ‘bb’], port=8000)
Return type str
The combos are cobinations of other PyExpLabSys components in commonly used configurations. Currently the only
implemented combination are:
• LiveContinuousLogger which combines a LiveSocket with a ContinuousDataSaver and
Table of Contents
* LiveContinuousLogger
– Auto-generated module documentation
3.7.1 Examples
LiveContinuousLogger
This example shows the case of using the combo to log values individually, using the “now” variety of the method
(LiveContinuousLogger.log_point_now()), which uses the time now as the x-value:
from time import sleep
from random import random
from math import sin
for _ in range(10):
# The two sine values here emulate a value to be logged
sine_one = sin(random())
sine_two = sin(random())
combo.log_point_now('dummy_sine_one', sine_one)
combo.log_point_now('dummy_sine_two', sine_two)
sleep(1)
combo.stop()
combo.stop()
Of course, like most of the underlying code, the combo also takes data at batches, as shown in the following example
(using LiveContinuousLogger.log_batch()):
from time import sleep, time
from math import sin, pi
combo.start()
combo.stop()
For the bacthes there is of course also a “now” variety (LiveContinuousLogger.log_batch_now()), which
there is no example for, but the difference is same as for the single point/value.
This module contains socket, database saver and logger heuristic combinations
class PyExpLabSys.combos.LiveContinuousLogger(name, codenames, continu-
ous_data_table, username, pass-
word, time_criteria=None,
absolute_criteria=None,
relative_criteria=None,
live_server_kwargs=None)
Bases: object
A combination of a LiveSocket and a ContinuousDataSaver that also does logging heuristics
FIXME explain the term log
__init__(name, codenames, continuous_data_table, username, password, time_criteria=None, abso-
lute_criteria=None, relative_criteria=None, live_server_kwargs=None)
Initialize local data
Parameters
• name (str) – The name to be used in the sockets
• codenames (sequence) – A sequence of codenames. These codenames are the mea-
surements codenames for the ContinuousDataSaver and they will also be used as
the codenames for the LiveSocket.
• continuous_data_table (str) – The continuous data table to log data to
• username (str) – The MySQL username
• password (str) – The password for username in the database
• time_criteria (float or dict) – (Optional) The time after which a point will
always be saved in the database. Either a single value, which will be used for all co-
denames or a dict of codenames to values. If supplying a dict, each codename must be
present as a key.
• absolute_criteria (float or dict) – (Optional) The absolute value difference
criteria. Either a single value or one for each codename, see time_criteria for details.
Settings for PyExpLabSys component are handled via the Settings class in the settings module.
To use the settings module instantiate a Settings object and access the settings as attributes:
User settings can be modified at run time simply by assigning a new value to the attributes:
>>> settings.util_log_max_emails_per_period = 7
>>> settings.util_log_max_emails_per_period
7
3.8.2 Details
The settings are handled in two layers; defaults and user settings.
The defaults are stored in the PyExpLabSys/defaults.yaml file.
Note: It is not possible to write to a setting that does not have a default
Note: In the defaults, a value of null is used to indicate a settings that must be overwritten by a user setting before
any modules tries to use it.
The user settings are stored in a user editable file. The path used is stored in the settings.USERSETTINGS_PATH
variable. On Linux system the user settings path is ~/.config.PyExpLabSys.user_settings.yaml.
Note: If the value is None, it means that your operating system is not yet supported by the sett ings module. This
should be reported as an issue on Github.
All Settings objects share the same settings, so changes made via one object will be used everywhere, in fact
that is what makes it possible to modify settings at runtime (as shown above). Do however note, that different
modules reads the settings at different points in time. Some will read them when an object from that module
is instantiated and others will read them at module import time. That means, that for some modules it will be
necessary to modify the settings before the rest of the PyExpLabSys modules is imported, in order to be able to modify
them at runtime. At which point in time the settings are read should be stated in the module documentation.
This module contains the modules used for settings for PyExpLabSys
To use the settings module instantiate a Settings object and access the settings as attributes:
The settings in the Settings are formed by 2 layers. The bottom layer are the defaults, that are stored in the
PyExpLabSys/defaults.yaml file. Op top of those are placed the user settings, that originate from the file whose path is
in the settings.USERSETTINGS_PATH variable. The user settings can me modified at run time as opposed to having
to write them to the user settings file before running. This is done simply by writing to the properties on the settings
object:
>>> settings.util_log_max_emails_per_period = 7
>>> settings.util_log_max_emails_per_period
7
All Settings objects share the same settings, so these changes will be used when using other parts of PyExpLabSys
that makes use of one of the settings. Do however note, that different parts of PyExpLabSys use the settings at
different times (instantiate, call etc.) so check with the documentation for each component when the settings needs to
be modified to take effect.
PyExpLabSys.settings.value_str(obj)
Return a object and type str or NOT_SET if obj is None
class PyExpLabSys.settings.Settings
Bases: object
The PyExpLabSys settings object
The settings are available to get and setable on this object as attributes i.e:
The settings are stored as a ChainMap of the defaults and the user settings and this ChainMap object containing
the current state of the settings is shared between all Settings objects.
To get a list of all available settings see the Settings.settings_names attribute. To get a pretty print of
all settings names, types, default values, user setting values (if any) use the Settings.print_settings()
method.
settings = ChainMap({'util_log_warning_email': 'FYS-list-CINF-FM@fysik.dtu.dk', 'util_
The settings ChainMap
settings_names = ['common_sql_reader_password', 'util_log_warning_email', 'util_log_err
The available setting names
__init__()
print_settings()
Pretty print of all default and user settings
PyExpLabSys.settings.main()
Main function used to simple testing
File parsers
File parsers.
Table of Contents
• File parsers
– XML based file formats
This file is used to parse XPS and ISS data from XML files from the SPECS program.
In this file format the spectra (called regions) are containd in region groups inside the files. This structure is mirrored
in the data structure below where classes are provided for the 3 top level objects:
Files -> Region Groups -> Regions
The parser is strict, in the sense that it will throw an exception if it encounters anything it does not understand. To
change this behavior set the EXCEPTION_ON_UNHANDLED module variable to False.
Usage examples
To use the file parse, simply feed the top level data structure a path to a data file and start to use it:
65
PyExpLabSys Documentation, Release 1.5
file_ = SpecsFile('path_to_my_xps_file.xml')
# Access the regions groups by iteration
for region_group in file_:
print '{} regions groups in region group: {}'.format(
len(region_group), region_group.name)
# or by index
region_group = file_[0]
# or by index
region = region_group[0]
# Files also have a useful str representation that shows the hierachi
print file_
Notes
The file format seems to basically be a dump, of a large low level data structure from the implementation language.
With an appropriate mapping of low level data structure types to python types (see details below and in the sim-
ple_convert function), this data structure could have been mapped in its entirety to python types, but in order to
provide a more clear data structure a more object oriented approach has been taken, where the top most level data
structures are implemented as classes. Inside of these classes, the data is parsed into numpy arrays and the remaining
low level data structures are parsed in python data structures with the simple_convert function.
Module Documentation
PyExpLabSys.file_parsers.specs.simple_convert(element)
Converts a XML data structure to pure python types.
Arrays are converted to numpy arrays, wherein the type conversion is:
Besides these types there are a few special elements that have a custom conversion.
• Enum are simply converted into their value, since enums are considered to be a program implementation
detail whose information is not relavant for a data file parser
• Any is skipped and replaced with its content
class PyExpLabSys.file_parsers.specs.SpecsFile(filepath, encoding=None)
Bases: list
This is the top structure for a parsed file which represents a list of RegionGroups
The class contains a ‘filepath’ attribute.
__init__(filepath, encoding=None)
Parse the XML and initialize the internal variables
regions_iter
Returns a iteration over the regions
search_regions_iter(search_term)
Returns an generator of search results for regions by name
Parameters search_term (str) – The term to search for (case sensitively)
Returns An iterator of maching regions
Return type generator
search_regions(search_term)
Returns an list of search results for regions by name
Parameters search_term (str) – The term to search for (case sensitively)
Returns A list of matching regions
Return type list
unix_timestamp
Returns the unix timestamp of the first region
get_analysis_method()
Returns the analysis method of the file
Raises ValueError – If more than one analysis method is used
class PyExpLabSys.file_parsers.specs.RegionGroup(xml)
Bases: list
Class that represents a region group, which consist of a list of regions
The class contains a ‘name’ and and ‘parameters’ attribute.
__init__(xml)
Initializes the region group
Expects to find 3 subelement; the name, regions and parameters. Anything else raises an exception.
Parsing parameters is not supported and therefore logs a warning if there are any.
class PyExpLabSys.file_parsers.specs.Region(xml)
Bases: object
Class that represents a region
The class contains attributes for the items listed in the ‘information_names’ class variable.
Some useful ones are:
• name: The name of the region
• region: Contains information like, dwell_time, analysis_method, scan_delta, excitation_energy etc.
All auxiliary information is also available from the ‘info’ attribute.
__init__(xml)
Parse the XML and initialize internal variables
Parameters xml (xml.etree.ElementTree.Element) – The region XML element
x
Returns the kinetic energy x-values as a Numpy array
x_be
Returns the binding energy x-values as a Numpy array
iter_cycles
Returns a generator of cycles
Each cycle is in itself a generator of lists of scans. To iterate over single scans do:
y_avg_cps
Returns the average counts per second as a Numpy array
unix_timestamp
Returns the unix timestamp of the first cycle
exception PyExpLabSys.file_parsers.specs.NotXPSException
Bases: exceptions.Exception
Exception for trying to interpret non-XPS data as XPS data
Note: This file parser went through a large re-write on ??? which changed the data structures of the resulting objects.
This means that upon upgrading it will be necessary to update code. The re-write was done to fix some serious errors
from the first version, like relying on the Report.TXT file for injections summaries. These are now fetched from the
more ordered CSV files.
class PyExpLabSys.file_parsers.chemstation.CHFile(filepath)
Bases: object
Class that implementats the Agilent .ch file format version 179
Warning: Not all aspects of the file header is understood, so there may and probably is information that is
not parsed. See the method _parse_header_status() for an overview of which parts of the header is
understood.
Note: Although the fundamental storage of the actual data has change, lots of inspiration for the parsing of the
header has been drawn from the parser in the ImportAgilent.m file in the chemplexity/chromatography project
project. All credit for the parts of the header parsing that could be reused goes to the author of that project.
values
numpy.array – The internsity values (y-value) or the spectrum. The unit for the values is given in meta-
data[‘units’]
metadata
dict – The extracted metadata
filepath
str – The filepath this object was loaded from
__init__(filepath)
Instantiate object
Parameters filepath (str) – The path of the data file
times
The time values (x-value) for the data set in minutes
class PyExpLabSys.file_parsers.chemstation.Injection(injection_dirpath,
load_raw_spectra=True,
read_report_txt=True)
Bases: object
The Injection class for the Chemstation data format
Parameters
• injection_dirpath (str) – The path of the directory of this injection
• reports (defaultdict) – Signal -> list_of_report_lines dict. Each report line is dict
of column headers to type converted column content. E.g:
The columns headers are also stored in :attr‘~metadata‘ under the columns key.
• reports_raw (defaultdict) – Same as reports except the content is not type con-
verted.
• metadata (dict) – Dict of metadata
• raw_files (dict) – Mapping of ch_file_name -> CHFile objects
• report_txt (str or None) – The content of the Report.TXT file from the injection
folder is any
__init__(injection_dirpath, load_raw_spectra=True, read_report_txt=True)
Instantiate Injection object
Parameters
• injection_dirpath (str) – The path of the injection directory
• load_raw_spectra (bool) – Whether to load raw spectra or not
• read_report_txt (bool) – Whether to read and save the Report.TXT file
exception PyExpLabSys.file_parsers.chemstation.NoInjections
Bases: exceptions.Exception
Exception raised when there are no injections in the sequence
class PyExpLabSys.file_parsers.chemstation.Sequence(sequence_dir_path)
Bases: object
The Sequence class for the Chemstation data format
Parameters
• injections (list) – List of Injection’s in this sequence
• sequence_dir_path (str) – The path of this sequence directory
• metadata (dict) – Dict of metadata
__init__(sequence_dir_path)
Instantiate object properties
Parameters sequence_dir_path (str) – The path of the sequence
full_sequence_dataset(column_names=None)
Generate peak name specific dataset
This will collect area values for named peaks as a function of time over the different injections.
Parameters column_names (dict) – A dict of the column names needed from the report
lines. The dict should hold the keys: ‘peak_name’, ‘retention_time’ and ‘area’. It defaults to:
column_names = {‘peak_name’: ‘Compound Name’, ‘retention_time’: ‘Retention Timemin’,
‘area’: ‘Area’}
Returns Mapping of signal_and_peak names and the values
Return type dict
PyExpLabSys.file_parsers.chemstation.parse_utf16_string(file_, encod-
ing=u’UTF16’)
Parse a pascal type UTF16 encoded string from a binary file object
Apps
Contents
* A subsection
5.1.1 A Section
A subsection
73
PyExpLabSys Documentation, Release 1.5
74 Chapter 5. Apps
CHAPTER 6
Hardware Drivers
This section documents the hardware drivers developed at CINF. Most of the drivers are for equipment to surface
science such as mass spectrometers and pressure gauges, but there are also some drivers for more general equipment
like temperature read out units.
Note: See some important notes on 64 bit Windows and instruments series in the beginning of the API
documentation.
There is a whole range of potentiostats (VMP2/VMP3, BiStat, VSP, SP-50/SP-150, MGP2, HVP-803, SP-200, SP-
300) that are covered by the same interface and which therefore with very small adjustments could be supported by
this module as well. Currently only the SP-150 is implemented, because that is the only one we have in-house. See
the section Use/Implement a new potentiostat for details.
75
PyExpLabSys Documentation, Release 1.5
This module currently implements the handful of techniques that are used locally (see a complete list at the top of
the module documentation). It does however implement a Technique base class, which does all the hard work of
formatting the technique arguments correctly, which means that writing a adding a new technique is limited to writing
a new class in which it is only required to specify which input arguments the technique takes and which fields it outputs
data.
Inheritance diagram
An inheritance diagram for the instruments and techniques (click the classes to get to their API documentation):
PyExpLabSys.drivers.bio_logic.GeneralPotentiostat PyExpLabSys.drivers.bio_logic.SP150
PyExpLabSys.drivers.bio_logic.CA
PyExpLabSys.drivers.bio_logic.CP
PyExpLabSys.drivers.bio_logic.CV
PyExpLabSys.drivers.bio_logic.Technique PyExpLabSys.drivers.bio_logic.CVA
PyExpLabSys.drivers.bio_logic.MIR
PyExpLabSys.drivers.bio_logic.OCV
PyExpLabSys.drivers.bio_logic.SPEIS
The example below is a complete run-able file demonstrating how to use the module, demonstrated with the OCV
technique.
"""OCV example"""
def run_ocv():
"""Test the OCV technique"""
ip_address = '192.168.0.257' # REPLACE THIS WITH A VALID IP
# Instantiate the instrument and connect to it
sp150 = SP150(ip_address)
sp150.connect()
# Instantiate the technique. Make sure to give values for all the
# arguments where the default values does not fit your purpose. The
# default values can be viewed in the API documentation for the
# technique.
ocv = OCV(rest_time_T=0.2,
record_every_dE=10.0,
record_every_dT=0.01)
time.sleep(0.1)
while True:
# Get the currently available data on channel 0 (only what has
# been gathered since last get_data)
data_out = sp150.get_data(0)
sp150.stop_channel(0)
sp150.disconnect()
if __name__ == '__main__':
run_ocv()
This example covers how most of the techniques would be used. A noticeable exception is the SPEIS technique,
which returns data from two different processes, on two different sets of data fields. It will be necessary to take this
into account, where the data is retrieved along these lines:
while True:
time.sleep(0.1)
data_out = sp150.get_data(0)
if data_out is None:
break
print('step', data_out.step)
else:
print('freq', data_out.freq)
print('abs_Ewe', data_out.abs_Ewe)
print('abs_I', data_out.abs_I)
print('Phase_Zwe', data_out.Phase_Zwe)
print('Ewe', data_out.Ewe)
print('I', data_out.I)
print('abs_Ece', data_out.abs_Ece)
print('abs_Ice', data_out.abs_Ice)
print('Phase_Zce', data_out.Phase_Zce)
print('Ece', data_out.Ece)
# Note, no time datafield, but a t
print('t', data_out.t)
print('Irange', data_out.Irange)
print('step', data_out.step)
For more examples of how to use the other techniques, see the integration test file on Github
External documentation
The full documentation for the EC-Lab Development Package is available from the BioLogic website BioLogic Web-
site and locally at CINF on the wiki.
To use a potentiostat that has not already been implemented, there are basically two options; implement it (3 lines of
code excluding documentation) or use the GeneralPotentiostat class directly.
class SP150(GeneralPotentiostat):
"""Specific driver for the SP-150 potentiostat"""
• Call __init__ from GeneralPotentiostat with the potentiostat type string and forward the address
and EClib_dll_path. The complete list of potentiostat type strings are listed in DEVICE_CODES.
As explained in Implement a new potentiostat, the only thing that is required to use a new potentiostat is to call
GeneralPotentiostat with the appropriate potentiostat type string. As an alternative to implementing the po-
tentiostat in the module, this can of course also be done directly. This example shows e.g. how to get a driver for the
BiStat potentiostat:
from PyExpLabSys.drivers.bio_logic import GeneralPotentiostat
potentiostat = GeneralPotentiostat(
type_='KBIO_DEV_BISTAT',
address='192.168.0.257', # Replace this with a valid IP ;)
EClib_dll_path=None
)
To use a new technique, it will be required to implement it as a new class. This can of course both be done directly
in the module and contributed back upstream or in custom code. The implementation of the OCV technique looks as
follows:
class OCV(Technique):
"""Open Circuit Voltage (OCV) technique class.
* time (float)
* Ewe (float)
* Ece (float) (only wmp3 series hardware)
"""
Args:
rest_time_t (float): The amount of time to rest (s)
record_every_dE (float): Record every dE (V)
record_every_dT (float): Record evergy dT (s)
E_range (str): A string describing the E range to use, see the
:data:`E_RANGES` module variable for possible values
"""
args = (
TechnArg('Rest_time_T', 'single', rest_time_T, '>=', 0),
TechnArg('Record_every_dE', 'single', record_every_dE, '>=', 0),
TechnArg('Record_every_dT', 'single', record_every_dT, '>=', 0),
As it can be seen, the new technique must inherit from Technique. This base class is responsible for bounds
checking of the arguments and for formatting them in the appropriate way before sending them to the potentiostat.
A class variable with a dict named data_fields must be defined, that describes which data fields the technique
makes data available at. See the docstring for Technique for a complete description of what the contents must be.
In the __init__ method, the technique implementation must reflect all the arguments the specification lists for
the technique (in this module, these arguments are made more Pythonic by; changing the names to follow naming
conventions except that symbols are still capital, infer the number of arguments in lists instead of specifically asking
for them and by leaving out arguments that can only have one value). All of the arguments from the specification must
then be put, in order, into the args tuple in the form the TechniqueArgument instances. The specification for the
arguments for the TechniqueArgument is in its docstring.
Then, finally, Technique.__init__() is called via super, with the args and the technique filename (is listed in
the specification) as arguments.
The last thing to do is to add an entry for the technique in the TECHNIQUE_IDENTIFIERS_TO_CLASS dict,
to indicate where the instrument should look, to figure out what the data layout is, when it receives data from this
technique. If the new technique is implemented in stand alone code, this will need to be hacked (see the attached
example).
In this file is a complete (re)implementation of the OCV technique as it would look if it was developed outside
of the module.
This module is a Python implementation of a driver around the EC-lib DLL. It can be used to control at least the
SP-150 potentiostat from Bio-Logic under 32 bit Windows.
Note: If it is desired to run this driver and the EC-lab development DLL on Linux, this can be achieved with Wine.
This will require installing both the EC-lab development package AND Python inside Wine. Getting Python installed
is easiest, if it is a 32 bit Wine environment, so before starting, it is recommended to set such an environment up.
NOTE: In a cursory test, it appears that also EClab itself runs under Wine.
Note: When using the different techniques with the EC-lib DLL, different technique files must be passed to the
library, depending on which series the instrument is in (VMPW series or SP-300 series). However, the definition
of which instruments are in which series was not clear from the specification, so instead it was copied from one of the
examples. The definition used is that if the device id of your instrument (see DEVICE_CODES for the full list of device
ids) is in the SP300SERIES list, then it is regarded as a SP-300 series device. If problems are encountered when
loading the technique, then this might be the issues and it will posible be necessary to customize SP300SERIES.
Note: On 64-bit Windows systems, you should use the EClib64.dll instead of the EClib.dll. If the EC-lab
development package is installed in the default location, this driver will try and load the correct DLL automatically, if
not, the DLL path will need to passed explicitely and the user will need to take 32 vs. 64 bit into account. NOTE: The
relevant 32 vs. 64 bit status is that of Windows, not of Python.
Note: All methods mentioned in the documentation are implemented unless mentioned in the list below:
• (General) BL_GetVolumeSerialNumber (Not implemented)
• (Communications) BL_TestCommSpeed (Not implemented)
• (Communications) BL_GetUSBdeviceinfos (Not implemented)
• (Channel information) BL_GetHardConf (N/A, only available w. SP300 series)
• (Channel information) BL_SetHardConf (N/A, only available w. SP300 series)
• (Technique) BL_UpdateParameters (Not implemented)
• (Start stop) BL_StartChannels (Not implemented)
• (Start stop) BL_StopChannels (Not implemented)
• (Data) BL_GetFCTData (Not implemented)
• (Misc) BL_SetExperimentInfos (Not implemented)
• (Misc) BL_GetExperimentInfos (Not implemented)
• (Misc) BL_SendMsg (Not implemented)
• (Misc) BL_LoadFlash (Not implemented)
Instrument classes:
• GeneralPotentiostat
• SP150
Techniques:
• CA
• CP
• CV
• CVA
• MIR
• OCV
• SPEIS
• Technique
class PyExpLabSys.drivers.bio_logic.DataField(name, type)
Bases: tuple
A named tuple used to defined a return data field for a technique
_asdict()
Return a new OrderedDict which maps field names to their values
classmethod _make(iterable, new=<built-in method __new__ of type object at 0x906d60>,
len=<built-in function len>)
Make a new DataField object from a sequence or iterable
_replace(_self, **kwds)
Return a new DataField object replacing specified fields with new values
name
Alias for field number 0
type
Alias for field number 1
class PyExpLabSys.drivers.bio_logic.TechniqueArgument(label, type, value, check,
check_argument)
Bases: tuple
The TechniqueArgument instance, that are used as args arguments, are named tuples with the following fields
(in order):
• label (str): the argument label mentioned in the specification
• type (str): the type used in the specification (‘bool’, ‘single’ and ‘integer’) and possibly wrap [] around
to indicate an array e.g. [bool]`
• value: The value to be passed, will usually be forwarded from __init__ args
• check (str): The bounds check to perform (if any), possible values are ‘>=’, ‘in’ and ‘in_float_range’
• check_argument: The argument(s) for the bounds check. For ‘in’ should be a float or int, for ‘in’ should
be a sequence and for ‘in_float_range’ should be a tuple of two floats
_asdict()
Return a new OrderedDict which maps field names to their values
classmethod _make(iterable, new=<built-in method __new__ of type object at 0x906d60>,
len=<built-in function len>)
Make a new TechniqueArgument object from a sequence or iterable
_replace(_self, **kwds)
Return a new TechniqueArgument object replacing specified fields with new values
check
Alias for field number 3
check_argument
Alias for field number 4
label
Alias for field number 0
type
Alias for field number 1
value
Alias for field number 2
class PyExpLabSys.drivers.bio_logic.GeneralPotentiostat(type_, address,
EClib_dll_path)
Bases: object
General driver for the potentiostats that can be controlled by the EC-lib DLL
A driver for a specific potentiostat type will inherit from this class.
Raises ECLibError – All regular methods in this class use the EC-lib DLL communications li-
brary to talk with the equipment and they will raise this exception if this library reports an error.
It will not be explicitly mentioned in every single method.
__init__(type_, address, EClib_dll_path)
Initialize the potentiostat driver
Parameters
• type (str) – The device type e.g. ‘KBIO_DEV_SP150’
• address (str) – The address of the instrument, either IP address or USB0, USB1 etc
• EClib_dll_path (str) – The path to the EClib DLL. The default directory of the
DLL is C:EC-Lab Development PackageEC-Lab Development Packageand the filename
is either EClib64.dll or EClib.dll depending on whether the operating system is 64 of 32
Windows respectively. If no value is given the default location will be used and the 32/64
bit status inferred.
Raises WindowsError – If the EClib DLL cannot be found
id_number
Return the device id as an int
device_info
Return the device information.
Returns
The device information as a dict or None if the device is not connected.
Return type dict or None
get_lib_version()
Return the version of the EClib communications library.
Returns The version string for the library
Return type str
get_error_message(error_code)
Return the error message corresponding to error_code
Parameters error_code (int) – The error number to translate
Returns The error message corresponding to error_code
Return type str
connect(timeout=5)
Connect to the instrument and return the device info.
Parameters timeout (int) – The connect timeout
Returns
The device information as a dict or None if the device is not connected.
Return type dict or None
Raises ECLibCustomException – If this class does not match the device type
disconnect()
Disconnect from the device
test_connection()
Test the connection
load_firmware(channels, force_reload=False)
Load the library firmware on the specified channels, if it is not already loaded
Parameters
• channels (list) – List with 1 integer per channel (usually 16), (0=False and 1=True),
that indicates which channels the firmware should be loaded on. NOTE: The length of
the list must correspond to the number of channels supported by the equipment, not the
number of channels installed. In most cases it will be 16.
• force_reload (bool) – If True the firmware is forcefully reloaded, even if it was
already loaded
Returns
List of integers indicating the success of loading the firmware on the specified channel. 0
is success and negative values are errors, whose error message can be retrieved with the
get_error_message method.
Return type list
is_channel_plugged(channel)
Test if the selected channel is plugged.
Parameters channel (int) – Selected channel (0-15 on most devices)
Returns Whether the channel is plugged
Return type bool
get_channels_plugged()
Get information about which channels are plugged.
Returns A list of channel plugged statusses as booleans
Return type (list)
get_channel_infos(channel)
Get information about the specified channel.
Parameters channel (int) – Selected channel, zero based (0-15 on most devices)
Returns
Channel infos dict. The dict is created by conversion from ChannelInfos class (type
ctypes.Structure). See the documentation for that class for a list of available dict
items. Besides the items listed, there are extra items for all the original items whose value
can be converted from an integer code to a string. The keys for those values are suffixed
by (translated).
Return type dict
get_message(channel)
Return a message from the firmware of a channel
load_technique(channel, technique, first=True, last=True)
Load a technique on the specified channel
Parameters
• channel (int) – The number of the channel to load the technique onto
• technique (Technique) – The technique to load
• first (bool) – Whether this technique is the first technique
• last (bool) – Thether this technique is the last technique
Raises ECLibError – On errors from the EClib communications library
get_data(channel)
Get data for the specified channel
Parameters channel (int) – The number of the channel (zero based)
Returns
A KBIOData object or None if no data was available
Return type KBIOData
convert_numeric_into_single(numeric)
Convert a numeric (integer) into a float
The buffer used to get data out of the device consist only of uint32s (most likely to keep its layout simple).
To transfer a float, the EClib library uses a trick, wherein the value of the float is saved as a uint32, by giving
the uint32 the integer values, whose bit-representation corresponds to the float that it should describe. This
function is used to convert the integer back to the corresponding float.
NOTE: This trick can also be performed with ctypes along the lines of: c_float.
from_buffer(c_uint32(numeric)), but in this driver the library version is used.
Parameters numeric (int) – The integer that represents a float
Returns The float value
Return type float
check_eclib_return_code(error_code)
Check a ECLib return code and raise the appropriate exception
class PyExpLabSys.drivers.bio_logic.SP150(address, EClib_dll_path=None)
Bases: PyExpLabSys.drivers.bio_logic.GeneralPotentiostat
Specific driver for the SP-150 potentiostat
__init__(address, EClib_dll_path=None)
Initialize the SP150 potentiostat driver
See the __init__ method for the GeneralPotentiostat class for an explanation of the arguments.
class PyExpLabSys.drivers.bio_logic.KBIOData(c_databuffer, c_data_infos,
c_current_values, instrument)
Bases: object
Class used to represent data obtained with a get_data call
The data can be obtained as lists of floats through attributes on this class. The time is always available through
the ‘time’ attribute. The attribute names for the rest of the data, are the same as their names as listed in the
field_names attribute. E.g:
• kbio_data.Ewe
• kbio_data.I
Provided that numpy is installed, the data can also be obtained as numpy arrays by appending ‘_numpy’ to the
attribute name. E.g:
• kbio_data.Ewe.numpy
• kbio_data.I_numpy
__init__(c_databuffer, c_data_infos, c_current_values, instrument)
Initialize the KBIOData object
Parameters
All of the entries in the dict must point to an list of DataField named tuples, where the two arguments are
the name and the C type of the field (usually c_float or c_uint32). The list of fields must be in the order
the data fields is specified in the specification.
__init__(args, technique_filename)
Initialize a technique
Parameters
• args (tuple) – Tuple of technique arguments as TechniqueArgument instances
• technique_filename (str) – The name of the technique filename.
Note: This must be the vmp3 series version i.e. name.ecc NOT name4.ecc, the replace-
ment of technique file names are taken care of in load technique
c_args(instrument)
Return the arguments struct
Parameters instrument (GeneralPotentiostat) – Instrument instance, should be an
instance of a subclass of GeneralPotentiostat
Returns An ctypes array of TECCParam
Return type array of TECCParam
Raises ECLibCustomException – Where the error codes indicate the following:
• -10000 means that an TechniqueArgument failed the ‘in’ test
• -10001 means that an TechniqueArgument failed the ‘>=’ test
• -10002 means that an TechniqueArgument failed the ‘in_float_range’ test
• -10010 means that it was not possible to find a conversion function for the defined type
• -10011 means that the value cannot be converted with the conversion function
_init_c_args(instrument)
Initialize the arguments struct
Parameters instrument (GeneralPotentiostat) – Instrument instance, should be an
instance of a subclass of GeneralPotentiostat
static _check_arg(arg)
Perform bounds check on a single argument
class PyExpLabSys.drivers.bio_logic.OCV(rest_time_T=10.0, record_every_dE=10.0,
record_every_dT=0.1,
E_range=’KBIO_ERANGE_AUTO’)
Bases: PyExpLabSys.drivers.bio_logic.Technique
Open Circuit Voltage (OCV) technique class.
The OCV technique returns data on fields (in order):
• time (float)
• Ewe (float)
• Ece (float) (only wmp3 series hardware)
data_fields = {'vmp3': [DataField(name='Ewe', type=<class 'ctypes.c_float'>), DataFiel
Data fields definition
E_we
^
| E_1
| /\
| / \
| / \ E_f
| E_i/ \ /
| \ /
| \/
| E_2
+----------------------> t
Parameters
• vs_initial (list) – List (or tuple) of 5 booleans indicating whether the current step
is vs. the initial one
• voltage_step (list) – List (or tuple) of 5 floats (Ei, E1, E2, Ei, Ef) indicating the
voltage steps (V)
• scan_rate (list) – List (or tuple) of 5 floats indicating the scan rates (mV/s)
• record_every_dE (float) – Record every dE (V)
• average_over_dE (bool) – Whether averaging should be performed over dE
• N_cycles (int) – The number of cycles
• begin_measuring_I (float) – Begin step accumulation, 1 is 100%
• end_measuring_I (float) – Begin step accumulation, 1 is 100%
• I_Range (str) – A string describing the I range, see the I_RANGES module variable
for possible values
• E_range (str) – A string describing the E range to use, see the E_RANGES module
variable for possible values
• Bandwidth (str) – A string describing the bandwidth setting, see the BANDWIDTHS
module variable for possible values
Raises ValueError – If vs_initial, voltage_step and scan_rate are not all of length 5
E_we
^
| E_1
| /\
| / \
| / \ E_f_____________
| E_i/ \ /<----------->|
| \ / t_f |_______E_i
| \/ |<----->
| E_2 | t_i
+------------------------------+-------------> t
|
trigger
Parameters
• vs_initial_scan (list) – List (or tuple) of 4 booleans indicating whether the cur-
rent scan is vs. the initial one
• voltage_scan (list) – List (or tuple) of 4 floats (Ei, E1, E2, Ef) indicating the voltage
steps (V) (see diagram above)
• scan_rate (list) – List (or tuple) of 4 floats indicating the scan rates (mV/s)
• record_every_dE (float) – Record every dE (V)
• average_over_dE (bool) – Whether averaging should be performed over dE
• N_cycles (int) – The number of cycles
• begin_measuring_I (float) – Begin step accumulation, 1 is 100%
• end_measuring_I (float) – Begin step accumulation, 1 is 100%
• vs_initial_step (list) – A list (or tuple) of 2 booleans indicating whether this
step is vs. the initial one
• voltage_step (list) – A list (or tuple) of 2 floats indicating the voltage steps (V)
• duration_step (list) – A list (or tuple) of 2 floats indicating the duration of each
step (s)
• record_every_dT (float) – A float indicating the change in time that leads to a
point being recorded (s)
• record_every_dI (float) – A float indicating the change in current that leads to a
point being recorded (A)
• trig_on_off (bool) – A boolean indicating whether to use the trigger
• I_Range (str) – A string describing the I range, see the I_RANGES module variable
for possible values
• E_range (str) – A string describing the E range to use, see the E_RANGES module
variable for possible values
• Bandwidth (str) – A string describing the bandwidth setting, see the BANDWIDTHS
module variable for possible values
Raises ValueError – If vs_initial, voltage_step and scan_rate are not all of length 5
Bases: PyExpLabSys.drivers.bio_logic.Technique
Chrono-Amperometry (CA) technique class.
The CA technique returns data on fields (in order):
• time (float)
• Ewe (float)
• I (float)
• cycle (int)
data_fields = {'common': [DataField(name='Ewe', type=<class 'ctypes.c_float'>), DataFi
Data fields definition
__init__(voltage_step=(0.35, ), vs_initial=(False, ), duration_step=(10.0, ), record_every_dT=0.1,
record_every_dI=5e-06, N_cycles=0, I_range=’KBIO_IRANGE_AUTO’,
E_range=’KBIO_ERANGE_2_5’, bandwidth=’KBIO_BW_5’)
Initialize the CA technique
NOTE: The voltage_step, vs_initial and duration_step must be a list or tuple with the same length.
Parameters
• voltage_step (list) – List (or tuple) of floats indicating the voltage steps (A). See
NOTE above.
• vs_initial (list) – List (or tuple) of booleans indicating whether the current steps
is vs. the initial one. See NOTE above.
• duration_step (list) – List (or tuple) of floats indicating the duration of each step
(s). See NOTE above.
• record_every_dT (float) – Record every dT (s)
• record_every_dI (float) – Record every dI (A)
• N_cycles (int) – The number of times the technique is REPEATED. NOTE: This
means that the default value is 0 which means that the technique will be run once.
• I_Range (str) – A string describing the I range, see the I_RANGES module variable
for possible values
• E_range (str) – A string describing the E range to use, see the E_RANGES module
variable for possible values
• Bandwidth (str) – A string describing the bandwidth setting, see the BANDWIDTHS
module variable for possible values
Raises ValueError – On bad lengths for the list arguments
class PyExpLabSys.drivers.bio_logic.SPEIS(vs_initial, vs_final, initial_voltage_step, fi-
nal_voltage_step, duration_step, step_number,
record_every_dT=0.1, record_every_dI=5e-
06, final_frequency=100000.0, ini-
tial_frequency=100.0, sweep=True, ampli-
tude_voltage=0.1, frequency_number=1,
average_n_times=1, correc-
tion=False, wait_for_steady=1.0,
I_range=’KBIO_IRANGE_AUTO’,
E_range=’KBIO_ERANGE_2_5’, band-
width=’KBIO_BW_5’)
Bases: PyExpLabSys.drivers.bio_logic.Technique
The 4d Systems module at present contains the Picaso Common driver, which at a minimum works for the Picaso
uLCD-28PTU LCD display, but likely will also work for other displays in the same series.
PyExpLabSys.drivers.four_d_systems.PicasoCommon PyExpLabSys.drivers.four_d_systems.PicasouLCD28PTU
Usage Example
import time
from PyExpLabSys.drivers.four_d_systems import PicasouLCD28PTU
# Text example
picaso = PicasouLCD28PTU(serial_device='/dev/ttyUSB0', baudrate=9600)
picaso.clear_screen()
for index in range(5):
picaso.move_cursor(index, index)
picaso.put_string('CINF')
# Touch example
picaso.move_cursor(7, 0)
picaso.put_string('Try and touch me!')
picaso.touch_set('enable')
for _ in range(25):
time.sleep(0.2)
print picaso.touch_get_status()
print picaso.touch_get_coordinates()
picaso.close()
four_d_systems module
Note: Only a small sub-set of the specification is plemented, but with the available examples it should be real easy to
add more commands.
Note: An internal method ‘_to_16_bit_rgb’ exists to convert a HTML hex color code or an RGB tuple of floats to the
irregular 16 bit RGB color scale this device use. It should make working with colors a lot easier.
Note: The displays must be activated for serial communication. At present the only way we know how to do that, is
to follow the procedure described in the serial specification, which involves taking it past a Windows program.
Note: At present only communication via the USB connection has been tested. For communication directly via the
internal connection on the Raspberry Pi it may be necessary to do some preparation in order to free the pins up for
serial communication.
See also:
Docs for this implementation are on the wiki at: https://cinfwiki.fysik.dtu.dk/cinfwiki/Equipment#Picaso_
uLCD-28PTU or online at: http://www.4dsystems.com.au/product/4D_Workshop_4_IDE/downloads
PyExpLabSys.drivers.four_d_systems.to_ascii(string)
Convert non-ascii character in a unicode string to ascii
PyExpLabSys.drivers.four_d_systems.to_ascii_utf8(string)
Convert non-ascii character in a utf-8 encoded string to ascii
class PyExpLabSys.drivers.four_d_systems.PicasoCommon(serial_device=’/dev/ttyUSB0’,
baudrate=9600, de-
bug=False)
Bases: object
Implementation of the common parts of the serial communication to the Picaso devices
Raises serial.serialutil.SerialException - All public methods in this class may raise
this exception if there are problems with the serial communication
__init__(serial_device=’/dev/ttyUSB0’, baudrate=9600, debug=False)
Initialize the driver
The serial device and the baudrate are configurable, as described below. The rest of the serial communi-
cation parameters are; bytesize: 8 bits, parity: None, stopbits: one (as per the manual) and a timeout of 3
seconds.
Parameters
• serial_device (str) – The serial device to open communication on
• baud_rate (int) – The baudrate for the communication
• debug (bool) – Enable a check of whether there are bytes left in waiting after a reply
has been fetched.
close()
Close the serial communication
_send_command(command, reply_length=0)
Send a command and return status and reply
Parameters
• command (str) – The command to send as a hex string e.g. '001B' for 0x001B
• reply_length (int) – The length of the expected reply i.e. WITHOUT an acknowl-
edge
Returns Reply is requested, otherwise None
Return type str
Raises PicasoException – If the command fails or if the reply does not have the requested
length
static _to_16_bit_rgb(color)
Convert a color to the non regular 16 bit RGB.
Parameters
• color (str or tuple) – 24 bit RGB HTML hex string e.g. '#ffffff'
• RGB tuple or floats e.g. `` (or) –
Returns A 2 byte hex string e.g. 'FFFF'
Return type str
static _from_16_bit_rgb(color)
Convert a non regular 16 bit RGB to tuple of float e.g (1.0, 0.0, 1.0)
Parameters color (str) – Color as 16 bit RGB string
Returns Color as tuple of floats e.g. (1.0, 0.0, 1.0)
Return type tuple
move_cursor(line, column)
Move the cursor to line, column and return boolean for success
The actual position in which the cursor is placed is based on the current text parameters such as width and
height
Parameters
• line (int) – The line number to move the cursor to
• column (int) – The column to move the cursor to
Raises PicasoException – If the command fails
put_string(string)
Write a string on the display
Note: It has not been investigated whether characters outside of ASCII can be used. If that becomes
necessary, try, and possibly consult the manual
Parameters string (str) – Ascii string to write, max length 511 chars
Returns The number of bytes written
Return type int
Raises PicasoException – If the command fails or if the reply does not have the expected
length
character_width(character)
Get the width of a character in pixels with the current font
Parameters character (str) – Character to get the width of
Returns The width in pixels
Return type int
Raises PicasoException – If the command fails or if the reply does not have the expected
length
Raises ValueError - If character does not have length 1
character_height(character)
Get the height of a character in pixels with the current font
Parameters character (str) – Character to get the height of
Returns The height in pixels
Return type int
Raises PicasoException – If the command fails or if the reply does not have the expected
length
Raises ValueError - If character does not have length 1
text_foreground_color(color)
Sets the foreground color of the text
Parameters color (tuple or string) – 24 bit RGB HTML hex string e.g. ‘#ffffff’ or
RGB tuple or floats e.g. (1.0, 1.0, 1.0)
Returns Previous color as tuple of floats e.g. (1.0, 1.0, 1.0)
Return type tuple
Raises PicasoException – If the command fails or if the reply does not have the expected
length
text_background_color(color)
Sets the background color of the text
Parameters color (tuple or string) – 24 bit RGB HTML hex string e.g. ‘#ffffff’ or
RGB tuple or floats e.g. (1.0, 1.0, 1.0)
Returns Previous color as tuple of floats e.g. (1.0, 1.0, 1.0)
Return type tuple
Raises PicasoException – If the command fails or if the reply does not have the expected
length
text_width(factor)
Sets the text width
Parameters factor (int) – Width multiplier (1-16) relative to default width
Returns Previous width multiplier
Return type int
Raises PicasoException – If the command fails or if the reply does not have the expected
length
text_height(factor)
Sets the text height
Parameters factor (int) – Height multiplier (1-16) relative to default height
Returns Previous height multiplier
Return type int
Raises PicasoException – If the command fails or if the reply does not have the expected
length
text_factor(factor)
Sets the text width and height
Parameters factor (int) – Width and height multiplier (1-16) relative to default width and
height
Returns Previous width and height multipliers
Return type tuple
Raises PicasoException – If the command fails or if the reply does not have the expected
length
text_x_gap(pixels)
Sets the horizontal gap between chars in pixels
Parameters pixels (int) – The requested horizontal gap in pixels
Returns The previous horizontal gap in pixels
Return type int
Raises PicasoException – If the command fails or if the reply does not have the expected
length
text_y_gap(pixels)
Sets the vertical gap between chars in pixels
Parameters pixels (int) – The requested vertical gap in pixels
Returns The previous vertical gap in pixels
Return type int
Raises PicasoException – If the command fails or if the reply does not have the expected
length
text_attribute(attribute, status=True)
Sets the text attribute status
Parameters
• attribute (str) – The attribute to set, can be one of ‘bold’, ‘inverse’, ‘italic’, ‘opacity’
and ‘underline’ where ‘inverse’ inter changes the back and foreground colors of the text
• status (bool) – Boolean for the text attribute status, where True means ‘on’ or ‘opaque’
in the case of opacity
Returns The previous status
Return type bool
Raises PicasoException – If the command fails or if the reply does not have the expected
length
Raises ValueError - If attribute is unknown
clear_screen()
Clear the screen
Raises PicasoException – If the command fails
draw_line(start, end, color)
Draw a line from x1, y1 to x2, y2 and return boolean for success
Parameters
• start (tuple) – Start point (x, y), where x and y are ints
• end (tuple) – End point (x, y), where x and y are ints
• color (tuple or string) – 24 bit RGB HTML hex string e.g. ‘#ffffff’ or RGB
tuple or floats e.g. (1.0, 1.0, 1.0)
Raises PicasoException – If the command fails
draw_rectangle(top_left, bottom_right, color)
Draw a rectangle
Parameters
• top_left (tuple) – Coordinates of top left corner (x, y)
• bottom_right (tuple) – Coordinates of bottom right corner (x, y)
• color (tuple or string) – 24 bit RGB HTML hex string e.g. ‘#ffffff’ or RGB
tuple or floats e.g. (1.0, 1.0, 1.0)
Raises PicasoException – If the command fails
draw_filled_rectangle(top_left, bottom_right, color)
Draw a filled rectangle
Parameters
• top_left (tuple) – Coordinates of top left corner (x, y)
• bottom_right (tuple) – Coordinates of bottom right corner (x, y)
• color (tuple or string) – 24 bit RGB HTML hex string e.g. ‘#ffffff’ or RGB
tuple or floats e.g. (1.0, 1.0, 1.0)
Raises PicasoException – If the command fails
move_origin(x, y)
Move the origin to a point, forming the basis for the next graphics or text command
Parameters
• x (int) – X-coordinate for the new origin
• y (int) – Y-coordinate for the new origin
Raises PicasoException – If the command fails
screen_mode(mode)
Sets the screen mode
Parameters mode (str) – The mode for the screen. Can be either 'landscape',
'landscape reverse', 'portrait' or 'portrait reverse'
Returns Returns previous screen mode on success or None on failure
Return type str
Raises PicasoException – If the command fails or if the reply does not have the expected
length
get_graphics_parameters(parameter)
Gets graphics parameters
Note: The meaning of the results from the 'last_object_*' parameters is not known. It was
expected to be coordinates, but they are much to large
Parameters
• parameter (str) – The parameter to fetch, can be 'x_max' for
• x resolution under the current orientation, 'y_max' for (the)
–
• y resolution under the current orientation, (the) –
• 'last_object_top', ('last_object_left',) –
• 'last_object_bottom' for the relevant ('last_object_right',) –
• for the last object. (parameter) –
Returns The requested parameter
Return type int
Raises PicasoException – If the command fails or if the reply does not have the expected
length
touch_detect_region(upper_left, bottom_right)
Specify a touch detection region
Parameters
• upper_left (tuple) – (x, y) for the upper left corner, where x and y are ints
• bottom_right (tuple) – (x, y) for the lower right corner, where x and y are ints
Raises PicasoException – If the command fails
touch_set(mode)
Set touch screen related parameters
Parameters
• mode (string) – The mode to set. It can be either 'enable';
• enables and initializes the touch screen, 'disable' (which) –
• disables the touch screen or 'default' which will reset
(which) –
• current active region to the default which is the full
screen (the) –
• area. –
Raises PicasoException – If the command fails
touch_get_status()
Return the state of the touch screen
Returns The state of the touch screen, can be either 'invalid/notouch', 'press',
'release', 'moving' or None on error
Return type str
Raises PicasoException – If the command fails or if the reply does not have the expected
length
touch_get_coordinates()
Return the coordinates of the LAST touch event
Returns (x, y) where x and y are ints
Return type tuple
Raises PicasoException – If the command fails or if the reply does not have the expected
length
get_display_model()
Get the display model
Returns The display model
Return type str
Raises PicasoException – If the command fails or if the reply does not have the expected
length
get_spe_version()
Get the version of the Serial Platform Environment
Returns The version or None on failure
Return type str
Raises PicasoException – If the command fails or if the reply does not have the expected
length
class PyExpLabSys.drivers.four_d_systems.PicasouLCD28PTU(serial_device=’/dev/ttyUSB0’,
baudrate=9600, de-
bug=False)
Bases: PyExpLabSys.drivers.four_d_systems.PicasoCommon
Driver for the Picaso 28 PTU Pi LCD display
For details on the methods that can be called on this class see the documentation for PicasoCommon
__init__(serial_device=’/dev/ttyUSB0’, baudrate=9600, debug=False)
exception PyExpLabSys.drivers.four_d_systems.PicasoException(message, excep-
tion_type)
Bases: exceptions.Exception
Exception for Picaso communication
The exception_type parameter can be either, 'failed' or 'unexpected_reply'
__init__(message, exception_type)
class PyExpLabSys.drivers.four_d_systems.Button(picaso, top_left, bottom_right,
text, text_justify=’center’,
left_justify_indent=None,
text_color=’#000000’, inac-
tive_color=’#B2B2B2’, ac-
tive_color=’#979797’)
Bases: object
Class that represents a button to use in the interface
__init__(picaso, top_left, bottom_right, text, text_justify=’center’, left_justify_indent=None,
text_color=’#000000’, inactive_color=’#B2B2B2’, active_color=’#979797’)
set_position(top_left, bottom_right)
Set position of the button
draw_button(active=False)
Draw button with either its active or inactive background color
The pfeiffer module contains drivers for equipment from Pfeiffer Vacuum. At present the module contains drivers for
the TPG 261 and TPG 262 pressure measurement and control units.
The TPG 261 and TPG 262 has the same communications protocol and therefore the driver has been implemented as
a common driver in the TPG26x class, which the TPG261 and TPG262 classes inherit from, as illustrated below.
PyExpLabSys.drivers.pfeiffer.TPG261
PyExpLabSys.drivers.pfeiffer.TPG26x
PyExpLabSys.drivers.pfeiffer.TPG262
The driver implements only a sub set of the specification, but given that the ground work has already been done, it
should be simple to implement more methods as they are needed.
Usage Example
The driver classes can be instantiated by specifying just the address of the serial communications port the unit is
connected to:
If the baud rate on the TPG 26x unit has been changed away from the default setting of 9600, then the correct baud
rate will need to be given as a parameter.
pfeiffer module
This module contains drivers for the following equipment from Pfeiffer Vacuum:
• TPG 262 and TPG 261 Dual Gauge. Dual-Channel Measurement and Control Unit for Compact Gauges
gauge_identification()
Return the gauge identication
Returns (id_code_1, id_1, id_code_2, id_2)
Return type tuple
pressure_unit()
Return the pressure unit
Returns the pressure unit
Return type str
rs232_communication_test()
RS232 communication test
Returns the status of the communication test
Return type bool
class PyExpLabSys.drivers.pfeiffer.TPG262(port=’/dev/ttyUSB0’, baudrate=9600)
Bases: PyExpLabSys.drivers.pfeiffer.TPG26x
Driver for the TPG 262 dual channel measurement and control unit
__init__(port=’/dev/ttyUSB0’, baudrate=9600)
Initialize internal variables and serial connection
Parameters
• port (str or int) – The COM port to open. See the documentation for pyserial for
an explanation of the possible value. The default value is ‘/dev/ttyUSB0’.
• baudrate (int) – 9600, 19200, 38400 where 9600 is the default
class PyExpLabSys.drivers.pfeiffer.TPG261(port=’/dev/ttyUSB0’, baudrate=9600)
Bases: PyExpLabSys.drivers.pfeiffer.TPG26x
Driver for the TPG 261 dual channel measurement and control unit
__init__(port=’/dev/ttyUSB0’, baudrate=9600)
Initialize internal variables and serial connection
Parameters
• port (str or int) – The COM port to open. See the documentation for pyserial for
an explanation of the possible value. The default value is ‘/dev/ttyUSB0’.
• baudrate (int) – 9600, 19200, 38400 where 9600 is the default
This section documents the hardware drivers developed at CINF. Most of the drivers are for equipment to surface
science such as mass spectrometers and pressure gauges, but there are also some drivers for more general equipment
like temperature read out units.
The drivers in this section only has autogenerated API documentation.
111
PyExpLabSys Documentation, Release 1.5
select_measurement_function(function)
Select a measurement function.
Keyword arguments: Function – A string stating the wanted measurement function.
read_configuration()
Read device configuration
set_auto_input_z(auto=False)
Change internal resitance
read()
Read a value from the device
PyExpLabSys.drivers.agilent_34410A.main()
Main function
read_flow()
Read the current flow-rate
read_full_range()
Report the full range of the device Apparantly this does not work for SLA-series. . .
set_flow(flowrate)
Set the setpoint of the flow
read_voltage_stepsize()
Reads the voltage step size
read_current_stepsize()
Read the current stepszie
increase_voltage()
Increase voltage one step
output_status(output_on=False)
Set the output status
read_output_status()
Read the output status
get_lock()
Lock the instrument for remote operation
This module contains a driver for the Vortex gas alarm central
Copyright 2014 CINF (https://github.com/CINF)
This Vortex driver is part of PyExpLabSys.
PyExpLabSys is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
version.
PyExpLabSys is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along with PyExpLabSys. If not, see <http:
//www.gnu.org/licenses/>.
The documentation for the Vortex is the property of and copyrighted to Crowcon: http://www.crowcon.com/
See also:
Docs for this implementation are on the wiki at: https://cinfwiki.fysik.dtu.dk/cinfwiki/Equipment#Vortex_Gas_
Alarm_System or online at: http://www.crowcon.com/uk/products/control-panels/vortex.html
PyExpLabSys.drivers.crowcon.DetConfMap
alias of DetectorConfigurationMap
PyExpLabSys.drivers.crowcon.DetLev
alias of DetectorLevels
class PyExpLabSys.drivers.crowcon.Status(code, value)
Bases: tuple
code
Alias for field number 0
value
Alias for field number 1
Note: In the manual the register numbers are 1-based, but when sent to minimal modbus they need to be 0
based.
Warning: This method uses “hidden” functions in the minimal modbus module for value conversion.
As they are hidden, they are not guarantied to preserve their interface, which means that this method
may break at any time
get_number_installed_detectors()
Get the number of installed detector inputs
This value is cached if requested. See docstring for __init__().
Returns The number of installed detectors
Return type int
get_number_installed_digital_outputs()
Get the number of installed digital outputs
Returns The number of installed digital inputs
Return type int
get_serial_number()
Get the serial number
Returns The serial number
Return type str
get_system_name()
Get the serial number
Returns The system name
Return type str
get_system_power_status()
Get the system power status
Returns A Status named tuple containing status code and string
Return type Status
get_system_status()
Get the system status
Returns
[‘All OK’] if no status bits (section 5.1.1 in the manual) has been set, otherwise one
string for each of the status bits that was set.
Return type list
get_type()
Get the device type
Returns The type of the device e.g. ‘Vortex’
Return type str
read_bool(register)
Read int from register and convert to boolean value
0 is considered False, 65535 True and remaining integer values are invalid.
Parameters register (int) – The register to read from
Returns The boolean value
Return type bool
read_register(*args, **kwargs)
Read register from instrument (with retries)
The argument definition is the same as for the minimalmodbus method, see the full documentation for
read_register for details.
read_string(*args, **kwargs)
Read string from instrument (with retries)
The argument definition is the same as for the minimalmodbus method, see the full documentation
read_string for details.
PyExpLabSys.drivers.crowcon.main()
Main function, used to simple functional test
PyExpLabSys.drivers.crowcon.register_to_bool(register)
Convert a register value to a boolean
0 is considered False, 65535 True and remaining integer values are invalid.
Parameters register (int) – The register value
Returns The boolean value
Return type bool
dataq.clear_buffer()
dataq.start()
sleep(0.1)
from pprint import pprint
try:
while True:
pprint(dataq.read())
sleep(0.5)
except KeyboardInterrupt:
dataq.stop()
else:
dataq.stop()
dataq.clear_buffer()
If the data card is being used on the limit of emptying the data buffer before it overflow, it might be useful to put the
calls to read in a try except:
while True:
try:
dataq.read()
except dataq_binary.BufferOverflow:
# Re-start i.e. stop and start
or, to simple start and stop the card for a short amount of time, if slow measurements, which would otherwise fill
buffer are required:
while True:
dataq.start()
sleep(0.1)
dataq.read()
dataq.stop()
# We really only need to measure every 10s
sleep(10)
On some Linux system, at the end of 2017, some models, e.g. the DI-1110 wasn’t automatically mounted. In that
case, it can be manually mounted with a command like this one:
On should be possible, on Debian based Linux systems to add an automatic mount rule along the lines of this thread:
https://askubuntu.com/questions/525016/cant-open-port-dev-ttyusb0
So, add a new udev rule /etc/udev/rules.d/99-dataq_di1110.rules
with this content:
# /etc/udev/rules.d/99-dataq_di1110.rules
# contains DataQ DI-1110 udev rule to patch default
# rules
SYSFS{idProduct}=="1110",
SYSFS{idVendor}=="0683",
RUN+="/sbin/modprobe -q usbserial product=0x1110 vendor=0x0683"
“sample rate divisor” information item (see the info method). See information about how to
calculate the valid input range above.
packet_size(size)
Set the packet size
The packet size is he amount of data acquired before it is placed in the read buffer. The available packet
sizes are the keys in packet_sizes class variable.
Parameters size (int) – The requested packet size
led_color(color)
Set the LED color
Parameters color (str) – The available colors are the keys in the led_colors class variable
read()
Read all values waiting
This method reads all available damples from the data card and returns for every channel the mean of those
samples.
The returned data is on the form of a list with one item for each item in the scan list and in the same
order. Each of the items is in them selves a dict, which holds the mean value of the samples, the number
of samples in the mean, the channel number (0-based) and information about how full the data buffer was,
at the time when it was read out. An example could be:
Driver and simple test case for Edwards Active Gauge Controler
class PyExpLabSys.drivers.edwards_agc.EdwardsAGC(port=’/dev/ttyUSB0’)
Bases: object
Primitive driver for Edwards Active Gauge Controler Complete manual found at http://www.idealvac.com/files/
brochures/Edwards_AGC_D386-52-880_IssueM.pdf
__init__(port=’/dev/ttyUSB0’)
comm(command)
Implements basic communication
gauge_type(gauge_number)
Return the type of gauge
read_pressure(gauge_number)
Read the pressure of a gauge
pressure_unit(gauge_number)
Read the unit of a gauge
current_error()
Read the current error code
software_version()
Return the software version of the controller
read_normal_speed_threshold()
Read the value for acknowledge the pump as normally running
read_standby_speed()
Read the procentage of full speed on standby
read_pump_status()
Read the overall status of the pump
read_service_status()
Read the overall status of the pump
set_standby_mode(standbymode)
Set the pump on or off standby mode
Note: At present only the PVCi driver is implemented and only partially
All requests for values (parameters) goes via value field names. To get a list of the available fields, have a look
at the keys in the fields dict of the common class and the sub-class. These fields names can then be used with
get_field() and get_fields() method or accessed as if they were attributes of the class.
Remember to call .close() after use.
__init__(port, slave_address=1, check_hardware_version=True)
Initialize communication
Parameters
• port (unicode) – The port specification of the device e.g. ‘/dev/????’
• slave_address (int) – The address of the slave device, default is 1
• check_hardware_version (bool) – Indicated whether a check should be per-
formed for correct hardware at __init__ time
close()
Close the serial connection
get_field(field_name)
Return the value for the field named field_name
Parameters field_name (str) – The name of the field to get. The names used are adapted
parameter names from the command list turned. See the keys in fields to see all possible
values.
Returns An object with type corresponding to the value (int, float or str)
Return type object
Raises KeyError – If the requested field_name is unknown
get_fields(fields=’common’)
Return a dict with fields and values for a list of fields
This method is specifically for getting multiple values in the shortest amount of time. It works by al-
ways reading the maximum amount of registers (32) at a time and then using the remaining payload for
subsequent values if they happen to be contained in the registers that have already been read.
Parameters fields (sequence or unicode) – A sequence (list, tuple) of fields names or
‘common’ which indicates fields with an address between 0x80 and 0x9E (this is the default)
or ‘all’.
Returns Field name to value mapping
Return type dict
class PyExpLabSys.drivers.epimax.PVCi(*args, **kwargs)
Bases: PyExpLabSys.drivers.epimax.PVCCommon
Driver for the PVCi device
For details of the functionality of this driver, see the docstring for the common base class PVCCommon
__init__(*args, **kwargs)
For specification for __init__ arguments, see PVCCommon.__init__()
PyExpLabSys.drivers.epimax.bytes_to_firmware_version(bytes_)
Convert 4 bytes to firmware type and version
PyExpLabSys.drivers.epimax.bytes_to_string(bytes_, valid_chars=None)
Convert the 16 bit integer values from registers to a string
Parameters valid_chars (sequence) – Sequence of two integers indicating the start and end
of a range of valid bytes (both values included). All chars outside the range will be filtered out.
PyExpLabSys.drivers.epimax.bytes_to_float(bytes_)
Convert 2 16 bit registers to a float
PyExpLabSys.drivers.epimax.bytes_to_slot_id(bytes_)
Convert 4 bytes to the slot ID
PyExpLabSys.drivers.epimax.bytes_to_status(bytes_, status_type)
Convert bytes to trip and digital input statuses
PyExpLabSys.drivers.epimax.byte_to_bits(byte)
Convert a byte to a list of bits
PyExpLabSys.drivers.epimax.raise_if_not_set(bits, index, parameter)
Raise a ValueError if bit is not set
PyExpLabSys.drivers.epimax.ion_gauge_status(bytes_, controller_type=None)
Read of ion gauge status
PyExpLabSys.drivers.epimax.bytes_to_bakeout_flags(bytes_)
Returns the bakeout flags from bytes
PyExpLabSys.drivers.epimax.run_module()
Tests basic functionality
Will init a PVCi on USB0 and out all info fields and gauge 1 pressure and bakeout info continuously
Driver for “fug NTN 140 - 6,5 17965-01-01” power supply Communication via the Probus V serial interface.
Written using the two documents:
1. Interface system Probus V - Documentation for RS232/RS422 Revision of document 2.4
2. Probus V - Command Reference Base Module ADDAT30 Firmware PIC0162 V4.0 Version of Document V2.22
Should be freely available from http://www.fug-elektronik.de/en/support/download.html (Available August 25 2017)
reset()
Resets device
stop(reset=True)
Closes device properly before exit
is_on()
Checks if output is ON (>DON) Returns True if ON
output(state=False)
Set output ON (>BON)
get_state()
Checks whether unit is in CV or CC mode (>DVR/>DIR)
identification_string()
Output serial number of device
set_voltage(value)
Sets the voltage (>S0)
get_voltage()
Reads the set point voltage (>S0A)
monitor_voltage()
Reads the actual (monitor) voltage (>M0)
ramp_voltage(value, program=0)
Activates ramp function for voltage value : ramp value in volts/second (>S0R)
ramp_voltage_running()
Return status of voltage ramp. True: still ramping False: ramp complete
set_current(value)
Sets the current (>S1)
get_current()
Reads the set point current (>S1A)
monitor_current()
Reads the actual (monitor) current (>M1)
ramp_current(value, program=0)
Activates ramp function for current. See ramp_voltage() for description.
ramp_current_running()
Return status of current ramp. True: still ramping False: ramp complete
read_H1()
Read H1 FIXME not yet done
print_states(t0=0)
Print the current state of the power supply
PyExpLabSys.drivers.fug.test()
Module test function
Python interface for Galaxy 3500 UPS. The driver uses the telnet interface of the device.
class PyExpLabSys.drivers.galaxy_3500.Galaxy3500(hostname)
Bases: object
Interface driver for a Galaxy3500 UPS.
__init__(hostname)
comm(command, keywords=None)
Send a command to the ups
alarms()
Return list of active alarms
battery_charge()
Return the battery charge state
temperature()
Return the temperature of the UPS
battery_status()
Return the battery voltage
output_measurements()
Return status of the device’s output
input_measurements()
Return status of the device’s output
set_current(current, channel=1)
Set the desired current
iv_scan(v_from, v_to, steps, settle_time, channel=1)
Perform iv_scan
Driver for the EL-USB-RT temperature and humidity USB device from Lascar
Calling read on the device will return either the temperature or the humidity.
If the first byte is it is a temperature. The next 2 bytes is a unsigned integer which, is used to calculate the temperature
as:
temp = -100 * 0.1 * (unsigned_short)
If the first byte is it is humidity. The next byte is an unsigned char, which is used to calculate the relative humidity as:
humidity = 0.5 * (unsigned_char)
class PyExpLabSys.drivers.lascar.ElUsbRt(device_path=None)
Bases: object
Driver for the EL-USB-RT device
__init__(device_path=None)
get_temperature_and_humidity()
Returns the temperature (in celcius, float) and relative humidity (in %, float) in a dict
get_temperature()
Returns the temperature (in celcius, float)
Omega CN7800 Modbus driver. Might also work with other CN units
class PyExpLabSys.drivers.omega_cn7800.CN7800(port)
Bases: object
Driver for the omega CN7800
__init__(port)
read_temperature()
Read the temperature from the device
This module contains drivers for equipment from Omega. Specifically it contains a driver for the ??? thermo couple
read out unit.
class PyExpLabSys.drivers.omega_cni.ISeries(port, baudrate=19200,
comm_stnd=’rs232’)
Bases: object
Driver for the iSeries omega temperature controllers
__init__(port, baudrate=19200, comm_stnd=’rs232’)
Initialize internal parameters
Parameters port – A serial port designation as understood by pySerial
command(command, response_length=None, address=None)
Run a command and return the result
Parameters
• command (str) – The command to execute
• response_length (int) – The expected legth of the response. Will force the driver
to wait untill this many characters is ready as a response from the device.
reset_device(address=None)
Reset the device
identify_device(address=None)
Return the identity of the device
read_temperature(address=None)
Return the temperature
close()
Close the connection to the device
class PyExpLabSys.drivers.omega_cni.CNi3244_C24(port)
Bases: PyExpLabSys.drivers.omega_cni.ISeries
Driver for the CNi3244_C24 device
__init__(port)
Initialize internal parameters
Parameters port – A serial port designation as understood by pySerial
__init__()
init_device()
Sensor needs to be initiated after power up
read_value(command)
Read a value from the sensor
read_pressure()
Read the pressure value
read_temperature()
Read the temperature value
This module contains the driver code for the QMG422 control box for a pfeiffer mass-spectrometer. The code should
in principle work for multiple type of electronics. It has so far been tested with a qme-125 box and a qme-??? box.
The module is ment as a driver and has very little function in itself. The module is ment to be used as a sub-module
for a large program providing the functionality to actually use the mass-spectrometer.
Known bugs: Not all code has a proper distinction between the various electronics. The qme-125 has many limitations
compared to the qme-??? and these limitations are not always properly expressed in the code or the output of the
module
class PyExpLabSys.drivers.pfeiffer_qmg422.qmg_422(port=’/dev/ttyS0’, speed=19200)
Bases: object
The actual driver class.
__init__(port=’/dev/ttyS0’, speed=19200)
Initialize the module
comm(command)
Communicates with Baltzers/Pferiffer Mass Spectrometer
Implements the low-level protocol for RS-232 communication with the instrument. High-level protocol
can be implemented using this as a helper
get_multiple_samples(number)
Read multiple samples from the device
config_channel(channel, mass=-1, speed=-1, enable=”, amp_range=0)
Config a MS channel for measurement
measurement_running()
Check if a measurement is running
waiting_samples()
Return number of waiting samples
mass_scan(first_mass, scan_width, amp_range=0)
Setup the mass spec for a mass scan
mass_time(ns)
Setup the mass spec for a mass-time measurement
Self contained module to run a Pfeiffer turbo pump including fall-back text gui and data logging.
class PyExpLabSys.drivers.pfeiffer_turbo_pump.CursesTui(turbo_instance)
Bases: threading.Thread
Text gui for controlling the pump
__init__(turbo_instance)
stop()
Cleanup terminal
class PyExpLabSys.drivers.pfeiffer_turbo_pump.TurboReader(turbo_instance)
Bases: threading.Thread
Keeps track of all data from a turbo pump with the intend of logging them
__init__(turbo_instance)
class PyExpLabSys.drivers.pfeiffer_turbo_pump.TurboLogger(turboreader, parameter,
maximumtime=600)
Bases: threading.Thread
Read a specific value and determine whether it should be logged
__init__(turboreader, parameter, maximumtime=600)
read_value()
Read the value of the logger
class PyExpLabSys.drivers.pfeiffer_turbo_pump.TurboDriver(adress=1,
port=’/dev/ttyUSB3’)
Bases: threading.Thread
The actual driver that will communicate with the pump
__init__(adress=1, port=’/dev/ttyUSB3’)
comm(command, read=True)
Implementaion of the communication protocol with the pump. The function deals with common syntax
need for all commands.
Parameters
• command (str) – The command to send to the pump
• read (Boolean) – If True, read only not action performed
Returns The reply from the pump
Return type Str
crc_calc(command)
Helper function to calculate crc for commands :param command: The command for which to calculate crc
:type command: str :return: The crc value :rtype: Str
read_rotation_speed()
Read the rotational speed of the pump
Returns The rotaional speed in Hz
Return type Float
read_set_rotation_speed()
Read the intended rotational speed of the pump
Returns The intended rotaional speed in Hz
Return type Int
read_operating_hours()
Read the number of operating hours
Returns Number of operating hours
Return type Int
read_gas_mode()
Read the gas mode :return: The gas mode :rtype: Str
read_vent_mode()
Read the venting mode :return: The venting mode :rtype: Str
read_sealing_gas()
Read whether sealing gas is applied :return: The sealing gas mode :rtype: Str
is_pump_accelerating()
Read if pump is accelerating :return: True if pump is accelerating, false if not :rtype: Boolean
turn_pump_on(off=False)
Spin the pump up or down :param off: If True the pump will spin down :type off: Boolean :return: Always
returns True :rtype: Boolean
read_temperature()
Read the various measured temperatures of the pump :return: Dictionary with temperatures :rtype: Dict
read_drive_power()
Read the current power consumption of the pump :return: Dictionary containing voltage, current and power
:rtype: Dict
Self contained module to run a SPECS sputter gun including fall-back text gui
class PyExpLabSys.drivers.specs_XRC1000.CursesTui(sourcecontrol)
Bases: threading.Thread
Defines a fallback text-gui for the source control.
__init__(sourcecontrol)
stop()
Cleanup the terminal
class PyExpLabSys.drivers.specs_XRC1000.XRC1000(port=None)
Bases: threading.Thread
Driver for X-ray Source Control - XRC 1000
__init__(port=None)
Initialize module
Establish serial connection and create status variable to expose the status for the instrument for the various
gui’s
comm(command)
Communication with the instrument
Implements the synatx need to send commands to instrument including handling carrige returns and extra
lines of ‘OK’ and other pecularities of the instrument.
Parameters command (str) – The command to send
Returns The reply to the command striped for protocol technicalities
Return type str
posible comands: REM?, IEM?, UAN?, IHV?, IFI?, UFI?, PAN?, SERNO?, ANO?, STAT?, OPE? REM,
LOC, IEM 20e-3, UAN 10e3, OFF, COOL, STAN, UAON, OPE, ANO 1, ANO 2
read_water_flow()
read the water flow from external hardware :return: water flow in L/min :rtype float
read_emission_current()
Read the emission current. Unit A :return: The emission current :rtype: float
read_filament_voltage()
Read the filament voltage. Unit V :return: The filament voltage :rtype: float
read_filament_current()
Read the filament current. Unit A :return: The filament current :rtype: float
read_anode_voltage()
Read the anode voltage. Unit V :return: The anode voltage :rtype: float
read_anode_power()
Read the anode voltage. Unit W :return: The anode voltage :rtype: float
standby()
Set the device on standby The function is not working entirely as intended. TODO: Implement check to
see if the device is alrady in standby :return: The direct reply from the device :rtype: str
operate()
Set the device in operation mode TODO: This function should only be activated from standby!!! :return:
The direct reply from the device :rtype: str
remote_enable(local=False)
Enable or disable remote mode :param local: If True the device is set to local, otherwise to remote :type
local: Boolean :return: The direct reply from the device :rtype: str
change_control()
Enable or disable remote mode :param local: If True the device is set to local, otherwise to remote :type
local: Boolean :return: The direct reply from the device :rtype: str
cooling()
Enable or disable water cooling :type local: Boolean :return: The direct reply from the device :rtype: str
update_status()
Update the status of the instrument
Runs a number of status queries and updates self.status
Returns The direct reply from the device
Return type str
Self contained module to run a SPECS sputter gun including fall-back text gui
class PyExpLabSys.drivers.specs_iqe11.CursesTui(sputtergun)
Bases: threading.Thread
Defines a fallback text-gui for the sputter gun.
__init__(sputtergun)
stop()
Cleanup the terminal
class PyExpLabSys.drivers.specs_iqe11.Puiqe11(simulate=False)
Bases: threading.Thread
Driver for ion sputter guns from SPECS
__init__(simulate=False)
Initialize module
Establish serial connection and create status variable to expose the status for the instrument for the various
gui’s
comm(command)
Communication with the instrument
Implements the synatx need to send commands to instrument including handling carrige returns and extra
lines of ‘OK’ and other pecularities of the instrument.
Parameters command (str) – The command to send
Returns The reply to the command striped for protocol technicalities
Return type str
read_sputter_current()
Read the sputter current. Unit mA :return: The sputter current :rtype: float
read_filament_voltage()
Read the filament voltage. Unit V :return: The filament voltage :rtype: float
read_filament_current()
Read the filament current. Unit A :return: The filament current :rtype: float
read_emission_current()
Read the emission current. Unit mA :return: The emission current :rtype: float
read_acceleration_voltage()
Read the acceleration voltage. Unit V :return: The acceleration voltage :rtype: float
read_temperature_energy_module()
Read the temperature of the electronics module This value is not extremely correct, use only as guideline.
:return: The temperature :rtype: float
standby()
Set the device on standby The function is not working entirely as intended. TODO: Implement check to
see if the device is alrady in standby :return: The direct reply from the device :rtype: str
operate()
Set the device in operation mode TODO: This function should only be activated from standby!!! :return:
The direct reply from the device :rtype: str
remote_enable(local=False)
Enable or disable remote mode :param local: If True the device is set to local, otherwise to remote :type
local: Boolean :return: The direct reply from the device :rtype: str
update_status()
Update the status of the instrument
Runs a number of status queries and updates self.status
Returns The direct reply from the device
Return type str
check_channel_status()
Check status of channel
Complete serial driver for the Tenma 72-2535, *72-2540, *72-2545, *72-2550, 72-2930 and *72-2940 (see details
below)
Note: * The driver has not been tested on the models with a *. However, the two models that has been
tested, seems like are built from the same template, so there is a very high probability that the generic
TenmaBase driver will work with those as well.
Implemented according to “Series Protocol V2.0 of Remote Control” (referred to in inline comments as the spec)
which can be downloaded from the link below.
Manual and specification can be downloaded from here: https://www.element14.com/community/ docs/DOC-
75108/l/protocol-information-for-tenma-72-2550-and-tenma-72-2535-qa-window- driver
class PyExpLabSys.drivers.tenma.Tenma722535(device, sleep_after_command=0.1)
Bases: PyExpLabSys.drivers.tenma.TenmaBase
Driver for the Tenma 72-2535 power supply
class PyExpLabSys.drivers.tenma.Tenma722550(device, sleep_after_command=0.1)
Bases: PyExpLabSys.drivers.tenma.TenmaBase
Driver for the Tenma 72-2550 power supply
class PyExpLabSys.drivers.tenma.Tenma722930(device, sleep_after_command=0.1)
Bases: PyExpLabSys.drivers.tenma.TenmaBase
Driver for the Tenma 72-2930 power supply
class PyExpLabSys.drivers.tenma.TenmaBase(device, sleep_after_command=0.1)
Bases: serial.serialposix.Serial
Serial driver for the Tenma 72-2535, *72-2540, *72-2545, *72-2550, 72-2930 and *72-2940 power supplies
Note: * The driver has not been tested on the models with a *. However, the two models that has been tested,
seems like are built from the same template, so there is a very high probability that the generic TenmaBase
driver will work with those as well.
__init__(device, sleep_after_command=0.1)
Initialize driver
Parameters
• device (str) – The serial device to connect to e.g. COM4 or /dev/ttyUSB0
• sleep_after_command (float) – (Optional) The time to sleep after sending a com-
mand, to make sure that the device is ready for another one. Defaults to 0.1, but quick tests
suggest that 0.05 might be enough.
com(command, decode_reply=True)
Send command to the device and possibly return reply
Parameters
• command (str) – Command as unicode object
• decode_reply (bool) – (Optional) Whether the reply should be utf-8 decoded to re-
turn a unicode object
get_actual_current()
Return the actual_current
Returns The actual current
Return type float
get_actual_voltage()
Return the actual voltage
Returns The actual coltage
Return type float
get_current()
Return the current setpoint
Returns The current setpoint
Return type float
get_identification()
Return the device identification
Returns E.g: ‘TENMA 72-2535 V2.0’
Return type str
get_voltage()
Return the voltage setpoint
Returns The voltage setpoint
Return type float
recall_memory(memory_number)
Recall memory of panel settings
Parameters number (int) – The number of the panel settings memory to recall
Raises ValueError – On invalid memory_number
save_memory(memory_number)
Recall memory of panel settings
Note: Saving to a memory slot seems to only be available for the memory slot currently active
Parameters number (int) – The number of the panel settings memory to recall
Raises ValueError – On invalid memory_number
set_beep(on_off )
Turn the beep on or off
on_off (bool): The beep status to set
set_current(current)
Sets the current setpoint
Parameters current (float) – The current to set
set_output(on_off )
Turn the output of or off
on_off (bool): The otput status to set
set_overcurrent_protection(on_off )
Set the over current protection (OCP) on or off
Parameters on_off (bool) – The overcurrent protection mode to set
set_overvoltage_protection(on_off )
Set the over voltage protection (OVP) on or off
Parameters on_off (bool) – The overvoltage protection mode to set
set_voltage(voltage)
Sets the voltage setpoint
Parameters voltage (float) – The voltage to set
status()
Return the status
The output is a dict with the following keys and types:
status = {
'channel1_mode': 'CV', # or 'CC' for constand current of voltage
'channel2_mode': 'CV', # or 'CC' for constand current of voltage
'beep_on': True,
'lock_on': False,
'output_on': True,
'tracking_status: 'Independent', # or 'Series' or 'Parallel'
}
PyExpLabSys.drivers.tenma.main()
Main module function, used for testing simple functional test
class PyExpLabSys.drivers.vivo_technologies.ThreadedBarcodeReader(device_path)
Bases: threading.Thread
Threaded Barcode Scanner that holds only the last value
__init__(device_path)
run()
The threaded run method
last_barcode_in_queue
Last barcode in the queue
wait_for_barcode
Last barcode property
oldest_barcode_from_queue
Get one barcode from the queue if there is one
close()
Close the device
This module implements a driver for the AL1000 syringe pump from World Precision Instruments
class PyExpLabSys.drivers.wpi_al1000.AL1000(port=’/dev/ttyUSB0’, baudrate=19200)
Bases: object
Driver for the AL1000 syringe pump
__init__(port=’/dev/ttyUSB0’, baudrate=19200)
get_firmware()
Retrieves the firmware version
Returns The firmware version
Return type str
get_rate()
Retrieves the pump rate
Returns The pumping rate
set_rate(num, unit=False)
Sets the pump rate.
Parameters
• num (float) – The flow rate (0 mL/min - 34.38 mL/min)
• unit (str) – For valid values see below.
Valid units are: UM=microL/min MM=milliL/min UH=microL/hr MH=milliL/hour
Returns Notihing. Printing the function yields space for success or error message
set_vol(num)
Sets the pumped volume to the pump. The pump will pump until the given volume has been dispensed.
read_all_pressures()
Read pressure from all sensors
list_all_gauges()
List all installed gauge cards
read_pressure(gauge_id)
Read the pressure from a specific gauge
filament_lit(gauge_id)
Report if the filament of a given gauge is lid
emission_status(gauge_id)
Read the status of the emission for a given gauge
set_smission_off(gauge_id)
Turn off emission from a given gauge
set_emission_on(gauge_id, filament)
Turn on emission for a given gauge
read_software_version()
Read gauge controller firmware version
read_pressure_unit()
Read which pressure unit is used
How To’s
This section contain howtos for different procedures associated with elements of PyExpLabSys. This could e.g. be the
installation and configuration of a requirement.
Contents
* A subsection
This HOWTO explains how to setup and configure a new bakeout box . . . FIXME
8.1.1 A Section
A subsection
155
PyExpLabSys Documentation, Release 1.5
Developer Notes
This chapter contains information useful for developers of PyExpLabSys. The documentation has the form of little
sections that each describe a small task.
Table of Contents
• Developer Notes
– Setting up logging for a component of PyExpLabSys
– Editing/Updating Documentation
157
PyExpLabSys Documentation, Release 1.5
This section describes how to set up logging for a component in PyExpLabSys with the logging module (i.e. the
meaning of the word “logging” that refers to text output of debug and status information to e.g. terminal and text files
NOT sending data to the database).
Note: This section specifically deals with setting up logging for a component in PyExpLabSys, not of a program
merely using PyExpLabSys. For information about how to set up logging for a program merely using PyExpLabSys,
see the standard library documentation and Setting up logging of your program for how to use some convenience
functions in PyExpLabSys.
Setting up a logger for a component of PyExpLabSys should be done in the manner recommended by the standard
library documentation for logging from libraries. I.e. in the beginning of the file to the following:
import logging
LOG = logging.getLogger(__name__)
LOG.addHandler(logging.NullHandler())
Where using __name__ as the name, will ensure that it gets a name that is the full qualified name of the module e.g.
PyExpLabSys.common.utilities.
If more fine grained logging is required, e.g. if a module consist of several large classes and it would preferable with
a logger per class, they can be set up in the same manner. Such class loggers should keep the __name__ as a prefix
followed by a “.” and the name of the class, i.e:
class MyClass(object):
"""My fancy class"""
pass
cd PYEXPLABSYSPATH/doc/source
python update-driver-only-autogen-stubs.py
git add drivers-autogen-only/*.rst
git cm "doc: Added new driver documentation stubs for <name of your driver>"
To add additional documentation for a driver, e.g. usage examples, that is not well suited to be placed directly in the
source file, follow this procedure.
In the PyExpLabSys documentation the driver documentation files are located in two different folders depending on
whether it is a stub or has extra documentation. To add extra documentation, first git move the file and then start to
edit and commit it as usual:
cd PYEXPLABSYSPATH/doc/source
git mv drivers-autogen-only/<name_of_your_driver_module>.rst drivers/
# Edit and commit as usual
It is useful to disable caching in your browser temporarily, when it is being used to preview local Sphinx pages. The
easiest way to disable browser cache temporarily, is to disable caching when the developer tools are open. For Firefox,
the procedure is:
1. Open developer view (F12).
2. Open the settings for developer view (there is a little gear in the headline of developer view, third icon from the
right)
3. Under “Advanced Settings” click “Disable Cache (when tool is open)”
In Chromium, the procedure is similar, except the check box is under “General”.
General restructured text primer is located here: http://sphinx-doc.org/rest.html. Most of the examples are from there.
Super short summary of that follows:
Sections
#####
parts
#####
********
chapters
********
sections
========
subsections
-----------
subsubsections
^^^^^^^^^^^^^^
paragraphs
""""""""""
The following is the convention for how to use those in PyExpLabSys and the overall structure.
• index.rst
– Uses parts
– includes the main table of contents that links to chapter files for common, drivers, apps etc.
– common.rst (or any other chapter file)
.. _my-reference-label:
Section to Cross-Reference
--------------------------
.. code-block:: python
import time
t0 = time.time()
# Stuff that takes time
print(time.time() - t0)
Lists
Bullet lists
* Item over two lines. Item over two lines. Item over two lines.
Item over two lines. Item over two lines. Item over two lines.
Numbered lists
Examples
Details
3. Then with the current module and class (if any) preprended
If you prefix the target with a ., then this search order is reversed.
Prefixing the target with a ~ will shorten the link text to only show the last part.
The standard way of writing docstrings, with arguments definitions, in Sphinx is quite ugly and almost unreadable as
pure text (which is annoying if you use an editor or IDE which will show you the standard help-invoked documentation.
The Napoleon extension to Sphinx (PyPi page) aims to fix this by letting you write docstring in the Google-style.
An example:
Args:
codename (str): The codename whose data should be checked for
timeout
Kwargs:
timeout (float): The timeout to use in seconds, defaults to 900s.
timestamp (float): Unix timestamp to compare to. Defaults to now.
Raises:
ValueError: If codename is unknown
TypeError: If timeout or unixtime are not floats (or ints where appropriate)
Returns:
bool: Whether the data is too old or not
"""
class MyClass(object):
"""Class that describes me
Attributes:
name (str): The name of me
birthdate (float): Unix timestamp for my birthdate and time
"""
"""Initialize parameters"""
self.name = name
self.birthdate = birthdate
@property
def age(self):
"""The approximate age of me in years"""
return (time.time() - self.birthdate) / (math.pi * 10**7)
• genindex
• modindex
• search
165
PyExpLabSys Documentation, Release 1.5
p PyExpLabSys.drivers.mks_937b, 135
PyExpLabSys.combos, 61 PyExpLabSys.drivers.mks_g_series, 136
PyExpLabSys.common.database_saver, 21 PyExpLabSys.drivers.mks_pi_pc, 136
PyExpLabSys.common.loggers, 27 PyExpLabSys.drivers.NGC2D, 111
PyExpLabSys.common.plotters, 30 PyExpLabSys.drivers.omega_cn7800, 137
PyExpLabSys.common.plotters_backend_qwt, PyExpLabSys.drivers.omega_cni, 137
33 PyExpLabSys.drivers.omega_D6400, 136
PyExpLabSys.common.sockets, 45 PyExpLabSys.drivers.omegabus, 138
PyExpLabSys.common.utilities, 56 PyExpLabSys.drivers.omron_d6fph, 139
PyExpLabSys.drivers.agilent_34410A, 111 PyExpLabSys.drivers.pfeiffer, 107
PyExpLabSys.drivers.agilent_34972A, 112 PyExpLabSys.drivers.pfeiffer_qmg420, 139
PyExpLabSys.drivers.bio_logic, 80 PyExpLabSys.drivers.pfeiffer_qmg422, 139
PyExpLabSys.drivers.bronkhorst, 113 PyExpLabSys.drivers.pfeiffer_turbo_pump,
PyExpLabSys.drivers.brooks_s_protocol, 141
113 PyExpLabSys.drivers.polyscience_4100,
PyExpLabSys.drivers.cpx400dp, 114 143
PyExpLabSys.drivers.crowcon, 115 PyExpLabSys.drivers.rosemount_nga2000,
PyExpLabSys.drivers.dataq_binary, 118 143
PyExpLabSys.drivers.dataq_comm, 122 PyExpLabSys.drivers.scpi, 143
PyExpLabSys.drivers.edwards_agc, 122 PyExpLabSys.drivers.specs_iqe11, 145
PyExpLabSys.drivers.edwards_nxds, 123 PyExpLabSys.drivers.specs_XRC1000, 144
PyExpLabSys.drivers.epimax, 124 PyExpLabSys.drivers.srs_sr630, 147
PyExpLabSys.drivers.four_d_systems, 99 PyExpLabSys.drivers.stahl_hv_400, 147
PyExpLabSys.drivers.freescale_mma7660fc, PyExpLabSys.drivers.stmicroelectronics_ais328dq,
126 148
PyExpLabSys.drivers.fug, 126 PyExpLabSys.drivers.stmicroelectronics_l3g4200d,
PyExpLabSys.drivers.galaxy_3500, 129 148
PyExpLabSys.drivers.honeywell_6000, 129 PyExpLabSys.drivers.tenma, 148
PyExpLabSys.drivers.inficon_sqm160, 130 PyExpLabSys.drivers.vivo_technologies,
PyExpLabSys.drivers.innova, 130 151
PyExpLabSys.drivers.intellemetrics_il800,PyExpLabSys.drivers.wpi_al1000, 152
132 PyExpLabSys.drivers.xgs600, 153
PyExpLabSys.drivers.isotech_ips, 132 PyExpLabSys.file_parsers.chemstation,
PyExpLabSys.drivers.keithley_2700, 133 69
PyExpLabSys.drivers.keithley_smu, 133 PyExpLabSys.file_parsers.specs, 65
PyExpLabSys.drivers.kjlc_pressure_gauge, PyExpLabSys.settings, 63
134
PyExpLabSys.drivers.lascar, 134
PyExpLabSys.drivers.mks_925_pirani, 135
167
PyExpLabSys Documentation, Release 1.5
169
PyExpLabSys Documentation, Release 1.5
170 Index
PyExpLabSys Documentation, Release 1.5
Index 171
PyExpLabSys Documentation, Release 1.5
172 Index
PyExpLabSys Documentation, Release 1.5
Index 173
PyExpLabSys Documentation, Release 1.5
174 Index
PyExpLabSys Documentation, Release 1.5
Index 175
PyExpLabSys Documentation, Release 1.5
176 Index
PyExpLabSys Documentation, Release 1.5
Index 177
PyExpLabSys Documentation, Release 1.5
178 Index
PyExpLabSys Documentation, Release 1.5
Index 179
PyExpLabSys Documentation, Release 1.5
180 Index
PyExpLabSys Documentation, Release 1.5
Index 181
PyExpLabSys Documentation, Release 1.5
Sys.drivers.agilent_34972A.Agilent34972ADriver Sys.drivers.kjlc_pressure_gauge.KJLC300
method), 112 method), 134
read_scan_list() (PyExpLab- read_software_version() (PyExpLab-
Sys.drivers.agilent_34972A.Agilent34972ADriver Sys.drivers.scpi.SCPI method), 144
method), 112 read_software_version() (PyExpLab-
read_sealing_gas() (PyExpLab- Sys.drivers.xgs600.XGS600Driver method),
Sys.drivers.pfeiffer_turbo_pump.TurboDriver 154
method), 142 read_sputter_current() (PyExpLab-
read_sem_voltage() (PyExpLab- Sys.drivers.specs_iqe11.Puiqe11 method),
Sys.drivers.pfeiffer_qmg422.qmg_422 146
method), 140 read_standby_speed() (PyExpLab-
read_sensor_types() (PyExpLab- Sys.drivers.edwards_nxds.EdwardsNxds
Sys.drivers.mks_937b.Mks937b method), method), 124
135 read_status() (PyExpLab-
read_serial() (PyExpLab- Sys.drivers.polyscience_4100.Polyscience4100
Sys.drivers.bronkhorst.Bronkhorst method), method), 143
113 read_string() (PyExpLabSys.drivers.crowcon.Vortex
read_serial() (PyExpLab- method), 118
Sys.drivers.mks_925_pirani.Mks925 method), read_temperature() (PyExpLab-
135 Sys.drivers.omega_cn7800.CN7800 method),
read_serial_number() (PyExpLab- 137
Sys.drivers.mks_g_series.MksGSeries read_temperature() (PyExpLab-
method), 136 Sys.drivers.omega_cni.ISeries method),
read_serial_number() (PyExpLab- 138
Sys.drivers.srs_sr630.SRS_SR630 method), read_temperature() (PyExpLab-
147 Sys.drivers.omron_d6fph.OmronD6fph
read_serial_numbers() (PyExpLab- method), 139
Sys.drivers.edwards_nxds.EdwardsNxds read_temperature() (PyExpLab-
method), 123 Sys.drivers.pfeiffer_turbo_pump.TurboDriver
read_service_status() (PyExpLab- method), 142
Sys.drivers.edwards_nxds.EdwardsNxds read_temperature() (PyExpLab-
method), 124 Sys.drivers.polyscience_4100.Polyscience4100
read_set_rotation_speed() (PyExpLab- method), 143
Sys.drivers.pfeiffer_turbo_pump.TurboDriver read_temperature() (PyExpLab-
method), 142 Sys.drivers.stahl_hv_400.StahlHV400
read_set_voltage() (PyExpLab- method), 147
Sys.drivers.cpx400dp.CPX400DPDriver read_temperature_energy_module() (PyExpLab-
method), 114 Sys.drivers.specs_iqe11.Puiqe11 method),
read_setpoint() (PyExpLab- 146
Sys.drivers.bronkhorst.Bronkhorst method), read_timestep() (PyExpLab-
113 Sys.drivers.pfeiffer_qmg422.qmg_422
read_setpoint() (PyExpLab- method), 140
Sys.drivers.mks_g_series.MksGSeries read_unit() (PyExpLabSys.drivers.bronkhorst.Bronkhorst
method), 136 method), 113
read_setpoint() (PyExpLab- read_unit() (PyExpLab-
Sys.drivers.polyscience_4100.Polyscience4100 Sys.drivers.polyscience_4100.Polyscience4100
method), 143 method), 143
read_setup() (PyExpLab- read_value() (PyExpLab-
Sys.drivers.omegabus.OmegaBus method), Sys.drivers.omega_D6400.OmegaD6400
138 method), 137
read_single_scan() (PyExpLab- read_value() (PyExpLab-
Sys.drivers.agilent_34972A.Agilent34972ADriver Sys.drivers.omegabus.OmegaBus method),
method), 112 138
read_software_version() (PyExpLab- read_value() (PyExpLab-
182 Index
PyExpLabSys Documentation, Release 1.5
Index 183
PyExpLabSys Documentation, Release 1.5
method), 23 128
scan_list() (PyExpLab- set_current() (PyExpLab-
Sys.drivers.dataq_binary.DataQBinary Sys.drivers.keithley_smu.KeithleySMU
method), 120 method), 133
SCPI (class in PyExpLabSys.drivers.scpi), 143 set_current() (PyExpLabSys.drivers.tenma.TenmaBase
scpi_comm() (PyExpLabSys.drivers.scpi.SCPI method), method), 150
144 set_current_limit() (PyExpLab-
screen_mode() (PyExpLab- Sys.drivers.cpx400dp.CPX400DPDriver
Sys.drivers.four_d_systems.PicasoCommon method), 114
method), 104 set_current_limit() (PyExpLab-
search_regions() (PyExpLab- Sys.drivers.isotech_ips.IPS method), 132
Sys.file_parsers.specs.SpecsFile method), set_current_limit() (PyExpLab-
67 Sys.drivers.keithley_smu.KeithleySMU
search_regions_iter() (PyExpLab- method), 133
Sys.file_parsers.specs.SpecsFile method), set_current_measure_range() (PyExpLab-
67 Sys.drivers.keithley_smu.KeithleySMU
select_measurement_function() (PyExpLab- method), 133
Sys.drivers.agilent_34410A.Agilent34410ADriverset_current_stepsize() (PyExpLab-
method), 111 Sys.drivers.cpx400dp.CPX400DPDriver
select_measurement_function() (PyExpLab- method), 114
Sys.drivers.keithley_2700.KeithleySMU set_device_address() (PyExpLab-
method), 133 Sys.drivers.mks_g_series.MksGSeries
sem_status() (PyExpLab- method), 136
Sys.drivers.pfeiffer_qmg422.qmg_422 set_direction() (PyExpLab-
method), 140 Sys.drivers.wpi_al1000.AL1000 method),
Sequence (class in PyExpLab- 153
Sys.file_parsers.chemstation), 70 set_dual_output() (PyExpLab-
serial_number() (PyExpLab- Sys.drivers.cpx400dp.CPX400DPDriver
Sys.drivers.dataq_comm.DataQ method), method), 114
122 set_emission_on() (PyExpLab-
set_ascii_mode() (PyExpLab- Sys.drivers.xgs600.XGS600Driver method),
Sys.drivers.dataq_comm.DataQ method), 154
122 set_float_mode() (PyExpLab-
set_auto_input_z() (PyExpLab- Sys.drivers.dataq_comm.DataQ method),
Sys.drivers.agilent_34410A.Agilent34410ADriver 122
method), 112 set_flow() (PyExpLabSys.drivers.bronkhorst.Bronkhorst
set_batch() (PyExpLabSys.common.sockets.LiveSocket method), 113
method), 52 set_flow() (PyExpLabSys.drivers.brooks_s_protocol.Brooks
set_batch_now() (PyExpLab- method), 114
Sys.common.sockets.LiveSocket method), set_flow() (PyExpLabSys.drivers.mks_g_series.MksGSeries
53 method), 136
set_beep() (PyExpLabSys.drivers.tenma.TenmaBase set_fun() (PyExpLabSys.drivers.wpi_al1000.AL1000
method), 150 method), 153
set_channel() (PyExpLab- set_ilimit_to_max() (PyExpLab-
Sys.drivers.pfeiffer_qmg422.qmg_422 Sys.drivers.isotech_ips.IPS method), 132
method), 140 set_integration_time() (PyExpLab-
set_comm_speed() (PyExpLab- Sys.drivers.agilent_34972A.Agilent34972ADriver
Sys.drivers.mks_925_pirani.Mks925 method), method), 112
135 set_integration_time() (PyExpLab-
set_control_mode() (PyExpLab- Sys.drivers.keithley_smu.KeithleySMU
Sys.drivers.bronkhorst.Bronkhorst method), method), 133
113 set_last_to_none() (PyExpLab-
set_current() (PyExpLab- Sys.common.sockets.DataPushSocket method),
Sys.drivers.fug.FUGNTN140Driver method), 51
184 Index
PyExpLabSys Documentation, Release 1.5
Index 185
PyExpLabSys Documentation, Release 1.5
186 Index
PyExpLabSys Documentation, Release 1.5
Index 187
PyExpLabSys Documentation, Release 1.5
W
wait_for_barcode (PyExpLab-
Sys.drivers.vivo_technologies.ThreadedBarcodeReader
attribute), 152
wait_for_queue_to_empty() (PyExpLab-
Sys.common.database_saver.DataSetSaver
method), 24
wait_for_queue_to_empty() (PyExpLab-
Sys.common.database_saver.SqlSaver
method), 26
waiting_samples() (PyExpLab-
Sys.drivers.pfeiffer_qmg422.qmg_422
method), 141
WARNING_EMAIL (in module PyExpLab-
Sys.common.utilities), 56
who_am_i() (PyExpLab-
Sys.drivers.stmicroelectronics_ais328dq.AIS328DQTR
method), 148
who_am_i() (PyExpLab-
Sys.drivers.stmicroelectronics_l3g4200d.L3G4200D
method), 148
write_enable() (PyExpLab-
Sys.drivers.omega_D6400.OmegaD6400
method), 137
X
x (PyExpLabSys.file_parsers.specs.Region attribute), 68
x_be (PyExpLabSys.file_parsers.specs.Region attribute),
68
XGS600Driver (class in PyExpLabSys.drivers.xgs600),
153
xgs_comm() (PyExpLab-
Sys.drivers.xgs600.XGS600Driver method),
153
XRC1000 (class in PyExpLab-
Sys.drivers.specs_XRC1000), 144
xy_values_table (PyExpLab-
Sys.common.database_saver.DataSetSaver
attribute), 22
Y
y_avg_counts (PyExpLabSys.file_parsers.specs.Region
attribute), 68
y_avg_cps (PyExpLabSys.file_parsers.specs.Region at-
tribute), 68
188 Index