VirtualScope#
- class VirtualScope( )[source]#
Bases:
ScopeDriverBaseOscilloscope simulated in-process: no transport, server, or hardware.
Every channel sees a signal from the start: a 1 kHz, 1 V peak
SineWaveon odd channels (channel 1, 3, …) and a 1 kHz, 1 V peakSquareWaveon even channels (2, 4, …). A capture is 1000 points across 10 horizontal divisions centered on the trigger, where the trigger source crosses the trigger level on the configured slope. A sine whose peaks miss the level aligns to its nearest peak; a square triggers on its edges at any level. Gaussian noise of 0.01 division is added, reduced by the square root of the average count inAVERAGEmode, and AC coupling removes the signal’s offset. Like an ADC, a capture clips at the screen edges: the vertical offset is the voltage at screen center, and the screen spans 4 divisions of the vertical scale above and below it.While running, every fetch and measurement reads a fresh capture.
stop,single, anddigitizecapture every channel at once, as a real acquisition does, and later fetches and measurements read that capture until the scope runs again, whatever settings or signals change meanwhile. Voltage measurements come from the same acquisition, clipped the same way, but sampled at 100 points per cycle over at most 10 cycles, so a slow timebase reads the signal’s true levels, as a real scope’s full-resolution record does, even when the 1000 fetched points alias. Frequency, period, and duty cycle come from the signal the capture was taken from. Every setting reads back as set.It simulates driving a scope from a script or notebook, so it has no screen or storage:
save_screenshot,save_settings, andload_settingsraiseNotImplementedError.Create a virtual scope.
- Parameters:
num_channels (int)
Number of analog-input channels, numbered from 1. Pass the same count to
InstroScope; a channel above it raisesValueError.signals (Mapping[int, SineWave | SquareWave] | None)
The signal on each listed channel. Channels left out see the default: a sine on odd channels, a square on even ones. Change a channel’s signal at any time with
set_signal.
- Raises:
ValueError –
num_channelsis less than 1, orsignalsnames a channel that does not exist.
Example:
from instro.scope import InstroScope, ScopeMeasurementType from instro.scope.drivers import VirtualScope from instro.scope.drivers.virtual import SineWave driver = VirtualScope(num_channels=4, signals={3: SineWave(frequency=5e3, amplitude=0.5)}) with InstroScope(name="scope", driver=driver, num_channels=4) as scope: scope.single() print(scope.measure(ScopeMeasurementType.VRMS, channel=1).latest) # about 0.71: sine print(scope.measure(ScopeMeasurementType.VRMS, channel=2).latest) # about 1.0: square print(scope.measure(ScopeMeasurementType.FREQUENCY, channel=3).latest) # 5000.0
Methods
No error queue; invalid settings, including NaN or infinite values, raise
ValueErrorwhen set.Nothing to disconnect.
Take one capture and stop; never times out, since the simulated signal always triggers.
A copy of the capture, so editing the returned samples leaves later reads unchanged.
Nothing to force: the simulated signal always triggers.
Read back the current acquisition mode.
Read back the acquisition run state (RUNNING / STOPPED).
Read back the waveforms-to-average count.
Read back input coupling on
channel.Read back the timebase (seconds/div).
Read back
channel's probe attenuation ratio.1000 points across the 10-division window.
Return the signal
channelsees.Read back the trigger status (ARMED / READY / TRIGGERED / …).
Read back
channel's vertical offset (volts).Read back
channel's vertical scale (V/div).Not supported: the virtual scope has no setup storage.
Voltages from the capture;
NaNfor frequency, period, and duty cycle on a signal with no edges.Nothing to connect to.
Free-run: every fetch and measurement reads a fresh capture.
Not supported: the virtual scope has no screen to capture.
Not supported: the virtual scope has no setup storage.
Accept any mode; only
AVERAGEchanges the capture, by reducing its noise.Set the number of waveforms to average.
Set AC/DC input coupling on
channel.Set the timebase to
seconds_per_div.Accepted and read back; waveforms are already referred to the probe tip.
Set the signal
channelsees; a stopped scope keeps showing its last capture.Set the trigger threshold to
level(volts).Accept either mode; the simulated signal always triggers.
EITHERaligns on the rising edge.Set the trigger source to analog
channel.Accept any type; captures align as an edge trigger.
Set the voltage at screen center; captures clip 4 divisions above and below it.
Set
channel's vertical scale tovolts_per_div(V/div).Ensure a measurement slot exists for
measurement_type/channelbefore the scope triggers.Capture every channel at once and stop; the simulated signal always triggers.
Freeze every channel's capture for later fetches and measurements; a stopped scope keeps its own.
- set_signal(
- signal: SineWave | SquareWave,
- channel: int,
Set the signal
channelsees; a stopped scope keeps showing its last capture.- Parameters:
signal (SineWave | SquareWave)
The signal at the probe tip.
channel (int)
Target channel (1-indexed).
- Raises:
ValueError –
channeldoes not exist.
- get_signal(
- channel: int,
Return the signal
channelsees.
- check_errors() None[source]#
No error queue; invalid settings, including NaN or infinite values, raise
ValueErrorwhen set.
- set_vertical_scale( ) None[source]#
Set
channel’s vertical scale tovolts_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.
- set_vertical_offset(offset: float, channel: int) None[source]#
Set the voltage at screen center; captures clip 4 divisions above and below it.
- set_probe_attenuation(factor: float, channel: int) None[source]#
Accepted and read back; waveforms are already referred to the probe tip.
- set_horizontal_scale(seconds_per_div: float) None[source]#
Set the timebase to
seconds_per_div. Applies globally to all channels.
- set_acquisition_mode(
- mode: AcquisitionMode,
Accept any mode; only
AVERAGEchanges the capture, by reducing its noise.
- get_acquisition_mode() AcquisitionMode[source]#
Read back the current acquisition mode.
- set_average_count(count: int) None[source]#
Set the number of waveforms to average. Only takes effect in
AcquisitionMode.AVERAGE.
- stop() None[source]#
Freeze every channel’s capture for later fetches and measurements; a stopped scope keeps its own.
- single() None[source]#
Capture every channel at once and stop; the simulated signal always triggers.
- digitize(timeout: float) None[source]#
Take one capture and stop; never times out, since the simulated signal always triggers.
Right after
single, keeps that shot instead of taking another, to work around anInstroScopebug (#716).
- get_acquisition_state() AcquisitionState[source]#
Read back the acquisition run state (RUNNING / STOPPED).
- fetch_waveform(
- channel: int,
A copy of the capture, so editing the returned samples leaves later reads unchanged.
- measure(
- measurement_type: ScopeMeasurementType,
- channel: int,
Voltages from the capture;
NaNfor frequency, period, and duty cycle on a signal with no edges.
- set_trigger_source(channel: int) None[source]#
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(
- trigger_type: TriggerType,
Accept any type; captures align as an edge trigger.
- set_trigger_level(level: float) None[source]#
Set the trigger threshold to
level(volts). Applies to the configured trigger source.
- set_trigger_slope(
- slope: TriggerSlope,
EITHERaligns on the rising edge.
- set_trigger_mode(
- mode: TriggerMode,
Accept either mode; the simulated signal always triggers.
- get_trigger_status() TriggerStatus[source]#
Read back the trigger status (ARMED / READY / TRIGGERED / …).
- setup_measurement(
- measurement_type: ScopeMeasurementType,
- channel: int,
Ensure a measurement slot exists for
measurement_type/channelbefore 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.