Skip to content

Commit 71049bd

Browse files
authored
Merge pull request #460 from AllenNeuralDynamics/feat-add-water
Add water calculation to launcher and aind-data-schema
2 parents d92c500 + fd7a7f9 commit 71049bd

File tree

14 files changed

+402
-275
lines changed

14 files changed

+402
-275
lines changed

src/DataSchemas/aind_behavior_vr_foraging.json

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5242,7 +5242,7 @@
52425242
"description": "The optional reward specification of the virtual site",
52435243
"oneOf": [
52445244
{
5245-
"$ref": "#/$defs/RewardSpecification"
5245+
"$ref": "#/$defs/VirtualSiteRewardSpecification"
52465246
},
52475247
{
52485248
"type": "null"
@@ -5328,6 +5328,33 @@
53285328
"title": "VirtualSiteLabels",
53295329
"type": "string"
53305330
},
5331+
"VirtualSiteRewardSpecification": {
5332+
"description": "THIS CLASS IS NOT MEANT TO BE DIRECTLY INSTANTIATED.\nSpecifies reward parameters and behavior for a virtual site.\n\nNote: This class is primarily used internally for runtime site generation\nand is not meant to be directly instantiated in task configuration DSL.",
5333+
"properties": {
5334+
"operant_logic": {
5335+
"$ref": "#/$defs/OperantLogic",
5336+
"description": "The optional operant logic of the reward"
5337+
},
5338+
"delay": {
5339+
"$ref": "#/$defs/Distribution",
5340+
"default": {
5341+
"family": "Scalar",
5342+
"distribution_parameters": {
5343+
"family": "Scalar",
5344+
"value": 0.0
5345+
},
5346+
"truncation_parameters": null,
5347+
"scaling_parameters": null
5348+
},
5349+
"description": "The optional distribution where the delay to reward will be drawn from"
5350+
}
5351+
},
5352+
"required": [
5353+
"operant_logic"
5354+
],
5355+
"title": "VirtualSiteRewardSpecification",
5356+
"type": "object"
5357+
},
53315358
"VisualCorridor": {
53325359
"description": "Defines a visual corridor segment in the VR environment.\n\nVisual corridors are the basic building blocks of the VR environment,\ndefining spatial regions with specific textures, dimensions, and positions.",
53335360
"properties": {

src/Extensions/AddRewardSite.bonsai

Lines changed: 12 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
xmlns:p1="clr-namespace:AindVrForagingDataSchema;assembly=Extensions"
66
xmlns:sys="clr-namespace:System;assembly=mscorlib"
77
xmlns:num="clr-namespace:Bonsai.Numerics;assembly=Bonsai.Numerics"
8-
xmlns:p2="clr-namespace:;assembly=Extensions"
98
xmlns="https://bonsai-rx.org/2018/workflow">
109
<Workflow>
1110
<Nodes>
@@ -114,67 +113,17 @@
114113
<Property Name="RenderSpecification" />
115114
</PropertyMappings>
116115
</Expression>
117-
<Expression xsi:type="GroupWorkflow">
118-
<Name>ReconstructReward</Name>
119-
<Workflow>
120-
<Nodes>
121-
<Expression xsi:type="SubscribeSubject">
122-
<Name>ActivePatch</Name>
123-
</Expression>
124-
<Expression xsi:type="PropertyMapping">
125-
<PropertyMappings>
126-
<Property Name="OperantLogic" Selector="RewardSpecification.OperantLogic" />
127-
<Property Name="Delay" Selector="RewardSpecification.Delay" />
128-
<Property Name="RewardFunction" Selector="RewardSpecification.RewardFunction" />
129-
</PropertyMappings>
130-
</Expression>
131-
<Expression xsi:type="Combinator">
132-
<Combinator xsi:type="p2:NullDistribution" />
133-
</Expression>
134-
<Expression xsi:type="PropertyMapping">
135-
<PropertyMappings>
136-
<Property Name="Amount" />
137-
<Property Name="Probability" />
138-
<Property Name="Available" />
139-
</PropertyMappings>
140-
</Expression>
141-
<Expression xsi:type="Combinator">
142-
<Combinator xsi:type="p1:RewardSpecification" />
143-
</Expression>
144-
<Expression xsi:type="WorkflowOutput" />
145-
</Nodes>
146-
<Edges>
147-
<Edge From="0" To="1" 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" />
151-
<Edge From="4" To="5" Label="Source1" />
152-
</Edges>
153-
</Workflow>
154-
</Expression>
155116
<Expression xsi:type="SubscribeSubject">
156117
<Name>ActivePatch</Name>
157118
</Expression>
158-
<Expression xsi:type="MemberSelector">
159-
<Selector>RewardSpecification</Selector>
160-
</Expression>
161-
<Expression xsi:type="IncludeWorkflow" Path="AllenNeuralDynamics.Core:FilterNotNull.bonsai" />
162-
<Expression xsi:type="Combinator">
163-
<Combinator xsi:type="rx:SubscribeWhen" />
164-
</Expression>
165-
<Expression xsi:type="SubscribeSubject">
166-
<Name>ActivePatch</Name>
167-
</Expression>
168-
<Expression xsi:type="MemberSelector">
169-
<Selector>RewardSpecification</Selector>
170-
</Expression>
171-
<Expression xsi:type="Combinator">
172-
<Combinator xsi:type="rx:Merge" />
119+
<Expression xsi:type="PropertyMapping">
120+
<PropertyMappings>
121+
<Property Name="OperantLogic" Selector="RewardSpecification.OperantLogic" />
122+
<Property Name="Delay" Selector="RewardSpecification.Delay" />
123+
</PropertyMappings>
173124
</Expression>
174125
<Expression xsi:type="Combinator">
175-
<Combinator xsi:type="rx:Take">
176-
<rx:Count>1</rx:Count>
177-
</Combinator>
126+
<Combinator xsi:type="p1:VirtualSiteRewardSpecification" />
178127
</Expression>
179128
<Expression xsi:type="PropertyMapping">
180129
<PropertyMappings>
@@ -215,26 +164,20 @@
215164
<Edge From="15" To="16" Label="Source4" />
216165
<Edge From="16" To="17" Label="Source1" />
217166
<Edge From="17" To="18" Label="Source1" />
218-
<Edge From="18" To="36" Label="Source1" />
167+
<Edge From="18" To="30" Label="Source1" />
219168
<Edge From="19" To="20" Label="Source1" />
220169
<Edge From="20" To="21" Label="Source1" />
221-
<Edge From="21" To="36" Label="Source2" />
170+
<Edge From="21" To="30" Label="Source2" />
222171
<Edge From="22" To="23" Label="Source1" />
223172
<Edge From="23" To="24" Label="Source1" />
224-
<Edge From="24" To="36" Label="Source3" />
225-
<Edge From="25" To="29" Label="Source1" />
173+
<Edge From="24" To="30" Label="Source3" />
174+
<Edge From="25" To="26" Label="Source1" />
226175
<Edge From="26" To="27" Label="Source1" />
227176
<Edge From="27" To="28" Label="Source1" />
228-
<Edge From="28" To="29" Label="Source2" />
229-
<Edge From="29" To="32" Label="Source1" />
177+
<Edge From="28" To="30" Label="Source4" />
178+
<Edge From="29" To="30" Label="Source5" />
230179
<Edge From="30" To="31" Label="Source1" />
231180
<Edge From="31" To="32" Label="Source2" />
232-
<Edge From="32" To="33" Label="Source1" />
233-
<Edge From="33" To="34" Label="Source1" />
234-
<Edge From="34" To="36" Label="Source4" />
235-
<Edge From="35" To="36" Label="Source5" />
236-
<Edge From="36" To="37" Label="Source1" />
237-
<Edge From="37" To="38" Label="Source2" />
238181
</Edges>
239182
</Workflow>
240183
</Expression>

src/Extensions/AindBehaviorVrForaging.Generated.cs

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13795,7 +13795,7 @@ public partial class VirtualSite
1379513795

1379613796
private OdorSpecification _odorSpecification;
1379713797

13798-
private RewardSpecification _rewardSpecification;
13798+
private VirtualSiteRewardSpecification _rewardSpecification;
1379913799

1380013800
private RenderSpecification _renderSpecification;
1380113801

@@ -13915,7 +13915,7 @@ public OdorSpecification OdorSpecification
1391513915
[System.Xml.Serialization.XmlIgnoreAttribute()]
1391613916
[Newtonsoft.Json.JsonPropertyAttribute("reward_specification")]
1391713917
[System.ComponentModel.DescriptionAttribute("The optional reward specification of the virtual site")]
13918-
public RewardSpecification RewardSpecification
13918+
public VirtualSiteRewardSpecification RewardSpecification
1391913919
{
1392013920
get
1392113921
{
@@ -14176,6 +14176,108 @@ public enum VirtualSiteLabels
1417614176
}
1417714177

1417814178

14179+
/// <summary>
14180+
/// THIS CLASS IS NOT MEANT TO BE DIRECTLY INSTANTIATED.
14181+
///Specifies reward parameters and behavior for a virtual site.
14182+
///
14183+
///Note: This class is primarily used internally for runtime site generation
14184+
///and is not meant to be directly instantiated in task configuration DSL.
14185+
/// </summary>
14186+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.6.1.0 (Newtonsoft.Json v13.0.0.0)")]
14187+
[System.ComponentModel.DescriptionAttribute(@"THIS CLASS IS NOT MEANT TO BE DIRECTLY INSTANTIATED.
14188+
Specifies reward parameters and behavior for a virtual site.
14189+
14190+
Note: This class is primarily used internally for runtime site generation
14191+
and is not meant to be directly instantiated in task configuration DSL.")]
14192+
[Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
14193+
[Bonsai.CombinatorAttribute(MethodName="Generate")]
14194+
public partial class VirtualSiteRewardSpecification
14195+
{
14196+
14197+
private OperantLogic _operantLogic;
14198+
14199+
private Distribution _delay;
14200+
14201+
public VirtualSiteRewardSpecification()
14202+
{
14203+
_operantLogic = new OperantLogic();
14204+
_delay = new Distribution();
14205+
}
14206+
14207+
protected VirtualSiteRewardSpecification(VirtualSiteRewardSpecification other)
14208+
{
14209+
_operantLogic = other._operantLogic;
14210+
_delay = other._delay;
14211+
}
14212+
14213+
/// <summary>
14214+
/// The optional operant logic of the reward
14215+
/// </summary>
14216+
[System.Xml.Serialization.XmlIgnoreAttribute()]
14217+
[Newtonsoft.Json.JsonPropertyAttribute("operant_logic", Required=Newtonsoft.Json.Required.Always)]
14218+
[System.ComponentModel.DescriptionAttribute("The optional operant logic of the reward")]
14219+
public OperantLogic OperantLogic
14220+
{
14221+
get
14222+
{
14223+
return _operantLogic;
14224+
}
14225+
set
14226+
{
14227+
_operantLogic = value;
14228+
}
14229+
}
14230+
14231+
/// <summary>
14232+
/// The optional distribution where the delay to reward will be drawn from
14233+
/// </summary>
14234+
[System.Xml.Serialization.XmlIgnoreAttribute()]
14235+
[Newtonsoft.Json.JsonPropertyAttribute("delay")]
14236+
[System.ComponentModel.DescriptionAttribute("The optional distribution where the delay to reward will be drawn from")]
14237+
public Distribution Delay
14238+
{
14239+
get
14240+
{
14241+
return _delay;
14242+
}
14243+
set
14244+
{
14245+
_delay = value;
14246+
}
14247+
}
14248+
14249+
public System.IObservable<VirtualSiteRewardSpecification> Generate()
14250+
{
14251+
return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new VirtualSiteRewardSpecification(this)));
14252+
}
14253+
14254+
public System.IObservable<VirtualSiteRewardSpecification> Generate<TSource>(System.IObservable<TSource> source)
14255+
{
14256+
return System.Reactive.Linq.Observable.Select(source, _ => new VirtualSiteRewardSpecification(this));
14257+
}
14258+
14259+
protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
14260+
{
14261+
stringBuilder.Append("OperantLogic = " + _operantLogic + ", ");
14262+
stringBuilder.Append("Delay = " + _delay);
14263+
return true;
14264+
}
14265+
14266+
public override string ToString()
14267+
{
14268+
System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
14269+
stringBuilder.Append(GetType().Name);
14270+
stringBuilder.Append(" { ");
14271+
if (PrintMembers(stringBuilder))
14272+
{
14273+
stringBuilder.Append(" ");
14274+
}
14275+
stringBuilder.Append("}");
14276+
return stringBuilder.ToString();
14277+
}
14278+
}
14279+
14280+
1417914281
/// <summary>
1418014282
/// Defines a visual corridor segment in the VR environment.
1418114283
///
@@ -17138,6 +17240,11 @@ public System.IObservable<string> Process(System.IObservable<VirtualSiteGenerato
1713817240
return Process<VirtualSiteGenerator>(source);
1713917241
}
1714017242

17243+
public System.IObservable<string> Process(System.IObservable<VirtualSiteRewardSpecification> source)
17244+
{
17245+
return Process<VirtualSiteRewardSpecification>(source);
17246+
}
17247+
1714117248
public System.IObservable<string> Process(System.IObservable<VisualCorridor> source)
1714217249
{
1714317250
return Process<VisualCorridor>(source);
@@ -17346,6 +17453,7 @@ public System.IObservable<string> Process(System.IObservable<ScalingParameters2>
1734617453
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<VideoWriterOpenCv>))]
1734717454
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<VirtualSite>))]
1734817455
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<VirtualSiteGenerator>))]
17456+
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<VirtualSiteRewardSpecification>))]
1734917457
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<VisualCorridor>))]
1735017458
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<WallTextures>))]
1735117459
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping<WaterValveCalibration>))]

