Scope (Oscilloscope)¤
Interface¤
Bases: Instrument
Oscilloscope instrument. Tracks scope state locally; call sync_configuration() after open() to refresh.
Parameters:
-
(name¤str) –Channel-name prefix for published data.
-
(driver¤ScopeDriverBase) –Concrete scope driver; owns its own transport::
scope = InstroScope( "scope", driver=Keysight1200X("
"), num_channels=4, ) -
(num_channels¤int) –Analog-input channel count.
-
(publishers¤list[Publisher] | None, default:None) –Publishers that receive emitted Measurement/Command data.
-
–**kwargs¤Default tags applied to every emitted Measurement/Command. Pass
dataset_rid="<rid>"to auto-create a NominalCorePublisher (uses the on-disk 'default' Nominal credential).
background_interval
property
writable
¤
background_interval
Seconds between background daemon iterations (0 = no wait).
add_publisher
¤
add_publisher(publisher: Publisher)
Register a publisher to receive this instrument's Measurement/Command data.
publish
¤
publish(data: Measurement | Command, **kwargs)
Fan data out to every configured publisher; kwargs pass through.
add_background_daemon_function
¤
add_background_daemon_function(method: Callable, *args, **kwargs)
Append method to the daemon's call list. Use define_background_daemon to replace instead.
get_channel
¤
get_channel(
channel_name: str,
length: int = 1,
wait_for_new_samples: bool = False,
timeout: float = 10.0,
) -> Measurement
Return the most recent length samples for channel_name from the in-memory buffer.
If the channel does not exist yet, or no sample is available, the code will always block until timeout expires.
Parameters:
-
(channel_name¤str) –Name of the channel to retrieve.
-
(length¤int, default:1) –Number of trailing samples to return.
-
(wait_for_new_samples¤bool, default:False) –Block until at least
lengthnew values arrive. -
(timeout¤float, default:10.0) –Seconds to wait when insufficient data exists or
wait_for_new_samples=True.
Raises:
-
RuntimeError–No background buffer;
start()was not called. -
ChannelNotFoundError–channel had no values and no data appeared before
timeout.wait_for_new_samples=Trueand channel did not appear withintimeout. -
ChannelValueTimeoutError–wait_for_new_samples=Trueand values did not arrive withintimeout.
get_single_channel_value
¤
get_single_channel_value(channel_name: str) -> float | None
Return the most recent sample for channel_name from the in-memory buffer.
This will not wait, if data is not available then None is returned.
Parameters:
Raises:
-
RuntimeError–No background buffer;
start()was not called.
define_background_daemon
¤
define_background_daemon(method: Callable, *args, **kwargs)
Replace all daemon functions with a single method (called with the given args).
sync_configuration
¤
sync_configuration() -> ScopeConfig
Bulk-query the instrument and overwrite the tracked ScopeConfig with live state.
Note that trigger source/type/level/slope/mode aren't bulk-queried — not all scopes expose every trigger field, so call the per-field getters where supported.
set_vertical_scale
¤
Set the vertical scale (V/div) on channel.
get_vertical_scale
¤
get_vertical_scale(channel: int, **kwargs) -> Measurement | None
Query the vertical scale (V/div) on channel.
set_vertical_offset
¤
Set the vertical offset (volts) on channel.
get_vertical_offset
¤
get_vertical_offset(channel: int, **kwargs) -> Measurement | None
Query the vertical offset (volts) on channel.
set_coupling
¤
Set AC/DC input coupling on channel.
get_coupling
¤
Query the input coupling mode on channel (published as a string).
set_probe_attenuation
¤
Set the probe attenuation ratio (e.g. 1, 10, 100) on channel.
get_probe_attenuation
¤
get_probe_attenuation(channel: int, **kwargs) -> Measurement | None
Query the probe attenuation ratio on channel.
set_horizontal_scale
¤
Set the timebase (seconds/div).
get_horizontal_scale
¤
get_horizontal_scale(**kwargs) -> Measurement | None
Query the timebase (seconds/div).
get_sample_rate
¤
get_sample_rate(**kwargs) -> Measurement | None
Query the current sample rate (Sa/s).
set_acquisition_mode
¤
set_acquisition_mode(mode: AcquisitionMode, **kwargs) -> Command
Set the acquisition mode (NORMAL/AVERAGE/HIRES/PEAK_DETECT/ENVELOPE).
get_acquisition_mode
¤
get_acquisition_mode(**kwargs) -> Command
Query the current acquisition mode (published as a string).
set_average_count
¤
Set the average count (waveforms averaged) used in AVERAGE acquisition mode.
stop_acquisition
¤
stop_acquisition(**kwargs) -> Command
Stop acquisition; records the acquisition timestamp if one was armed.
get_acquisition_state
¤
get_acquisition_state(**kwargs) -> Command
Query RUNNING/STOPPED. If STOPPED while armed, records the acquisition timestamp.
fetch_waveform
¤
fetch_waveform(
channel: int, timeout: float = 5.0, **kwargs
) -> Measurement
Fetch the acquired waveform from channel.
Timestamps are ns relative to the trigger point (negative = pre-trigger).
If an acquisition is armed, blocks up to timeout seconds for it to
complete; raises TimeoutError if it doesn't.
measure
¤
measure(
measurement_type: ScopeMeasurementType,
channel: int = 1,
timeout: float = 5.0,
**kwargs,
) -> Measurement | None
Take a built-in measurement on channel.
Timestamps default to the last recorded acquisition time (falls back to
time.time_ns() if none). If an acquisition is armed, blocks up to
timeout seconds for it to complete; raises TimeoutError if it doesn't.
set_trigger_source
¤
Set the trigger source to channel.
set_trigger_type
¤
set_trigger_type(trigger_type: TriggerType, **kwargs) -> Command
Set the trigger type (EDGE, PULSE, …).
set_trigger_level
¤
Set the trigger level (volts).
set_trigger_slope
¤
set_trigger_slope(slope: TriggerSlope, **kwargs) -> Command
Set the trigger edge slope (RISING/FALLING/EITHER).
set_trigger_mode
¤
set_trigger_mode(mode: TriggerMode, **kwargs) -> Command
Set the trigger mode (AUTO/NORMAL).
get_trigger_status
¤
get_trigger_status(**kwargs) -> Command
Query the trigger status (published as a string).
save_screenshot
¤
Capture a screenshot and save it. to_instrument=True writes to the scope's filesystem; otherwise to the host.
save_settings
¤
Save scope setup. to_instrument=True writes to the scope's filesystem; otherwise to the host.
load_settings
¤
Recall a scope setup. from_instrument=True reads from the scope's filesystem; otherwise from the host.
Invalidates the tracked ScopeConfig since instrument state changed externally;
call sync_configuration() to refresh.
Types & Configuration¤
Oscilloscope shared types: coupling, acquisition/trigger modes, waveform data, tracked config.
Coupling
¤
TriggerType
¤
TriggerSlope
¤
TriggerMode
¤
AcquisitionState
¤
WaveformData
dataclass
¤
ChannelConfig
dataclass
¤
ChannelConfig(
vertical_scale: float | None = None,
vertical_offset: float | None = None,
coupling: Coupling | None = None,
probe_attenuation: float | None = None,
)
Tracked per-channel state. Fields start as None and populate on set/query.
TriggerConfig
dataclass
¤
TriggerConfig(
source: int | None = None,
type: TriggerType | None = None,
level: float | None = None,
slope: TriggerSlope | None = None,
mode: TriggerMode | None = None,
)
Tracked trigger state (source channel, type, level (V), slope, mode). Fields start as None.
ScopeConfig
dataclass
¤
ScopeConfig(
channels: dict[int, ChannelConfig] = dict(),
trigger: TriggerConfig = TriggerConfig(),
acquisition_mode: AcquisitionMode | None = None,
average_count: int | None = None,
horizontal_scale: float | None = None,
)
Tracked scope state: per-channel (1-based), trigger, acquisition mode, average count, timebase.
channels
class-attribute
instance-attribute
¤
channels: dict[int, ChannelConfig] = field(default_factory=dict)
trigger
class-attribute
instance-attribute
¤
trigger: TriggerConfig = field(default_factory=TriggerConfig)
acquisition_mode
class-attribute
instance-attribute
¤
acquisition_mode: AcquisitionMode | None = None
Driver Interface¤
Bases: ABC
Vendor scope driver contract. Concrete drivers compose a transport (typically VisaDriver).
Channels are 1-indexed analog input numbers throughout — the wrapper
instrument (InstroScope) is responsible for range-checking against the
declared num_channels.
open
abstractmethod
¤
open() -> None
Open the underlying transport. Idempotent.
Concrete drivers also perform any one-shot instrument setup here
(e.g. *CLS, remote-mode handshake).
check_errors
abstractmethod
¤
check_errors() -> None
Drain the vendor's error queue; raise RuntimeError if any error is pending.
Used between setup commands and any blocking query — calling a data query while the scope's error queue holds a syntax error would hang.
set_vertical_scale
abstractmethod
¤
Set channel's vertical scale to volts_per_div (V/div).
Drivers may snap to the nearest hardware-supported step. Callers that
need the actual applied value should get_vertical_scale() afterward.
get_vertical_scale
abstractmethod
¤
Read back channel's vertical scale (V/div).
set_vertical_offset
abstractmethod
¤
Set channel's vertical offset to offset (volts).
get_vertical_offset
abstractmethod
¤
Read back channel's vertical offset (volts).
set_coupling
abstractmethod
¤
Set AC/DC input coupling on channel.
get_coupling
abstractmethod
¤
Read back input coupling on channel.
set_probe_attenuation
abstractmethod
¤
Set channel's probe attenuation ratio (e.g. 1, 10, 100, 1000).
get_probe_attenuation
abstractmethod
¤
Read back channel's probe attenuation ratio.
set_horizontal_scale
abstractmethod
¤
set_horizontal_scale(seconds_per_div: float) -> None
Set the timebase to seconds_per_div. Applies globally to all channels.
get_horizontal_scale
abstractmethod
¤
get_horizontal_scale() -> float
Read back the timebase (seconds/div).
get_sample_rate
abstractmethod
¤
get_sample_rate() -> float
Read back the current sample rate (samples per second).
This is the effective hardware rate the scope is acquiring at; it depends on the timebase, memory depth, and interpolation settings.
set_acquisition_mode
abstractmethod
¤
set_acquisition_mode(mode: AcquisitionMode) -> None
Set the acquisition mode.
Drivers should raise NotImplementedError for AcquisitionMode
values their scope doesn't support (e.g. Keysight 1200X has no
ENVELOPE mode).
get_acquisition_mode
abstractmethod
¤
get_acquisition_mode() -> AcquisitionMode
Read back the current acquisition mode.
set_average_count
abstractmethod
¤
set_average_count(count: int) -> None
Set the number of waveforms to average. Only takes effect in AcquisitionMode.AVERAGE.
get_average_count
abstractmethod
¤
get_average_count() -> int
Read back the waveforms-to-average count.
stop
abstractmethod
¤
stop() -> None
Stop acquisition. Leaves the captured data intact for fetch_waveform / measure.
single
abstractmethod
¤
single() -> None
Arm a single-shot acquisition.
Non-blocking — use get_acquisition_state to poll for STOPPED, or
prefer digitize() which combines arming and waiting.
digitize
abstractmethod
¤
Arm a single acquisition and block until the trigger fires and the capture completes.
Acquisition is global — all enabled channels capture simultaneously. On success the scope is left stopped with valid data ready for readout.
Parameters:
Raises:
-
TimeoutError–Trigger did not fire within
timeout. The driver clears any pending operation so the session stays usable.
get_acquisition_state
abstractmethod
¤
get_acquisition_state() -> AcquisitionState
Read back the acquisition run state (RUNNING / STOPPED).
fetch_waveform
abstractmethod
¤
fetch_waveform(channel: int) -> WaveformData
Fetch the most recently acquired waveform from channel.
Returns:
-
WaveformData–WaveformDatawithtimesin nanoseconds relative to the -
WaveformData–trigger point (negative = pre-trigger) and
voltagesalready -
WaveformData–scaled through the configured probe attenuation.
setup_measurement
¤
setup_measurement(
measurement_type: ScopeMeasurementType, channel: int
) -> None
Ensure a measurement slot exists for measurement_type/channel before the scope triggers.
Required for instruments (e.g. Tektronix) that compute measurements
during acquisition — the slot must be present at trigger time or the
first measure() returns stale/invalid data. Default is a no-op for
instruments (e.g. Keysight 1200X) that compute on demand.
measure
abstractmethod
¤
measure(measurement_type: ScopeMeasurementType, channel: int) -> float
Read a built-in measurement (VPP, VMAX, VMIN, VAVG, VRMS, …) on channel.
Returns math.nan when the scope reports its invalid-measurement
sentinel (no valid acquisition yet, channel off, etc.).
set_trigger_source
abstractmethod
¤
set_trigger_source(channel: int) -> None
Set the trigger source to analog channel.
Drivers typically cache this value because the trigger-level SCPI on some scopes requires the source channel in the same command.
set_trigger_type
abstractmethod
¤
set_trigger_type(trigger_type: TriggerType) -> None
Set the trigger type (EDGE, PULSE, …).
set_trigger_level
abstractmethod
¤
set_trigger_level(level: float) -> None
Set the trigger threshold to level (volts). Applies to the configured trigger source.
set_trigger_slope
abstractmethod
¤
set_trigger_slope(slope: TriggerSlope) -> None
Set the trigger edge slope (RISING / FALLING / EITHER).
set_trigger_mode
abstractmethod
¤
set_trigger_mode(mode: TriggerMode) -> None
Set the trigger sweep mode (AUTO / NORMAL).
AUTO forces an acquisition if no trigger fires within the timeout; NORMAL waits indefinitely for a real trigger.
force_trigger
abstractmethod
¤
force_trigger() -> None
Force a trigger event immediately, regardless of the configured conditions.
get_trigger_status
abstractmethod
¤
get_trigger_status() -> TriggerStatus
Read back the trigger status (ARMED / READY / TRIGGERED / …).
save_screenshot
abstractmethod
¤
save_screenshot(filepath: str, to_instrument: bool = False) -> bytes
Capture a screenshot.
Parameters:
-
(filepath¤str) –Output path. When
to_instrument=Falsethis is a host path; whenTrueit is a path on the scope's filesystem (USB stick, internal storage). -
(to_instrument¤bool, default:False) –When
True, the scope writes the file itself and this returnsb"". WhenFalse, the image is transferred to the host, written tofilepath, and the raw bytes are returned for in-memory use.
save_settings
abstractmethod
¤
Save the current scope setup. Path semantics mirror :meth:save_screenshot.
load_settings
abstractmethod
¤
Recall a scope setup from name.
With from_instrument=True the scope reads from its own filesystem;
otherwise the host reads name and pushes the bytes to the scope.
After loading, the calling InstroScope should invalidate its
tracked ScopeConfig and resync if a fresh view is needed.
Vendor Drivers¤
Keysight 1200X¤
Keysight InfiniiVision 1200 X-Series oscilloscope driver (EDUX1052G and family).
Keysight1200X
¤
Keysight1200X(visa_resource: str | VisaConfig)
Bases: ScopeDriverBase
SCPI driver for Keysight InfiniiVision 1200 X-Series oscilloscopes.
digitize
¤
digitize(timeout: float) -> None
:DIGitize the cached trigger source, then *OPC? under a scoped VISA timeout.
On timeout, clear() aborts the pending op and restores the session.
get_acquisition_state
¤
get_acquisition_state() -> AcquisitionState
:OPERegister:CONDition? bit 3 (0x08) — set = RUNNING, clear = STOPPED.
fetch_waveform
¤
fetch_waveform(channel: int) -> WaveformData
Fetch the waveform from channel over WORD (unsigned 16-bit, LSB-first), 1000 points.
measure
¤
measure(measurement_type: ScopeMeasurementType, channel: int) -> float
Install then query a built-in measurement on channel.
The install form runs first as a guard — bad command syntax surfaces
via check_errors() before we'd block on the query. The vendor's
invalid-measurement sentinel maps to NaN.
get_trigger_status
¤
get_trigger_status() -> TriggerStatus
:OPERegister:CONDition? bits: 0x20 = ARMED, 0x08 = AUTO (running), else TRIGGERED.
save_screenshot
¤
:SAVE:IMAGe to the scope, or :DISPlay:DATA? PNG,COLor and write locally.
save_settings
¤
:SAVE:SETup to scope memory or to the host (:SYSTem:SETup?).
load_settings
¤
:RECall:SETup from scope memory, or send local bytes via :SYSTem:SETup.
setup_measurement
¤
setup_measurement(
measurement_type: ScopeMeasurementType, channel: int
) -> None
Ensure a measurement slot exists for measurement_type/channel before the scope triggers.
Required for instruments (e.g. Tektronix) that compute measurements
during acquisition — the slot must be present at trigger time or the
first measure() returns stale/invalid data. Default is a no-op for
instruments (e.g. Keysight 1200X) that compute on demand.
Siglent SDS1000X-E¤
Siglent SDS1000X-E series oscilloscope driver (SDS1104X-E and family).
SiglentSDS1000XE
¤
SiglentSDS1000XE(visa_resource: str | VisaConfig)
Bases: ScopeDriverBase
SCPI driver for Siglent SDS1000X-E series oscilloscopes (SDS1104X-E and family).
check_errors
¤
check_errors() -> None
Poll CMR? then EXR? and raise on the first non-zero code (no error queue on Siglent).
digitize
¤
digitize(timeout: float) -> None
Arm a single acquisition then poll INR? bit 0 (new signal acquired) until set or timeout.
fetch_waveform
¤
fetch_waveform(channel: int) -> WaveformData
Fetch the full waveform from channel over C{n}:WF? DAT2 (signed 8-bit codes).
measure
¤
measure(measurement_type: ScopeMeasurementType, channel: int) -> float
Query a built-in parameter via C{n}:PAVA?; unavailable/sentinel results map to NaN.
save_screenshot
¤
Transfer a screen dump (SCDP, a raw BMP) to the host and write it to filepath.
save_settings
¤
Save the panel setup to a USB file (STPN) or transfer it to the host (PNSU?).
load_settings
¤
Recall a panel setup from a USB file (RCPN) or push host bytes back (PNSU).
The host-side PNSU write-back is known to wedge the USBTMC interface on some
SDS1000X-E firmware; prefer from_instrument=True (USB stick) over USB connections.
setup_measurement
¤
setup_measurement(
measurement_type: ScopeMeasurementType, channel: int
) -> None
Ensure a measurement slot exists for measurement_type/channel before the scope triggers.
Required for instruments (e.g. Tektronix) that compute measurements
during acquisition — the slot must be present at trigger time or the
first measure() returns stale/invalid data. Default is a no-op for
instruments (e.g. Keysight 1200X) that compute on demand.
Tektronix 2 Series MSO¤
Tektronix 2 Series MSO oscilloscope driver (MSO22, MSO24).
Tektronix2SeriesMSO
¤
Tektronix2SeriesMSO(visa_resource: str | VisaConfig)
Bases: ScopeDriverBase
SCPI driver for Tektronix 2 Series MSO oscilloscopes (MSO22, MSO24).
digitize
¤
digitize(timeout: float) -> None
SEQuence+RUN, then *OPC? under a scoped VISA timeout. clear() on timeout to restore the session.
fetch_waveform
¤
fetch_waveform(channel: int) -> WaveformData
Fetch the waveform from channel over RIBinary (signed 16-bit).
setup_measurement
¤
setup_measurement(
measurement_type: ScopeMeasurementType, channel: int
) -> None
Ensure a persistent measurement slot exists for this type and channel.
Uses MEASUrement:ADDMEAS <type> to create the slot atomically with
the target type — this avoids the race where ADDNew "MEAS<n>" +
MEAS<n>:TYPe creates a slot that briefly computes under the scope's
default type (typically Period) before the type change takes effect,
causing the first measure() call to return a stale, wrong-type
value. ADDMEAS doesn't take a name; the new slot's name (the scope
auto-assigns the next MEAS<n>) is recovered by diffing
MEASUrement:LIST? before and after the add.
Tektronix computes measurements during acquisition, so the slot must exist before the scope triggers for results to be valid.
clear_measurements
¤
clear_measurements() -> None
Delete every measurement slot on the scope and reset the local cache.
measure
¤
measure(measurement_type: ScopeMeasurementType, channel: int) -> float
Read a built-in measurement from a persistent slot; the vendor's invalid sentinel maps to NaN.