Skip to content

Commit 0139d1a

Browse files
authored
Implement stop delay as a distribution instead of scalar value (#450)
1 parent ea328bc commit 0139d1a

File tree

5 files changed

+145
-90
lines changed

5 files changed

+145
-90
lines changed

src/DataSchemas/aind_behavior_vr_foraging.json

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3013,11 +3013,17 @@
30133013
"type": "boolean"
30143014
},
30153015
"stop_duration": {
3016-
"default": 0,
3017-
"description": "Duration (s) the animal must stop for to lock its choice",
3018-
"minimum": 0,
3019-
"title": "Stop Duration",
3020-
"type": "number"
3016+
"$ref": "#/$defs/Distribution",
3017+
"default": {
3018+
"family": "Scalar",
3019+
"distribution_parameters": {
3020+
"family": "Scalar",
3021+
"value": 0.0
3022+
},
3023+
"truncation_parameters": null,
3024+
"scaling_parameters": null
3025+
},
3026+
"description": "Duration (s) the animal must stop for to lock its choice"
30213027
},
30223028
"time_to_collect_reward": {
30233029
"default": 100000,

src/Extensions/AddRewardSite.bonsai

Lines changed: 6 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -121,64 +121,11 @@
121121
<Expression xsi:type="SubscribeSubject">
122122
<Name>ActivePatch</Name>
123123
</Expression>
124-
<Expression xsi:type="MemberSelector">
125-
<Selector>RewardSpecification</Selector>
126-
</Expression>
127-
<Expression xsi:type="PropertyMapping">
128-
<PropertyMappings>
129-
<Property Name="Delay" Selector="Delay" />
130-
</PropertyMappings>
131-
</Expression>
132-
<Expression xsi:type="SubscribeSubject">
133-
<Name>ActivePatch</Name>
134-
</Expression>
135-
<Expression xsi:type="MemberSelector">
136-
<Selector>RewardSpecification</Selector>
137-
</Expression>
138-
<Expression xsi:type="MemberSelector">
139-
<Selector>OperantLogic</Selector>
140-
</Expression>
141-
<Expression xsi:type="PropertyMapping">
142-
<PropertyMappings>
143-
<Property Name="IsOperant" Selector="IsOperant" />
144-
<Property Name="TimeToCollectReward" Selector="TimeToCollectReward" />
145-
<Property Name="GraceDistanceThreshold" Selector="GraceDistanceThreshold" />
146-
</PropertyMappings>
147-
</Expression>
148-
<Expression xsi:type="SubscribeSubject">
149-
<Name>ActivePatch</Name>
150-
</Expression>
151-
<Expression xsi:type="MemberSelector">
152-
<Selector>RewardSpecification.OperantLogic.StopDuration</Selector>
153-
</Expression>
154-
<Expression xsi:type="SubscribeSubject">
155-
<Name>StopDurationOffset</Name>
156-
</Expression>
157-
<Expression xsi:type="Combinator">
158-
<Combinator xsi:type="rx:CombineLatest" />
159-
</Expression>
160-
<Expression xsi:type="Combinator">
161-
<Combinator xsi:type="rx:Take">
162-
<rx:Count>1</rx:Count>
163-
</Combinator>
164-
</Expression>
165-
<Expression xsi:type="Add" />
166-
<Expression xsi:type="PropertyMapping">
167-
<PropertyMappings>
168-
<Property Name="StopDuration" />
169-
</PropertyMappings>
170-
</Expression>
171-
<Expression xsi:type="Combinator">
172-
<Combinator xsi:type="p1:OperantLogic">
173-
<p1:IsOperant>true</p1:IsOperant>
174-
<p1:StopDuration>0</p1:StopDuration>
175-
<p1:TimeToCollectReward>100000</p1:TimeToCollectReward>
176-
<p1:GraceDistanceThreshold>10</p1:GraceDistanceThreshold>
177-
</Combinator>
178-
</Expression>
179124
<Expression xsi:type="PropertyMapping">
180125
<PropertyMappings>
181-
<Property Name="OperantLogic" />
126+
<Property Name="OperantLogic" Selector="RewardSpecification.OperantLogic" />
127+
<Property Name="Delay" Selector="RewardSpecification.Delay" />
128+
<Property Name="RewardFunction" Selector="RewardSpecification.RewardFunction" />
182129
</PropertyMappings>
183130
</Expression>
184131
<Expression xsi:type="Combinator">
@@ -198,24 +145,10 @@
198145
</Nodes>
199146
<Edges>
200147
<Edge From="0" To="1" Label="Source1" />
201-
<Edge From="1" To="2" Label="Source1" />
202-
<Edge From="2" To="18" Label="Source1" />
203-
<Edge From="3" To="4" Label="Source1" />
148+
<Edge From="1" To="4" Label="Source1" />
149+
<Edge From="2" To="3" Label="Source1" />
150+
<Edge From="3" To="4" Label="Source2" />
204151
<Edge From="4" To="5" Label="Source1" />
205-
<Edge From="5" To="6" Label="Source1" />
206-
<Edge From="6" To="14" Label="Source1" />
207-
<Edge From="7" To="8" Label="Source1" />
208-
<Edge From="8" To="10" Label="Source1" />
209-
<Edge From="9" To="10" Label="Source2" />
210-
<Edge From="10" To="11" Label="Source1" />
211-
<Edge From="11" To="12" Label="Source1" />
212-
<Edge From="12" To="13" Label="Source1" />
213-
<Edge From="13" To="14" Label="Source2" />
214-
<Edge From="14" To="15" Label="Source1" />
215-
<Edge From="15" To="18" Label="Source2" />
216-
<Edge From="16" To="17" Label="Source1" />
217-
<Edge From="17" To="18" Label="Source3" />
218-
<Edge From="18" To="19" Label="Source1" />
219152
</Edges>
220153
</Workflow>
221154
</Expression>

src/Extensions/AindBehaviorVrForaging.Generated.cs

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8336,7 +8336,7 @@ public partial class OperantLogic
83368336

83378337
private bool _isOperant;
83388338

8339-
private double _stopDuration;
8339+
private Distribution _stopDuration;
83408340

83418341
private double _timeToCollectReward;
83428342

@@ -8345,7 +8345,7 @@ public partial class OperantLogic
83458345
public OperantLogic()
83468346
{
83478347
_isOperant = true;
8348-
_stopDuration = 0D;
8348+
_stopDuration = new Distribution();
83498349
_timeToCollectReward = 100000D;
83508350
_graceDistanceThreshold = 10D;
83518351
}
@@ -8378,9 +8378,10 @@ public bool IsOperant
83788378
/// <summary>
83798379
/// Duration (s) the animal must stop for to lock its choice
83808380
/// </summary>
8381+
[System.Xml.Serialization.XmlIgnoreAttribute()]
83818382
[Newtonsoft.Json.JsonPropertyAttribute("stop_duration")]
83828383
[System.ComponentModel.DescriptionAttribute("Duration (s) the animal must stop for to lock its choice")]
8383-
public double StopDuration
8384+
public Distribution StopDuration
83848385
{
83858386
get
83868387
{
@@ -15277,6 +15278,51 @@ public override string ToString()
1527715278
}
1527815279

1527915280

15281+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.6.1.0 (Newtonsoft.Json v13.0.0.0)")]
15282+
[Newtonsoft.Json.JsonConverter(typeof(JsonInheritanceConverter), "family")]
15283+
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
15284+
[Bonsai.CombinatorAttribute(MethodName="Generate")]
15285+
public partial class Delay
15286+
{
15287+
15288+
public Delay()
15289+
{
15290+
}
15291+
15292+
protected Delay(Delay other)
15293+
{
15294+
}
15295+
15296+
public System.IObservable<Delay> Generate()
15297+
{
15298+
return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Delay(this)));
15299+
}
15300+
15301+
public System.IObservable<Delay> Generate<TSource>(System.IObservable<TSource> source)
15302+
{
15303+
return System.Reactive.Linq.Observable.Select(source, _ => new Delay(this));
15304+
}
15305+
15306+
protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
15307+
{
15308+
return false;
15309+
}
15310+
15311+
public override string ToString()
15312+
{
15313+
System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
15314+
stringBuilder.Append(GetType().Name);
15315+
stringBuilder.Append(" { ");
15316+
if (PrintMembers(stringBuilder))
15317+
{
15318+
stringBuilder.Append(" ");
15319+
}
15320+
stringBuilder.Append("}");
15321+
return stringBuilder.ToString();
15322+
}
15323+
}
15324+
15325+
1528015326
[System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.6.1.0 (Newtonsoft.Json v13.0.0.0)")]
1528115327
[Newtonsoft.Json.JsonConverter(typeof(JsonInheritanceConverter), "family")]
1528215328
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
@@ -16217,6 +16263,45 @@ private static System.IObservable<TResult> Process<TResult>(System.IObservable<V
1621716263
}
1621816264

1621916265

16266+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.6.1.0 (Newtonsoft.Json v13.0.0.0)")]
16267+
[System.ComponentModel.DefaultPropertyAttribute("Type")]
16268+
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Combinator)]
16269+
public partial class MatchDelay : Bonsai.Expressions.SingleArgumentExpressionBuilder
16270+
{
16271+
16272+
public Bonsai.Expressions.TypeMapping Type { get; set; }
16273+
16274+
public override System.Linq.Expressions.Expression Build(System.Collections.Generic.IEnumerable<System.Linq.Expressions.Expression> arguments)
16275+
{
16276+
var typeMapping = Type;
16277+
var returnType = typeMapping != null ? typeMapping.GetType().GetGenericArguments()[0] : typeof(Delay);
16278+
return System.Linq.Expressions.Expression.Call(
16279+
typeof(MatchDelay),
16280+
"Process",
16281+
new System.Type[] { returnType },
16282+
System.Linq.Enumerable.Single(arguments));
16283+
}
16284+
16285+
16286+
private static System.IObservable<TResult> Process<TResult>(System.IObservable<Delay> source)
16287+
where TResult : Delay
16288+
{
16289+
return System.Reactive.Linq.Observable.Create<TResult>(observer =>
16290+
{
16291+
var sourceObserver = System.Reactive.Observer.Create<Delay>(
16292+
value =>
16293+
{
16294+
var match = value as TResult;
16295+
if (match != null) observer.OnNext(match);
16296+
},
16297+
observer.OnError,
16298+
observer.OnCompleted);
16299+
return System.ObservableExtensions.SubscribeSafe(source, sourceObserver);
16300+
});
16301+
}
16302+
}
16303+
16304+
1622016305
[System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.6.1.0 (Newtonsoft.Json v13.0.0.0)")]
1622116306
[System.ComponentModel.DefaultPropertyAttribute("Type")]
1622216307
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Combinator)]
@@ -17093,6 +17178,11 @@ public System.IObservable<string> Process(System.IObservable<AindBehaviorVrForag
1709317178
return Process<AindBehaviorVrForagingTaskLogicVector3>(source);
1709417179
}
1709517180

