The bio_logic module

This module implements a driver for the SP-150 BioLogic potentiostat.

The implementation is built up around the notion of an instrument and techniques. To communicate with the device, it is required to first create an instrument, and then a technique and then load the technique onto the instrument. This implementation was chosen because it closely reflects that way the specification is written and the official ECLab program is structured.

This driver communicates with the potentiostats via the EC-lib dll, which is present in the ECLab development packages. This package must be installed before the driver can be used. It can be downloaded from the BioLogic website.

See the Usage Example sections some examples on how to use this driver.

See the Inheritance diagram for an inheritance diagram, that gives a good overview over the available instruments and techniques.

Note

See some important notes on 64 bit Windows and instruments series in the beginning of the API documentation.

Implementation status and details

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.

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):

Inheritance diagram of SP150, CA, CP, CV, CVA, MIR, OCV, SPEIS

Usage Example

The example below is a complete run-able file demonstrating how to use the module, demonstrated with the OCV technique.

"""OCV example"""

from __future__ import print_function
import time
from PyExpLabSys.drivers.bio_logic import SP150, OCV


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)

    # Load the technique onto channel 0 of the potentiostat and start it
    sp150.load_technique(0, ocv)
    sp150.start_channel(0)

    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)

        # If there is none, assume the technique has finished
        if data_out is None:
            break

        # The data is available in lists as attributes on the data
        # object. The available data fields are listed in the API
        # documentation for the technique.
        print("Time:", data_out.time)
        print("Ewe:", data_out.Ewe)

        # If numpy is installed, the data can also be retrieved as
        # numpy arrays
        #print('Time:', data_out.time_numpy)
        #print('Ewe:', data_out.Ewe_numpy)
        time.sleep(0.1)

    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('Process index', data_out.process)
    if data_out.process == 0:
        print('time', data_out.time)
        print('Ewe', data_out.Ewe)
        print('I', data_out.I)
        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 Website and locally at CINF on the wiki.

Use/Implement a new potentiostat

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.

Implement a new potentiostat

The SP150 class is implemented in the following manner:

class SP150(GeneralPotentiostat):
    """Specific driver for the SP-150 potentiostat"""

    def __init__(self, address, EClib_dll_path=None):
        """Initialize the SP150 potentiostat driver

        See the __init__ method for the GeneralPotentiostat class for an
        explanation of the arguments.
        """
        super(SP150, self).__init__(
            type_='KBIO_DEV_SP150',
            address=address,
            EClib_dll_path=EClib_dll_path
        )

As it can be seen, the implementation of a new potentiostat boils down to:

  • Inherit from GeneralPotentiostat
  • Take address and EClib_dll_path as arguments to __init__
  • 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.

Use GeneralPotentionstat

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 potentiostat 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
)

The complete list of potentiostat type strings are listed in DEVICE_CODES.

Use/Implement a new technique

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.

    The OCV technique returns data on fields (in order):

    * time (float)
    * Ewe (float)
    * Ece (float) (only wmp3 series hardware)
    """

    #: Data fields definition
    data_fields = {
        'vmp3': [DataField('Ewe', c_float), DataField('Ece', c_float)],
        'sp300': [DataField('Ewe', c_float)],
    }

    def __init__(self, rest_time_T=10.0, record_every_dE=10.0,
                 record_every_dT=0.1, E_range='KBIO_ERANGE_AUTO'):
        """Initialize the OCV technique

        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),
            TechnArg('E_Range', E_RANGES, E_range, 'in', E_RANGES.values()),
        )
        super(OCV, self).__init__(args, 'ocv.ecc')

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.

bio_logic API

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:
Techniques:
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(**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(**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)[source]

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 library 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)[source]

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()[source]

Return the version of the EClib communications library.

Returns:The version string for the library
Return type:str
get_error_message(error_code)[source]

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)[source]

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()[source]

Disconnect from the device

test_connection()[source]

Test the connection

load_firmware(channels, force_reload=False)[source]

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)[source]

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()[source]

Get information about which channels are plugged.

