STG4000

class STGX(serial=None)[source]

The STGX is the base class for the STG4000 and wraps the basic USB interface and reads all the properties that are determined by the specific STG connected to your PC. Additionally methods for downloading or streaming are implemented by subclasses. Ideally, just use from stg.api import STG4000, and you will get the class implementing all bells and whistles.

When initialized without arguments, i.e. stg = STG4000(), it looks through your USB ports and connects with the first STGs it finds. If you want to use a specific STG, initialize the class with the serial number of the device, e.g. using stg = STG4000(serial=12345).

Immediatly after the connection is established, we eagerly read all properties from the stimulator, e.g. the number of channels or the output resolution. This read-only properties are than cached, to prevent any later overhead. This means it might take a few seconds until the stg is initialized, but it saves you precious milliseconds when you later stimulate.

Because at any time, only one process can be connected with a specific STG the connection is implemented using a with ... as idiom. This should therefore be relatively safe. It is still possible that the STG can get into a weird state. In that case, try turning it off and on again.

Note

  • Properties are eagerly loaded and cached during initalization

property DAC_resolution

Return the DAC resolution in bits

Return type

int

property channel_count

returns the number of stimulation channels

Return type

int

property current_range_in_mA

Return the current range in mA

Return type

float

property current_range_in_uA

Return the current range in uA

Return type

float

property current_resolution_in_mA

Return the current resolution in mA

Return type

float

property current_resolution_in_uA

Return the current resolution in µA

Return type

float

property manufacturer

Returns the name of the manufacturer

Return type

str

property name

returns the model name, i.e. STG4002/4/8

Return type

str

property serial_number

Returns the serial number of the device

Return type

int

sleep(duration_in_ms)[source]

sleep for duration in milliseconds

property time_resolution_in_ms

Return the time resolution in ms

Return type

float

property time_resolution_in_us

Return the time resolution in µs

Return type

float

property trigin_count

returns the number of trigger inputs

Return type

int

property version

Returns the current hardware and software version

Return type

str

property voltage_range_in_uV

Return the voltage range in uV

Return type

float

property voltage_resolution_in_uV

Return the voltage resolution in µV

Return type

float

Download

class STG4000(serial=None)[source]

This class implements the interface to download, start and stop stimulation.

At this point, you should pay attention to two specific details. First, indexing starts at 0. That means, the first channel is channel 0. Second, there is a difference between channels and triggers for the STG. Triggers are mapped to channels according to a channelmap. That means a single trigger can start stimulation of a whole set of channels. During initialization of the STG, we give this a sensible default. That means, all triggers are mapped to the respective channels following diagonal identity, i.e. trigger 0 maps to channel 0. Use diagonalize_triggermap() to repeat this normalization.

Example

import time
from stg.api import STG4000

stg = STG4000()
stg.download(0,[1,-1, 0], [0.1, 0.1, 49.8])
while True:
    time.sleep(0.5)
    a.trigger()
    stg.start_stimulation([0])

Note

  • Indexing starts at zero

  • Differentiate triggers and channels

diagonalize_triggermap()[source]

Give each trigger a sensible channel

Use this function to normalize the mapping of trigger to channel to a diagonal identity, i.e. trigger 0 maps to channel 0, so on.

Trigger

0

1

2

3

4

5

6

7

Channel

0

1

2

3

4

5

6

7

download(channel_index=0, amplitudes_in_mA=[0], durations_in_ms=[0], mode='current')[source]

Download a stimulation signal

Warning

Any previous data sent to that channel is erased. Other channels stay untouched.

The signal is compressed as amplitudes and their respective durations

Parameters
  • channel_index (int) – The index of the channel for which to download the signal. Indexing starts at 0

  • amplitudes_in_mA (List[float]) – a list of amplitudes in mA/mV delivered for the corresponding duration

  • durations_in_ms (List[float]) – a list of durations in ms determing how long each corresponding amplitude is delivered

  • mode (str) – defaults to current

Example

stg.download(channel_index = 0,
             amplitudes_in_mA = [1, -1, 0],
             durations_in_ms = [.1, .1, .488])
set_mode(channel_index=[], mode='current')[source]

set a single or all channels to voltage or current mode

Parameters
  • channel_index (list) – defaults to [], which sets the mode at all channels. Give it a list of integers to set the mode only for a specific subset of channels, e.g. [0,1].

  • mode (str ("current", "voltage")) – defaults to current

Warning

Because we primarily use current-mode, voltage mode is relatively untested. Additionally, i so far have not tested the behavior when different channels are in different modes. Be safe, and just set all channels to current-mode with stg.set_mode("current")

Return type

int

