Architecture#
Overview#
polar-bits supports three hutches and a Raman setup at the 4ID-POLAR beamline, all
sharing a common codebase in id4_common with beamline-specific overrides in
separate packages.
src/
├── id4_common/ # Shared: devices, plans, callbacks, utils
├── id4_b/ # 4IDB-specific startup and config extras
├── id4_g/ # 4IDG-specific startup and config extras
├── id4_h/ # 4IDH-specific startup and config extras
├── id4_raman/ # Raman-specific startup and config extras
├── id4_common_qserver/ # Shared QueueServer components
├── id4_b_qserver/ # 4IDB QueueServer config and launch script
├── id4_g_qserver/ # 4IDG QueueServer config and launch script
├── id4_h_qserver/ # 4IDH QueueServer config and launch script
└── id4_raman_qserver/ # Raman QueueServer config and launch script
What goes where#
Layer |
Location |
Examples |
|---|---|---|
Core shared devices |
|
undulator, monochromator, KB mirrors |
Shared scan plans |
|
|
Data callbacks |
|
SPEC writer, NeXus writer, dichro stream |
Session utilities |
|
device loader, counters, HKL utilities |
Safety suspenders |
|
shutter-based suspenders |
Instrument overrides |
|
startup.py, iconfig_extras.yml |
Startup Flow#
startup.py orchestrates session initialization in this order:
Load
iconfig.ymlSet up APS DM integration (
aps_dm_setup)Initialize
RE(RunEngine),cat(databroker catalog),bec, and supplementary data streamsConditionally load SPEC / NeXus callbacks based on
iconfig.ymlLoad dichro stream callback
Prompt user to load devices — calls
make_devices()which readsdevices.ymlConnect devices tagged with that beamline’s station labels
Install shutter suspenders on the RunEngine
Station Labels#
Device loading is controlled by labels defined in devices.yml. Each beamline
connects only devices whose labels intersect with its stations list:
Beamline |
Stations loaded |
|---|---|
4IDB |
|
4IDG |
|
4IDH |
|
Raman |
|
Common labels:
Label |
Meaning |
|---|---|
|
Loaded by all hutches (shared upstream/optics devices) |
|
Instrument-specific devices |
|
Added to the supplemental baseline data stream |
|
Functional category — used for filtering |
To make a device available to an additional beamline, add that beamline’s label
to its entry in devices.yml. That is the only change required.
Device Registry (devices.yml)#
src/id4_common/configs/devices.yml is the single source of truth for all
device definitions. Each entry maps a Python class path to EPICS PV details:
id4_common.devices.aps_xbpm.MyXBPM:
- name: aps_xbpm
prefix: S04
labels: ["core", "source", "baseline"]
Multiple instances of the same class are listed as a YAML sequence under one class key. See Configuration for the full YAML schema.
Deferred EPICS Connection Pattern#
make_devices() instantiates all device objects without making EPICS
connections. Only connect_device() (via wait_for_connection()) triggers
actual EPICS interaction.
Rule: Never subscribe to or read from EPICS/PVA signals inside __init__.
Instead, implement _post_connect_setup() on the device class:
class MyDevice(Device):
signal = Component(EpicsSignalRO, "PV:NAME")
def _post_connect_setup(self):
"""Called by connect_device() after EPICS connection is live."""
self.signal.subscribe(self._my_callback, run=False)
connect_device() calls this hook automatically after wait_for_connection()
succeeds.
Key Components in id4_common/#
devices/#
~66 device modules covering the full instrument:
Area detectors:
ad_eiger1M,ad_lambda,ad_lightfield,ad_vimbaX-ray diagnostics:
aps_xbpm,aps_undulator,aps_statusOptics:
kb_generic(KB mirror factory),transfocator_device(transfocator factory)Monochromator / energy:
monochromator,energy_deviceDiffractometer:
polar_diffractometerDetectors:
scaler,vortex_xmap,vortex_xspress3_*Utilities:
shutters,electromagnet,chopper_device
plans/#
local_scans—lup,ascan,grid_scan,rel_grid_scan,count,qxscandm_plans— APS Data Management workflow submissioncenter_maximum,flyscan_demo,workflow_plan
callbacks/#
spec_data_file_writer— SPEC.datoutputnexus_data_file_writer— NeXus/HDF5 outputdichro_stream— circular dichroism processing
utils/#
~33 utility modules including device loader, counters class, HKL/crystallography helpers, DM integration, attenuator control, and more.