Programming interface


This section defines terminology used in this documentation and provides an overview of how signals can be generated with the Pulse Streamer API.

Pulse pattern

The pulse pattern is a sequence of levels, defining the signal to generate. It is defined as an array of (duration, level) tuples, in other words, using Run-Length Encoding (RLE). In contrast to defining pulse patterns as an array of values with equal time durations, the RLE encoded pattern is more memory efficient, especially for patterns that consist of levels of both short and long durations.

The duration is always specified in nanoseconds. The level is either 0 or 1 for digital output or a real number between -1 and +1 in Volt for analog outputs. See the Hardware section for more details on the electrical properties of the generated signals.


The following code shows how to define a pulse pattern similar to the one shown in the image above. In addition, it shows an example of an analog pattern definition.

pulse_patt = [(100, 0), (200, 1), (80, 0), (300, 1), (60, 0)]
analog_patt = [( 50, 0), (100, 0.5), (200, 0.3), (50, -0.1), (10, 0)]

Creating sequences

Before a pattern can be sent for streaming to the Pulse Streamer outputs, they have to be mapped to the output channels. All these steps are performed with the Sequence object, which is created with PulseStreamer.createSequence(). The digital and analog channel assignment is done with the setDigital() and setAnalog() methods, respectively.

from pulsestreamer import PulseStreamer

ps = PulseStreamer('pulsestreamer')

seq = ps.createSequence()
seq.setDigital(0, pulse_patt)
seq.setDigital(2, pulse_patt)
seq.setAnalog(0, analog_patt)

Sequence transformation

Sequence transformation methods enable the creation of complex sequences from simpler sub-sequences. The sequence data can be repeated or combined with another sequence. These operations, while inherently simple, have a few edge cases that are important to know. Concatenation and repetition operations are non-destructive. In other words, they preserve original sequence objects (immutability). The result is stored in a newly created sequence object. Internally, the sequence stores a map of the channel number and the pattern data with the pattern data unmodified. In general, this results in a sequence that consists of patterns having different durations. On concatenation or repetitions, however, it is intuitively expected that a sequence is treated as a solid unit with every pattern of the same duration. Therefore, before concatenating the sequence data, the pattern durations are padded to the common duration.

When two sub-sequences being concatenated have a different set of mapped channels, the resulting sequence will include them all. This is explained with the following example. Let’s assume we have two sequences, seq1 and seq2, which we want to concatenate. The seq1 has patterns mapped to channels (0,2), and seq2 has channels (0,1), as shown in the code below.

seq1 = ps.createSequence()
seq1.setDigital(0, patt1)
seq1.setDigital(2, patt2)

seq2 = ps.createSequence()
seq2.setDigital(0, patt3)
seq2.setDigital(1, patt4)

seq3 = seq1 + seq2   # concatenation

During the concatenation, the channel lists of the two sequences are compared and the output sequence seq3 will include them all (0,1,2). As a first step, a new sequence object seq3 will be created as a copy of seq1, and an empty pattern will be assigned to the channel 1. Next, all patterns in seq3 will be padded to the duration of the longest one, which is essentially the sequence duration. Finally, the pattern data from seq2 will be appended to the corresponding patterns of the seq3.

The duration padding is always performed with the value of the last element in the pattern. When there is no previous element, the default value is used. The repetition process behaves similarly and can be qualitatively understood as multiple concatenations of the object with itself.


Now, any of the sequence objects created before can be sent for streaming by calling the method, as shown in the following example for the sequence seq.

On streaming, the sequence object is converted to a hardware-specific run-length encoded data block, which can be understood as an array of Sequence steps. Every step defines the state of all channels and the duration to hold the state. Sequences support a number of useful methods, like repetition, concatenation, preview plotting, etc. With this basic set of methods, complex sequences can be built from smaller and simpler sub-sequences.


Internally, the Pulse Streamer hardware is always splitting the sequence data into 8 nanosecond long chunks. When a sequence is shorter than 8 ns or its length is not an exact multiple of 8 ns the extra time will be padded to complete the last chunk. You can observe the effects of such padding if you try to stream a short pulse repetitively.

