Everything involving asynchronicity in acquisition instruments is in this file.
In particular, this includes getting curves and continuously averaging curves.
Using the coroutine syntax introduced in python 3.4+ would make the code more elegant, but it would not be compatible with python 2.7. Hence we have chosen to implement all asynchronous methods such that a promise is returned (a Future-object in python). The promise implements the following methods:
All asynchronous methods also have a blocking equivalent that directly returns the result once it is ready:
Finally, this implmentation using standard python Futures makes it possible to use transparently pyrpl asynchronous methods inside python 3.x coroutines.
Example
This example shows a typical acquisition use case where a sequence of n aquisitions of simultaneous oscilloscope and network analyzer traces are launched
from asyncio import ensure_future, event_loop
async def my_acquisition_routine(n):
for i in range(n):
print("acquiring scope")
fut = ensure_future(p.rp.scope.run_single())
print("acquiring na")
data2 = await p.networkanalyzer.run_single()
# both acquisitions are carried out simultaneously
data1 = await fut
print("loop %i"%i, data1, data2)
ensure_future(my_acquisition_coroutine(10))
eventloop.run_until_complete()
pyrpl.acquisition_module.
AcquisitionModule
(parent, name=None)[source]¶Bases: pyrpl.modules.Module
The asynchronous mode is supported by a sub-object “run” of the module. When an asynchronous acquisition is running and the widget is visible, the current averaged data are automatically displayed. Also, the run object provides a function save_curve to store the current averaged curve on the hard-drive.
The full API of the “run” object is the following.
Methods:
(All methods return immediately) single(): performs an asynchronous acquisition of trace_average curves.
The function returns a promise of the result: an object with a ready() function, and a get() function that blocks until data is ready.
- continuous(): continuously acquires curves, and performs a
- moving average over the trace_average last ones.
- pause(): stops the current acquisition without restarting the
- averaging
stop(): stops the current acquisition and restarts the averaging. save_curve(): saves the currently averaged curve (or curves for scope) curve(): the currently averaged curve
Attributes:
curve_name (str): name of the curve to create upon saving trace_average (int): number of averages in single (not to confuse with
averaging per point)data_avg (array of numbers): array containing the current averaged curve current_avg (int): current number of averages
Setup Attributes:
RunningStateProperty
for available options.MIN_DELAY_CONTINUOUS_MS
= 40¶MIN_DELAY_SINGLE_MS
= 0¶continuous
()[source]¶continuously acquires curves, and performs a moving average over the trace_average last ones.
current_avg
¶curve
(timeout=None)[source]¶Same as curve_async, except:
curve_async
()[source]¶Launches the acquisition for one curve with the current parameters.
curve_name
¶name of the curve to save.
data_avg
¶data_x
¶x-axis of the curves to plot. :return:
running_state
¶Indicates whether the instrument is running acquisitions or not. See RunningStateProperty
for available options.
save_curve
()[source]¶Saves the curve(s) that is (are) currently displayed in the gui in the db_system. Also, returns the list [curve_ch1, curve_ch2]...
setup
(**kwds)¶running_state
Indicates whether the instrument is running acquisitions or not. See RunningStateProperty
for available options.
trace_average
¶number of curves to average in single mode. In continuous mode, a moving window average is performed.
curve_name
name of the curve to save.
single
(timeout=None)[source]¶single_async
()[source]¶Performs an asynchronous acquisition of trace_average curves.
trace_average
number of curves to average in single mode. In continuous mode, a moving window average is performed.
pyrpl.acquisition_module.
CurveFuture
(module, min_delay_ms=20)[source]¶Bases: pyrpl.async_utils.PyrplFuture
The basic acquisition of instruments is an asynchronous process:
For instance, when the scope acquisition has been launched, we know that the curve won’t be ready before duration(), but if the scope is waiting for a trigger event, this could take much longer. Of course, we want the event loop to stay alive while waiting for a pending curve. That’s the purpose of this future object.
After its creation, it will perform the following actions:
- stay inactive for a time given by instrument._remaining_time()
- after that, it will check every min_refresh_delay if a new curve is ready with instrument._data_ready()
- when data is ready, its result will be set with the instrument data, as returned by instrument._get_data()
pyrpl.acquisition_module.
RunFuture
(module, min_delay_ms)[source]¶Bases: pyrpl.async_utils.PyrplFuture
Uses several CurveFuture to perform an average.
2 extra functions are provided to control the acquisition:
pause(): stalls the acquisition
start(): (re-)starts the acquisition (needs to be called at the beginning)
The format for curves are:
pyrpl.acquisition_module.
RunningStateProperty
(options=['running_single', 'running_continuous', 'paused', 'stopped'], **kwargs)[source]¶pyrpl.acquisition_module.
SignalLauncherAcquisitionModule
(module)[source]¶Bases: pyrpl.modules.SignalLauncher
class that takes care of emitting signals to update all possible displays
autoscale_x
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶clear_curve
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶display_curve
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶scan_finished
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶unit_changed
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶update_point
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶x_log_toggled
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶This file contains a number of methods for asynchronous operations.
pyrpl.async_utils.
PyrplFuture
[source]¶Bases: <MagicMock id='139827382130128'>.Future
A promise object compatible with the Qt event loop.
We voluntarily use an object that is different from the native QFuture because we want a promise object that is compatible with the python 3.5+ asyncio patterns (for instance, it implements an __await__ method...).
cancelled
¶Returns whether the promise has been cancelled.
exception
¶Blocks until: a. the result is ready –> returns None b. an exception accured in the execution –> returns the exception the Qt event-loop is allowed to run in parallel.
done
¶Checks whether the result is ready or not.
add_done_callback
¶callback function – add a callback to execute when result becomes available. The callback function takes 1 argument (the result of the promise).
await_exception
(timeout=None)[source]¶Return the exception raised by the call that the future represents.
Parameters: | timeout – The number of seconds to wait for the exception if the future isn’t done. If None, then there is no limit on the wait time. |
---|---|
Returns: | The exception raised by the call that the future represents or None if the call completed without raising. |
Raises: |
|
await_result
(timeout=None)[source]¶Return the result of the call that the future represents. Will not return until either timeout expires or future becomes “done”.
There is one potential deadlock situation here: The deadlock occurs if we await_result while at the same time, this future needs to await_result from another future since the eventloop will be blocked. —> To be safe, don’t use await_result() in a Qt slot. You should rather use result() and add_done_callback() instead.
Parameters: | timeout – The number of seconds to wait for the result if the future isn’t done. If None, then there is no limit on the wait time. |
---|---|
Returns: | The result of the call that the future represents. |
Raises: |
|
pyrpl.async_utils.
sleep
(delay)[source]¶Sleeps for delay
seconds + runs the event loop in the background.
- This function will never return until the specified delay in seconds is elapsed.
- During the execution of this function, the qt event loop (== asyncio event-loop in pyrpl) continues to process events from the gui, or from other coroutines.
- Contrary to time.sleep() or async.sleep(), this function will try to achieve a precision much better than 1 millisecond (of course, occasionally, the real delay can be longer than requested), but on average, the precision is in the microsecond range.
- Finally, care has been taken to use low level system-functions to reduce CPU-load when no events need to be processed.
More details on the implementation can be found on the page: https://github.com/lneuhaus/pyrpl/wiki/Benchmark-asynchronous-sleep-functions.
The parameters of any module are controlled by descriptors deriving from
BaseAttribute
.
An attribute is a field that can be set or get by several means:
Of course, the gui/parameter file/actual values have to stay “in sync” each time the attribute value is changed. The necessary mechanisms are happening behind the scene, and they are coded in this file.
pyrpl.attributes.
AttributeList
(parent, module, *args, **kwargs)[source]¶Bases: list
A list of attributes.
This class is not an attribute/property by itself, but is the object returned by AttributeListProperty that correctly extends list methods to communicate a change in the list throughout pyrpl.
When a list-specific operation is performed that alters the values, the AttributeListProperty object is informed about this and will ensure the correct propagation of the signal.
selected
¶pyrpl.attributes.
BaseAttribute
[source]¶Bases: object
base class for attribute - only used as a placeholder
pyrpl.attributes.
BaseProperty
(default=None, doc='', ignore_errors=False, call_setup=False)[source]¶Bases: pyrpl.attributes.BaseAttribute
A Property is a special type of attribute that is not mapping a fpga value, but rather an attribute _name of the module. This is used mainly in SoftwareModules
An attribute is a field that can be set or get by several means:
The concrete derived class need to have certain attributes properly defined:
default
= None¶launch_signal
(module, new_value, appendix=[])[source]¶Updates the widget and other subscribers with the module’s value.
validate_and_normalize
(obj, value)[source]¶This function should raise an exception if the value is incorrect. Normalization can be:
value_updated
(module, value=None, appendix=[])[source]¶Once the value has been changed internally, this function is called to perform the following actions:
Note for developers: We might consider moving the 2 last points in a connection behind the signal “attribute_changed”.
widget
= None¶pyrpl.attributes.
BasePropertyListProperty
(*args, **kwargs)[source]¶Bases: pyrpl.attributes.BaseProperty
An arbitrary length list of items that behave like BaseProperty.
A derived class FloatPropertyListProperty(BasePropertyListProperty) will behave as a list of FloatProperty-like items.
default
= []¶element_cls
¶the class of the elements of the list
pyrpl.attributes.
BaseRegister
(address, bitmask=None, **kwargs)[source]¶Bases: pyrpl.attributes.BaseProperty
Registers implement the necessary read/write logic for storing an attribute on the redpitaya. Interface for basic register of type int. To convert the value between register format and python readable format, registers need to implement “from_python” and “to_python” functions
default
= None¶pyrpl.attributes.
BoolIgnoreProperty
(default=None, doc='', ignore_errors=False, call_setup=False)[source]¶Bases: pyrpl.attributes.BoolProperty
An attribute for booleans
default
= False¶pyrpl.attributes.
BoolProperty
(default=None, doc='', ignore_errors=False, call_setup=False)[source]¶Bases: pyrpl.attributes.BaseProperty
A property for a boolean value
default
= False¶pyrpl.attributes.
BoolRegister
(address, bit=0, bitmask=None, invert=False, **kwargs)[source]¶Bases: pyrpl.attributes.BaseRegister
, pyrpl.attributes.BoolProperty
Inteface for boolean values, 1: True, 0: False. invert=True inverts the mapping
pyrpl.attributes.
ComplexAttributeListProperty
(*args, **kwargs)[source]¶Bases: pyrpl.attributes.BasePropertyListProperty
, pyrpl.attributes.ComplexProperty
pyrpl.attributes.
ComplexProperty
(min=<MagicMock name='mock.inf.__neg__()' id='139827380281936'>, max=<MagicMock name='mock.inf' id='139827380218960'>, increment=0, log_increment=False, **kwargs)[source]¶pyrpl.attributes.
ConstantIntRegister
(address, bits=32, bitmask=None, **kwargs)[source]¶Bases: pyrpl.attributes.IntRegister
Implements an int register that only interacts with the FPGA once and subsequently returns the first read value from python memory.
pyrpl.attributes.
CurveProperty
(no_curve_first=False, show_childs=False, **kwargs)[source]¶Bases: pyrpl.attributes.CurveSelectProperty
property for a curve whose widget plots the corresponding curve.
Unfortunately, the widget does not allow to select the curve, i.e. selection must be implemented with another CurveSelectProperty.
pyrpl.attributes.
CurveSelectListProperty
(no_curve_first=False, show_childs=False, **kwargs)[source]¶Bases: pyrpl.attributes.CurveSelectProperty
same as above, but widget is a list to select from
pyrpl.attributes.
CurveSelectProperty
(no_curve_first=False, show_childs=False, **kwargs)[source]¶Bases: pyrpl.attributes.SelectProperty
An attribute to select a curve from all available ones.
The curve object is loaded to instance._name_object, where ‘name’ stands for the name of this attribute. The property can be set by either passing a CurveDB object, or a curve id.
pyrpl.attributes.
DataProperty
(default=None, doc='', ignore_errors=False, call_setup=False)[source]¶Bases: pyrpl.attributes.BaseProperty
Property for a dataset (real or complex), that can be plotted.
pyrpl.attributes.
FilterProperty
(default=None, doc='', ignore_errors=False, call_setup=False)[source]¶Bases: pyrpl.attributes.BaseProperty
An attribute for a list of bandwidth. Each bandwidth has to be chosen in a list given by self.valid_frequencies(module) (evaluated at runtime). If floats are provided, they are normalized to the nearest values in the list. Individual floats are also normalized to a singleton. The number of elements in the list are also defined at runtime. A property for a list of float values to be chosen in valid_frequencies(module).
pyrpl.attributes.
FilterRegister
(address, filterstages, shiftbits, minbw, **kwargs)[source]¶Bases: pyrpl.attributes.BaseRegister
, pyrpl.attributes.FilterProperty
Interface for up to 4 low-/highpass filters in series (filter_block.v)
correction_factors
= {0.5: 0.7, 0.25: 1.65, 0.001953125: 1.0, 0.00390625: 1.0, 0.125: 1.17, 0.015625: 1.02, 0.03125: 1.04, 0.0078125: 1.01, 0.0625: 1.08}¶pyrpl.attributes.
FloatAttributeListProperty
(*args, **kwargs)[source]¶Bases: pyrpl.attributes.BasePropertyListProperty
, pyrpl.attributes.FloatProperty
pyrpl.attributes.
FloatProperty
(min=<MagicMock name='mock.inf.__neg__()' id='139827380281936'>, max=<MagicMock name='mock.inf' id='139827380218960'>, increment=0, log_increment=False, **kwargs)[source]¶Bases: pyrpl.attributes.NumberProperty
An attribute for a float value.
default
= 0.0¶pyrpl.attributes.
FloatRegister
(address, bits=14, bitmask=None, norm=1.0, signed=True, invert=False, **kwargs)[source]¶Bases: pyrpl.attributes.IntRegister
, pyrpl.attributes.FloatProperty
Implements a fixed point register, seen like a (signed) float from python
pyrpl.attributes.
FrequencyProperty
(**kwargs)[source]¶Bases: pyrpl.attributes.FloatProperty
An attribute for frequency values Same as FloatAttribute, except it cannot become negative.
pyrpl.attributes.
FrequencyRegister
(address, **kwargs)[source]¶Bases: pyrpl.attributes.FloatRegister
, pyrpl.attributes.FrequencyProperty
Registers that contain a frequency as a float in units of Hz
CLOCK_FREQUENCY
= 125000000.0¶pyrpl.attributes.
GainRegister
(address, bits=14, bitmask=None, norm=1.0, signed=True, invert=False, **kwargs)[source]¶Bases: pyrpl.attributes.FloatRegister
A register used mainly for gains, that replaces round-off to zero by round-off to the lowest-possible value.
avoid_round_off_to_zero
= True¶pyrpl.attributes.
IORegister
(read_address, write_address, direction_address, outputmode=True, **kwargs)[source]¶Bases: pyrpl.attributes.BoolRegister
Interface for digital outputs if argument outputmode is True, output mode is set, else input mode
pyrpl.attributes.
IntProperty
(min=<MagicMock name='mock.inf.__neg__()' id='139827380281936'>, max=<MagicMock name='mock.inf' id='139827380218960'>, increment=1, log_increment=False, **kwargs)[source]¶pyrpl.attributes.
IntRegister
(address, bits=32, bitmask=None, **kwargs)[source]¶Bases: pyrpl.attributes.BaseRegister
, pyrpl.attributes.IntProperty
Register for integer values encoded on less than 32 bits.
pyrpl.attributes.
LongRegister
(address, bits=32, bitmask=None, **kwargs)[source]¶Bases: pyrpl.attributes.IntRegister
Interface for register of python type int/long with arbitrary length ‘bits’ (effectively unsigned)
pyrpl.attributes.
ModuleAttribute
(default=None, doc='', ignore_errors=False, call_setup=False)[source]¶Bases: pyrpl.attributes.BaseProperty
This is the base class for handling submodules of a module.
The actual implementation is found in module_attributes.ModuleProperty. This object is only used inside the Module class
pyrpl.attributes.
NumberProperty
(min=<MagicMock name='mock.inf.__neg__()' id='139827380281936'>, max=<MagicMock name='mock.inf' id='139827380218960'>, increment=0, log_increment=False, **kwargs)[source]¶Bases: pyrpl.attributes.BaseProperty
Abstract class for ints and floats
default
= 0¶pyrpl.attributes.
PWMRegister
(address, CFG_BITS=24, PWM_BITS=8, **kwargs)[source]¶Bases: pyrpl.attributes.FloatRegister
FloatRegister that defines the PWM voltage similar to setting a float.
pyrpl.attributes.
PhaseProperty
(min=<MagicMock name='mock.inf.__neg__()' id='139827380281936'>, max=<MagicMock name='mock.inf' id='139827380218960'>, increment=0, log_increment=False, **kwargs)[source]¶Bases: pyrpl.attributes.FloatProperty
An attribute to represent a phase
pyrpl.attributes.
PhaseRegister
(address, bits=32, bitmask=None, invert=False, **kwargs)[source]¶Bases: pyrpl.attributes.FloatRegister
, pyrpl.attributes.PhaseProperty
Registers that contain a phase as a float in units of degrees.
pyrpl.attributes.
Plotter
(legend='value')[source]¶Bases: pyrpl.attributes.BaseProperty
property for plotting in the GUI window.
passing a value, list of values, or a dict of color-value pairs results in plotting the values as a function of time in the GUI
pyrpl.attributes.
ProxyProperty
(path_to_target, **kwargs)[source]¶Bases: pyrpl.attributes.BaseProperty
An attribute that is a proxy to another attribute.
This attribute essentially behaves like the one that is reached by instance.path_to_target, always staying in synch.
pyrpl.attributes.
SelectProperty
(options=[], **kwargs)[source]¶Bases: pyrpl.attributes.BaseProperty
change_options
(instance, new_options)[source]¶Changes the possible options acceptable by the Attribute:
default
= None¶get_default
(instance)[source]¶returns the default value. default is pre-defined value if that is not a valid option. Otherwise the first valid option is taken, and if that is not possible (no options), None is taken.
pyrpl.attributes.
SelectRegister
(address, bitmask=None, options={}, **kwargs)[source]¶Bases: pyrpl.attributes.BaseRegister
, pyrpl.attributes.SelectProperty
Implements a selection register, such as for multiplexers.
The options must be a dict, where the keys indicate the available options and the values indicate the corresponding fpga register values. If different keys point to the same register value, the keys are nevertheless distinguished (allows implementing aliases that may vary over time if options is a callable object).
pyrpl.attributes.
StringProperty
(default=None, doc='', ignore_errors=False, call_setup=False)[source]¶Bases: pyrpl.attributes.BaseProperty
An attribute for string (there is no corresponding StringRegister).
default
= ''¶pyrpl.attributes.
TextProperty
(default=None, doc='', ignore_errors=False, call_setup=False)[source]¶Bases: pyrpl.attributes.StringProperty
Same as StringProperty, but the gui displays it as multi-line text.
pyrpl.curvedb.
CurveDB
(name='some_curve')[source]¶Bases: object
all
()[source]¶Returns: | A list of all CurveDB objects on the computer. |
---|---|
Return type: | list of CurveDB |
all_pks
()[source]¶Returns: | A list of the primary keys of all CurveDB objects on the computer. |
---|---|
Return type: | list of int |
childs
¶create
(*args, **kwds)[source]¶Creates a new curve, first arguments should be either Series(y, index=x) or x, y. kwds will be passed to self.params
file_extension
= '.dat'¶get_child
(name)[source]¶Returns the child of the curve with name ‘name’
Parameters: | name (str) – Name of the child curve to be retrieved. If several childs have the same name, the first one is returned. |
---|---|
Returns: | the child curve |
Return type: | CurveDB |
name
¶parent
¶pk
¶(int) – The primary Key of the
pyrpl.errors.
ExpectedPyrplError
(message='', **kwargs)[source]¶Bases: exceptions.Exception
Raise when an unexpected error occurs that should be reported
ENDC
= '\x1b[0m'¶STARTC
= '\x1b[35m'¶pyrpl_error_message
= '\x1b[35m\n\n\n An expected error occured in PyRPL. Please follow the instructions\n in this error message and retry! \x1b[0m'¶pyrpl.errors.
UnexpectedPyrplError
(message='', **kwargs)[source]¶Bases: exceptions.Exception
Raise when an unexpected error occurs that should be reported
ENDC
= '\x1b[0m'¶STARTC
= '\x1b[35m'¶pyrpl_error_message
= '\x1b[35m\n\n\n An unexpected error occured in PyRPL. Please help us to improve the\n program by copy-pasting the full error message and optionally some\n additional information regarding your setup on\n https://www.github.com/lneuhaus/pyrpl/issues as a new issue. It is\n possible that we can help you to get rid of the error. If your error\n is related to improper usage of the PyRPL API, your report will\n help us improve the documentation. Thanks! \x1b[0m'¶pyrpl.memory.
MemoryBranch
(parent, branch)[source]¶Bases: object
Represents a branch of a memoryTree
All methods are preceded by an underscore to guarantee that tab expansion of a memory branch only displays the available subbranches or leaves. A memory tree is a hierarchical structure. Nested dicts are interpreted as subbranches.
Parameters: |
|
---|
pyrpl.memory.
MemoryTree
(filename=None, source=None, _loadsavedeadtime=3.0)[source]¶Bases: pyrpl.memory.MemoryBranch
The highest level of a MemoryBranch construct. All attributes of this object that do not start with ‘_’ are other MemoryBranch objects or Leaves, i.e. key - value pairs.
Parameters: | filename (str) – The filename of the .yml file defining the MemoryTree structure. |
---|
pyrpl.memory.
get_config_file
(filename=None, source=None)[source]¶returns the path to a valid, existing config file with possible source specification
pyrpl.module_attributes.
ModuleDict
(parent, name=None)[source]¶Bases: pyrpl.modules.Module
container class that loosely resembles a dictionary which contains submodules
Setup Attributes:
setup
(**kwds)¶Sets the module up for acquisition with the current setup attribute values.
setup_attributes
¶pyrpl.module_attributes.
ModuleDictProperty
(module_cls=None, default=None, doc='', ignore_errors=False, **kwargs)[source]¶Bases: pyrpl.module_attributes.ModuleProperty
default_module_cls
¶alias of Module
pyrpl.module_attributes.
ModuleList
(parent, name=None, element_cls=<class 'pyrpl.modules.Module'>, default=[])[source]¶Bases: pyrpl.modules.Module
, list
a list of modules Setup Attributes:
setup
(**kwds)¶Sets the module up for acquisition with the current setup attribute values.
setup_attributes
¶pyrpl.module_attributes.
ModuleListProperty
(element_cls, default=None, doc='', ignore_errors=False)[source]¶Bases: pyrpl.module_attributes.ModuleProperty
A property for a list of submodules.
default
= []¶module_cls
¶alias of ModuleList
pyrpl.module_attributes.
ModuleProperty
(module_cls, default=None, doc='', ignore_errors=False, call_setup=False, **kwargs)[source]¶Bases: pyrpl.attributes.ModuleAttribute
A property for a submodule.
The ModuleAttribute is declared with: ModuleAttribute(module_cls, default, doc)
The module_cls is instantiated in the __init__ of the parent module
default
= {}¶Modules are the basic building blocks of Pyrpl.
The internal structure of the FPGA is made of individual modules, each
performing a well defined task. Each of these FPGA modules are represented
in python by a HardwareModule
.
Higher-level operations, for instance those that need a coordinated
operation of several HardwareModules is performed by a SoftwareModule,
defined in a class derived from Module
.
Thus, all modules (both HardwareModule
and Software modules inherit
from Module
which gives them basic capabilities such as displaying
their attributes in the GUI having their state load and saved in the config
file.
pyrpl.modules.
DoSetup
(parent)[source]¶Bases: object
A context manager that allows to nicely write Module setup functions.
Usage example in Module._setup()
:
def _setup(self):
# _setup_ongoing is False by default
assert self._setup_ongoing == False
with self.do_setup:
# now _setup_ongoing is True
assert self._setup_ongoing == True
# do stuff that might fail
raise BaseException()
# even if _setup fails, _setup_ongoing is False afterwards or in
# the next call to _setup()
assert self._setup_ongoing == False
pyrpl.modules.
HardwareModule
(parent, name=None)[source]¶Bases: pyrpl.modules.Module
Module that directly maps a FPGA module. In addition to BaseModule’s requirements, HardwareModule classes must have the following class attributes:
- addr_base (int): the base address of the module, such as 0x40300000
Setup Attributes:
parent
= None¶setup
(**kwds)¶Sets the module up for acquisition with the current setup attribute values.
pyrpl.modules.
Module
(parent, name=None)[source]¶Bases: object
A module is a component of pyrpl doing a specific task.
Module is the base class for instruments such as the Scope/Lockbox/NetworkAnalyzer. A module can have a widget to build a graphical user interface on top of it. It is composed of attributes (see attributes.py) whose values represent the current state of the module (more precisely, the state is defined by the value of all attributes in _setup_attributes) The module can be slaved or freed by a user or another module. When the module is freed, it goes back to the state immediately before being slaved. To make sure the module is freed, use the syntax:
with pyrpl.mod_mag.pop('owner') as mod: mod.do_something() mod.do_something_else()
- Attributes:
- get_setup_attributes(): returns a dict with the current values of
- the setup attributes
set_setup_attributes(**kwds)
: sets the provided setup_attributes- (setup is not called)
- save_state(name): saves the current ‘state’ (using
- get_setup_attribute) into the config file
- load_state(name): loads the state ‘name’ from the config file (setup
- is not called by default)
erase_state(name): erases state ‘name’ from config file create_widget(): returns a widget according to widget_class
setup(**kwds)
: first, performsset_setup_attributes(**kwds)
,then calls _setup() to set the module ready for acquisition. This method is automatically created by ModuleMetaClass and it combines the docstring of individual setup_attributes with the docstring of _setup()
- free(): sets the module owner to None, and brings the module back the
- state before it was slaved equivalent to module.owner = None)
- get_yml(state=None): get the yml code representing the state “state’
- or the current state if state is None
- set_yml(yml_content, state=None): sets the state “state” with the
- content of yml_content. If state is None, the state is directly loaded into the module.
- name: attributed based on name at instance creation
- (also used as a section key in the config file)
states (list): the list of states available in the config file owner (string): a module can be owned (reserved) by a user or another
module. The module is free if and only if owner is None
- pyrpl (
Pyrpl
): recursively looks through parent modules until it- reaches the Pyrpl instance
Class attributes to be implemented in derived class:
- all individual attributes (instances of BaseAttribute)
- _setup_attributes: attribute names that are touched by setup(**kwds)/ saved/restored upon module creation
- _gui_attributes: attribute names to be displayed by the widget
- _callback_attributes: attribute_names that triggers a callback when their value is changed in the base class, _callback just calls setup()
- _widget_class: class of the widget to use to represent the module in the gui(a child of ModuleWidget)
Methods to implement in derived class:
_setup(): sets the module ready for acquisition/output with the current attribute’s values. The metaclass of the module autogenerates a function like this:
def setup(self, **kwds): """ _ docstring is the result of the following pseudocode: _ print(DOCSTRING_OF_FUNCTION("_setup")) for attribute in self.setup_attributes: print(DOCSTRING_OF_ATTRIBUTE(attribute)) """ self.set_setup_attributes(kwds) return self._setup()_ownership_changed(old, new): this function is called when the module owner changes it can be used to stop the acquisition for instance.
Setup Attributes:
c
¶Returns a MemoryBranch object used for storing data in the configuration file.
The branch corresponding to the module is a subbranch of the parent module’s branch with the name of the module.
erase_state
(name)[source]¶Removes the state “name’ from the config file :param name: name of the state to erase :return: None
get_setup_attributes
()[source]¶Returns a dict with the current values of the setup attributes.
Recursively calls get_setup_attributes for sub_modules and assembles a hierarchical dictionary.
Returns: | contains setup_attributes and their current values. |
---|---|
Return type: | dict |
get_yml
(state=None)[source]¶Parameters: | state – The name of the state to inspect. If state is None–> |
---|
then, use the current instrument state. :return: a string containing the yml code
load_state
(name=None)[source]¶Loads the state with name “name” from the config file. If state_branch is left unchanged, uses the normal class_section.states convention.
name
= None¶owner
¶pyrpl
¶Recursively looks through patent modules untill pyrpl instance is reached.
save_state
(name=None)[source]¶Saves the current state under the name “name” in the config file. If state_section is left unchanged, uses the normal class_section.states convention.
set_setup_attributes
(**kwds)[source]¶Sets the values of the setup attributes. Without calling any callbacks
set_yml
(yml_content, state=None)[source]¶Parameters: |
|
---|
then, use the current instrument state and reloads it immediately :return: None
setup
(**kwds)¶Sets the module up for acquisition with the current setup attribute values.
setup_attributes
¶return – a dict with the current values of the setup attributes. Recursively collects setup_attributes for sub_modules.
states
¶Returns the names of all saved states of the module.
pyrpl.modules.
ModuleMetaClass
(classname, bases, classDict)[source]¶Bases: type
Generate Module classes with two features: - __new__ lets attributes know what name they are referred to in the class that contains them. - __new__ also lists all the submodules. This info will be used when instantiating submodules at module instanciation time. - __init__ auto-generates the function setup() and its docstring
pyrpl.modules.
SignalLauncher
(module)[source]¶Bases: <MagicMock name='mock.QtCore' id='139827381803152'>.QObject
Object that is used to handle signal the emission for a Module
.
A QObject that is connected to the widgets to update their value when attributes of a module change. Any timers needed to implement the module functionality shoud be implemented here as well.
change_options
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶change_ownership
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶connect_widget
(widget)[source]¶Establishes all connections between the module and the widget by name.
emit_signal_by_name
(name, *args, **kwds)[source]¶Emits signal “name” with the specfified args and kwds.
refresh_filter_options
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶update_attribute_by_name
= <MagicMock name='mock.QtCore.Signal()' id='139827380610576'>¶# DEPRECATED DOCSTRING - KEEP UNTIL DOCUMENTATION IS READY pyrpl.py - high-level lockbox functionality
A lockbox is a device that converts a number of input signals into a number of output signals suitable to stabilize a physical system in a desired state. This task is generally divided into two steps: 1) bring the system close the desired state where it can be linearized 2) keep it there using linear control.
The task is further divided into several subtasks: 0a) Condition the input signals so that they are suitable for the next steps - offset removal - input filters - demodulation / lockin - inversion 0b) Estimate the system state from the past and present history of input and output signals. 0c) Build a filter for the output signals such that they can be conveniently addressed with higher-level lockbox logic.
1) As above: apply reasonable action to the outputs to approach the system to the desired state. We generally call this the ‘search’ step. - provide a number of algorithms/recipes to do this
2) As above: Turn on linear feedback. We call this the ‘lock’ step. - connect the input signals with appropriate gain to the outputs - the gain depends on the state of the system, so internal state representation will remain useful here
This naturally divides the lockbox object into 3 subcomponents: a) inputs b) internal model c) outputs
which will be interconnected by the algorithms that come with the model and make optimal use of the available inputs and outputs. The job of the configuration file is to provide a maximum of information about the inputs, outputs and the physical system (=internal model) so that the lockbox is effective and robust. The lockbox will usually require both a coarse-tuning and an optimization step for optimum performance, which will both adjust the various parameters for the best match between model and real system.
Let’s make this reasoning more clear with an example:
A Fabry-Perot cavity is to be locked near resonance using a PDH scheme. The incident laser beam goes through a phase modulator. The cavity contains a piezo with estimated bandwidth 10 kHz (appearance of first resonance) and a displacement of 350 nm/V that goes into the piezo amplifier. To limit the effect of amplifier noise, we have inserted an RC lowpass between amplifier and piezo with a cutoff frequency of 100 Hz. The laser contains another piezo with estimated bandwidth of 50 kHz that changes the laser frequency by 5 MHz/V. An RC filter provides a lowpass with 1kHz cutoff. Finally, the cavity can be tuned through its temperature with a bandwidth slower than 0.1 Hz. We estimate from thermal expansion coefficients that 1 V to the Peltier amplifier leading to 3 K heating of the cavity spacer should lead to 30ppm/K*20cm*3K/V = 18 micron/V length change. Both reflection and transmission of the cavity are available error signals. The finesse of the cavity is 5000, and therefore there are large regions of output signals where no useful error signal can be obtained.
We first generate a clean list of available inputs and outputs and some parameters of the cavity that we know already:
# also possible # in2: pdh # for externally generated pdh
# we insert a bias-T with separation frequency around 1 MHz behind out1 # this allows us to use the fast output for both the piezo and PDH modulator:
amplitude: 0.1 frequency: 50e6
type: fabryperot wavelength: 1064e-9 finesse: 5000 # round-trip length in m (= twice the length for ordinary Fabry-Perot) length: 0.72 lock: # lock methods in order of preferrence
- order:
- pdh reflection transmission
# when approaching a resonance, we can either abruptly jump or smoothly # ramp from one error signal to another. We specify our preferrence with # the order of keywords after transition transition: [ramp, jump] # target value for our lock. The API provides many ways to adjust this at # runtime target:
detuning: 0
# search algorithms to use in order of preferrence, as available in model search:
drift bounce
Having selected fabryperot as modeltype, the code will automatically search for a class named fabryperot in the file model.py to provide for the internal state representation and all algorithms. You can create your own model by adding other classes to this file, or by inheriting from existing ones and adding further functionality. The naming of all other configuration parameters is linked to the model, since all functionality that makes use of these para- meters is implemented there. Another very often used model type is “interferometer”. The only difference is here that
pyrpl.pyrpl.
Pyrpl
(config=None, source=None, **kwargs)[source]¶Bases: object
Higher level object, in charge of loading the right hardware and software module, depending on the configuration described in a config file.
Parameters: |
|
---|
hardware_modules
¶List of all hardware modules loaded in this configuration.
load_software_modules
()[source]¶load all software modules defined as root element of the config file.
modules
¶pyrpl.pyrpl_utils.
Bijection
(*args, **kwargs)[source]¶Bases: dict
This class defines a bijection object based on dict
It can be used exactly like dict, but additionally has a property ‘inverse’ which contains the inverted {value: key} dict.
pyrpl.pyrpl_utils.
DuplicateFilter
(name='')[source]¶Bases: logging.Filter
Prevent multiple repeated logging message from polluting the console
pyrpl.pyrpl_utils.
get_base_module_class
(module)[source]¶returns the base class of module that has the same name as module
pyrpl.pyrpl_utils.
get_class_name_from_module_name
(module_name)[source]¶returns the class name corresponding to a module_name
pyrpl.pyrpl_utils.
get_unique_name_list_from_class_list
(cls_list)[source]¶returns a list of names using cls.name if unique or cls.name1, cls.name2... otherwise. Order of the name list matches order of cls_list, such that iterating over zip(cls_list, name_list) is OK
pyrpl.pyrpl_utils.
recursive_setattr
(root, path, value)[source]¶returns root.path = value (i.e. root.attr1.attr2 = value)
pyrpl.pyrpl_utils.
setloglevel
(level='info', loggername='pyrpl')[source]¶sets the log level to the one specified in config file
pyrpl.redpitaya.
RedPitaya
(config=None, **kwargs)[source]¶Bases: object
cls_modules
= [<class 'pyrpl.hardware_modules.hk.HK'>, <class 'pyrpl.hardware_modules.ams.AMS'>, <class 'pyrpl.hardware_modules.scope.Scope'>, <class 'pyrpl.hardware_modules.sampler.Sampler'>, <class 'pyrpl.hardware_modules.asg.Asg'>, <class 'pyrpl.hardware_modules.asg.Asg'>, <class 'pyrpl.hardware_modules.pwm.Pwm'>, <class 'pyrpl.hardware_modules.pwm.Pwm'>, <class 'pyrpl.hardware_modules.iq.Iq'>, <class 'pyrpl.hardware_modules.iq.Iq'>, <class 'pyrpl.hardware_modules.iq.Iq'>, <class 'pyrpl.hardware_modules.pid.Pid'>, <class 'pyrpl.hardware_modules.pid.Pid'>, <class 'pyrpl.hardware_modules.pid.Pid'>, <class 'pyrpl.hardware_modules.trig.Trig'>, <class 'pyrpl.hardware_modules.iir.iir.IIR'>]¶restartserver
(port=None)[source]¶restart the server. usually executed when client encounters an error
pyrpl.redpitaya_client.
DummyClient
[source]¶Bases: object
Class for unitary tests without RedPitaya hardware available
fpgamemory
= {'1074790420': 1}¶