src/Extensions/TriggeredCameras.bonsai

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<WorkflowBuilder Version="2.8.5"
2+
<WorkflowBuilder Version="2.9.0"
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core"
55
xmlns:p1="clr-namespace:AindVrForagingDataSchema;assembly=Extensions"
@@ -142,7 +142,7 @@
142142
<VideoExtension>mp4</VideoExtension>
143143
<OutputArguments>-vf "scale=out_color_matrix=bt709:out_range=full" -c:v h264_nvenc -pix_fmt nv12 -color_range full -colorspace bt709 -color_trc linear -tune hq -preset p4 -rc vbr -cq 12 -b:v 0M -maxrate 700M -bufsize 350M</OutputArguments>
144144
<InputArguments>-colorspace rgb -color_primaries bt709 -color_trc linear</InputArguments>
145-
<Verbosity>Verbose</Verbosity>
145+
<Verbosity>Warning</Verbosity>
146146
<FrameRate>0</FrameRate>
147147
</Expression>
148148
</Nodes>

src/aind_behavior_vr_foraging/cli.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,46 @@
1+
import os
12
import typing as t
3+
from pathlib import Path
24

3-
from pydantic import Field, RootModel
4-
from pydantic_settings import BaseSettings, CliApp, CliSubCommand
5+
from pydantic import AwareDatetime, Field, RootModel
6+
from pydantic_settings import BaseSettings, CliApp, CliPositionalArg, CliSubCommand
57