Returns:A list of channel plugged statusses as booleans
Return type:(list)
get_channel_infos(channel)[source]

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)[source]

Return a message from the firmware of a channel

load_technique(channel, technique, first=True, last=True)[source]

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

define_bool_parameter(label, value, index, tecc_param)[source]

Defines a boolean TECCParam for a technique

This is a library convinience function to fill out the TECCParam struct in the correct way for a boolean value.

Parameters:
  • label (str) – The label of the parameter
  • value (bool) – The boolean value for the parameter
  • index (int) – The index of the parameter
  • tecc_param (TECCParam) – An TECCParam struct
define_single_parameter(label, value, index, tecc_param)[source]

Defines a single (float) TECCParam for a technique

This is a library convinience function to fill out the TECCParam struct in the correct way for a single (float) value.

Parameters:
  • label (str) – The label of the parameter
  • value (float) – The float value for the parameter
  • index (int) – The index of the parameter
  • tecc_param (TECCParam) – An TECCParam struct
define_integer_parameter(label, value, index, tecc_param)[source]

Defines an integer TECCParam for a technique

This is a library convinience function to fill out the TECCParam struct in the correct way for a integer value.

Parameters:
  • label (str) – The label of the parameter
  • value (int) – The integer value for the parameter
  • index (int) – The index of the parameter
  • tecc_param (TECCParam) – An TECCParam struct
start_channel(channel)[source]

Start the channel

Parameters:channel (int) – The channel number
stop_channel(channel)[source]

Stop the channel

Parameters:channel (int) – The channel number
get_current_values(channel)[source]

Get the current values for the spcified channel

Parameters:channel (int) – The number of the channel (zero based)
Returns:A dict of current values information
Return type:dict
get_data(channel)[source]

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)[source]

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)[source]

Check a ECLib return code and raise the appropriate exception

class PyExpLabSys.drivers.bio_logic.SP150(address, EClib_dll_path=None)[source]

Bases: PyExpLabSys.drivers.bio_logic.GeneralPotentiostat

Specific driver for the SP-150 potentiostat

__init__(address, EClib_dll_path=None)[source]

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)[source]

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)[source]

Initialize the KBIOData object

Parameters:
Raises:

ECLibCustomException – Where the error codes indicate the following: * -20000 means that the technique has no entry in TECHNIQUE_IDENTIFIERS_TO_CLASS * -20001 means that the technique class has no data_fields class variable * -20002 means that the data_fields class variables of the technique does not contain the right information

_init_data_fields(instrument)[source]

Initialize the data fields property

_parse_data(c_databuffer, timebase, instrument)[source]

Parse the data

Parameters:timebase (float) – The timebase for the time calculation

See __init__() for information about remaining args

data_field_names

Return a list of extra data fields names (besides time)

class PyExpLabSys.drivers.bio_logic.Technique(args, technique_filename)[source]

Bases: object

Base class for techniques

All specific technique classes inherits from this class.

Properties available on the object:

  • technique_filename (str): The name of the technique filename
  • args (tuple): Tuple containing the Python version of the parameters (see __init__() for details)
  • c_args (array of TECCParam): The c-types array of TECCParam

A specific technique, that inherits from this class must overwrite the data_fields class variable. It describes what the form is, of the data that the technique can receive. The variable should be a dict on the following form:

  • Some techniques, like OCV, have different data fields depending on the series of the instrument. In these cases the dict must contain both a ‘wmp3’ and a ‘sp300’ key.
  • For cases where the instrument class distinction mentioned above does not exist, like e.g. for CV, one can simply define a ‘common’ key.
  • All three cases above assume that the first field of the returned data is a specially formatted time field, which must not be listed directly.
  • Some techniques, like e.g. SPEIS returns data for two different processes, one of which does not contain the time field (it is assumed that the process that contains time is 0 and the one that does not is 1). In this case there must be a ‘common’ and a ‘no-time’ key (see the implementation of SPEIS for details).

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)[source]

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 replacement of technique file names are taken care of in load technique

c_args(instrument)[source]

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)[source]

Initialize the arguments struct

