RunControl Device Class
RunControl is a Device subclass for
software-driven run state management.
Use it directly for most software-driven data acquisition, or subclass it for more complex hardware-integrated and external run-control workflows.
What RunControl Provides
RunControl packages a small software run loop into a normal tree-facing
Device. In the current implementation it provides:
runState(for exampleStopped/Running)runRate(iteration frequency)runCount(loop counter)Optional
cmdcallback executed each run loop iteration
When runState is set to Running, RunControl starts a background
thread. That thread sleeps for the selected runRate, calls the optional
cmd callback, and increments runCount. When runState leaves the
running state, the thread exits and is joined.
This makes RunControl a good fit when the system needs a simple
operator-visible “start a repeating loop” control surface without building a
custom thread manager from scratch.
When To Use RunControl
Use RunControl when the important behavior is a repeated loop whose state
should be visible and editable from the tree.
Common fits include:
Software acquisition loops
Periodic trigger or polling actions
Application-level run/stop coordination
Simple supervisory loops that call one function at a selected rate
If the operation is instead a one-shot or finite multi-step procedure, see Process Device Class.
What You Usually Set
Most RunControl definitions use just a few parameters:
hiddento keep the node in a dedicated run-control view rather than the normal tree display.ratesto define the available loop-rate selections.statesto define the available run-state labels.cmdfor the function or command invoked once per loop iteration.
In practice, cmd and rates are the most important ones because they
define what the loop does and how fast it runs.
Subclassing And Override Points
In practice, subclassing is often the general way to use RunControl.
Supplying cmd=... is enough for a simple periodic software loop, but many
real systems need start/stop behavior around hardware triggers, counters,
readout enables, or run bookkeeping.
In the current implementation, the main override points are:
_setRunStateto integrate with external run-control hardware or software when the state changes._setRunRatewhen changing the selected rate should trigger additional application behavior._runwhen the default “sleep, callcmd, incrementrunCount” loop is not sufficient.
Concrete Example
One common pattern is:
When the run starts, read the current state, reset counters, and enable the hardware path that should produce data.
While the run is active, wait for new frames or events and publish the accumulated count through
runCount.When the run stops, disable the same trigger or readout path cleanly.
This example reflects that style:
import pyrogue as pr
import time
class AcquisitionRunControl(pr.RunControl):
def __init__(self, **kwargs):
super().__init__(
name='RunControl',
description='Control a frame-based acquisition run',
hidden=True,
rates={0: 'Auto'},
states={0: 'Stopped', 1: 'Running'},
**kwargs,
)
def _start_run(self):
# Capture the current state before enabling acquisition.
self.root.ReadAll()
trigger = self.root.TriggerRegisters
trigger.ResetCounters()
self.root.CountReset()
trigger.Enable.set(True)
def _stop_run(self):
self.root.TriggerRegisters.Enable.set(False)
def _run(self):
self._start_run()
self.runCount.set(0)
try:
while self.runState.valueDisp() == 'Running':
# Wait for one more recorded frame and publish the total.
channel = self.root.DataWriter.getChannel(1)
channel.waitFrameCount(self.runCount.value() + 1, 1000000000)
self.runCount.set(channel.getFrameCount())
time.sleep(0.01)
finally:
self._stop_run()
API Reference
See RunControl for generated API details.