7.4 KiB
7.4 KiB
team1k
Python control library and server for the TEAM1k X-ray detector.
Communicates directly with the detector FPGA via UDP. Uses EPICS PV Access (PVA) for the image stream and basic controls (areaDetector-style), and a TCP protocol for the Python client.
Architecture
Client machine Detector machine
+--------------+ +-------------------------------+
| | TCP (control+data) | team1k-server |
| Client |<--------------------->| Register I/O (UDP:42000) |
| (Python) | | TCP client server |
| | | Buffered frame capture |
+--------------+ | PVA server (areaDetector) |
| PVA streamer (IMAGE) |
EPICS clients | Power supply monitoring |
+--------------+ | Auto-reconnect |
| pvget/CSS/ | PVA (IMAGE stream) | |
| other tools |<--------------------->| Acquisition subprocess |
+--------------+ | UDP data recv (UDP:41000) |
| Frame assembly |
| -> locking_shmring |
+-------------------------------+
Installation
pip install .
For notebook progress bars (optional):
pip install ".[client]"
Dependencies
locking_shmring— shared memory ring buffer (must be installed separately)p4p— EPICS PV Access for Pythonpyyaml— YAML config parsingpyvisa,pyvisa-py— power supply controlnumpy,pyserial
Configuration
Create a YAML config file:
detector:
ip: "10.0.0.32"
register_port: 42000
data_port: 41000
auto_reconnect: true
reconnect_interval: 5.0
adc:
clock_frequency_mhz: 50
data_delay: 0x180
order_7to0: 0x89abcdef
order_15to8: 0x01234567
digital_signals:
order_7to0: 0x24FFFFFF
order_15to8: 0xF5F310FF
polarity: 0x0014
defaults:
exposure_mode: 3
trigger_mode: external
trigger_polarity: rising
integration_time_ms: 4.0
server:
pv_prefix: "TEAM1K:"
client_port: 42010
peripherals:
bellow_port: "/dev/CameraBellowStage"
detector_power:
port: "/dev/DetectorPowerSupply"
voltage_step: 0.2
channels:
1: { voltage: 5.0, current: 2.0, ovp: 6.0 }
2: { voltage: 3.3, current: 1.0, ovp: 4.0 }
tec:
port: "/dev/TECsPowerSupply"
voltage_step: 0.2
channels:
1: { voltage: 12.0, current: 3.0, ovp: 14.0 }
Running the server
team1k-server --config config.yaml --log-level INFO
Options:
--config YAML config file path
--detector-ip Override detector IP address
--pv-prefix Override PVA prefix
--client-port Override TCP client port
--log-level DEBUG, INFO, WARNING, ERROR (default: INFO)
The server starts DAQ automatically after initialization (continuous mode). The PVA IMAGE stream is always live.
Client usage
The Python client connects via TCP. No EPICS/p4p installation needed.
Basic usage
from team1k import Client
client = Client("detector-machine")
# Configure
client.exposure_mode = 3 # GlobalCDS
client.trigger_mode = 1 # External
client.integration_time = 4.0 # ms
# Status
print(client.state) # "Acquiring"
print(client.frame_rate) # 500.0
# Capture frames (shows progress bar)
frames = client.capture(100)
print(frames.shape) # (100, 1024, 1024)
print(frames.dtype) # uint16
client.close()
Capture modes
# Fixed number of frames
frames = client.capture(num_frames=100)
# Capture for a duration
frames = client.capture(duration=5.0)
# Open-ended capture (start/stop)
stream = client.start_capture()
# ... do something ...
frames = stream.stop()
# Disable progress bar
frames = client.capture(100, progress=False)
Peripherals
# Bellow stage
client.insert_detector()
client.retract_detector()
# Detector power
client.power_on()
client.power_off()
print(client.power_status) # {1: {"voltage": 5.01, "current": 1.2}, ...}
# TEC
client.tec_on()
client.tec_off()
print(client.tec_status)
Advanced
# Direct register access
value = client.read_register(22)
client.write_register(22, 3)
# Reconnect after power cycle
client.power_on()
client.reconnect()
# Full status
print(client.status())
# Context manager
with Client("detector-machine") as c:
frames = c.capture(100)
PV Access interface
All PVs are prefixed with TEAM1K: by default. Follows areaDetector conventions with RW + _RBV readback pattern.
Acquisition PVs
| PV | Type | RW | Description |
|---|---|---|---|
Acquire / _RBV |
bool | RW | Start/stop DAQ |
AcquireTime / _RBV |
float | RW | Integration time (seconds) |
ExposureMode / _RBV |
enum | RW | Rolling/Rolling with Pause/Global/Global with CDS |
TriggerMode / _RBV |
enum | RW | Internal/External |
ArrayCounter_RBV |
int | RO | Total frames acquired |
FrameRate_RBV |
float | RO | Current frame rate (Hz) |
DetectorState_RBV |
enum | RO | Disconnected/Initializing/Idle/Acquiring/Error |
MaxSizeX_RBV / MaxSizeY_RBV |
int | RO | 1024, 1024 |
IMAGE |
NTNDArray | RO | Live image stream |
Peripheral PVs
| PV | Type | RW | Description |
|---|---|---|---|
Bellow:Insert |
bool | RW | Write true to insert |
Bellow:Retract |
bool | RW | Write true to retract |
Bellow:Position_RBV |
int | RO | Current position |
Power:Enable / _RBV |
bool | RW | Detector power on/off |
Power:ChN:Voltage_RBV |
float | RO | Channel N voltage |
Power:ChN:Current_RBV |
float | RO | Channel N current |
TEC:Enable / _RBV |
bool | RW | TEC power on/off |
TEC:ChN:Voltage_RBV |
float | RO | Channel N voltage |
TEC:ChN:Current_RBV |
float | RO | Channel N current |
Package structure
src/team1k/
detector/ # Direct UDP communication with detector FPGA
udp_transport.py # Low-level UDP socket
registers.py # Register read/write protocol
data_port.py # Data port + loopback registration
chip_config.py # Chip constants (1024x1024, packet layout)
commands.py # Detector commands (exposure, trigger, etc.)
adc.py # Si570 I2C clock programming
acquisition/ # High-throughput data path
receiver.py # Acquisition subprocess (UDP -> shmring)
pva/ # EPICS PV Access (areaDetector-style)
interface.py # PVA server, RW PVs with _RBV readbacks
streamer.py # shmring -> NTNDArray live stream
peripherals/ # Hardware peripherals
power_base.py # VISA power supply base class
power_supply.py # Detector power supply
tec.py # TEC controller
bellow_stage.py # Camera bellow stage (serial)
config.py # YAML configuration loader
state.py # DetectorState enum
server.py # Main server entry point
tcp_server.py # TCP client handler
tcp_protocol.py # Shared TCP message framing
capture.py # Buffered frame capture (shmring -> TCP)
client.py # Pure-TCP client library