Parameters:instrument (GeneralPotentiostat) – Instrument instance, should be an instance of a subclass of GeneralPotentiostat
static _check_arg(arg)[source]

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')[source]

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 = {'sp300': [DataField(name='Ewe', type=<class 'ctypes.c_float'>)], 'vmp3': [DataField(name='Ewe', type=<class 'ctypes.c_float'>), DataField(name='Ece', type=<class 'ctypes.c_float'>)]}

Data fields definition

__init__(rest_time_T=10.0, record_every_dE=10.0, record_every_dT=0.1, E_range='KBIO_ERANGE_AUTO')[source]

Initialize the OCV technique

Parameters:
  • 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 E_RANGES module variable for possible values
class PyExpLabSys.drivers.bio_logic.CV(vs_initial, voltage_step, scan_rate, record_every_dE=0.1, average_over_dE=True, N_cycles=0, begin_measuring_I=0.5, end_measuring_I=1.0, I_range='KBIO_IRANGE_AUTO', E_range='KBIO_ERANGE_2_5', bandwidth='KBIO_BW_5')[source]

Bases: PyExpLabSys.drivers.bio_logic.Technique

Cyclic Voltammetry (CV) technique class.

The CV technique returns data on fields (in order):

  • time (float)
  • Ec (float)
  • I (float)
  • Ewe (float)
  • cycle (int)
data_fields = {'common': [DataField(name='Ec', type=<class 'ctypes.c_float'>), DataField(name='I', type=<class 'ctypes.c_float'>), DataField(name='Ewe', type=<class 'ctypes.c_float'>), DataField(name='cycle', type=<class 'ctypes.c_uint'>)]}

Data fields definition

__init__(vs_initial, voltage_step, scan_rate, record_every_dE=0.1, average_over_dE=True, N_cycles=0, begin_measuring_I=0.5, end_measuring_I=1.0, I_range='KBIO_IRANGE_AUTO', E_range='KBIO_ERANGE_2_5', bandwidth='KBIO_BW_5')[source]

Initialize the CV technique:

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

class PyExpLabSys.drivers.bio_logic.CVA(vs_initial_scan, voltage_scan, scan_rate, vs_initial_step, voltage_step, duration_step, record_every_dE=0.1, average_over_dE=True, N_cycles=0, begin_measuring_I=0.5, end_measuring_I=1.0, record_every_dT=0.1, record_every_dI=1, trig_on_off=False, I_range='KBIO_IRANGE_AUTO', E_range='KBIO_ERANGE_2_5', bandwidth='KBIO_BW_5')[source]

Bases: PyExpLabSys.drivers.bio_logic.Technique

Cyclic Voltammetry Advanced (CVA) technique class.

The CVA technique returns data on fields (in order):

  • time (float)
  • Ec (float)
  • I (float)
  • Ewe (float)
  • cycle (int)
data_fields = {'common': [DataField(name='Ec', type=<class 'ctypes.c_float'>), DataField(name='I', type=<class 'ctypes.c_float'>), DataField(name='Ewe', type=<class 'ctypes.c_float'>), DataField(name='cycle', type=<class 'ctypes.c_uint'>)]}

Data fields definition

__init__(vs_initial_scan, voltage_scan, scan_rate, vs_initial_step, voltage_step, duration_step, record_every_dE=0.1, average_over_dE=True, N_cycles=0, begin_measuring_I=0.5, end_measuring_I=1.0, record_every_dT=0.1, record_every_dI=1, trig_on_off=False, I_range='KBIO_IRANGE_AUTO', E_range='KBIO_ERANGE_2_5', bandwidth='KBIO_BW_5')[source]

Initialize the CVA technique:

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 current 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

class PyExpLabSys.drivers.bio_logic.CP(current_step=(5e-05, ), vs_initial=(False, ), duration_step=(10.0, ), record_every_dT=0.1, record_every_dE=0.001, N_cycles=0, I_range='KBIO_IRANGE_100uA', E_range='KBIO_ERANGE_2_5', bandwidth='KBIO_BW_5')[source]

Bases: PyExpLabSys.drivers.bio_logic.Technique

