Skip to main content

A python library/GUI to access and control motors via the APT protocol.

Project description

pyThorlabsAPT

pyThorlabsAPT is a Python library/GUI interface to control any motor compatible with the Thorlabs APT communication protocol. The package is composed of two parts, a low-level driver to perform basic operations, and a high-level GUI, written with PyQt5, which can be easily embedded into other GUIs. The low-level driver is essentially a wrapper of the excellent package thorlabs_apt, with a few tweaks to speed up loading time and error handling. Since thorlabs_apt is not available via pip, its code has been embedded in the code of this package, here. A virtual (software-simulated) backend is also included, so the driver and the GUI can be used and tested without any real hardware, APT.dll, or the Thorlabs APT software installed.

The interface can work either as a stand-alone application, or as a module of ergastirio.

Table of Contents

Installation

The package uses the Thorlabs APT.dll shared library, and therefore the low-level driver and the real (non-virtual) GUI only work under Windows. The virtual backend, however, works on any platform. To install, follow these steps:

  1. Install the script via the package manager pip,
pip install pyThorlabsAPT==0.11

Important: due to a bug of pypi, if you run just '''pip install pyThorlabsAPT''' it might default to a stale version 0.21, which was wrongly uploaded on pypi in the past and it does not work. Make sure you specify the version.

  1. Install the APT software from here (clik on the tab 'Archive'). The version of the software (32 or 64 bit) must match the one of your python installation.

  2. Locate the file APT.dll which has been installed on your computer by the APT software. This file will typically be in the folder "[APT Installation Folder]\APT Server", where [APT Installation Folder] is the installation folder of the APT software (typically [APT Installation Folder] = C:\Program Files\Thorlabs\APT). Copy the APT.dll into one of these locations:

    • C:\Windows\System32.
    • The folder of your python application.
    • Inside the "[Python packages folder]\pyThorlabsAPT horlabs_apt". Most of the times [Python packages folder] = "[Python folder]\Lib\site-packages".

Steps 2 and 3 are only needed to talk to real hardware; they can be skipped entirely if you only intend to use the virtual driver (see Virtual mode below).

These steps are enough to run the low-level driver of pyThorlabsAPT. In order to use the GUI, it is necessary to install additional libraries, specified in the requirements.txt file,

pip install abstract_instrument_interface>=0.10
pip install "PyQt5>=5.15.6"
pip install pyqtgraph
pip install numpy

Usage via the low-level driver

pyThorlabsAPT can be used to control a device from the command line or from your Python script.

The class pyThorlabsAPT wraps the connected device's low-level Motor object (defined in thorlabs_apt for real hardware, or in pyThorlabsAPT.thorlabs_apt_virtual for the simulated backend) and exposes the subset of its properties and methods needed to find, connect to, and operate a stage. A full list of properties, attributes, and methods is available below. Note: the documentation below was partially compiled with the help of Claude - mistakes are possible.

Creating a driver instance

pyThorlabsAPT(virtual=False)
Parameter Type Description
virtual bool, optional If True, use the virtual backend (pyThorlabsAPT.thorlabs_apt_virtual) instead of real hardware (see Virtual mode below). Default is False.

Virtual mode (no hardware needed)

Passing virtual=True makes the driver simulate APT motors instead of talking to the real APT.dll. Two virtual motors with different specs are available. This is useful for testing or demoing the package without a physical instrument, and works even if the Thorlabs APT software is not installed.

from pyThorlabsAPT.driver import pyThorlabsAPT
instrument = pyThorlabsAPT(virtual=True)
available_devices = instrument.list_devices()
print(available_devices)
instrument.connect_device(device_addr=available_devices[0][1])
instrument.move_home()
print(instrument.position)   # returns a simulated, time-varying position while homing
instrument.disconnect_device()

Properties

The following are implemented as Python @property. Reading or setting either of these requires a device to be connected; otherwise, accessing them raises an AttributeError (no underlying Motor object has been created yet).

