Package: dareplane-utils
Dareplane Python UtilsThis module includes utilities for python which are used within the dareplane
framework. It contains functionality which shared can be reused within multiple modules.
This currently includes:ADefaultServer- which will be loaded an extended within each module to implement the dareplane APIlogging- which contains the standard formatting and a SocketHandler which is modified to sendjsonrepresentations of the logging records to the default logging server port (9020). This is used to enable cross process logging.AStreamWatcherimplementation - which is a utility class to query a single LSL stream into a ring buffer.Default Dareplane ServerThis default server is used by allDareplanepython modules as a starting
point for theirTCPsocket. The idea is to have a single source for common
functionality and patch everything that is model specific on top of thisFunctional incarnationsCurrently we are faced with two functional incarnations of serversSpawning functionality from the server in a separate thread, being linked via events to the
main thread (usually the server).Spawning a subprocess for running functionality - Currently necessary for runningpsychopyas it cannot be run from outside the main thread.LoggingThe logging tools allow two main entry point, which arefrom dareplane_utils.logging.logger import get_logger, which is used to get a logger with the default configuration andfrom dareplane_utils.logging.server import LogRecordSocketReceiverwhich is used to spawn up a server for consolidating logs of different processes.StreamWatcherStreamWatcher are a convenient utility around LSL stream inlets. They are basically a ring buffer for reading data to a numpy array.
StreamWatchers are:initialized with a target stream name and a buffer size in seconds specified bybuffer_sizeconnected to the target LSL streamupdated to fetch the latest data (usually done in a loop)initialize a StreamWatcherfromdareplane_utils.stream_watcher.lsl_stream_watcherimportStreamWatcherSTREAM_NAME="my_stream"BUFFER_SIZE_S=5# the required buffer size will be calculated from the LSL# streams meta datasw=StreamWatcher(STREAM_NAME,buffer_size_s=BUFFER_SIZE_S,)connect to the stream# Either use the self.name or a provided identifier dict to hook up to an LSL streamsw.connect_to_stream()updatesw.update()Update will call the following method:defupdate(self):"""Look for new data and update the buffer"""samples,times=self.inlet.pull_chunk()self.add_samples(samples,times)self.samples=samplesself.n_new+=len(samples)Getting dataTo get the data from the StreamWatcher you can either grab the full ring buffer
from the instance attributessw.buffer# ring buffer for datasw.buffer_t# ring buffer for time stampssw.curr_i# current position of the head in the ring bufferor you usually want the more convenient way by using theunfold_buffermethod,
which returns a chronologically sorted array ([-1] is the most recent data
point and [0] is the oldest data point).sw.unfold_buffer()# sorted datasw.unfold_buffer_t()# sorted time stamps## The above is using the following implementationdefunfold_buffer(self):returnnp.vstack([self.buffer[self.curr_i:],self.buffer[:self.curr_i]])