Chrono-Potentiometry (CP) technique class.

The CP 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'>), DataField(name='I', type=<class 'ctypes.c_float'>), DataField(name='cycle', type=<class 'ctypes.c_uint'>)]}

Data fields definition

__init__(current_step=(5e-05, ), vs_initial=(False, ), duration_step=(10.0, ), record_every_dT=0.1, record_every_dE=0.001, N_cycles=0, I_range='KBIO_IRANGE_100uA', E_range='KBIO_ERANGE_2_5', bandwidth='KBIO_BW_5')[source]

Initialize the CP technique

NOTE: The current_step, vs_initial and duration_step must be a list or tuple with the same length.

Parameters:
  • current_step (list) – List (or tuple) of floats indicating the current 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_dE (float) – Record every dE (V)
  • 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.CA(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')[source]

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'>), DataField(name='I', type=<class 'ctypes.c_float'>), DataField(name='cycle', type=<class 'ctypes.c_uint'>)]}

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')[source]

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, final_voltage_step, duration_step, step_number, record_every_dT=0.1, record_every_dI=5e-06, final_frequency=100000.0, initial_frequency=100.0, sweep=True, amplitude_voltage=0.1, frequency_number=1, average_n_times=1, correction=False, wait_for_steady=1.0, I_range='KBIO_IRANGE_AUTO', E_range='KBIO_ERANGE_2_5', bandwidth='KBIO_BW_5')[source]

Bases: PyExpLabSys.drivers.bio_logic.Technique

Staircase Potentio Electrochemical Impedance Spectroscopy (SPEIS) technique class

The SPEIS technique returns data with a different set of fields depending on which process steps it is in. If it is in process step 0 it returns data on the following fields (in order):

  • time (float)
  • Ewe (float)
  • I (float)
  • step (int)

If it is in process 1 it returns data on the following fields:

  • freq (float)
  • abs_Ewe (float)
  • abs_I (float)
  • Phase_Zwe (float)
  • Ewe (float)
  • I (float)
  • abs_Ece (float)
  • abs_Ice (float)
  • Phase_Zce (float)
  • Ece (float)
  • t (float)
  • Irange (float)
  • step (float)

Which process it is in, can be checked with the process property on the KBIOData object.

data_fields = {'common': [DataField(name='Ewe', type=<class 'ctypes.c_float'>), DataField(name='I', type=<class 'ctypes.c_float'>), DataField(name='step', type=<class 'ctypes.c_uint'>)], 'no_time': [DataField(name='freq', type=<class 'ctypes.c_float'>), DataField(name='abs_Ewe', type=<class 'ctypes.c_float'>), DataField(name='abs_I', type=<class 'ctypes.c_float'>), DataField(name='Phase_Zwe', type=<class 'ctypes.c_float'>), DataField(name='Ewe', type=<class 'ctypes.c_float'>), DataField(name='I', type=<class 'ctypes.c_float'>), DataField(name='Blank0', type=<class 'ctypes.c_float'>), DataField(name='abs_Ece', type=<class 'ctypes.c_float'>), DataField(name='abs_Ice', type=<class 'ctypes.c_float'>), DataField(name='Phase_Zce', type=<class 'ctypes.c_float'>), DataField(name='Ece', type=<class 'ctypes.c_float'>), DataField(name='Blank1', type=<class 'ctypes.c_float'>), DataField(name='Blank2', type=<class 'ctypes.c_float'>), DataField(name='t', type=<class 'ctypes.c_float'>), DataField(name='Irange', type=<class 'ctypes.c_uint'>), DataField(name='step', type=<class 'ctypes.c_uint'>)]}

Data fields definition

__init__(vs_initial, vs_final, initial_voltage_step, final_voltage_step, duration_step, step_number, record_every_dT=0.1, record_every_dI=5e-06, final_frequency=100000.0, initial_frequency=100.0, sweep=True, amplitude_voltage=0.1, frequency_number=1, average_n_times=1, correction=False, wait_for_steady=1.0, I_range='KBIO_IRANGE_AUTO', E_range='KBIO_ERANGE_2_5', bandwidth='KBIO_BW_5')[source]

