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

  1. Import: The deviceaccess module contains all necessary classes and methods

  2. Initial Setup: Set up dmap file name according to your configuration

  3. Device Creation: Device() opens a connection to the hardware with the handle defined in the dmap file

  4. Get Accessor: Accessors are type-safe handles to registers, regardless of the underlying hardware

  5. Read/Write: read() and write() transfer data to/from hardware

  6. Data 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: