State Machines
When designing operant behaviour assays in systems neuroscience, it is useful to describe the task as a sequence of states that the system goes through (e.g. stimulus on, stimulus off, reward, inter-trial interval, etc). Progression through these states is driven by events, which can be either internal or external to the system (e.g. button press, timeout, stimulus offset, movement onset). It is common to describe the interplay between states and events in the form of a finite-state machine diagram, or graph, where nodes are states, and arrows are events.
For example, a simple reaction time task where the subject needs to press a button as fast as possible following a stimulus is described in the following diagram:
The task begins with an inter-trial interval (ITI), followed by stimulus presentation. After stimulus onset, advancement to the next state can happen only when the subject presses the button (success trial) or a timeout elapses (miss trial). Depending on which event is triggered first, the task advances either to the reward state, or missed state. At the end, the task goes back to the beginning of the ITI state for the next trial.
The exercises below will show you how to translate the above diagram of states and events into an equivalent Bonsai workflow, which can be easily adapted and modified to describe many different operant behaviour tasks.
Exercise 1: Declaring and logging external events
In this worksheet, we will be using an Arduino or a camera as an interface to detect external behaviour events. For experimental purposes, it is very helpful to record and timestamp all of these events, independently of which state the task is in.
- Connect a digital sensor (e.g. beam-break, button, TTL) into Arduino pin 8.
- Insert a
DigitalInputsource and set it to Arduino pin 8. - Insert a
Timestampcombinator. - Insert a
CsvWritersink and configure itsFileNameproperty with a file name ending in.csv. - Run the workflow and activate the digital sensor a couple of times. Stop the workflow and confirm that the events were successfully timestamped and logged in the
.csvfile.
Exercise 2: Inter-trial interval and stimulus presentation
Translating a state machine diagram into a Bonsai workflow begins by identifying the initial state of the task (i.e. the beginning of each trial). It is often convenient to consider the inter-trial interval period as the initial state, followed by stimulus presentation.
- Insert a
Timersource and set itsDueTimeproperty to be about 3 seconds. - Insert a
Sinkoperator and set itsNameproperty toStimulusOn. - Double-click on the
Sinknode to open up its internal specification.
The Sink operator allows you to specify arbitrary processing side-effects without affecting the original flow of events. It is often used to trigger and control stimulus presentation in response to events in the task. Inside the internal specification, Source1 represents input events arriving at the sink. In the specific case of Sink operators, the WorkflowOutput node can be safely ignored.
- Insert a
Booleanoperator followingSource1and set itsValueproperty toTrue. - Insert a
DigitalOutputsink and connect it to Arduino pin 13. - Run the workflow a couple of times and verify that the sequence of events is progressing correctly.
Note: Opening a new connection to the Arduino can take several seconds due to the way the Firmata protocol is implemented. This may introduce a slight delay in starting the task. This delay is only present at the start of the workflow and will not affect the behavior of the state machine.
- In the main top-level workflow, insert a
Delayoperator and set itsDueTimeproperty to a couple of seconds. - Copy the
StimulusOnoperator and insert it after theDelay(you can either copy-paste or recreate it from scratch). - Rename the new operator to
StimulusOffand double-click it to open up its internal representation. - Set the
Valueproperty of theBooleanoperator toFalse. - Run the workflow a couple of times. Is it behaving as you would expect?
- Insert a
Repeatoperator after theStimulusOff. - Run the worklow. Can you describe in your own words what is happening?
- Optional: Draw a marble diagram for
Timer,StimulusOn,Delay, andRepeat.
Exercise 3: Driving state transitions with external behaviour events
- Delete the
Delayoperator. - Insert a
SelectManyoperator afterStimulusOn, and set itsNameproperty toResponse. - Double-click on the
SelectManynode to open up its internal specification.
The SelectMany operator is used here to create a new state for every input event. Source1 represents the input event that created the state, and WorkflowOutput will be used to report the end result from the state (e.g. whether the response was a success or failure).
- Insert a
DigitalInputsource and set it to Arduino pin 8. - Insert a
Takeoperator and set itsCountproperty to 1. - Insert a
Booleanoperator and set itsValueproperty toTrue. - Delete the
Source1operator. - Connect the
Booleanoperator toWorkflowOutput. - Run the workflow a couple of times. Is it behaving as you would expect?
Exercise 4: Timeout and choice
- Still inside the
SelectMany, insert aTimersource and set itsDueTimeproperty to be about 1 second. - Insert a
Booleanoperator and set itsValueproperty toFalse. - Insert the
Ambcombinator and connect to it both of theBooleanoperators. - Connect the output of
AmbtoWorkflowOutput. - Run the workflow a couple of times, open the visualizer of the
Responsenode, and describe what is being plotted.
Exercise 5: Specifying conditional task outcomes
-
Insert a
Conditionoperator after theStimulusOffnode, and set itsNameproperty toSuccess. - Insert another
Conditionoperator in a new branch off theStimulusOffnode, and set itsNameproperty toMiss. - Double-click on the
Conditionoperator to open up its internal specification. -
Insert a
BitwiseNotoperator afterSource1. - In the top-level workflow, insert a
Mergeoperator and connect to it the outputs of both conditional branches.