Initialize the SPEIS technique

Parameters:
  • vs_initial (bool) – Whether the voltage step is vs. the initial one
  • vs_final (bool) – Whether the voltage step is vs. the final one
  • initial_step_voltage (float) – The initial step voltage (V)
  • final_step_voltage (float) – The final step voltage (V)
  • duration_step (float) – Duration of step (s)
  • step_number (int) – The number of voltage steps
  • record_every_dT (float) – Record every dT (s)
  • record_every_dI (float) – Record every dI (A)
  • final_frequency (float) – The final frequency (Hz)
  • initial_frequency (float) – The initial frequency (Hz)
  • sweep (bool) – Sweep linear/logarithmic (True for linear points spacing)
  • amplitude_voltage (float) – Amplitude of sinus (V)
  • frequency_number (int) – The number of frequencies
  • average_n_times (int) – The number of repeat times used for frequency averaging
  • correction (bool) – Non-stationary correction
  • wait_for_steady (float) – The number of periods to wait before each frequency
  • 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.MIR(rcmp_value)[source]

Bases: PyExpLabSys.drivers.bio_logic.Technique

Manual IR (MIR) technique class

The MIR technique returns no data.

data_fields = {}

Data fields definition

__init__(rcmp_value)[source]

Initialize the MIR technique

Parameters:rcmp_value (float) – The R value to compensate
class PyExpLabSys.drivers.bio_logic.DeviceInfos[source]

Bases: _ctypes.Structure

Device information struct

Fields:

  • DeviceCode <class ‘ctypes.c_int’>
  • RAMsize <class ‘ctypes.c_int’>
  • CPU <class ‘ctypes.c_int’>
  • NumberOfChannels <class ‘ctypes.c_int’>
  • NumberOfSlots <class ‘ctypes.c_int’>
  • FirmwareVersion <class ‘ctypes.c_int’>
  • FirmwareDate_yyyy <class ‘ctypes.c_int’>
  • FirmwareDate_mm <class ‘ctypes.c_int’>
  • FirmwareDate_dd <class ‘ctypes.c_int’>
  • HTdisplayOn <class ‘ctypes.c_int’>
  • NbOfConnectedPC <class ‘ctypes.c_int’>
class PyExpLabSys.drivers.bio_logic.ChannelInfos[source]

Bases: _ctypes.Structure

Channel information structure

Fields:

  • Channel <class ‘ctypes.c_int’>
  • BoardVersion <class ‘ctypes.c_int’>
  • BoardSerialNumber <class ‘ctypes.c_int’>
  • FirmwareCode <class ‘ctypes.c_int’>
  • FirmwareVersion <class ‘ctypes.c_int’>
  • XilinxVersion <class ‘ctypes.c_int’>
  • AmpCode <class ‘ctypes.c_int’>
  • NbAmp <class ‘ctypes.c_int’>
  • LCboard <class ‘ctypes.c_int’>
  • Zboard <class ‘ctypes.c_int’>
  • MUXboard <class ‘ctypes.c_int’>
  • GPRAboard <class ‘ctypes.c_int’>
  • MemSize <class ‘ctypes.c_int’>
  • MemFilled <class ‘ctypes.c_int’>
  • State <class ‘ctypes.c_int’>
  • MaxIRange <class ‘ctypes.c_int’>
  • MinIRange <class ‘ctypes.c_int’>
  • MaxBandwidth <class ‘ctypes.c_int’>
  • NbOfTechniques <class ‘ctypes.c_int’>
class PyExpLabSys.drivers.bio_logic.CurrentValues[source]

Bases: _ctypes.Structure

Current values structure

