Cavity Display¶
displays/cavity_display/ is the primary real-time fault monitoring dashboard for the SC Linac. It shows fault status across all 296 cavities organized in a hierarchical tree, with optional heatmap visualization and audio alerts for unacknowledged alarms.
Architecture overview¶
cavity_display/
├── backend/
│ ├── backend_cavity.py — per-cavity fault collection and PV monitoring
│ ├── backend_machine.py — builds the BackendCavity hierarchy
│ ├── fault.py — individual fault condition (PV + threshold + description)
│ └── runner.py — continuous polling service
├── frontend/
│ ├── cavity_widget.py — individual cavity tile (color-coded by severity)
│ ├── gui_cavity.py — cavity row in tree view
│ ├── gui_cryomodule.py — cryomodule section in tree view
│ ├── gui_machine.py — top-level display
│ ├── alarm_sidebar.py — persistent unacknowledged alarm list
│ ├── audio_manager.py — escalating audio alerts
│ └── heatmap/ — alternative 2D grid visualization
│ ├── color_mapper.py
│ ├── heatmap_cavity_widget.py
│ └── heatmap_cm_widget.py
├── cavity_display.py — PyDM Display entry point
└── utils/
├── faults.csv — fault definitions (PV suffix, threshold, description)
└── utils.py
Backend¶
BackendCavity (backend/backend_cavity.py)¶
Extends Cavity with fault monitoring. Key methods:
create_faults()— parsesfaults.csvand instantiatesFaultobjects keyed by hash. Each fault knows its PV name, threshold, and human-readable description._batch_pv_init()— connects status output PVs usingPV.batch_create(). Input fault PVs are read-only and fetched viacaget_many()(no persistent PV objects).get_faults()— returns current fault status by batch-reading fault input PVs.check_archives()— queries the EPICS archiver for historical fault frequency over a configurable time window.
Fault (backend/fault.py)¶
Represents one fault condition. Computes: - Current status (OK / WARNING / ALARM / INVALID) by comparing PV value to threshold - Severity (maps to PyDM alarm color conventions) - Description string for display
runner.py¶
Continuous service loop:
1. Calls check_cavities() on all BackendCavity objects
2. Publishes fault summary to output PVs (for archiver and other displays)
3. Sleeps BACKEND_SLEEP_TIME between iterations
4. Handles Ctrl+C gracefully during initialization
Frontend¶
Tree view hierarchy¶
gui_machine.py (GUIMachine)
└── gui_cryomodule.py (GUICryomodule) ×60
└── gui_cavity.py (GUICavity) ×8
└── cavity_widget.py (CavityWidget)
CavityWidget shows a colored tile — green (no alarm), yellow (warning), red (alarm), gray (invalid) — that reflects the worst current fault severity for that cavity. Clicking a tile expands a fault detail panel.
AlarmSidebar (frontend/alarm_sidebar.py)¶
Persistent list of unacknowledged alarms across all cavities. Items remain until an operator explicitly acknowledges them. Provides a scrollable view separate from the main tree.
AudioAlertManager (frontend/audio_manager.py)¶
Escalating audio alerts: - ALARM severity → sound immediately - WARNING severity → sound after 2-minute grace period - Per-cavity rate limiting: no more than one sound per cavity per 5 minutes, preventing alert storms - Logs alert events separately from the main application log
Heatmap (frontend/heatmap/)¶
Alternative visualization showing all cavities as a 2D color grid:
ColorMapper— maps numeric fault count (0 tovmax) to a Blue → White → Red gradient using a non-linear normalized scale (0.5 = white = neutral)HeatmapCavityWidget— single cavity cellHeatmapCMWidget— one cryomodule row with 8 cavity cellsSeverityFilter— filters which fault severities are shown
Key design choices¶
- Fault PVs read via
caget_many()— fault input PVs are never stored asPVobjects. Batch reads minimize connection overhead for 296 cavities × N faults. - Only output PVs are
PVobjects — needed forput()calls (publishing fault summaries); everything else is read-only via batch CA. - Archive-based trend alerts — historical fault frequency (e.g., "faulted 10 times today") supplements instantaneous severity for context-aware alerting.
faults.csvdrives fault definitions — adding a new fault condition requires only a CSV row, no code change. The CSV is packaged in the wheel and verified in CI.
Entry points¶
sc-cavity # cavity display
sc-faults # fault decoder sub-display
sc-fcount # fault count sub-display