diff --git a/bonsai/Bonsai.config b/bonsai/Bonsai.config
index 5bb5d83b..17823b2b 100644
--- a/bonsai/Bonsai.config
+++ b/bonsai/Bonsai.config
@@ -5,9 +5,12 @@
-
-
+
+
+
+
+
@@ -21,7 +24,7 @@
-
+
@@ -35,13 +38,14 @@
-
+
+
@@ -69,7 +73,10 @@
+
+
+
@@ -102,6 +109,7 @@
+
@@ -111,9 +119,12 @@
-
-
+
+
+
+
+
@@ -127,7 +138,7 @@
-
+
@@ -140,13 +151,14 @@
-
+
+
diff --git a/src/Extensions/CreateOdorMix.cs b/src/Extensions/CreateOdorMix.cs
deleted file mode 100644
index 6c5b4bcf..00000000
--- a/src/Extensions/CreateOdorMix.cs
+++ /dev/null
@@ -1,182 +0,0 @@
-using Bonsai;
-using System;
-using System.ComponentModel;
-using System.Linq;
-using System.Reactive.Linq;
-using Harp.Olfactometer;
-using Bonsai.Harp;
-
-[Description("Creates a Harp Message that sets the target flow for each channel, assuming target full and a percentage of odor for each channel from the total target odor percentage")]
-public class CreateOdorMix:Source
-{
- private float channel0 = 0;
- [Range(0, 1)]
- [Editor(DesignTypes.SliderEditor, DesignTypes.UITypeEditor)]
- [Description("Odor dilution percentage for channel 0.")]
- public float PercentageChannel0
- {
- get { return channel0; }
- set { channel0 = value; }
- }
-
- private float channel1 = 0;
- [Range(0, 1)]
- [Editor(DesignTypes.SliderEditor, DesignTypes.UITypeEditor)]
- [Description("Odor dilution percentage for channel 1.")]
- public float PercentageChannel1
- {
- get { return channel1; }
- set { channel1 = value; }
- }
-
- private float channel2 = 0;
- [Range(0, 1)]
- [Editor(DesignTypes.SliderEditor, DesignTypes.UITypeEditor)]
- [Description("Odor dilution percentage for channel 2.")]
- public float PercentageChannel2
- {
- get { return channel2; }
- set { channel2 = value; }
- }
- private float channel3 = 0;
-
- [Range(0, 1)]
- [Editor(DesignTypes.SliderEditor, DesignTypes.UITypeEditor)]
- [Description("Odor dilution percentage for channel 3. This Value will be ignored if Channel3AsCarrier is set to True.")]
- public float PercentageChannel3
- {
- get { return channel3; }
- set { channel3 = value; }
- }
-
- public bool channel3AsCarrier = false;
- [Description("Specifies if Channel3 should be used as an odor or carrier channel. If True, the flow value value of Channel3 will be set to TotalFlow.")]
- public bool Channel3AsCarrier
- {
- get { return channel3AsCarrier; }
- set {
- channel3AsCarrier = value;
- channel3 = channel3AsCarrier ? float.NaN : 0;
- }
- }
-
- private int targetOdorFlow = 100;
- [Range(0, 100)]
- [Editor(DesignTypes.SliderEditor, DesignTypes.UITypeEditor)]
- [Description("The target odor flow for each channel, assuming PercentageChannelX = 1.")]
- public int TargetOdorFlow
- {
- get { return targetOdorFlow; }
- set { targetOdorFlow = value; }
- }
-
-
- private int totalFlow = 1000;
- [Range(0, 1000)]
- [Editor(DesignTypes.SliderEditor, DesignTypes.UITypeEditor)]
- [Description("The total desired flow at the end of the manifold. This value will be used to automatically calculate the carrier(s) flow.")]
- public int TotalFlow
- {
- get { return totalFlow; }
- set { totalFlow = value; }
- }
-
- private OdorMixMessages ConstructMessage(){
- var adjustedOdorFlow0 = (int)(TargetOdorFlow * channel0);
- var adjustedOdorFlow1 = (int)(TargetOdorFlow * channel1);
- var adjustedOdorFlow2 = (int)(TargetOdorFlow * channel2);
- var adjustedOdorFlow3 = channel3AsCarrier ? 0 : (int)(TargetOdorFlow * channel3);
- var carrierFlow = totalFlow - (adjustedOdorFlow0 + adjustedOdorFlow1 + adjustedOdorFlow2 + adjustedOdorFlow3);
-
- var channelsTargetFlow = ChannelsTargetFlow.FromPayload(MessageType.Write, new ChannelsTargetFlowPayload(
- adjustedOdorFlow0,
- adjustedOdorFlow1,
- adjustedOdorFlow2,
- channel3AsCarrier ? totalFlow : adjustedOdorFlow3,
- carrierFlow));
-
- adjustedOdorFlow3 = channel3AsCarrier ? totalFlow : adjustedOdorFlow3;
- var odorValveState = OdorValveState.FromPayload(MessageType.Write,
- (
- (adjustedOdorFlow0 > 0 ? OdorValves.Valve0 : OdorValves.None) |
- (adjustedOdorFlow1 > 0 ? OdorValves.Valve1 : OdorValves.None) |
- (adjustedOdorFlow2 > 0 ? OdorValves.Valve2 : OdorValves.None) |
- (adjustedOdorFlow3 > 0 ? OdorValves.Valve3 : OdorValves.None)
- ));
-
- return new OdorMixMessages()
- {
- ChannelsTargetFlow = channelsTargetFlow,
- OdorValveState = odorValveState
- };
- }
-
- private OdorMixMessages ConstructMessage(int odorIndex, double concentration){
-
- var adjustedOdorFlow0 = 0;
- var adjustedOdorFlow1 = 0;
- var adjustedOdorFlow2 = 0;
- var adjustedOdorFlow3 = 0;
-
- switch (odorIndex)
- {
- case 0:
- adjustedOdorFlow0 = (int)(TargetOdorFlow * concentration);
- break;
- case 1:
- adjustedOdorFlow1 = (int)(TargetOdorFlow * concentration);
- break;
- case 2:
- adjustedOdorFlow2 = (int)(TargetOdorFlow * concentration);
- break;
- case 3:
- if (channel3AsCarrier){
- throw new Exception("Channel 3 is set as carrier. Cannot set flow for this channel.");
- }
- adjustedOdorFlow3 = (int)(TargetOdorFlow * concentration);
- break;
- default:
- throw new Exception("Invalid channel number. Must be between 0 and 3.");
- }
-
- var carrierFlow = totalFlow - (adjustedOdorFlow0 + adjustedOdorFlow1 + adjustedOdorFlow2 + adjustedOdorFlow3);
-
- var channelsTargetFlow = ChannelsTargetFlow.FromPayload(MessageType.Write, new ChannelsTargetFlowPayload(
- adjustedOdorFlow0,
- adjustedOdorFlow1,
- adjustedOdorFlow2,
- channel3AsCarrier ? totalFlow : adjustedOdorFlow3,
- carrierFlow));
-
- adjustedOdorFlow3 = channel3AsCarrier ? totalFlow : adjustedOdorFlow3;
- var odorValveState = OdorValveState.FromPayload(MessageType.Write,
- (
- (adjustedOdorFlow0 > 0 ? OdorValves.Valve0 : OdorValves.None) |
- (adjustedOdorFlow1 > 0 ? OdorValves.Valve1 : OdorValves.None) |
- (adjustedOdorFlow2 > 0 ? OdorValves.Valve2 : OdorValves.None) |
- (adjustedOdorFlow3 > 0 ? OdorValves.Valve3 : OdorValves.None)
- ));
-
- return new OdorMixMessages()
- {
- ChannelsTargetFlow = channelsTargetFlow,
- OdorValveState = odorValveState
- };
- }
-
- public IObservable Generate(IObservable source)
- {
- return source.Select(value => ConstructMessage());
- }
-
- public override IObservable Generate()
- {
- return Observable.Return(ConstructMessage());
- }
-
-}
-
-public class OdorMixMessages{
- public HarpMessage ChannelsTargetFlow {get; set;}
- public HarpMessage OdorValveState {get; set;}
-}
diff --git a/src/olfactometer_calibration.bonsai b/src/olfactometer_calibration.bonsai
index 2000c908..ace5a0bc 100644
--- a/src/olfactometer_calibration.bonsai
+++ b/src/olfactometer_calibration.bonsai
@@ -14,7 +14,7 @@
xmlns:p8="clr-namespace:AllenNeuralDynamics.VersionControl;assembly=AllenNeuralDynamics.VersionControl"
xmlns:scr="clr-namespace:Bonsai.Scripting.Expressions;assembly=Bonsai.Scripting.Expressions"
xmlns:p9="clr-namespace:Harp.Olfactometer;assembly=Harp.Olfactometer"
- xmlns:p10="clr-namespace:;assembly=Extensions"
+ xmlns:p10="clr-namespace:AllenNeuralDynamics.HarpUtils;assembly=AllenNeuralDynamics.HarpUtils"
xmlns:p11="clr-namespace:AllenNeuralDynamics.Core.Logging;assembly=AllenNeuralDynamics.Core"
xmlns:p12="clr-namespace:Harp.Olfactometer;assembly=Extensions"
xmlns:p13="clr-namespace:Harp.TimestampGeneratorGen3;assembly=Harp.TimestampGeneratorGen3"
@@ -277,8 +277,9 @@
-
+
COMx
+ StartExperiment
RigSchema
@@ -294,8 +295,9 @@
-
+
COMx
+ StartExperiment
@@ -685,6 +687,13 @@
+
+ InitialState
+
+
+
+
+
@@ -1913,8 +1922,10 @@
LoggingRootPath
+ Behavior
Olfactometer.harp
bin
+ HarpDevice
@@ -1939,8 +1950,10 @@
LoggingRootPath
+ Behavior
ClockGenerator.harp
bin
+ HarpDevice
@@ -1971,8 +1984,10 @@
LoggingRootPath
+ Behavior
AnalogInput.harp
bin
+ HarpDevice
@@ -1995,7 +2010,7 @@
HarpAnalogInput
-
+
@@ -2056,6 +2071,7 @@
LoggingRootPath
+
EndSession
config
json
@@ -2141,6 +2157,7 @@
LoggingRootPath
+
Session.json
Config
json
@@ -2153,6 +2170,7 @@
LoggingRootPath
+
Rig
Config
json
@@ -2165,6 +2183,7 @@
LoggingRootPath
+
TaskLogic
Config
json
@@ -2233,6 +2252,7 @@
SoftwareEvents
LoggingRootPath
+ Behavior