Fields:

  • State <class ‘ctypes.c_int’>
  • MemFilled <class ‘ctypes.c_int’>
  • TimeBase <class ‘ctypes.c_float’>
  • Ewe <class ‘ctypes.c_float’>
  • EweRangeMin <class ‘ctypes.c_float’>
  • EweRangeMax <class ‘ctypes.c_float’>
  • Ece <class ‘ctypes.c_float’>
  • EceRangeMin <class ‘ctypes.c_float’>
  • EceRangeMax <class ‘ctypes.c_float’>
  • Eoverflow <class ‘ctypes.c_int’>
  • I <class ‘ctypes.c_float’>
  • IRange <class ‘ctypes.c_int’>
  • Ioverflow <class ‘ctypes.c_int’>
  • ElapsedTime <class ‘ctypes.c_float’>
  • Freq <class ‘ctypes.c_float’>
  • Rcomp <class ‘ctypes.c_float’>
  • Saturation <class ‘ctypes.c_int’>
class PyExpLabSys.drivers.bio_logic.DataInfos[source]

Bases: _ctypes.Structure

DataInfos structure

Fields:

  • IRQskipped <class ‘ctypes.c_int’>
  • NbRaws <class ‘ctypes.c_int’>
  • NbCols <class ‘ctypes.c_int’>
  • TechniqueIndex <class ‘ctypes.c_int’>
  • TechniqueID <class ‘ctypes.c_int’>
  • ProcessIndex <class ‘ctypes.c_int’>
  • loop <class ‘ctypes.c_int’>
  • StartTime <class ‘ctypes.c_double’>
class PyExpLabSys.drivers.bio_logic.TECCParam[source]

Bases: _ctypes.Structure

Technique parameter

Fields:

  • ParamStr <class ‘PyExpLabSys.drivers.bio_logic.c_char_Array_64’>
  • ParamType <class ‘ctypes.c_int’>
  • ParamVal <class ‘ctypes.c_int’>
  • ParamIndex <class ‘ctypes.c_int’>
class PyExpLabSys.drivers.bio_logic.TECCParams[source]

Bases: _ctypes.Structure

Technique parameters

Fields:

  • len <class ‘ctypes.c_int’>
  • pParams <class ‘PyExpLabSys.drivers.bio_logic.LP_TECCParam’>
exception PyExpLabSys.drivers.bio_logic.ECLibException(message, error_code)[source]

Bases: exceptions.Exception

Base exception for all ECLib exceptions

__init__(message, error_code)[source]

x.__init__(…) initializes x; see help(type(x)) for signature

exception PyExpLabSys.drivers.bio_logic.ECLibError(message, error_code)[source]

Bases: PyExpLabSys.drivers.bio_logic.ECLibException

Exception for ECLib errors

__init__(message, error_code)[source]

x.__init__(…) initializes x; see help(type(x)) for signature

exception PyExpLabSys.drivers.bio_logic.ECLibCustomException(message, error_code)[source]

Bases: PyExpLabSys.drivers.bio_logic.ECLibException

Exceptions that does not originate from the lib

__init__(message, error_code)[source]

x.__init__(…) initializes x; see help(type(x)) for signature

PyExpLabSys.drivers.bio_logic.structure_to_dict(structure)[source]

Convert a ctypes.Structure to a dict

PyExpLabSys.drivers.bio_logic.reverse_dict(dict_)[source]

Reverse the key/value status of a dict

PyExpLabSys.drivers.bio_logic.DEVICE_CODES = {0: 'KBIO_DEV_VMP', 1: 'KBIO_DEV_VMP2', 2: 'KBIO_DEV_MPG', 3: 'KBIO_DEV_BISTA', 4: 'KBIO_DEV_MCS200', 5: 'KBIO_DEV_VMP3', 6: 'KBIO_DEV_VSP', 7: 'KBIO_DEV_HCP803', 8: 'KBIO_DEV_EPP400', 9: 'KBIO_DEV_EPP4000', 10: 'KBIO_DEV_BISTAT2', 11: 'KBIO_DEV_FCT150S', 12: 'KBIO_DEV_VMP300', 13: 'KBIO_DEV_SP50', 14: 'KBIO_DEV_SP150', 15: 'KBIO_DEV_FCT50S', 16: 'KBIO_DEV_SP300', 17: 'KBIO_DEV_CLB500', 18: 'KBIO_DEV_HCP1005', 19: 'KBIO_DEV_CLB2000', 20: 'KBIO_DEV_VSP300', 21: 'KBIO_DEV_SP200', 22: 'KBIO_DEV_MPG2', 23: 'KBIO_DEV_SP100', 24: 'KBIO_DEV_MOSLED', 27: 'KBIO_DEV_SP240', 255: 'KBIO_DEV_UNKNOWN'}

