LocalCommand
LocalCommand is the right choice when a tree action should
run Python logic rather than write a hardware command register. It gives the
tree a normal Command node, but the implementation stays in software.
Typical use cases:
Orchestration steps such as initialization or reset sequences
File and configuration workflows
Helper actions that combine multiple Variable or Device operations
Operator-visible procedures that do not map to one hardware strobe bit
When To Use LocalCommand
Use LocalCommand when the important interaction is a procedure rather than
state.
That makes it the software-defined counterpart to RemoteCommand:
LocalCommandruns Python-defined behaviorRemoteCommandperforms an action through a hardware-backed write path
If the action really lives in a memory-mapped register field, especially a
reset pulse or trigger bit, RemoteCommand is usually the better fit. If
the action is “run this workflow”, LocalCommand usually reads better in
the tree.
What You Usually Set
Most LocalCommand definitions use the shared command behavior from
Command, plus a small set of parameters that shape
the local action itself:
functionfor the Python callback to executevaluefor the default command argument, when the command takes oneretValuewhen the command returns a value and you want the return type to be described clearlydescriptionfor operator-facing help texthiddenandgroupsfor presentation and workflow policy
How Invocation Works
LocalCommand is an alias-style specialization of
BaseCommand. The callback wrapper can supply any subset of
these keyword arguments:
rootdevcmdarg
That means the callback can be as small or as explicit as the job requires. A
simple no-argument helper works fine, but so does a callback that needs access
to the surrounding Device, the Root, the command node itself, or a
user-supplied argument.
The common invocation forms are:
cmd()cmd(arg)cmd.call(arg)
If the callback accepts arg, then value=... becomes the command’s
default argument. Calling the command without an explicit argument uses that
stored default.
Example Patterns
Device-Local Procedure
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.LocalCommand(
name='SoftReset',
description='Run the device software reset sequence',
function=self._soft_reset,
))
def _soft_reset(self):
# Device-specific software sequence
self.countReset()
self.initialize()
This is the simplest LocalCommand pattern: expose a named tree action and
back it with ordinary Python logic.
Command With An Argument
Many LocalCommand nodes are thin wrappers around a higher-level software
workflow that needs one input value, such as a file path, a numeric count, or
an option string.
import pyrogue as pr
class ConfigRoot(pr.Root):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.LocalCommand(
name='LoadConfig',
description='Load configuration from a YAML file',
value='',
function=self._load_config,
))
def _load_config(self, arg):
self.loadYaml(name=arg, writeEach=False, modes=['RW', 'WO'])
Here, value='' establishes the default argument shape and lets the command
be called either as LoadConfig('/path/file.yml') or by reusing the stored
default argument.
Using the @self.command Decorator
Device.command() provides a compact way to define a LocalCommand inline
next to the logic it wraps.
In the current implementation:
The decorator creates
LocalCommand(function=...)under the hood.If you do not pass
name=..., the function name becomes the command name.The decorated function may accept any subset of
root,dev,cmd, andarg.
This is often the cleanest form for small device-local procedures because the tree-facing command and the Python logic are defined together.
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
@self.command(description='Capture the current state to disk', value='')
def SaveSnapshot(arg):
self.saveYaml(name=arg, modes=['RW', 'RO', 'WO'])
The decorator form still creates a LocalCommand(function=...) under the
hood. Use whichever form reads more clearly in the surrounding code.
It is also a good fit for callbacks that want explicit access to the command context:
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
@self.command(description='Report the current device path')
def ReportPath(cmd):
print(f'Command path: {cmd.path}')
@self.command(value=1, description='Generate a requested number of frames')
def GenerateFrames(arg, dev):
for _ in range(arg):
dev._gen_frame()
These examples show the main decorator patterns: a default-name command, a
callback that uses the command object itself, and a callback that uses both an
argument and the surrounding Device.
Built-In Command Functions
PyRogue includes a small set of built-in command helper functions on
BaseCommand, but those helpers are mainly useful for
commands that have a meaningful backing value or write path.
In practice:
LocalCommandusually uses a custom Python callback.BaseCommand.nothingis the main built-in helper that is naturally useful forLocalCommanditself.The write-oriented helpers such as
touchOneandtoggleare discussed in RemoteCommand, where they are used most often.
nothing is a no-op handler. It is occasionally useful as a placeholder
while bringing up a tree shape or when a command node should exist before its
real implementation is attached.
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.LocalCommand(
name='ReservedAction',
description='Placeholder command for a future software action',
function=pr.BaseCommand.nothing,
))
What To Explore Next
Hardware-backed commands: RemoteCommand
Shared command behavior: Command
Tree-level placement and decorators: Device
API Reference
LocalCommand is an alias-style specialization of
BaseCommand.
For full API documentation, see: