Write EPICS IOC databases in human-readable YAML. Compile to standard .db files.
yaml2epics modernizes the EPICS developer experience without breaking compatibility with existing infrastructure. Define your entire control system in a single YAML file — the compiler generates validated .db databases, startup scripts, and documentation.
EPICS .db files are powerful but painful to author. Field names are cryptic, typos are silently ignored, and there's no built-in validation:
record(ai, "XRAY:HV:VoltRead") {
field(DESC, "Voltage Readback")
field(INP, "XRAY:HV:VoltRamp CP")
field(EGU, "kV")
field(PREC, "1")
field(HOPR, "160")
field(HIHI, "155")
field(HIGH, "140")
field(HHSV, "MAJOR")
field(HSV, "MINOR")
}
- name: "HV:VoltRead"
type: ai
description: Voltage Readback
input: XRAY:HV:VoltRamp
link_mode: cp
units: kV
precision: 1
range: [0, 160]
alarms:
minor_high: 140
major_high: 155Same output. Validated before compilation. Self-documenting.
# Install
pip install pyyaml
pip install -e .
# Compile an example
yaml2epics examples/xray_imaging/xray_system.yaml -o ./generated -v
# Run the IOC
cd generated
softIoc -d x-ray_imaging_system.dbgenerated/
├── detector.db # Per-device database files
├── xraytube.db
├── shutter.db
├── cabinet.db
├── lowvoltage.db
├── x-ray_imaging_system.db # Combined system database
├── st.cmd # IOC startup script (with asyn config)
└── interfaces.md # Auto-generated documentation
Catches real mistakes before your IOC loads them:
calcrecord withoutputfield → error (should usecalcout)- Duplicate PV names → error
- Invalid scan rates → error
- Alarm thresholds in wrong order → error
- Description exceeding 40 characters → warning
Alarms — one block instead of eight fields:
alarms:
major_high: 155 # → HIHI=155, HHSV=MAJOR
minor_high: 140 # → HIGH=140, HSV=MINOR
minor_low: 10 # → LOW=10, LSV=MINOR
major_low: 5 # → LOLO=5, LLSV=MAJOR
deadband: 0.5 # → HYST=0.5Links — readable mode names:
input: DET:TempSim
link_mode: cp # instead of "DET:TempSim CP"Short name resolution — forward links auto-resolve:
# In a device with prefix "XRAY"
forward_link: "HV:Status" # → FLNK = "XRAY:HV:Status"Named calculation inputs:
expression: "A*B"
inputs:
a: { pv: XRAY:HV:VoltRead, mode: cp }
b: { pv: XRAY:HV:CurrRead, mode: cp }Document your physical connections alongside the records:
interfaces:
- id: det_gige
type: gige
address: 192.168.1.100
port: 8080
- id: hv_serial
type: serial
address: /dev/ttyS0
baud: 9600
devices:
- id: detector
prefix: DET
interface_ref: det_gige
records: [...]The startup script auto-generates drvAsynIPPortConfigure / drvAsynSerialPortConfigure comments for each interface.
For any EPICS field not in the simplified schema:
raw_fields:
ADEL: "0.1"
MDEL: "0.01"
SMOO: "0.5"name: X-Ray Imaging System
author: Your Name
version: "1.0.0"
ioc_name: xray-sim
interfaces:
- id: detector_eth
type: gige # gige | serial | modbus_tcp | modbus_rtu | gpib | simulated
address: 192.168.1.100
port: 8080
devices:
- id: detector
name: Pixel Detector
prefix: DET
interface_ref: detector_eth
records:
- name: Temperature
type: ai
description: Detector Temperature
units: C
scan: 2s
precision: 1
input: DET:TempSim
link_mode: cp
range: [-30, 60]
alarms:
minor_high: 40
major_high: 50| Type | Description |
|---|---|
ai / ao |
Analog input / output |
bi / bo |
Binary input / output |
calc |
Calculation (no output) |
calcout |
Calculation with output |
mbbi / mbbo |
Multi-bit binary (up to 16 states) |
longin / longout |
Long integer input / output |
stringin / stringout |
String input / output |
seq |
Sequence with delays |
yaml2epics <input.yaml> [options]
Options:
-o, --output-dir DIR Output directory (default: ./generated)
-V, --validate-only Validate without generating files
-v, --verbose Show detailed output
The examples/xray_imaging/ directory contains a complete control system definition with five subsystems, including a linear pixel detector with GigE readout, X-ray tube HV control (RS-232), shutter with interlocks (Modbus TCP), cabinet safety system, and low voltage power supplies (GPIB/SCPI). All subsystems include simulated physics (HV ramping, temperature drift, radiation levels) that run in softIoc.
yaml2epics examples/xray_imaging/xray_system.yaml -o ./out -v
cd out && softIoc -d x-ray_imaging_system.dbgit clone https://github.com/ElmaddinGuliyev/yaml2epics.git
cd yaml2epics
pip install -e ".[dev]"
pytest -vSee CONTRIBUTING.md for guidelines.
-
epics2yamlreverse compiler — import existing.dbfiles - Node.js WebSocket dashboard — real-time web UI from YAML definitions
- Template inheritance — define reusable device types
- Auto-generated Phoebus
.boboperator screens - VS Code extension with YAML schema autocomplete
- Waveform and areaDetector record support
- Integration testing with softIoc
MIT — see LICENSE.
Elmaddin Guliyev — Staff Scientist, Thermo Fisher Scientific
- Rad Detect AI
- Ph.D. Physics, University of Groningen