Device number to device name translation dict

PyExpLabSys.drivers.bio_logic.FIRMWARE_CODES = {0: 'KBIO_FIRM_NONE', 1: 'KBIO_FIRM_INTERPR', 4: 'KBIO_FIRM_UNKNOWN', 5: 'KBIO_FIRM_KERNEL', 8: 'KBIO_FIRM_INVALID', 10: 'KBIO_FIRM_ECAL'}

Firmware number to firmware name translation dict

PyExpLabSys.drivers.bio_logic.AMP_CODES = {0: 'KBIO_AMPL_NONE', 1: 'KBIO_AMPL_2A', 2: 'KBIO_AMPL_1A', 3: 'KBIO_AMPL_5A', 4: 'KBIO_AMPL_10A', 5: 'KBIO_AMPL_20A', 6: 'KBIO_AMPL_HEUS', 7: 'KBIO_AMPL_LC', 8: 'KBIO_AMPL_80A', 9: 'KBIO_AMPL_4AI', 10: 'KBIO_AMPL_PAC', 11: 'KBIO_AMPL_4AI_VSP', 12: 'KBIO_AMPL_LC_VSP', 13: 'KBIO_AMPL_UNDEF', 14: 'KBIO_AMPL_MUIC', 15: 'KBIO_AMPL_NONE_GIL', 16: 'KBIO_AMPL_8AI', 17: 'KBIO_AMPL_LB500', 18: 'KBIO_AMPL_100A5V', 19: 'KBIO_AMPL_LB2000', 20: 'KBIO_AMPL_1A48V', 21: 'KBIO_AMPL_4A10V'}

Amplifier number to aplifier name translation dict

PyExpLabSys.drivers.bio_logic.I_RANGES = {0: 'KBIO_IRANGE_100pA', 1: 'KBIO_IRANGE_1nA', 2: 'KBIO_IRANGE_10nA', 3: 'KBIO_IRANGE_100nA', 4: 'KBIO_IRANGE_1uA', 5: 'KBIO_IRANGE_10uA', 6: 'KBIO_IRANGE_100uA', 7: 'KBIO_IRANGE_1mA', 8: 'KBIO_IRANGE_10mA', 9: 'KBIO_IRANGE_100mA', 10: 'KBIO_IRANGE_1A', 11: 'KBIO_IRANGE_BOOSTER', 12: 'KBIO_IRANGE_AUTO', 13: 'KBIO_IRANGE_10pA', 14: 'KBIO_IRANGE_1pA'}

I range number to I range name translation dict

PyExpLabSys.drivers.bio_logic.BANDWIDTHS = {1: 'KBIO_BW_1', 2: 'KBIO_BW_2', 3: 'KBIO_BW_3', 4: 'KBIO_BW_4', 5: 'KBIO_BW_5', 6: 'KBIO_BW_6', 7: 'KBIO_BW_7', 8: 'KBIO_BW_8', 9: 'KBIO_BW_9'}

Bandwidth number to bandwidth name translation dict

PyExpLabSys.drivers.bio_logic.E_RANGES = {0: 'KBIO_ERANGE_2_5', 1: 'KBIO_ERANGE_5', 2: 'KBIO_ERANGE_10', 3: 'KBIO_ERANGE_AUTO'}

E range number to E range name translation dict

PyExpLabSys.drivers.bio_logic.STATES = {0: 'KBIO_STATE_STOP', 1: 'KBIO_STATE_RUN', 2: 'KBIO_STATE_PAUSE'}

State number to state name translation dict