Example 1. Your sequence consists of 3 ns high-level and 2 ns low-level and you stream it with infinite repetitions, the resulting signal will have 3 ns high-level but 5 ns low-level. Therefore, the actual pulse frequency will be 125 MHz instead of 200 MHz. For continuous periodic signals, you can solve this problem by creating a sequence of repetitive pulses that has a duration which is multiple of 8 ns. One easy way to guarantee that sequence duration is a multiple of 8 ns is to repeat it 8 times using Sequence.repeat() method, which will repeat the sequence data in PC memory before sending it to the Pulse Streamer hardware.

Example 2. You want to stream a sequence that is 12345 ns long and you want to repeat it infinitely by setting n_runs=-1. Since this sequence duration is not a multiple of 8 ns (12345 ns / 8 ns = 1543.125) the Pulse Streamer will allocate 1544 chunks, and the actual sequence duration will be 1544 * 8ns = 12352 ns, or 7 ns longer.

Sequence step

The sequence step is the smallest element of a sequence that contains information on the state of every output of the Pulse Streamer and the duration to hold this state. The image below explains the relation between Sequence step, Sequence, and OutputState objects.



In a typical use of the client API, the user does not have to care about how to create or operate on the sequence data directly. All necessary functionality is enclosed within the API presented in this article. The description of the Sequence data corresponds to the RAW data as it is required by the hardware. The internal API data structures are implemented slightly differently for each programming language, aiming at the optimization of the client performance. Furthermore, the RAW sequence data format is hardware-dependent and future Pulse Streamer models are likely to use a different format. See also: Low-level RPC interface.

Module level functions


search_serial (str) – Pulse Streamer serial number as a string.


List of DeviceInfo objects.

This function searches and returns basic information about discovered Pulse Streamers. If non-empty search_serial string is provided, then information is returned only for a specific Pulse Streamer unit.

The returned value is a list of DeviceInfo objects containing the IP address and basic information.

class DeviceInfo

This class contains read-only information about the discovered Pulse Streamer.

Property name

Example data




Device IP address



Device serial number



Pulse Streamer hostname


“Pulse Streamer 8/2”

Pulse Streamer model name



FPGA ID number



Firmware version



Hardware version

The discovery algorithm sends Pulse Streamer specific query packets overall available and active network interfaces and listens for responses from the connected Pulse Streamers.


The findPulseStreamers() is capable of finding the devices and reporting their IP addresses even in the networks without dynamic IP assignment by a DHCP server or an improper IP address configuration. Therefore, it might happen that the reported Pulse Streamer IP is not accessible from your network. For example, when the reported IP is (static fallback) and your PC is configured as, you will not be able to connect to the Pulse Streamer. This is because of the way how IP networks operate. However, you will still be able to discover this Pulse Streamer and learn its IP, which is very helpful for identifying network connection problems.


The PulseStreamer class is a wrapper for the RPC interface provided by the Pulse Streamer hardware. It handles the connection to the hardware and exposes all available methods. This class is implemented in various supported programming languages with consistently named methods. However, in some languages, additional functionality common to that language is also implemented, like callback functions in MATLAB.

class PulseStreamer

The class constructor accepts a single string argument, which can be either the IP address or a hostname by which the Pulse Streamer can be reached in the network. The constructor fails when the ip has an incorrect value or the device is not reachable. The Pulse Streamer hardware has a static fallback address “”. This allows operation when the Pulse Streamer is directly connected to a PC network card and without requiring any additional configuration.


ip (str) – IP address or hostname of the Pulse Streamer.


Reset the Pulse Streamer device to the default state. All outputs are set to 0V, and all functional configurations are set to default. The automatic rearm functionality is enabled, and the clock source is the internal clock of the device. No specific trigger functionality is enabled, which means that each sequence is streamed immediately when its upload is completed.


Perform a soft reboot of the device without power-cycling.


