-
Couldn't load subscription status.
- Fork 7
Serial data acquisition and plot
This page will describe the code used to perform the data acquisition and plotting as part of the ninjaGUI main acquisition loop. This part of the code is executed inside the acquisitionFunction callback.
The code starts with a check to see if the loop has been running for more than ten seconds without receiving data (the tt1 variable saves the last time data was acquired. After that, the serial acquisition function (ReadBytesAvailable) is called. This is an anonymous function that will be different depending on the instrument, but it is expected to return an array of data (datatemp), the number of samples acquired (packlen, it could potentially indicate that each channel got a different number of samples). It should also return the bytes that were not used during the decoding of the acquisition (in case an incomplete package was read), as well as an array containing the remote triggers, if they exist (triggstemp).
After that, the acquired data is stored in the data buffers in memory. The devices are not expected to return timestamps for the data, so the samples are placed one after the other in the order they were received from the serial function.
After that, if labstreaming layer is enabled an present, the data is streamed. The data is pushed as a single chunk, with the column dimension being the time, and each row represents a different channel. The fNIRS data channels are first on the array, then the auxiliaries, then the stim marks (generated from the stim mark button on the GUI) and finally the remote triggers.
After that, the signal is plotted. Due to inefficiencies with the way the plotting function works in Matlab, it is necessary to manage how often the plotting function is called, otherwise it becomes a bottleneck that delays acquisition. For this reason, the code first checks when was the last time the data was plotted (stored in the variable tp1). If more than 100 ms have passed, then the plotting is called again.
Since not all data will be plotted, a subset of the data (based on the channels we want to display and the time interval) is stored in a variable called plotbuffer. Creating an additional variable for plotting is unavoidable, as the data might need to be converted to either optical density or to hemoglobin concentration.
After that, the code checks if the "Plot Data" checkbox is checked, and only calls the plotting functions if it is checked. This was implemented as the data display invariably delays the data acquisition. It is recommended not to plot the data in real time when there is a time sensitive application (for example, when we want to synchronize data streams).
After plotting, the GUI calls the drawnow function with the limitrate option. This further limits the refresh rate of the plot in order to minimize delays.