Skip to content

Commit 8ffdd78

Browse files
committed
Add 6th exercise on conditional task outcomes
1 parent c3dfbd6 commit 8ffdd78

7 files changed

Lines changed: 763 additions & 2 deletions

tutorials/hobgoblin-reaction.md

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ In order to translate our simple reaction time task in the previous exercises in
144144
- Insert a [`SelectMany`] operator after `StimOn`, and set its `Name` property to `Response`.
145145
- Double-click on the [`SelectMany`] node to open up its internal specification.
146146

147+
> [!Note]
148+
> 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).
149+
147150
:::workflow
148151
![Stimulus presentation](../workflows/hobgoblin-reactiontime-stimulus-response-input.bonsai)
149152
:::
@@ -158,15 +161,17 @@ In order to translate our simple reaction time task in the previous exercises in
158161
- Run the workflow a couple of times and validate the state machine is responding to the button press.
159162

160163
> [!Note]
161-
> The [`Condition`] operator allows you to specify arbitrary rules for accepting or rejecting inputs. Only inputs which pass the filter specified inside the [`Condition`] are allowed to proceed. Using an [`Equal`] operator allows us to filter only messages from that pin. It also has the beneficial side effect of only detecting a button press (when the value changes fron `None` > `GP2`) instead of a button release (`GP2`>`None`).
164+
> The [`Condition`] operator allows you to specify arbitrary rules for accepting or rejecting inputs. The `WorkflowOutput` node always needs to be specified with a `bool` input, the result of whether the input is accepted (`True`) or rejected (`False`). Only inputs which pass the filter specified inside the [`Condition`] are allowed to proceed. Using an [`Equal`] operator here allows us to filter only messages from that pin and also has the beneficial side effect of only detecting a button press (when the value changes fron `None` > `GP2`) instead of a button release (`GP2`>`None`).
162165
163166
### Exercise 5: Timeout and choice
164167

168+
We will modify our previous workflow to include a timeout during which the responder must make a choice.
169+
170+
**`Response`**:
165171
:::workflow
166172
![Stimulus presentation](../workflows/hobgoblin-reactiontime-stimulus-response-timeout.bonsai)
167173
:::
168174

169-
**`Response`**:
170175
- Inside the `Response` node, insert a [`Timer`] source and set its `DueTime` property to be about 1 second.
171176
- Insert a [`Boolean`] operator and set the `Value` property to `False`
172177
- Insert another [`Boolean`] operator after the [`Condition`] operator and set the `Value` property to `True`
@@ -175,8 +180,63 @@ In order to translate our simple reaction time task in the previous exercises in
175180

176181
_Describe in your own words what the above modified workflow is doing._
177182

