-
Notifications
You must be signed in to change notification settings - Fork 0
Program Structure
StimControl is a programmatically generated MATLAB app. It uses handle structs and similar data types to manage its connected features:
- GUI features are managed in
h - connected devices are managed in
d - save paths are managed in
path - general protocol parameters are managed in
g - trial-specific stimulation parameters are managed in
p - the timer that manages experiment execution logic is stored in
t - state machine flags are handled in
f
In the Session tab, state logic is handled jointly by a timer, t, the dependent variable status, and the flags struct f. When the program is in different states, different buttons are made available. See the figure below for a full overview of the state machine logic.

-
stopTrial- set to true when the STOP button is pressed -
startTrial- set to true when the START or START SINGLE TRIAL buttons are pressed, or after the inter-trial interval during an experiment -
passive- set to true when the START PASSIVE button is pressed -
pause- set to true when the PAUSE button is pressed -
resume- set to true when the RESUME button is pressed -
runningExperiment- set to true when START button is pressed -
trialLoaded- set to true when a trial has been loaded, used to track individual trial loading over an experiment -
trialFinished-
| Status Name | Meaning | Lamp Colour | Start | Stop | Pause | Resume | StartPassive | SingleTrial |
|---|---|---|---|---|---|---|---|---|
| Not Initialised | devices not ready | dark grey | n | n | n | n | n | n |
| No protocol loaded | No protocol loaded | teal | n | n | n | n | y | n |
| Ready | Trial loaded | green | y | n | n | n | y | y |
| Running | Actively stimulating / acquiring | orange | n | y | n | n | n | n |
| Inter-trial | running an experiment, in the inter-trial interval | white | n | y | y | n | n | n |
| Paused | inter-trial, with the inter-trial countdown paused | teal | n | y | n | y | n | n |
| Stopping | Stopping a trial and flushing data | red | n | n | n | n | n | n |
| Awaiting Trigger | in passive mode, will enter 'running' when external trigger is received | teal | n | y | n | n | n | n |
| Error | Something has gone wrong | red | - | - | - | - | - | - |
To allow nesting, protocols are constructed using a tree structure, similar to an abstract syntax tree. TrialData holds all the tree logic, and nodes are individual StimulusBlock objects (both found in StimControl/common). Leaf nodes contain the parsed parameters for stimulus definitions, and parent nodes contain execution information for the stimulus blocks (child relationship, start delay, repeat delay, etc.).
Once the tree has been constructed, nodes are traversed to form the actual parameter structure passed to StimControl, which is sorted per target device, where each target device has the following fields:
- params (an ordered 1xN array of parameters, the structure for which is defined at the top of readProtocol)
- sequence (an ordered 1xM list of integers 1<i<N, where each entry in the list is the index of the param to execute)
- delay (an ordered 1xM list of doubles, where each double is the ms time to wait from the end of the previous stim in that device/channel's stimulus train to the onset of the current stim)
In the interests of saving memory, after the tree is parsed to stimulus parameters, its node data is deleted. Be aware of this when debugging and choose breakpoints appropriately.
Although the tree is analogous to an abstract syntax tree, it's made more complicated by a few things:
- additional modes of execution to parse (simultaneous or oddball, not just sequential)
- the ability to target multiple devices in both dependent and independent ways I've done my best to document within the buildParams function (the main tree traversal function) but can only apologise if some bug forces you to dive back in there.
- TrialData tree can be queried using obj.Plot