Use this method to create a new hardware-specific Sequence object. A hardware-specific sequence object has the same functionality as Sequence and implements early checks for hardware limits. For example, an attempt to assign a pattern to a non-existing channel or setting analog voltage outside the DAC range will result in an error. The generic Sequence object’s normal behavior is to check hardware limits only on the call to method.


Hardware-specific Sequence object.

Setting constant output state


Set the outputs to a constant state. Calling the method without a parameter will result in the default output state with all output set to 0V. If you set the device to a constant output, an eventually currently streamed sequence is stopped. It is not possible to retrigger the last streamed sequence after setting the Pulse Streamer constant. OutputState.ZERO is a constant equal to OutputState([],0,0).

Alternatively, the state parameter can be specified as a tuple consisting of three elements ([],0,0).

ps.constant(OutputState([1, 2, 5], 0, 0))
# or
ps.constant(([1, 2, 5], 0, 0))

state (OutputState) – OutputState object that defines the state of outputs or a tuple.

Running pulse sequences

This section describes methods that allow to run sequences and configure trigger properties. You can repeat a pulse sequence infinitely or an integer number of times. If you want to stop a running sequence and force it to the final, specified in the function call, you can do this by calling the method forceFinal().[, n_runs=PulseStreamer.REPEAT_INFINITELY[, final=OutputState.ZERO]])

Sends the sequence to the Pulse Streamer. After the sequence has been repeated the given n_runs, the constant state final will be reached. All parameters except sequence have default values and can be omitted. By default, the sequence is started immediately. Alternatively, you can select when the output of the sequence starts with setTrigger() to a software-based trigger started with startNow() or to an external hardware trigger.

If the sequence is empty, then the final state will set immediately.

The sequence parameter of the stream() method also accepts an RLE sequence defined as a list of 4 element tuples of the following format: (duration_ns, [channels_to_set_HIGH], analogV_0, analogV_1)[(100, [1, 2], 0, 0), (10, [2], 0, 0), (5, [], 0, 0)])
  • sequence (Sequence) – Sequence object or a list of tuples.

  • n_runs (int) – Number of times to repeat the sequence. Infinite repetitions if n_runs<0. There is also a symbolic constant REPEAT_INFINITELY=-1

  • final (OutputState) – OutputState object, which defines the constant output after the sequence has finished.

PulseStreamer.setTrigger(start[, rearm=TriggerRearm.AUTO])

Defines how the uploaded sequence is triggered.

If you want to trigger the Pulse Streamer by using the external trigger input of the device, you have to set the start parameter to one of the following values: start=TriggerStart.HARDWARE_RISING (rising edge on the trigger input), start=TriggerStart.HARDWARE_FALLING (falling edge on the trigger input) or start=TriggerStart.HARDWARE_RISING_AND_FALLING (both edges are active).

If the automatic rearm functionality is enabled (rearm=TriggerRearm.AUTO), which is the default power-on state, you can re-trigger a sequence which is finished, by providing an appropriate trigger signal, depending on start argument. You can disable the automatic rearm by passing rearm=TriggerRearm.MANUAL.

If the automatic rearm functionality is disabled, you can manually rearm the Pulse Streamer by calling the method rearm()

  • start (TriggerStart) – Defines the source of the trigger signal

  • rearm (TriggerRearm) – Enables or disables trigger automatic rearm.


Queries the hardware for the currently active trigger start condition.


Returns TriggerStart value.


Queries the hardware for the currently active rearming method.


Returns TriggerRearm value.


Starts streaming the sequence present in the Pulse Streamer’s memory. The behavior of this method depends on the trigger configuration performed with setTrigger() method.

If the start is TriggerStart.IMMEDIATE, n_runs>=0, and the sequence has finished, then startNow() will trigger the sequence again.

If the start is TriggerStart.SOFTWARE then the sequence is started every time the startNow() is called. In case of the rearm=TriggerRearm.MANUAL the method startNow() will trigger the sequence only once. Call rearm() to manually rearm the trigger.

If the start is set to one of the hardware sources, then this method does nothing.