start_stimulation(triggerIndex=[])[source]

starts all trigger inputs or a selection based on a list

Parameters

triggerIndex (List[int]) – defaults to [], which starts stimulation at all channels. Give it a list of integers to start a specific subset of triggers, e.g. [0,1].

stop_stimulation(triggerIndex=[])[source]

stops all trigger inputs or a selection based on a list

Parameters

triggerIndex (List[int]) – defaults to [], which stops stimulation at all channels. Give it a list of integers to start a specific subset of triggers, e.g. [0,1].

Stream

class STG4000Streamer(serial=None)[source]

This class implements the interface to stream data.

Quote from the documentation of the DLL:

The Streaming mode works by use of two ring buffers which hold data. One is in PC memory and managed by the DLL, and one is in on-board STG memory. Data is transfered from PC memory to the STG via the USB bus in time slices of one millisecond.

The user can define both the size of the ring buffer in DLL memory and in the STG memory. Once the Streaming mode is started, the STG request data from the PC. The data rate from PC to STG is variable and controlled by the STG. The STG request data from the PC at a rate to keep its internal ringbuffer at about half full.

It is the responsibility of the user to keep the ring buffer in the memory of the PC filled, so the DLL can supply sufficient data to the STG. To do so, the Windows DLL allows to define a “callback” function which is called whenever new data is needed, or more precise, as soon as the ring buffer in the memory of the PC falls below the user defined threshold.

Small buffers have the advantage of a low latency between data generation in the callback funtion and its output as a analog signal from the STG. However for low latency to work, the user-written callback function has to be fast and to produce a steady flow of data.

For you, that means you have to set two parameters carefully when you initialize the streaming mode with start_streaming(). These parameters are the buffer_in_s, which defines the size of the buffer in the DLL, and the capacity_in_s, which defines the size of the buffer on the STG. Both buffers need to be at least as large the the signal you want to buffer. Yet, larger buffer means that the latency when updating it becomes larger, too. Too short buffers will fail without error, and too large buffers might cause

Streaming is implemented by constantly reading the stimulation signal you have set with set_signal() for each channel, and pushing this signal into the DLL-buffer as soon as there is enough space. This is done within its own thread, and if you use set_signal() it is thread-safe. Yet, space in the DLL becomes available at the speed the STG pulls data from the DLL. That means not only that there is a natural jitter, but there are also racing conditions if you update your signal faster than data is actually being pulled from the STG.

Note

  • Uncontrolled racing conditions when adapting stimulation online

  • Extensively test the optimal buffer sizes for your stimulation signal

Example

import time
from stg.api import STG4000

buffer_in_s=0.05 # how large is the buffer in the DLL?
capacity_in_s=.1 # how large is the buffer on the STG?

stg = STG4000()
stg.start_streaming(capacity_in_s=capacity_in_s,
                    buffer_in_s=buffer_in_s)
while True:
    stg.set_signal(0, amplitudes_in_mA=[0], durations_in_ms=[.1])
    time.sleep(0.5)
    stg.set_signal(0, amplitudes_in_mA=[1, -1, 0], durations_in_ms=[.1, .1, 49.7])
    time.sleep(buffer_in_s / 2)

Warning

This class inherits from STG4000 and therefore you can use this class also to download, start, and stop stimulation. How these two modes mix has not been tested so far. Be safe and use either or.

property output_rate_in_hz

Constant at 50 kHz.

Type

the rate at which the stg will send out data

Return type

int

set_signal(channel_index=0, amplitudes_in_mA=[0], durations_in_ms=[0])[source]

sets the signal to be continually appended to the buffer

Parameters
  • channel_index (int = 0) – the channel for which the new signal is to be defined

  • amplitudes_in_mA (List[float,] = [0]) – a list of amplitudes in mA

  • durations_in_ms (List[float,] = [0]) –

  • list of durations in ms (a) –

The amplitudes and durations are decompressed (decompress()) to the sampling rate defined in output_rate_in_hz.

start_streaming(capacity_in_s=1, buffer_in_s=0.1, callback_percent=10)[source]

start streaming

sets the STG into streaming mode and creates buffers of the respective sizes within the DLL and on the STG. After the thread has initalized, it starts pushing data as set by set_signal() as soon as space is left in the DLL buffer.

Parameters
  • capacity_in_s (float = 1) – the size of the buffer in the DLL

  • buffer_in_s (float = 0.1) – the size of the buffer on the STG

  • callback_percent (int = 10) – at what state of the DLL-buffer the DLL should request new data. Should have no effect in this implementation, because we constanly push data into the buffer as soon as there is enough space.

stop_streaming()[source]

closes the thread started when calling start_streaming() gracefully