Pure-python library for Fermilab control system
Project description
pacsys
Pure-Python library for Fermilab's control system.
About
ACNET (Accelerator Control NETwork) is the control system used at Fermilab's particle accelerators. PACSys provides a simple Python interface to read, write, and stream ACNET data without needing to understand the underlying protocols.
Features
- Read/Write/Stream any ACNET data types with synchronous or async APIs
- Multiple backends to connect to DPM, DMQ, and ACL
- Full DRF3 parser for data requests with automatic conversion
- Utilities for device database, SSH tunneling, and more
- Command-line tools like in EPICS -
acget,acput,acmonitor,acinfo
Installation
pip install pacsys
Device API (recommended)
import pacsys
from pacsys import Device, Verify, KerberosAuth
# Create a device -- DRF is validated immediately
dev = Device("M:OUTTMP")
# Read different properties
temperature = dev.read() # READING (scaled value)
setpoint = dev.setting() # SETTING property
is_on = dev.status(field="on") # STATUS field ON
alarm = dev.analog_alarm() # ANALOG alarm
# Full reading with metadata
reading = dev.get()
print(f"{reading.value} {reading.units}") # e.g. "72.5 DegF"
# Write with automatic readback verification
result = dev.write(72.5, verify=Verify(tolerance=0.5))
assert result.verified
# Control commands with shortcuts
dev.on()
dev.off()
dev.reset()
# Device database metadata (scaling, limits, units)
info = dev.info()
print(info.description) # "Outside temperature"
print(info.reading.common_units) # "DegF"
print(info.reading.min_val) # 0.0
# Stream data
with dev.with_event("p,1000").subscribe() as stream:
for reading, handle in stream.readings(timeout=10):
print(reading.value)
# Immutable -- modifications return new instances
periodic_dev = dev.with_event("p,1000")
sliced_dev = dev.with_range(0, 10)
Backend API
import time
import pacsys
# Read a device value through global backend
temperature = pacsys.read("M:OUTTMP")
print(f"Temperature: {temperature}")
# Stream real-time data through global backend
with pacsys.subscribe(["M:OUTTMP@p,1000"]) as stream:
for reading, handle in stream.readings(timeout=30):
print(f"{reading.name}: {reading.value}")
# Stream with callback dispatch mode through dedicated DPM instance
# WORKER (default): callbacks on dedicated worker thread, protects event loop
# DIRECT: callbacks inline on reactor thread (lower latency)
with pacsys.dpm(dispatch_mode=pacsys.DispatchMode.DIRECT) as backend:
handle = backend.subscribe(
["M:OUTTMP@p,1000"],
callback=lambda r, h: print(r.value),
)
time.sleep(10)
handle.stop()
# Write through authenticated DPM instance (requires kerberos ticket)
with pacsys.dpm(auth=pacsys.KerberosAuth(), role="testing") as backend:
backend.write("Z:ACLTST", 72.5)
Async capabilities
Native async versions with same API surface.
import pacsys.aio as aio
# Module-level API (mirrors pacsys.read, pacsys.get, etc.)
value = await aio.read("M:OUTTMP")
reading = await aio.get("M:OUTTMP")
# Explicit async backend
async with aio.dpm(auth=pacsys.KerberosAuth()) as backend:
await backend.write("Z:ACLTST", 72.5)
# Async streaming
async with await backend.subscribe(["M:OUTTMP@p,1000"]) as stream:
async for reading, handle in stream.readings(timeout=30):
print(f"{reading.name}: {reading.value}")
# AsyncDevice
from pacsys.aio import AsyncDevice
dev = AsyncDevice("M:OUTTMP", backend=backend)
temp = await dev.read()
await dev.on()
SSH Utilities
Port tunneling, SFTP, and interactive processes over multi-hop SSH.
import pacsys
# Execute commands with automatic Kerberos auth
with pacsys.ssh(["jump.fnal.gov", "target.fnal.gov"]) as ssh:
result = ssh.exec("hostname")
print(result.stdout) # target
# ACL can be run on the fly - beam switch, DB, etc.
with pacsys.ssh("clx01.fnal.gov") as ssh:
result = ssh.acl("read M:OUTTMP") # "M:OUTTMP = 72.500 DegF"
CLI Tools
EPICS-style command-line tools:
# Read devices
acget M:OUTTMP Z:ACLTST
acget --format json M:OUTTMP
# Write devices (requires authentication)
acput Z:ACLTST 72.5
acput -a kerberos --verify --tolerance 0.5 Z:ACLTST 72.5
# Monitor (streaming)
acmonitor M:OUTTMP
acmonitor -n 10 M:OUTTMP@p,500
# Device info (DB + property reads)
acinfo -v M:OUTTMP
Tools are aliased under pacsys-get, pacsys-put, pacsys-monitor, pacsys-info.
Requirements
- Python 3.10+
- For writes: Kerberos credentials with appropriate role or console class assigned
- For some utilities: must run on the controls network or have SSH access to it
Documentation
See the full documentation for guides, API reference, and protocol details.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pacsys-0.2.0.tar.gz.
File metadata
- Download URL: pacsys-0.2.0.tar.gz
- Upload date:
- Size: 386.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5ee78e17ce03e0a7a9e759742479f5e286cc9dad2ca23d7da75eca6e8fc1e31
|
|
| MD5 |
864659794c001937ddafc24b52dd0312
|
|
| BLAKE2b-256 |
0733c6ba07620a01cace7fa732e8a9018f23052f7d0e05efd1daa8012f5ab97d
|
File details
Details for the file pacsys-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pacsys-0.2.0-py3-none-any.whl
- Upload date:
- Size: 288.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ffaa8c18f3d940f5927253e8f56d6e0adfcb54550c2ebdec0535ad555b9f6414
|
|
| MD5 |
242261d507f4aa3a2a4a550738f6b737
|
|
| BLAKE2b-256 |
a136ef74a29450473c9f447bd30bb1e76c5ccc09e14e28dd1da3a0c951f9751e
|