Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

CI Coverage PyPI License

dls_motor_scanning

Tools for characterising the motion performance of EPICS motors.

Two commands are provided:

  • scan drives a motor through a range in fixed steps, recording the position actually reached and the time each move took, then reports the positioning error and move time as statistics, a data file and a plot.
  • calibrate fits a 5th order polynomial that converts an unscaled feedback device, such as a potentiometer read as raw ADC counts, into engineering units, and emits it as an EPICS calc record and an Excel formula.
What Where
Source https://github.com/DiamondLightSource/dls-motor-scanning
PyPI pip install dls-motor-scanning
Docker docker run ghcr.io/diamondlightsource/dls-motor-scanning:latest
Releases https://github.com/DiamondLightSource/dls-motor-scanning/releases

Scanning a motor

dls-motor-scanning scan MOTOR START STOP STEP DELAY [options]

START, STOP and STEP are in the motor's engineering units, and DELAY is the settling time in seconds to wait after each move before reading back. Scan PS-MO-WIRE-01:Y from 40 to 45 in half-EGU steps, with no settling time:

dls-motor-scanning scan PS-MO-WIRE-01:Y 40 45 0.5 0

The scan direction follows START and STOP, so a reverse scan needs no sign on the step:

dls-motor-scanning scan PS-MO-WIRE-01:Y 45 40 0.5 0

Each run writes Scan_<motor>_<date>_<start>_<stop>_<step>.txt and .png into the current directory, and prints a summary of the move times and position errors.

Option Effect
--extra-pv PV Read PV at each step and add it as a column and a third plot panel
--trigger-pv PV Pulse PV high then low after each move, for example to fire a detector
--trigger-width SECS How long the trigger is held high (default 1.0)
--trigger-post-delay SECS How long to wait after the trigger returns low (default 0.0)
--timestamp Add a UTC timestamp column taken from the EPICS timestamp of the readback
--no-txt Do not write the data file
--no-png Do not save the plot
--no-plot Do not open a plot window

The output file

The data file is space separated, with a header row naming the columns:

Desired Actual MoveTime Timestamp(UTC)
40.5 40.499 1.1394305229187012 2026-08-14T09:15:56.375000Z
41.0 40.9992 1.1742472648620605 2026-08-14T09:15:57.625000Z

Timestamp(UTC) is the timestamp the IOC put on the readback record, not the time the client received it, which makes it directly comparable with archiver data. It appears only when --timestamp is given, as does the --extra-pv column.

Plotting on a remote machine

--plot needs a working display. Over a slow link, or on a headless machine, prefer:

dls-motor-scanning scan PS-MO-WIRE-01:Y 40 45 0.5 0 --no-plot

which skips the interactive window entirely and just writes the png.

A note on backends. cothread integrates with Qt and not with Tk, and the two segfault if combined. PyQt5 is therefore a dependency, and the tool selects qtagg explicitly rather than letting matplotlib work through its own candidate list, which would fall back to tkagg. If Qt cannot be imported, or DISPLAY is unset, the interactive plot is skipped with a message instead of taking the process down with it.

The png is always rendered under Agg and written to disk before any GUI toolkit is touched, so a display problem can never cost you the saved plot.

Calibrating a feedback device

dls-motor-scanning calibrate CSV_PATH [options]

The CSV needs one integer column, taken as the raw feedback, and one float column, taken as the scaled position to calibrate against:

raw,encoder
0,2.0
200,2.5
400,3.0
dls-motor-scanning calibrate pot.csv --raw-input-pv BL01I-MO-POT-01:ADC --excel-cell C2

This prints the six coefficients, a Builder records.calc entry with them loaded into fields B to G, and an equivalent Excel formula referencing --excel-cell.

Development

uv sync
uv run pytest

The scan code reaches EPICS through cothread.catools, which is imported lazily so the tests, --help and the calibrate command all work without an IOC. The test suite substitutes a fake Channel Access layer, so a full scan can be exercised without hardware.

Download files

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

Source Distribution

dls_motor_scanning-1.0.0b2.tar.gz (78.6 kB view details)

Uploaded Source

Built Distribution

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

dls_motor_scanning-1.0.0b2-py3-none-any.whl (21.9 kB view details)

Uploaded Python 3

File details

Details for the file dls_motor_scanning-1.0.0b2.tar.gz.

File metadata

  • Download URL: dls_motor_scanning-1.0.0b2.tar.gz
  • Upload date:
  • Size: 78.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dls_motor_scanning-1.0.0b2.tar.gz
Algorithm Hash digest
SHA256 bbb2955bcad3d0b62aa3504e906d5c976fa14c62ba159c38289b607fff163b15
MD5 f3eb5f0a2ea96100c96c13e5a7b54e4e
BLAKE2b-256 23bdfffa59e8e6b54ad63a27a689d200bf1695698beb8f2e057a3264183a2c8f

See more details on using hashes here.

File details

Details for the file dls_motor_scanning-1.0.0b2-py3-none-any.whl.

File metadata

File hashes

Hashes for dls_motor_scanning-1.0.0b2-py3-none-any.whl
Algorithm Hash digest
SHA256 40682e259bae7f48caea1ec3156c7bab559d43c4115652736fde6f23af263ee9
MD5 820c9bf72cd7cd81385c3c2c7f6af663
BLAKE2b-256 d42d3fd16d8d12d88fef67407e34e4af53f4f54ad8050631b7253d5c7d3fb90c

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.0b2 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page