Rearm the trigger in case the Pulse Streamer has reached the final state of the current sequence and the trigger rearm method was set to TriggerRearm.MANUAL. Returns True on success.


bool True or False


Interrupts the sequence and sets the final state. This method does not modify the output state if the sequence has already finished and the Pulse Streamer is in the final state.

If no final state was declared in the current sequence, the output of Pulse Streamer will change to (or stay in) the last known constant state.

The recommended way to stop the Pulse Streamer streaming is to set its output to a constant value via the method constant(), described above.

PulseStreamer.setCallbackFinished(callback_func) (MATLAB only)

Allows to set up a callback function, which will be called after the sequence streaming has finished. The callback function will be called with the following signature callbackFunction(pulseStreamer_obj). An example of such a function is shown below.

function callbackFunction(pulseStreamer)
    % this is an example of a callback function

    disp('hasFinishedCallback - Pulse Streamer finished.');


Requesting the streaming state

The following methods allow you to request whether the Pulse Streamer has a sequence in memory, whether a sequence is currently being streamed or if it has already finished.


Returns True if the Pulse Streamer memory contains a sequence.


True or False.


Returns True if the Pulse Streamer is currently streaming a sequence. When the sequence has finished and the device remains in the final state, this method returns False again.


True or False.


Returns True if the Pulse Streamer remains in the final state after having finished a sequence.


True or False.

Using an external clock

The Pulse Streamer can be clocked from three different clock sources. By default, the internal clock of the device is used. It is also possible use an external clock of 125MHz (sampling clock) or an external 10MHz reference signal. You can choose the clock source via selectClock(). For more information on the required electrical parameters of an external clock signal, please see the section Hardware.


Set the hardware clock source.


source (ClockSource) – Specifies the clock source for the Pulse Streamer hardware.


Returns a ClockSource element with the clock source currently used by the Pulse Streamer.


ClockSource Current clock source

Also, you can apply a continuous square wave of 125MHz to the dedicated Pulse Streamer output channels as an external clock signal for other devices to be synchronized with the Pulse Streamer.


Set a persistent square wave with a frequency of 125 MHz to the selected digital outputs. The 125 MHz will remain and will not be affected by any other settings applied to this channel unless the corresponding channel is deselected via setSquareWave125MHz() or the method reset() is called. A call to this method without a parameter will disable the 125 MHz signal on all channels it was enabled before.

ps.setSquareWave125MHz(channels=[1, 2, 5])

channels (list) – defines to which channels the 125 MHz square wave should be applied.

Hardware identification


String containing the serial number which is the same as MAC address of the Ethernet interface.


String containing FPGA ID number.


String containing the firmware version number of the connected Pulse Streamer.


String containing the hardware revision number of the connected Pulse Streamer.


hostname (str) – Hostname string to set for the connected Pulse Streamer.

Set hostname of the connected Pulse Streamer.


Depending on your network environment, this setting may not affect how your Pulse Streamer is identified in the network. However, the stored hostname will be returned when you call getHostname().


String containing the hostname of the connected Pulse Streamer.

Calibrating the analog outputs

Pulse Streamer 8/2 devices shipped with firmware version v1.3.0 or later (published in July 2020) already include calibration data for analog outputs, and no further user action is required. Devices shipped with older firmware require analog output calibration in order to achieve specified accuracy, see Hardware. You can perform this calibration yourself by following the steps described below. The calibration requires a sufficiently accurate multimeter (not an oscilloscope) connected to the analog outputs (can be done one channel at a time).

Calibration procedure

  1. Connect the multimeter to the analog output of the Pulse Streamer. The measurement has to be performed at 50 Ohm load, so you will need to attach 50 Ohm termination.

  2. Using the Pulse Streamer API, set the analog output to several values and record multimeter readings. This has to be done at least for -0.9 and +0.9 output values.

  3. Calculate the slope

    slope = \frac{voltage_{+0.9V} - voltage_{-0.9V}}{1.8}

  4. Calculate the offset

    offset = voltage_{+0.9V} - slope*0.9

  5. Perform the steps 1 to 4 for each analog output.

  6. Call the setAnalogCalibration() and specify both offsets and slopes.

  7. Reboot the Pulse Streamer to apply the new calibration data (from firmware v1.5.0 on, the device is rebooted automatically).


If you perform repeated calibration, you have to reset the slope and offset to values 1 and 0, respectively. Failing to do so will lead to invalid calibration data.

PulseStreamer.setAnalogCalibration(dc_offset_a0=0, dc_offset_a1=0, slope_a0=1, slope_a1=1)

Sends the DC-offset and slope of each analog channel to the Pulse Streamer and stores it to internal memory. These values will be applied after reboot. With firmware version v1.5.0 or later, this is done automatically. If you use a former firmware of the Pulse Streamer 8/2, you will have to power cycle your device.

  • dc_offset_a0 – The DC offset of analog channel 0

  • dc_offset_a1 – The DC offset of analog channel 1

  • slope_a0 – The gradient of the transfer function of analog channel 0

  • slope_a1 – The gradient of the transfer function of analog channel 1

If you need help during the calibration procedure, please contact


Returns the stored calibration values of your Pulse Streamer. These values will be rounded according to the DAC resolution. If you call this method immediately after setAnalogCalibration(), the returned data will not reflect the actual calibration state.


structure of the four calibration values rounded to the DAC resolution.

Modify the network configuration

By default, the Pulse Streamer 8/2 will attempt to acquire an IP address via DHCP. If you want to assign a specific IP address to your Pulse Streamer, you can disable DHCP and configure a static IP instead. We recommend using our graphical user interface (Windows only) to modify the Pulse Streamer 8/2 network configuration. For more information, please have a look at Network Connection. Alternatively, the following methods allow you to configure the device’s network settings via our client software interfaces.

PulseStreamer.setNetworkConfiguration(dhcp, ip='', netmask='', gateway='', testmode=True)

Enables DHCP or sets static IP address, Netmask and Standard Gateway. If testmode=True, the configuration is applied temporarily. Power-cycling will restore the former configuration. If testmode=False, the configuration will be applied permanently and the device is rebooted.

  • dhcp (bool) – DHCP enable/disable True/False

  • ip (str) – static IP address (If dhcp=True, this value is ignored)

  • netmask (str) – Netmask for static IP address configuration (If dhcp=True, this value is ignored)

  • gateway (str) – Standard gateway for static IP address configuration (If dhcp=True, this value is ignored)

  • testmode (bool) – If True, the configuration is applied temporarily. Power-cycling will restore the former configuration. If False, the configuration will be applied permanently and the device is rebooted.


permanent (bool) – If True, the method returns network settings stored in the device’s configuration file. If False, the method returns the current network settings of the device.


structure of the current or stored network settings


Applies current (and successfully tested) network configuration permanently and the device is rebooted.


class ClockSource(enumeration)

This enumeration describes the selectable clock sources of the Pulse Streamer


Use internal clock generator (default)


Use external 125 MHz clock signal


Derive clock from external 10 MHz reference signal

class TriggerStart(enumeration)

This enumeration describes the selectable start modes of the Pulse Streamer


Trigger immediately after a sequence is uploaded. (default)


Trigger by calling startNow() method.


External trigger on the rising edge.


External trigger on the falling edge.


External trigger on rising and falling edges.

class TriggerRearm(enumeration)

This enumeration describes the rearm functionality of the Pulse Streamer


Trigger immediately after a sequence is uploaded. (default)


Trigger once only and do not rearm automatically. Rearm manually via the rearm() method.


The Sequence contains information about the patterns and channel assignments. It also handles the mapping of patterns (see Pulse pattern) to output channels and has a number of built-in methods that operate on the whole sequence, like concatenation, repetitions, visualization, etc.


While the same pattern can be mapped to one or more channels, successive mappings to the same channel will replace the previous mapping.

class Sequence

Class constructor. The Sequence is a generic class without early hardware limit checks. Since this class is not aware of hardware-specific limitations, like available channels or analog range, the validation will be performed only during an attempt to stream this Sequence object.