68
from aind_behavior_vr_foraging import __semver__, regenerate
7-
from aind_behavior_vr_foraging.data_mappers import DataMapperCli
8-
from aind_behavior_vr_foraging.data_qc import DataQcCli
99
from aind_behavior_vr_foraging.launcher import ClabeCli
1010

1111

12+
class DataMapperCli(BaseSettings, cli_kebab_case=True):
13+
data_path: os.PathLike = Field(description="Path to the session data directory.")
14+
repo_path: os.PathLike = Field(
15+
default=Path("."), description="Path to the repository. By default it will use the current directory."
16+
)
17+
curriculum_suggestion: t.Optional[os.PathLike] = Field(
18+
default=None, description="Path to curriculum suggestion file."
19+
)
20+
session_end_time: AwareDatetime | None = Field(
21+
default=None,
22+
description="End time of the session in ISO format. If not provided, will use the time the data mapping is run.",
23+
)
24+
25+
def cli_cmd(self):
26+
from aind_behavior_vr_foraging.data_mappers import cli_cmd
27+
28+
return cli_cmd(self)
29+
30+
31+
class DataQcCli(BaseSettings, cli_kebab_case=True):
32+
data_path: CliPositionalArg[os.PathLike] = Field(description="Path to the session data directory.")
33+
version: str = Field(default=__semver__, description="Version of the dataset.")
34+
report_path: Path | None = Field(
35+
default=None, description="Path to save the Html QC report. If not provided, report is not saved."
36+
)
37+
38+
def cli_cmd(self):
39+
from aind_behavior_vr_foraging.data_qc import cli_cmd
40+
41+
return cli_cmd(self)
42+
43+
1244
class VersionCli(RootModel):
1345
root: t.Any
1446

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import os
2+
from typing import Optional
3+
4+
5+
def calculate_consumed_water(session_path: os.PathLike) -> Optional[float]:
6+
"""Calculate the total volume of water consumed during a session.
7+
8+
Args:
9+
session_path (os.PathLike): Path to the session directory.
10+
11+
Returns:
12+
Optional[float]: Total volume of water consumed in milliliters, or None if unavailable.
13+
"""
14+
from aind_behavior_vr_foraging.data_contract import dataset
15+
16+
reward = dataset(session_path)["Behavior"]["SoftwareEvents"]["GiveReward"].load()
17+
extra = dataset(session_path)["Behavior"]["SoftwareEvents"]["ForceGiveReward"].load()
18+
total = 0
19+
if reward.has_data is False and extra.has_data is False:
20+
return None
21+
if reward.has_data:
22+
total += reward.data["data"].sum() * 1e-3
23+
if extra.has_data:
24+
total += extra.data["data"].sum() * 1e-3
25+
return total

0 commit comments

Comments
 (0)