Property Type Description
Can be set?
Notes
position float Current position of the motor. Yes Setting it starts a non-blocking absolute move. Poll is_in_motion (or call instrument.motor.position again) to know when the move has finished.
is_in_motion bool Whether the motor is currently moving. No

Other attributes

Attribute Type Description
connected bool True if a device is currently connected, False otherwise.
motor Motor instance The underlying real or virtual Motor object, created by connect_device() upon a successful connection. Does not exist until a device has been connected.
list_valid_devices list List of devices found by the most recent call to list_devices().

Methods

Method Returns Description
list_devices() list Returns a list of all available devices. Each element is a 2-element tuple (identity, address), where identity is an integer hardware-type code and address is the integer serial number to pass to connect_device().
connect_device(device_addr) (str or int, int) Attempts to connect to the device identified by device_addr (its serial number, as returned by list_devices()). Returns (Msg, ID): Msg is device_addr on success, or an error message on failure; ID is 1 if connection was successful, 0 otherwise. Raises ValueError if device_addr does not match any device returned by the most recent call to list_devices().
disconnect_device() (str, int) Attempts to disconnect the currently connected device. Returns (Msg, ID), analogous to connect_device(). Raises RuntimeError if no device is currently connected.
move_home(blocking=False) None Moves the motor to its home position (position 0).
move_jog(direction, blocking=False) None Jogs the motor by the currently configured jog step size (see get_jog_parameters/set_jog_parameters), in the given direction (see Direction and units constants below).
stop_profiled() None Stops any ongoing movement (profiled stop).
get_stage_axis_info() (float, float, int, float) Returns (min_pos, max_pos, units, pitch) for the connected stage. units is an integer code (see Direction and units constants below).
set_stage_axis_info(min_pos, max_pos, units, pitch) None Sets the stage axis parameters.
get_jog_parameters() (int, int, float, float, float, float) Returns (Mode, StopMode, StepSize, MinVel, Accn, MaxVel).
set_jog_parameters(Mode, StopMode, StepSize, MinVel, Accn, MaxVel) None Sets the jog parameters.

Note: unlike earlier versions of this package, pyThorlabsAPT no longer subclasses the underlying Motor object, so properties/methods of Motor that are not listed above (e.g. hardware_info, move_by(), move_to(), enable()/disable(), velocity/PID parameters, etc.) are not directly exposed on the driver. After connecting, you can still reach them via the motor attribute, e.g. instrument.motor.hardware_info.

Direction and units constants

move_jog() and get_stage_axis_info()/set_stage_axis_info() use a few integer constants. These are defined on the backend module in use, not on the pyThorlabsAPT class itself:

from pyThorlabsAPT.thorlabs_apt import MOVE_FWD, MOVE_REV, STAGE_UNITS_MM, STAGE_UNITS_DEG
# or, when using the virtual driver:
from pyThorlabsAPT.thorlabs_apt_virtual import MOVE_FWD, MOVE_REV, STAGE_UNITS_MM, STAGE_UNITS_DEG
Constant Value Meaning
MOVE_FWD 1 Move/jog in the forward direction.
MOVE_REV 2 Move/jog in the reverse direction.
STAGE_UNITS_MM 1 Stage units in millimeters.
STAGE_UNITS_DEG 2 Stage units in degrees.

Examples

from pyThorlabsAPT.driver import pyThorlabsAPT
from pyThorlabsAPT.thorlabs_apt import MOVE_FWD
import time

instrument = pyThorlabsAPT()
available_devices = instrument.list_devices()              # Check which devices are available
print(available_devices)

device_addr = available_devices[0][1]                      # The address is the 2nd element of each tuple
instrument.connect_device(device_addr=device_addr)          # Connect to the first available device

instrument.move_home()                                      # Start homing
while instrument.is_in_motion:                               # Poll until homing is done
    time.sleep(0.1)

instrument.position = 10                                    # Start a non-blocking absolute move to position 10
while instrument.is_in_motion:
    time.sleep(0.1)
print(instrument.position)

instrument.move_jog(MOVE_FWD)                                # Jog forward by one jog step
print(instrument.get_stage_axis_info())                      # (min_pos, max_pos, units, pitch)

instrument.disconnect_device()                               # Disconnect the device

Usage as a stand-alone GUI interface

The installation sets up an entry point for the GUI. Just typing

pyThorlabsAPT

in the command prompt will start the GUI. Pass -virtual to start it with the simulated driver instead of real hardware (useful for testing without a physical motor):

pyThorlabsAPT -virtual

Embed the GUI within another GUI

The GUI controller can also be easily integrated within a larger graphical interface, as shown in the example below.

import PyQt5.QtWidgets as Qt  # QApplication, QWidget, QGridLayout, QLabel, QVBoxLayout
import pyThorlabsAPT

app = Qt.QApplication([])
window = Qt.QWidget()

# The GUI needs to be contained inside a widget object
widget_containing_interface_GUI = Qt.QWidget()
widget_containing_interface_GUI.setStyleSheet(
    ".QWidget {
"
    "border: 1px solid black;
"
    "border-radius: 4px;
"
    "}"
)

# Create the interface object for the motor (pass virtual=True to use the simulated driver instead of real hardware)
Interface = pyThorlabsAPT.interface(app=app, virtual=False)
Interface.verbose = False  # set the verbosity of the interface logger to False
# At any time during the software execution, the position read by the instrument can be accessed via Interface.output['Position']
# Moreover, one could also set up a signal to automatically call another function whenever the position is updated, by
#
#       Interface.sig_update_position.connect(foo)
#
# Every time the position is read from the instrument, the function foo is called and the new position is passed as argument

# Create the GUI for the motor
view = pyThorlabsAPT.gui(interface=Interface, parent=widget_containing_interface_GUI)

# Create additional GUI
gridlayoutwidget = Qt.QWidget()
gridlayout = Qt.QGridLayout()
gridlayout.addWidget(Qt.QLabel("Additional GUI 1"), 0, 0)
gridlayout.addWidget(Qt.QLabel("Additional GUI 2"), 1, 0)
gridlayout.addWidget(Qt.QLabel("Additional GUI 3"), 0, 1)
gridlayout.addWidget(Qt.QLabel("Additional GUI 4"), 1, 1)
gridlayoutwidget.setLayout(gridlayout)

layout = Qt.QVBoxLayout()
layout.addWidget(widget_containing_interface_GUI)
layout.addWidget(gridlayoutwidget)
layout.addStretch(1)
window.setLayout(layout)

window.show()
app.exec()  # Start the event loop.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pythorlabsapt-0.12.tar.gz (201.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pythorlabsapt-0.12-py3-none-any.whl (198.2 kB view details)

Uploaded Python 3

File details

Details for the file pythorlabsapt-0.12.tar.gz.

File metadata

  • Download URL: pythorlabsapt-0.12.tar.gz
  • Upload date:
  • Size: 201.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for pythorlabsapt-0.12.tar.gz
Algorithm Hash digest
SHA256 5705451f6482951ef46f26d4320b84b147040bf017f8f5cc7c20cd844e260ccd
MD5 f2d96915b5d5d07caf2e031759380cba
BLAKE2b-256 4d58c6544d812ef41e724c689b8d8b9ab843626927a6fb528bd3ee8065257649

See more details on using hashes here.

File details

Details for the file pythorlabsapt-0.12-py3-none-any.whl.

File metadata

  • Download URL: pythorlabsapt-0.12-py3-none-any.whl
  • Upload date:
  • Size: 198.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for pythorlabsapt-0.12-py3-none-any.whl
Algorithm Hash digest
SHA256 c0f3705f27a67aac33d75578bd635335c00121e28a2ab2e13da1aed517b946c1
MD5 b4a78f32d452157a07426a39c484999b
BLAKE2b-256 6ec5eaaeff02d528f70f09bef0299bdd30735b6e9ed28f9d42c3e27d59d76a08

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page