What is PyRPL?

PyRPL is an open-source software package providing many instruments on cheap FPGA hardware boards, e.g.:

  • oscilloscopes,

  • network analyzers,

  • lock-in amplifiers,

  • multiple automatic feedback controllers,

  • digital filters of very high order (24),

  • and much more.

PyRPL currently runs exclusively on the Red Pitaya.

The Red Pitaya (a.k.a. STEM Lab) (http://www.redpitaya.com, see full documentation) is an affordable (ca. 260 Euros) FPGA board with fast (125 MHz) analog inputs and outputs.

PyRPL comes with a graphical user interface (GUI).

See our GUI manual or the video tutorial on youtube.

PyRPL has a convenient Python API.

See High-level API example or Low-level API example, and the full API documentation .

PyRPL binary executables for Windows, Linux and macOS

can be easily downloaded and run without any installation work.

PyRPL’s code is entirely public on github and can be customized,

including the Verilog source code for the FPGA which is based on the official Red Pitaya software version 0.95.

PyRPL is already used in many research groups all over the world.

See for yourself the Feedback by PyRPL users.

PyRPL is free software and comes with the MIT License.

Read the license for more details!

Manual

Low-level API example

# import pyrpl library
import pyrpl

# create an interface to the Red Pitaya
r = pyrpl.Pyrpl().redpitaya

r.hk.led = 0b10101010  # change led pattern

# measure a few signal values
print("Voltage at analog input1: %.3f" % r.sampler.in1)
print("Voltage at analog output2: %.3f" % r.sampler.out2)
print("Voltage at the digital filter's output: %.3f" % r.sampler.iir)

# output a function U(t) = 0.5 V * sin(2 pi * 10 MHz * t) to output2
r.asg0.setup(waveform='sin',
             amplitude=0.5,
             frequency=10e6,
             output_direct='out2')

# demodulate the output signal from the arbitrary signal generator
r.iq0.setup(input='asg0',   # demodulate the signal from asg0
            frequency=10e6,  # demodulaltion at 10 MHz
            bandwidth=1e5)  # demodulation bandwidth of 100 kHz

# set up a PID controller on the demodulated signal and add result to out2
r.pid0.setup(input='iq0',
             output_direct='out2',  # add pid signal to output 2
             setpoint=0.05, # pid setpoint of 50 mV
             p=0.1,  # proportional gain factor of 0.1
             i=100,  # integrator unity-gain-frequency of 100 Hz
             input_filter = [3e3, 10e3])  # add 2 low-passes (3 and 10 kHz)

# modify some parameters in real-time
r.iq0.frequency += 2.3  # add 2.3 Hz to demodulation frequency
r.pid0.i *= 2  # double the integrator unity-gain-frequency

# take oscilloscope traces of the demodulated and pid signal
data = r.scope.single(input1='iq0', input2='pid0',
                     duration=1.0, trigger_source='immediately')

High-level API example

# import pyrpl library
import pyrpl

# create a Pyrpl object and store the configuration in a file 'filter-cavity.yml'
p = pyrpl.Pyrpl(config='filter-cavity')

# ... connect hardware (a Fabry-Perot cavity in this example) and
#     configure its paramters with the PyRPL GUI that shows up

# sweep the cavity length
p.lockbox.sweep()

# calibrate the cavity parameters
p.lockbox.calibrate()

# lock to the resonance with a predefined sequence
p.lockbox.lock()

# launch two different measurements simultaneously
transfer_function = p.network_analyzer.single_async(
        input='lockbox.reflection', output='out2',
        start=1e3, stop=1e6, points=10000, rbw=1000)
spectrum = p.spectrum_analyzer.single_async(
        input='in2', span=1e5, trace_averages=10)

# wait for measurements to finish
while not transfer_function.done() and not spectrum.done():
    # check whether lock was lost
    if not p.lockbox.is_locked():
        # re-lock the cavity
        p.lockbox.relock()
        # re-start measurements
        transfer_function = p.network_analyzer.single_async()
        spectrum = p.spectrum_analyzer.single_async()

# display a measurement result in the curve browser
p.curve_viewer.curve = transfer_function.result()

Additional Resources

Old documentation sections

The following sections are legacy documentation kept for reference. Please prefer the Manual section for current guidance.

Current build status

code coverage Download pyrpl join chat on gitter License

Releases

Version 0.9.9.1 (August 6, 2026)

  • include dynamically imported lockbox models in PyInstaller executables

  • prevent frozen-app import failures from being obscured by an invalid fallback import

  • make PyQt5 selection deterministic when other Qt bindings are installed in the build environment

  • smoke-test the Windows executable before publishing a binary release

Version 0.9.9.0 (August 5, 2026)

  • add compatibility with Red Pitaya OS 3, including FPGA overlay loading and automatic installation of the compatible hard-float monitor server

  • improve Red Pitaya OS-version detection and command-output parsing

  • disable Nagle’s algorithm for monitor-server requests to avoid delayed small register transactions, especially on Windows

  • allow lockbox inputs and outputs to be added and removed dynamically and persist their selected signal classes

  • make lockbox widgets robust to unconfigured inputs and Qt tab initialization, and isolate lockbox/PID state between tests

  • keep constant scope traces visible when they coincide with a grid line

  • modernize imports and formatting and update the test suite for Python 3.13

Version 0.9.8.0

  • add compatibility with Red Pitaya Gen 2

  • add smarter reloadfpga="auto" startup behavior, reloading the FPGA image only when the PyRPL bitfile is not already loaded

  • improve and modernize the documentation

  • improve SSH connection handling

  • support Python through version 3.13; Python 3.14 is not yet supported because of changes to asyncio

  • modernize continuous integration and testing; remote hardware tests can remain sensitive to network latency between GitHub-hosted runners and the Red Pitaya

Version 0.9.5.0

  • merges the “0.9.3-develop” branch with accumulated upgrades from over 2 years

  • last version to support Python 2.7 (though not running tests anymore)

  • tested on Python 3.6 and 3.7

  • significant improvements to IIR filter module

Version 0.9.4.0

  • smoother transitions of output voltages during lockbox stage transitions

  • extend automatic Red Pitaya discovery to multiple network adapters and STEMlab OS 0.98

  • improve the documentation hosted on pyrpl.org and provide a video tutorial

  • automatically generate Windows, Linux, and macOS binaries for releases and publish them on SourceForge

Version 0.9.3.x and earlier

There are no release notes for PyRPL versions prior to version 0.9.4.0.