Stream Process API#
- class joulescope.v0.driver.StreamProcessApi[source]#
This API is used to chain multiple processing callbacks that are called when new data is received from the Joulescope.
The Joulescope driver will call notify() when new data is available. It will call close() when streaming is stopped.
- close()[source]#
Close the processing instance. [optional]
This method may be called from the USB thread.
- start(stream_buffer)[source]#
Start a new streaming session. [optional]
- Parameters:
stream_buffer – The
StreamBufferinstance which contains the new data from the Joulescope. This same instance will be passed to futurestream_notify()calls, too.
This method will be called from the USB thread. The processing duration must be very short to prevent dropping samples. You should post any significant processing to a separate thread.
- stop()[source]#
Stop the existing streaming session. [optional]
This method will be called from the USB thread.
- stream_notify(stream_buffer)[source]#
Notify that new data is available from the Joulescope.
- Parameters:
stream_buffer – The
StreamBufferinstance which contains the new data from the Joulescope.- Returns:
False to continue streaming. True to stop streaming.
This method will be called from the USB thread. The processing duration must be very short to prevent dropping samples. You should post any significant processing to a separate thread.
Threads#
The stream process methods, such as stream_notify, the stop_fn
given to Device.start, and
statistics callbacks all run on the USB thread. Keep them fast, since
slow callbacks drop samples, and do not call back into the device from
them. Pass results to your thread with a queue.Queue or a
threading.Event. For statistics, use
Device.statistics_iter
instead of a callback. See Statistics API.
Run length#
There are three ways to decide how long a capture runs:
Sample count (recommended):
device.start(stop_fn, duration)stops afterdurationseconds of samples, at the sample rate. The device stops itself, even if your thread is busy, and callsstop_fn(event, message)on the USB thread.stop_fnis also called when the device stops for any other reason, such as removal. Usecontiguous_durationinstead to require that the duration has no missing samples.Blocking read:
device.read(duration)does the same as (1) and returns the samples, when the samples fit in the stream buffer.Wall-clock loop:
device.start(), then loop untiltime.time()reaches the end time, thendevice.stop(). The capture length then includes the USB startup delay and your thread’s scheduling, so the sample count varies from run to run. The loop also does not notice when the device stops on an error, unless you also givestop_fn.
Use (1) or (2) for a fixed duration. Only use a loop for open-ended
captures that end on Ctrl-C or on an external condition, and still give
stop_fn. Here is the recommended pattern:
import joulescope
import threading
with joulescope.scan_require_one(config='auto') as device:
done = threading.Event()
def stop_fn(event, message): # runs on the USB thread
done.set()
device.start(stop_fn=stop_fn, duration=10.0)
while not done.wait(0.1): # a timeout keeps Ctrl-C responsive
pass
For statistics, the equivalent of (1) is a count:
device.statistics_iter(count=duration * reduction_frequency).