PyExpLabSys.drivers.bio_logic.TECHNIQUE_IDENTIFIERS = {0: 'KBIO_TECHID_NONE', 100: 'KBIO_TECHID_OCV', 101: 'KBIO_TECHID_CA', 102: 'KBIO_TECHID_CP', 103: 'KBIO_TECHID_CV', 104: 'KBIO_TECHID_PEIS', 105: 'KBIO_TECHID_POTPULSE', 106: 'KBIO_TECHID_GALPULSE', 107: 'KBIO_TECHID_GEIS', 108: 'KBIO_TECHID_STACKPEIS_SLAVE', 109: 'KBIO_TECHID_STACKPEIS', 110: 'KBIO_TECHID_CPOWER', 111: 'KBIO_TECHID_CLOAD', 112: 'KBIO_TECHID_FCT', 113: 'KBIO_TECHID_SPEIS', 114: 'KBIO_TECHID_SGEIS', 115: 'KBIO_TECHID_STACKPDYN', 116: 'KBIO_TECHID_STACKPDYN_SLAVE', 117: 'KBIO_TECHID_STACKGDYN', 118: 'KBIO_TECHID_STACKGEIS_SLAVE', 119: 'KBIO_TECHID_STACKGEIS', 120: 'KBIO_TECHID_STACKGDYN_SLAVE', 121: 'KBIO_TECHID_CPO', 122: 'KBIO_TECHID_CGA', 123: 'KBIO_TECHID_COKINE', 124: 'KBIO_TECHID_PDYN', 125: 'KBIO_TECHID_GDYN', 126: 'KBIO_TECHID_CVA', 127: 'KBIO_TECHID_DPV', 128: 'KBIO_TECHID_SWV', 129: 'KBIO_TECHID_NPV', 130: 'KBIO_TECHID_RNPV', 131: 'KBIO_TECHID_DNPV', 132: 'KBIO_TECHID_DPA', 133: 'KBIO_TECHID_EVT', 134: 'KBIO_TECHID_LP', 135: 'KBIO_TECHID_GC', 136: 'KBIO_TECHID_CPP', 137: 'KBIO_TECHID_PDP', 138: 'KBIO_TECHID_PSP', 139: 'KBIO_TECHID_ZRA', 140: 'KBIO_TECHID_MIR', 141: 'KBIO_TECHID_PZIR', 142: 'KBIO_TECHID_GZIR', 150: 'KBIO_TECHID_LOOP', 151: 'KBIO_TECHID_TO', 152: 'KBIO_TECHID_TI', 153: 'KBIO_TECHID_TOS', 155: 'KBIO_TECHID_CPLIMIT', 156: 'KBIO_TECHID_GDYNLIMIT', 157: 'KBIO_TECHID_CALIMIT', 158: 'KBIO_TECHID_PDYNLIMIT', 159: 'KBIO_TECHID_LASV', 167: 'KBIO_TECHID_MP', 169: 'KBIO_TECHID_CASG', 170: 'KBIO_TECHID_CASP'}

Technique number to technique name translation dict

PyExpLabSys.drivers.bio_logic.TECHNIQUE_IDENTIFIERS_TO_CLASS = {'KBIO_TECHID_CA': <class 'PyExpLabSys.drivers.bio_logic.CA'>, 'KBIO_TECHID_CP': <class 'PyExpLabSys.drivers.bio_logic.CP'>, 'KBIO_TECHID_CV': <class 'PyExpLabSys.drivers.bio_logic.CV'>, 'KBIO_TECHID_CVA': <class 'PyExpLabSys.drivers.bio_logic.CVA'>, 'KBIO_TECHID_OCV': <class 'PyExpLabSys.drivers.bio_logic.OCV'>, 'KBIO_TECHID_SPEIS': <class 'PyExpLabSys.drivers.bio_logic.SPEIS'>}

Technique name to technique class translation dict. IMPORTANT. Add newly implemented techniques to this dictionary

PyExpLabSys.drivers.bio_logic.SP300SERIES = ['KBIO_DEV_SP100', 'KBIO_DEV_SP200', 'KBIO_DEV_SP300', 'KBIO_DEV_VSP300', 'KBIO_DEV_VMP300', 'KBIO_DEV_SP240']

List of devices in the WMP4/SP300 series