If you want to have early limit checks, channel number validation, please create a hardware-specific Sequence object with PulseStreamer.createSequence() method. This, however, requires an active connection to the hardware.

setDigital(channels, pattern)

Assign a pattern to a digital output. The same pattern can be assigned to one or more channels simultaneously.

sequence.setDigital(0, patt1)
sequence.setDigital([1,2,6], patt2)
  • channels (list[int]) – Digital channel number(s) as labeled on the Pulse Streamer connectors panel.

  • pattern (list) – A pattern to be assigned to the channel.


Inverts level values in the stored pattern for the specified channel.

sequence.setDigital(1, [(10, 0), (20, 1), (80, 0)])
# is equivalent to
sequence.setDigital(1, [(10, 1), (20, 0), (80, 1)])

channel (int) – Digital channel number.

setAnalog(channels, pattern)

Assign a pattern to an analog output. The same pattern can be assigned to one or more channels simultaneously.

sequence.setAnalog([0,1], patt2)
  • channels (list[int]) – Analog channel number(s) as labeled on the Pulse Streamer connectors panel.

  • pattern (list) – A pattern to be assigned to the channel.


Inverts level values in the pattern for the specified channel.

sequence.setAnalog(0, [(100, -0.1), (200, 0), (800,  0.5)])
# is equivalent to
sequence.setAnalog(0, [(100,  0.1), (200, 0), (800, -0.5)])

channel (int) – Analog channel number.


Sequence.isempty() (in MATLAB)

Returns True if the sequence is empty.


Returns sequence duration in nanoseconds.


Returns the last state in the sequence as an OutputState object.


OutputState Last state of the sequence.


Returns the run-length encoded (RLE) sequence data. This method is called automatically by the method.


Run-length encoded data.


static Sequence.repeat(sequence, n_times)

Returns the sequence data duplicated n_times. The sequence data in the original object remains unmodified. In case the Sequence object consists of patterns with different durations, they will be padded to the longest one, which defines sequence duration as returned by Sequence.getDuration() method. In this context, a Sequence shall be understood as a set of patterns all of the same duration.

In Python, you can repeat sequences similarly to lists by multiplying it by a number.

# The following three lines are fully equivalent
seq1 = Sequence.repeat(seq, 5)
seq1 = seq * 5
seq1 = 5 * seq
  • sequence (Sequence) – Sequence object to be repeated.

  • n_times (int) – Number of times the sequence is repeated.


Returns a new Sequence object with data duplicated n_times.

static Sequence.concatenate(sequence1, sequence2)

Creates a new Sequence object with a sequence of sequence2 object appended at the end of this sequence. Both object, sequence1 and sequence2, remain unmodified. In case the sequence1 sequence consists of patterns with different durations, they will be padded to the longest one, which defines sequence duration as returned by Sequence.getDuration() method. In this context, a Sequence shall be understood as a set of patterns all of the same duration.

This method is exposed directly in LabVIEW. However, in MATLAB and Python, it is exposed only as the override of the concatenation operator. This allows for transparent use of any function of these languages that implicitly use concatenation. See the example code for each language.

seq3 = seq1 + seq2

Returns a new Sequence object with concatenated data.



Plots the sequence data for digital outputs. Plotting is done into the current axes. (Only in MATLAB and LabView)


Plots sequence data for analog outputs. Plotting is done into the current axes. (Only in MATLAB and LabView)


Calls plotDigital() and plotAnalog() and shows the results as subplots in a single figure. Plotting is done in the current figure.

An example of the plot() output is shown in the image below.



(Python only)

Since the Python Client release v1.6.1, importing the module matplotlib for plot() is optional. If you want to use visualization with Python, please ensure you have the package matplotlib installed.


The OutputState is a simple value class that contains information on the state of every output of the Pulse Streamer.

class OutputState
OutputState(channels, A0, A1)

