Getting Started
Installation
Prerequisites
Python 3.12 or higher, might work with older versions but not tested
CMake 3.16 or higher (for building from source)
ChimeraTK DeviceAccess library installed
Repository-Based Installation on Debian/Ubuntu systems
If you haven’t already, add the public DOOCS Package Repository to your system, receive the DESY DOOCS key and add the DOOCS repository.
wget -O - https://doocs-web.desy.de/pub/doocs/DOOCS-key.gpg.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/doocs-keyring.gpg
sudo sh -c 'echo "deb https://doocs-web.desy.de/pub/doocs $(lsb_release -cs) main" > /etc/apt/sources.list.d/doocs.list'
Installation of the actual Python bindings package can then be done via apt, the package is named python3-mtca4upy:
sudo apt update && sudo apt-get install python3-mtca4upy
From Source
# Clone the repository
git clone https://github.com/ChimeraTK/ChimeraTK-DeviceAccess-PythonBindings.git
cd ChimeraTK-DeviceAccess-PythonBindings
# Build and install
mkdir build && cd build
cmake ..
make
sudo make install
Your First Program
Let’s create a simple program to read a value from a device.
Prerequisites
You will need a device with a map file, that can be referenced in a dmap with the respective backend. For testing purposes, you can use the dummy backend with a dummy device map entry like this:
# DEVICE_LABEL backend_specification
someDummyDevice (dummy?map=./someDummyModule.map)
someSharedDummyDevice (sharedMemoryDummy?map=someDummyModule.map)
Note
When testing application code, it is often beneficial not to rely on real hardware. ChimeraTK-DeviceAccess provides two backends for this purpose, the ChimeraTK::DummyBackend and the ChimeraTK::SharedDummyBackend. The DummyBackend emulates a devices’ register space in application memory. The SharedDummyBackend allocates the registers in shared memory, so it can be access from multiple processes. E.g., QtHardMon or Chai can be used to stimulate and monitor a running application. Hence, these backends provide a generic way to test input-/output- operations on the application.
The following snippet gives a map file with a 32-bit scalar register and an 8-bit array register, that can be used with the dummy backends:
# name nr of elements address size bar width fracbits signed access
SENSORS.TEMPERATURE 0x01 0x00000000 0x00000004 0x0 32 4 1 RW
SENSORS.SET_POINT 0x01 0x00000004 0x00000004 0x0 32 4 1 RW
SENSORS.WAVEFORM 0x08 0x00000008 0x00000020 0x0 32 0 1 RW
Basic Example
import deviceaccess as da
da.setDMapFilePath("documentationExamples/someCrate.dmap")
device = da.Device("someDummyDevice")
device.open()
# Read a value
temperature = device.getScalarRegisterAccessor(float, "SENSORS.TEMPERATURE")
temperature.read()
print(f"Current temperature: {float(temperature)} °C")
# Write a value
setpoint = device.getScalarRegisterAccessor(float, "SENSORS.SET_POINT")
setpoint.set(25.0)
setpoint.write()
# Verify the write
setpoint.read()
print(f"Setpoint is now: {float(setpoint)} °C")
Step-by-Step Explanation
Import: The
deviceaccessmodule contains all necessary classes and methodsInitial Setup: Set up dmap file name according to your configuration
Device Creation:
Device()opens a connection to the hardware with the handle defined in the dmap fileGet Accessor: Accessors are type-safe handles to registers, regardless of the underlying hardware
Read/Write:
read()andwrite()transfer data to/from hardwareData Access: Accessors behave like the data they represent and can be used like Python types (e.g., float, int, list, even numpy arrays) after reading
Note
By default, all read and write operations are synchronous - they block until the operation completes. Check the User Guide for asynchronous patterns and advanced usage.
Next Steps
Now that you have the basics:
See Examples for more real-world patterns
Read the User Guide for deeper concepts
Check the API Reference for complete API details
Browse Frequently Asked Questions for common questions