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