Controls, analysis, and displays for SC Linac operations.
- Python: 3.12+ (tested on 3.12 and 3.13)
- GUI stack: PyDM + PyQt5/Qt
- Includes packaged displays, configuration YAML/JSON, and example data
- PyDM-based operator displays for SC Linac
- Unified command-line interface for all displays and applications
- Hierarchical setup control (global → linac → cryomodule → cavity)
- Analysis utilities using NumPy/SciPy/scikit-learn
- Plotting with matplotlib and pyqtgraph
- EPICS/Channel Access via caproto and pyepics
- Configuration with YAML/JSON
- Packaged calibration and example data
- Simulated EPICS IOC service for testing and development
- Python >= 3.12
- Qt runtime (PyQt5)
- On Linux headless environments (CI/containers), Xvfb or offscreen Qt
Core dependencies (installed automatically):
- pydm, PyQt5, qtpy, pyqtgraph
- numpy, scipy, scikit-learn, matplotlib
- pydantic, pyyaml, h5py
- requests, urllib3, caproto
- lcls-tools and edmbutton from GitHub
System packages (Linux, recommended for headless testing):
- xvfb, libxkbcommon-x11-0, libglu1-mesa, libxcb-xinerama0
From PyPI (if published):
pip install sc_linac_physicsFrom source:
git clone git@github.com:slaclab/sc_linac_physics.git
cd sc_linac_physics
pip install -U pip setuptools wheel
# Development + testing tools:
pip install -e ".[dev,test]"
# Or just the package:
# pip install -e .Notes:
- If behind a firewall, ensure access to GitHub for dependency sources:
After installation, the following commands are available:
# List all available applications
sc-linac list
# Launch displays and applications
sc-linac cavity-display # Launch the cavity control display.
sc-linac fault-count # Launch the fault count display.
sc-linac fault-decoder # Launch the fault decoder display.
sc-linac srf-home # Launch the SRF home display.
sc-linac auto-setup # Launch the auto setup GUI.
sc-linac microphonics # Launch the microphonics GUI.
sc-linac q0-measurement # Launch the Q0 measurement GUI.
sc-linac quench-processing # Launch the quench processing GUI.
sc-linac tuning # Launch the tuning GUI.sc-srf-home # SRF home overview display - main control interface
sc-cavity # Cavity control and monitoring display
sc-faults # Cavity fault decoder with detailed diagnostics
sc-fcount # Cavity fault count display and statisticssc-quench # Quench processing application
sc-setup # Automated cavity setup (GUI)
sc-q0 # Q0 measurement application
sc-tune # Cavity tuning interfaceThe setup commands provide hierarchical control from global (entire machine) down to individual cavities:
Global Level - Entire Machine
sc-setup-all # Setup all cryomodules
sc-setup-all --no_hl # Setup all except HL cryomodules
sc-setup-all --shutdown # Shutdown all cryomodulesLinac Level
sc-setup-linac -l 0 # Setup Linac 0 (all cryomodules in linac)
sc-setup-linac -l 1 # Setup Linac 1
sc-setup-linac -l 2 --shutdown # Shutdown Linac 2Cryomodule Level
sc-setup-cm -cm 01 # Setup Cryomodule 01 (all cavities)
sc-setup-cm -cm 02 # Setup Cryomodule 02
sc-setup-cm -cm H1 --shutdown # Shutdown Cryomodule H1
sc-setup-cm -cm 03 -off # Shutdown Cryomodule 03 (short form)Cavity Level
sc-setup-cav -cm 01 -cav 1 # Setup specific cavity
sc-setup-cav -cm 02 -cav 3 # Setup CM02, cavity 3
sc-setup-cav -cm 01 -cav 2 -off # Shutdown specific cavityFor testing and development without live hardware:
sc-sim # Start simulated IOC service
sc-sim --list-pvs # List all available PVs
sc-sim --interfaces=127.0.0.1 # Run on localhost onlyPython import check:
import sc_linac_physics
print("Package version:", getattr(sc_linac_physics, "__version__", "unknown"))Programmatic display launching:
from sc_linac_physics.cli import launchers
# Launch displays programmatically
launchers.launch_srf_home()
launchers.launch_cavity_display()
launchers.launch_fault_decoder()
launchers.launch_fault_count()
# Launch applications
launchers.launch_quench_processing()
launchers.launch_auto_setup()
launchers.launch_q0_measurement()
launchers.launch_tuning()You can also launch displays using PyDM directly:
pydm path/to/your_display.uiTip: Set PYDM_DEFAULT_PROTOCOL=fake to try displays without live PVs:
export PYDM_DEFAULT_PROTOCOL=fake
sc-cavityHeadless usage (e.g., servers/CI):
export QT_QPA_PLATFORM=offscreen
# or use Xvfb:
xvfb-run -a sc-srf-homeDisplays:
sc-srf-home- SRF home overview displaysc-cavity- Cavity control and monitoringsc-faults- Fault decodersc-fcount- Fault count display
Applications:
sc-quench- Quench processingsc-setup- Auto setup GUIsc-q0- Q0 measurementsc-tune- Tuning application
Setup Commands:
sc-setup-all- Global setup (all cryomodules)sc-setup-linac- Linac level setupsc-setup-cm- Cryomodule level setupsc-setup-cav- Cavity level setup
Simulation:
sc-sim- Simulated IOC service
# Setup entire machine
sc-setup-all
# Setup all except high-level cryomodules
sc-setup-all --no_hl
# Setup specific linac
sc-setup-linac -l 0
# Setup specific cryomodule
sc-setup-cm -cm 01
# Setup specific cavity
sc-setup-cav -cm 01 -cav 1
# Shutdown examples (add --shutdown or -off to any command)
sc-setup-all --shutdown
sc-setup-linac -l 0 -off
sc-setup-cm -cm 01 --shutdown
sc-setup-cav -cm 01 -cav 1 -off- Cryomodules:
01,02,03,H1,H2,04-35 - Cavities:
1through8 - Linacs:
0through3
Examples:
sc-setup-cav -cm 01 -cav 1 # Cryomodule 01, cavity 1
sc-setup-cav -cm H1 -cav 5 # High-level cryomodule H1, cavity 5
sc-setup-cm -cm 15 # Cryomodule 15Set up environment:
git clone git@github.com:slaclab/sc_linac_physics.git
cd sc_linac_physics
pip install -U pip setuptools wheel
pip install -e ".[dev,test]"Code style and lint:
flake8 . --count --max-complexity=10 --max-line-length=120 --show-source --statistics
black --check .
# To auto-format:
# black .Run tests with coverage (Linux headless):
export QT_QPA_PLATFORM=offscreen
pytest
# Run specific test files
pytest tests/test_cli.py -v
pytest tests/test_launchers.py -vCombine multi-version coverage (if you test with multiple Python versions):
python -m pip install --upgrade coverage
coverage combine
coverage report -m
coverage html -d htmlcov- Create your display file in
src/sc_linac_physics/displays/ - Add a launcher function in
launchers.py:
def launch_my_display():
"""Launch my custom display."""
from pydm import PyDMApplication
from pathlib import Path
app = PyDMApplication()
display_path = Path(__file__).parent / "displays" / "my_display.ui"
app.make_main_window(str(display_path))
app.exec_()- Add a script entry in
pyproject.toml:
[project.scripts]
sc-my-display = "sc_linac_physics.launchers:launch_my_display"- Add tests in
tests/test_launchers.py
- Create your script with a
main()function - Add an entry in
pyproject.toml:
[project.scripts]
sc-my-tool = "sc_linac_physics.path.to.module:main"- Reinstall:
pip install -e . - Test:
sc-my-tool --help
Releases are automated with semantic-release on pushes to the main branch.
- Commit messages follow the Angular convention (examples below)
- Version is derived from commit history and written to pyproject.toml
- GitHub Releases are created with changelog and build artifacts (sdist/wheel)
- Tags are formatted as v{version} (e.g., v0.2.3)
Commit message examples:
feat(q0): add automated calibration routinefeat(cli): add hierarchical setup commandsfix(display): prevent crash when PV is disconnecteddocs: update operator instructionsrefactor: simplify analysis pipelinechore: update CI Python versionsperf: speed up data loadingtest(cli): add comprehensive CLI test coverageBREAKING CHANGE: rename module sc_linac_physics.foo to sc_linac_physics.bar
Note: Upload to PyPI is disabled by default; artifacts are attached to GitHub Releases.
Packaged data included under the distribution:
- displays/*
- applications/q0/calibrations/*
- applications/q0/data/*
- Any *.ui, *.yaml, *.yml, *.json files
Access packaged files robustly via importlib.resources (Python 3.12+), not relative paths.
Example:
from importlib.resources import files
base = files("sc_linac_physics")
display_dir = base / "displays"
for p in display_dir.iterdir():
if p.suffix == ".ui":
print("Found display:", p)- Qt errors in headless environments:
- Set
QT_QPA_PLATFORM=offscreenor use Xvfb (xvfb-run -a ...)
- Set
- PV connections during development:
- Use
PYDM_DEFAULT_PROTOCOL=faketo test UI flow without EPICS
- Use
- Import issues when developing:
- Ensure editable install (
-e) or add src/ to PYTHONPATH
- Ensure editable install (
- CLI command not found after installation:
- Reinstall with
pip install -e .or check that your virtual environment is activated - Verify console_scripts entry points in pyproject.toml
- Reinstall with
- Invalid cryomodule name:
- Use just the number (e.g.,
01,H1) notCM01 - Valid choices shown in error message or help text
- Use just the number (e.g.,
- Open issues and pull requests are welcome
- Please run black and flake8 locally before submitting
- Add tests for new features/bugfixes where possible
- Use conventional commit messages (Angular style) to drive automated releases
This project is licensed under the terms described in the LICENSE file included with the repository.
- Lisa Zacarias (zacarias@slac.stanford.edu)
- Sebastian Aderhold (aderhold@slac.stanford.edu)
- Derikka Bisi (dabisi@slac.stanford.edu)
- Haley Marts (hmarts@slac.stanford.edu)
See CHANGELOG.md for release notes (auto-generated by semantic-release).
COPYRIGHT © SLAC National Accelerator Laboratory. All rights reserved. This work is supported in part by the U.S. Department of Energy, Office of Basic Energy Sciences under contract DE-AC02-76SF00515.
Neither the name of the Leland Stanford Junior University, SLAC National Accelerator Laboratory, U.S. Department of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.