Class constructor. Input parameters specify the state of each output of the Pulse Streamer. Digital and analog output values are specified differently. In order to set a HIGH level at the digital channel, add the channel number to the channels list, for example channels=[0,2,3] will set HIGH level on the channels 0, 2 and 3. All other digital channels will be set to LOW. Output values at each of two analog outputs are specified with corresponding parameters A0 and A1.

  • channels (list) – List of digital channels to be set HIGH.

  • A0 (float) – Analog output 0 voltage in Volt.

  • A1 (float) – Analog output 1 voltage in Volt.


This is a helper constant equal to OutputState([], 0, 0).

Advanced (Beta) features

Synchronized Pulse Streamer (Python only)

With our programming examples in Python, we provide the class SyncPulseStreamer as a wrapper class for the client interface of the Pulse Streamer 8/2. It combines two Pulse Streamer 8/2 (requires firmware version v1.4.0 or later) and is currently only available for the Python client.

Synchronization concept and setup

One Pulse Streamer master generates the clock signal and trigger for one Pulse Streamer slave. The only necessary preparation is that digital channel 6 of the master must be connected to the external clock input of the slave as well as digital channel 7 of the master must be connected to the trigger input of the slave. To avoid race conditions between the trigger and trigger-sampling clock-edge, we recommend using cables of equal length.

The features of the resulting SyncPulseStreamer object can be described as follows:

  • 14 digital channels (6 of the master, 8 of the slave)

  • 4 analog channels (2 in each case master/slave)

  • The slave is delayed by a constant time offset of ~70ns (internal + cable)

  • Increased ({\sim}x*\sqrt{2}) RMS jitter of the 8 digital channels of the slave (< 75 ps)

  • In this configuration, devices with hardware Version 2.x (devices before 2021) have a 100mV ripple on the digital channels of the slave due to the external clock signal. The analog outputs are not affected.

Usage and sequence generation

The Pulse Streamer synchronization wrapper offers the same API-structure as the original Pulse Streamer client if possible. For a detailed description of the Pulse Streamer 8/2 API, please have a look at the Programming interface section and the provided Python example.

When it comes to sequence generation, unlike the original method createSequence(), the equivalent method of the sync-wrapper returns two sequence objects, one for the Pulse Streamer master and one for the Pulse Streamer slave. You can set the digital and analog channels of both sequences independently. Setting Channel 6 (clock signal) of the master will be ignored, and channel 7 (trigger) of the master will be overwritten by the stream method).

If you want to use a parameter n_runs>1 with the stream() function, you should ensure that the two sequences are of equal duration. Therefore the stream() prints a warning message if the duration of the two sequences differs.

To compensate for the delay of the Pulse Streamer slave, you can add an empty pulse as a first pulse to each channel of the master sequence, as it is shown in the Python code example. In that case, you have to take into account that if you want to use n_runs>1, you have to subtract the delay from the last pulses of the master-sequence, or you can accordingly pad the slave-sequence. The drawback is that this either requires the same state at the beginning and the end of the channel pattern, or you have to deal with the padding. Furthermore, you have to take into account that when a sequence is given to the method stream() of the Pulse Streamer or to the transformation-methods (see Transformation) of the Sequence class, all channels are padded with the last value to the longest channel duration. For further information, please have a look at the sections Creating sequences and Sequence.

Just to give you the complete information of the padding issue: Due to the internal design of the Pulse Streamer, the device itself will pad the last sequence step to a duration that the sequence duration as a whole is a multiple of 8ns (which means a prolongation between 0 and 7ns). This step is executed before the parameter n_runs is applied (see Streaming).

Further Limitations

  1. If you use the synchronized Pulse Streamer with a fast external trigger, it is possible that the Pulse Streamer master is ready for retriggering and the slave is not and vice versa. Therefore, you should always poll the method hasFinished() before retriggering the Pulse Streamer with the external trigger.

  2. If you stream a second pulse pattern into an already running sequence, you previously should set the Pulse Streamer to a constant state by using the methods constant() or reset(). Otherwise, the new sequence of the Pulse Streamer slave might already be triggered by the still running stream of the Pulse Streamer master.