Repository navigation
Processes
Nodes are capable of running multiple background processes. Background processes can be used to, e.g., continuously analyze a signal and extract features from it. An example of this is to do real-time R-peak detection of an ECG signal, to be used as a basis for, e.g., HRV-analysis.
A background process is always written as a class method, i.e., the body of a basic node with one background process is written as follows:
class MidasNodeExample(MidasNodeBase):
def __init__(self, *args):
super().__init__(*args)
## Add example process to the list of background processes
self.process_list.append(self.my_background_process)
# ------------------------------------------------------------------------------
# Function running in the background
# ------------------------------------------------------------------------------
def my_background_process(self):
# this is an example, so do nothing
passAny function added to the array self.process_list is automatically started and stopped. All such processes are run using the multiprocessing library in Python.
A more complete example of a background process is described next. In this example the process is constantly updating two secondary channels by calculating values from 10 second time-windows of primary data. The self.run_state.value is the poison-pill variable of the BaseNode, which is used to determine whether the node is running or not.
def background_process_example2(self):
# The process loops while the node is running. The variable run_state.value is
# the poison-pill of the node.
while self.run_state.value:
# Pull 10 seconds of 'primary' data
snapshot = self.snapshot_data(self.channel_names)
data, times = self.unpack_snapshot(snapshot, self.channel_names, [10, 10])
# Calculate mean and standard deviation of this 10 second chunk from
# channel 0
if data[0]:
new_value1 = np.mean(data[0])
new_value2 = np.std(data[0])
else:
new_value1 = 0.0
new_value2 = 0.0
# Obtain a time-stamp for new values
time_stamp = lsl.local_clock()
# Push mean to first secondary data channel
self.push_sample_secondary(0, time_stamp, new_value1)
# Push standard deviation to second secondary data channel
self.push_sample_secondary(1, time_stamp, new_value2)
# Sleep until next sample (note: for accurate timing you don't want
# to use time.sleep)
time.sleep(1.0)