183+
### Exercise 6: Specifying conditional task outcomes
184+
185+
We will now modify our workflow to set up a transition to the next state.
186+
187+
:::workflow
188+
![Stimulus response outcomes](../workflows/hobgoblin-reactiontime-stimulus-response-outcomes.bonsai)
189+
:::
190+
191+
- Insert a [`Condition`] operator after the `StimOff` node, and set its `Name` property to `Success`.
192+
- In a new branch from `StimOff`, insert another [`Condition`], and set its `Name` property to `Miss`.
193+
- Insert a [`SelectMany`] operator after the `Success` condition and change its `Name` property to `Reward`.
194+
- Insert a [`SelectMany`] operator after the `Miss` condition and change its `Name` property to `Fail`.
195+
196+
We will now implement the task logic inside our nodes.
197+
198+
**`Miss`**:
199+
:::workflow
200+
![Stimulus response miss condition](../workflows/hobgoblin-reactiontime-stimulus-response-miss-condition.bonsai)
201+
:::
202+
203+
- Double-click on the `Miss` node to open up its internal specification.
204+
- Insert a [`BitwiseNot`] operator after `Source1`.
205+
206+
_Why did we need to specify something for the `Miss` condition?_
207+
_Why did we not need to specify anything for the `Success` condition?_
208+
209+
> [!Note]
210+
> The [`Condition`] operator is often used to represent choice points in the task. Other than [`Equal`], you can use operators such as [`NotEqual`], [`GreaterThan`], etc for specifying such tests.
211+
212+
Inside the `Reward` and `Fail` node you can specify your own logic to signal the state of the trial.
213+
For example, to make the LED blink three times in rapid succession for the `Reward` node:
214+
215+
**`Reward`**:
216+
:::workflow
217+
![Stimulus response miss condition](../workflows/hobgoblin-reactiontime-stimulus-response-outcomes-reward.bonsai)
218+
:::
219+
220+
- Delete the `Source1` operator.
221+
- Copy the fixed-interval blinking LED from [Exercise 1](#exercise-1-generating-a-fixed-interval-stimulus).
222+
- In the [`Timer`] node, set both the `DueTime` and the `Period` properties to 100ms.
223+
- In the [`Delay`] node, set the `DueTime` properties to 100ms.
224+
- Delete the [`Repeat`] node.
225+
- Insert a [`RepeatCount`], set the `Count` property to 3.
226+
- Insert the [`Last`] operator, and connect it to `WorkflowOutput`.
227+
228+
_Try out your state machine and check whether you understand the behavior of the reward signal._
229+
230+
- Copy the workflow in the `Reward` node and paste it into the `Miss` condition.
231+
- **Optional**: Modify the `Fail` state in some way to signal a different trial outcome (e.g. make the LED blink more times, or move a motor).
232+
233+
- In the top-level workflow, insert a [`Merge`] operator and connect to it the outputs of both conditional branches and before the [`Repeat`] node.
234+
235+
_Try out your state machine and introduce variations to the task behavior and conditions._
236+
178237
<!--Reference Style Links -->
179238
[`BehaviorSubject`]: xref:Bonsai.Reactive.BehaviorSubject
239+
[`BitwiseNot`]: xref:Bonsai.Expressions.BitwiseNotBuilder
180240
[`Boolean`]: xref:Bonsai.Expressions.BooleanProperty
181241
[`Condition`]: xref:Bonsai.Reactive.Condition
182242
[`CreateMessage`]: xref:Harp.Hobgoblin.CreateMessage
@@ -189,12 +249,16 @@ _Describe in your own words what the above modified workflow is doing._
189249
[`DigitalOutputSetPayload`]: xref:Harp.Hobgoblin.CreateDigitalOutputSetPayload
190250
[`DigitalOutputClearPayload`]: xref:Harp.Hobgoblin.CreateDigitalOutputClearPayload
191251
[`Equal`]: xref:Bonsai.Expressions.EqualBuilder
252+
[`GreaterThan`]: xref:Bonsai.Expressions.GreaterThanBuilder
192253
[`HarpMessage`]: xref:Bonsai.Harp.HarpMessage
254+
[`Last`]: xref:Bonsai.Reactive.Last
193255
[`Merge`]: xref:Bonsai.Reactive.Merge
194256
[`MulticastSubject`]: xref:Bonsai.Expressions.MulticastSubject
257+
[`NotEqual`]: xref:Bonsai.Expressions.NotEqualBuilder
195258
[`Parse`]: xref:Harp.Hobgoblin.Parse
196259
[`PublishSubject`]: xref:Bonsai.Reactive.PublishSubject
197260
[`Repeat`]: xref:Bonsai.Reactive.Repeat
261+
[`RepeatCount`]: xref:Bonsai.Reactive.RepeatCount
198262
[`SelectMany`]: xref:Bonsai.Reactive.SelectMany
199263
[`Sink`]: xref:Bonsai.Reactive.Sink
200264
[`SubscribeSubject`]: xref:Bonsai.Expressions.SubscribeSubject
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<WorkflowBuilder Version="2.8.5"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns="https://bonsai-rx.org/2018/workflow">
5+
<Workflow>
6+
<Nodes>
7+
<Expression xsi:type="WorkflowInput">
8+
<Name>Source1</Name>
9+
</Expression>
10+
<Expression xsi:type="BitwiseNot" />
11+
<Expression xsi:type="WorkflowOutput" />
12+
</Nodes>
13+
<Edges>
14+
<Edge From="0" To="1" Label="Source1" />
15+
<Edge From="1" To="2" Label="Source1" />
16+
</Edges>
17+
</Workflow>
18+
</WorkflowBuilder>
Lines changed: 52 additions & 0 deletions
Loading
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<WorkflowBuilder Version="2.8.5"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core"
5+
xmlns:p1="clr-namespace:Harp.Hobgoblin;assembly=Harp.Hobgoblin"
6+
xmlns:harp="clr-namespace:Bonsai.Harp;assembly=Bonsai.Harp"
7+
xmlns="https://bonsai-rx.org/2018/workflow">
8+
<Workflow>
9+
<Nodes>
10+
<Expression xsi:type="Combinator">
11+
<Combinator xsi:type="rx:Timer">
12+
<rx:DueTime>PT0.1S</rx:DueTime>
13+
<rx:Period>PT0S</rx:Period>
14+
</Combinator>
15+
</Expression>
16+
<Expression xsi:type="p1:CreateMessage">
17+
<harp:MessageType>Write</harp:MessageType>
18+
<harp:Payload xsi:type="p1:CreateDigitalOutputSetPayload">
19+
<p1:DigitalOutputSet>GP15</p1:DigitalOutputSet>
20+
</harp:Payload>
21+
</Expression>
22+
<Expression xsi:type="MulticastSubject">
23+
<Name>Hobgoblin Commands</Name>
24+
</Expression>
25+
<Expression xsi:type="Combinator">
26+
<Combinator xsi:type="rx:Delay">
27+
<rx:DueTime>PT0.1S</rx:DueTime>
28+
</Combinator>
29+
</Expression>
30+
<Expression xsi:type="p1:CreateMessage">
31+
<harp:MessageType>Write</harp:MessageType>
32+
<harp:Payload xsi:type="p1:CreateDigitalOutputClearPayload">
33+
<p1:DigitalOutputClear>GP15</p1:DigitalOutputClear>
34+
</harp:Payload>
35+
</Expression>
36+
<Expression xsi:type="MulticastSubject">
37+
<Name>Hobgoblin Commands</Name>
38+
</Expression>
39+
<Expression xsi:type="Combinator">
40+
<Combinator xsi:type="rx:RepeatCount">
41+
<rx:Count>3</rx:Count>
42+
</Combinator>
43+
</Expression>
44+
<Expression xsi:type="Combinator">
45+
<Combinator xsi:type="rx:Last" />
46+
</Expression>
47+
<Expression xsi:type="WorkflowOutput" />
48+
</Nodes>
49+
<Edges>
50+
<Edge From="0" To="1" Label="Source1" />
51+
<Edge From="1" To="2" Label="Source1" />
52+
<Edge From="2" To="3" Label="Source1" />
53+
<Edge From="3" To="4" Label="Source1" />
54+
<Edge From="4" To="5" Label="Source1" />
55+
<Edge From="5" To="6" Label="Source1" />
56+
<Edge From="6" To="7" Label="Source1" />
57+
<Edge From="7" To="8" Label="Source1" />
58+
</Edges>
59+
</Workflow>
60+
</WorkflowBuilder>

0 commit comments

Comments
 (0)