17181+
public System.IObservable<string> Process(System.IObservable<Delay> source)
17182+
{
17183+
return Process<Delay>(source);
17184+
}
17185+
1709617186
public System.IObservable<string> Process(System.IObservable<Amount> source)
1709717187
{
1709817188
return Process<Amount>(source);
@@ -17264,6 +17354,7 @@ public System.IObservable<string> Process(System.IObservable<ScalingParameters2>
1726417354
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<WebCamera>))]
1726517355
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<AindBehaviorServicesRigVisualStimulationVector3>))]
1726617356
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<AindBehaviorVrForagingTaskLogicVector3>))]
17357+
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<Delay>))]
1726717358
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<Amount>))]
1726817359
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<Probability>))]
1726917360
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<Available>))]

src/Extensions/InstantiateSite.bonsai

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core"
55
xmlns:scr="clr-namespace:Bonsai.Scripting.Expressions;assembly=Bonsai.Scripting.Expressions"
6-
xmlns:gl="clr-namespace:Bonsai.Shaders;assembly=Bonsai.Shaders"
76
xmlns:p1="clr-namespace:AindVrForagingDataSchema;assembly=Extensions"
7+
xmlns:p2="clr-namespace:AllenNeuralDynamics.Core;assembly=AllenNeuralDynamics.Core"
8+
xmlns:gl="clr-namespace:Bonsai.Shaders;assembly=Bonsai.Shaders"
89
xmlns:dsp="clr-namespace:Bonsai.Dsp;assembly=Bonsai.Dsp"
910
xmlns:harp="clr-namespace:Bonsai.Harp;assembly=Bonsai.Harp"
10-
xmlns:p2="clr-namespace:AllenNeuralDynamics.Core;assembly=AllenNeuralDynamics.Core"
1111
xmlns:p3="clr-namespace:Bonsai.Numerics.Distributions;assembly=Bonsai.Numerics"
1212
xmlns:bv="clr-namespace:BonVision;assembly=BonVision"
1313
xmlns="https://bonsai-rx.org/2018/workflow">
@@ -151,8 +151,25 @@
151151
<Expression xsi:type="MemberSelector">
152152
<Selector>OperantLogic.StopDuration</Selector>
153153
</Expression>
154+
<Expression xsi:type="Combinator">
155+
<Combinator xsi:type="p1:SampleDistribution" />
156+
</Expression>
157+
<Expression xsi:type="SubscribeSubject">
158+
<Name>StopDurationOffset</Name>
159+
</Expression>
160+
<Expression xsi:type="Combinator">
161+
<Combinator xsi:type="rx:FirstOrDefault" />
162+
</Expression>
163+
<Expression xsi:type="Combinator">
164+
<Combinator xsi:type="rx:WithLatestFrom" />
165+
</Expression>
166+
<Expression xsi:type="Add" />
154167
<Expression xsi:type="scr:ExpressionTransform">
155-
<scr:Expression>TimeSpan.FromSeconds(it)</scr:Expression>
168+
<scr:Name>Math.Max(0, it)</scr:Name>
169+
<scr:Expression>Math.Max(0, it)</scr:Expression>
170+
</Expression>
171+
<Expression xsi:type="Combinator">
172+
<Combinator xsi:type="p2:TimeSpanFromSeconds" />
156173
</Expression>
157174
<Expression xsi:type="PropertyMapping">
158175
<PropertyMappings>
@@ -161,7 +178,7 @@
161178
</Expression>
162179
<Expression xsi:type="Combinator">
163180
<Combinator xsi:type="gl:Timer">
164-
<gl:DueTime>PT0.0000001S</gl:DueTime>
181+
<gl:DueTime>PT0S</gl:DueTime>
165182
</Combinator>
166183
</Expression>
167184
<Expression xsi:type="WorkflowInput">
@@ -178,12 +195,18 @@
178195
<Edges>
179196
<Edge From="0" To="1" Label="Source1" />
180197
<Edge From="1" To="2" Label="Source1" />
181-
<Edge From="2" To="3" Label="Source1" />
198+
<Edge From="2" To="5" Label="Source1" />
182199
<Edge From="3" To="4" Label="Source1" />
183-
<Edge From="4" To="6" Label="Source1" />
184-
<Edge From="5" To="6" Label="Source2" />
200+
<Edge From="4" To="5" Label="Source2" />
201+
<Edge From="5" To="6" Label="Source1" />
185202
<Edge From="6" To="7" Label="Source1" />
186203
<Edge From="7" To="8" Label="Source1" />
204+
<Edge From="8" To="9" Label="Source1" />
205+
<Edge From="9" To="10" Label="Source1" />
206+
<Edge From="10" To="12" Label="Source1" />
207+
<Edge From="11" To="12" Label="Source2" />
208+
<Edge From="12" To="13" Label="Source1" />
209+
<Edge From="13" To="14" Label="Source1" />
187210
</Edges>
188211
</Workflow>
189212
</Expression>

src/aind_behavior_vr_foraging/task_logic.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,10 @@ class OperantLogic(BaseModel):
228228
"""
229229

230230
is_operant: bool = Field(default=True, description="Will the trial implement operant logic")
231-
stop_duration: float = Field(
232-
default=0, ge=0, description="Duration (s) the animal must stop for to lock its choice"
231+
stop_duration: distributions.Distribution = Field(
232+
default=scalar_value(0),
233+
validate_default=True,
234+
description="Duration (s) the animal must stop for to lock its choice",
233235
)
234236
time_to_collect_reward: float = Field(
235237
default=100000, ge=0, description="Time(s) the animal has to collect the reward"

0 commit comments

Comments
 (0)