From bb34bd1372d5292e5f7149dbeb450068b3ba8c6f Mon Sep 17 00:00:00 2001 From: glopesdev <glopesdev@users.noreply.github.com> Date: Mon, 16 Oct 2023 22:16:29 +0100 Subject: [PATCH] Add operators for monitoring device synch status --- src/Aeon.Acquisition/Aeon.Acquisition.csproj | 2 +- src/Aeon.Acquisition/HeartbeatMonitor.bonsai | 75 +++++++++ .../SynchronizerMonitor.bonsai | 145 ++++++++++++++++++ 3 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 src/Aeon.Acquisition/HeartbeatMonitor.bonsai create mode 100644 src/Aeon.Acquisition/SynchronizerMonitor.bonsai diff --git a/src/Aeon.Acquisition/Aeon.Acquisition.csproj b/src/Aeon.Acquisition/Aeon.Acquisition.csproj index 782ab54..ff30574 100644 --- a/src/Aeon.Acquisition/Aeon.Acquisition.csproj +++ b/src/Aeon.Acquisition/Aeon.Acquisition.csproj @@ -6,7 +6,7 @@ <PackageTags>Bonsai Rx Project Aeon Acquisition</PackageTags> <TargetFramework>net472</TargetFramework> <VersionPrefix>0.5.0</VersionPrefix> - <VersionSuffix>build231007</VersionSuffix> + <VersionSuffix>build231008</VersionSuffix> </PropertyGroup> <ItemGroup> diff --git a/src/Aeon.Acquisition/HeartbeatMonitor.bonsai b/src/Aeon.Acquisition/HeartbeatMonitor.bonsai new file mode 100644 index 0000000..3d9bcce --- /dev/null +++ b/src/Aeon.Acquisition/HeartbeatMonitor.bonsai @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8"?> +<WorkflowBuilder Version="2.8.1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core" + xmlns:harp="clr-namespace:Bonsai.Harp;assembly=Bonsai.Harp" + xmlns:sys="clr-namespace:System;assembly=mscorlib" + xmlns="https://bonsai-rx.org/2018/workflow"> + <Description>Captures the sequence of heartbeats from the specified source as a named group.</Description> + <Workflow> + <Nodes> + <Expression xsi:type="ExternalizedMapping"> + <Property Name="Name" /> + </Expression> + <Expression xsi:type="rx:CreateObservable"> + <Name /> + <Workflow> + <Nodes> + <Expression xsi:type="ExternalizedMapping"> + <Property Name="Name" /> + </Expression> + <Expression xsi:type="SubscribeSubject"> + <Name>DeviceEvents</Name> + </Expression> + <Expression xsi:type="harp:Parse"> + <harp:Register xsi:type="harp:TimestampedTimestampSeconds" /> + </Expression> + <Expression xsi:type="harp:ConvertTimestamped"> + <Workflow> + <Nodes> + <Expression xsi:type="WorkflowInput"> + <Name>Source1</Name> + </Expression> + <Expression xsi:type="ExternalizedMapping"> + <Property Name="Value" DisplayName="Name" Category="Subject" /> + </Expression> + <Expression xsi:type="PropertySource" TypeArguments="SubscribeSubject,sys:String"> + <MemberName>Name</MemberName> + <Value>DeviceEvents</Value> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:WithLatestFrom" /> + </Expression> + <Expression xsi:type="MemberSelector"> + <Selector>Item2</Selector> + </Expression> + <Expression xsi:type="WorkflowOutput" /> + </Nodes> + <Edges> + <Edge From="0" To="3" Label="Source1" /> + <Edge From="1" To="2" Label="Source1" /> + <Edge From="2" To="3" Label="Source2" /> + <Edge From="3" To="4" Label="Source1" /> + <Edge From="4" To="5" Label="Source1" /> + </Edges> + </Workflow> + </Expression> + <Expression xsi:type="WorkflowOutput" /> + </Nodes> + <Edges> + <Edge From="0" To="1" Label="Source1" /> + <Edge From="0" To="3" Label="Source2" /> + <Edge From="1" To="2" Label="Source1" /> + <Edge From="2" To="3" Label="Source1" /> + <Edge From="3" To="4" Label="Source1" /> + </Edges> + </Workflow> + </Expression> + <Expression xsi:type="WorkflowOutput" /> + </Nodes> + <Edges> + <Edge From="0" To="1" Label="Source1" /> + <Edge From="1" To="2" Label="Source1" /> + </Edges> + </Workflow> +</WorkflowBuilder> \ No newline at end of file diff --git a/src/Aeon.Acquisition/SynchronizerMonitor.bonsai b/src/Aeon.Acquisition/SynchronizerMonitor.bonsai new file mode 100644 index 0000000..f7db6fe --- /dev/null +++ b/src/Aeon.Acquisition/SynchronizerMonitor.bonsai @@ -0,0 +1,145 @@ +<?xml version="1.0" encoding="utf-8"?> +<WorkflowBuilder Version="2.8.1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core" + xmlns:harp="clr-namespace:Bonsai.Harp;assembly=Bonsai.Harp" + xmlns:num="clr-namespace:Bonsai.Numerics;assembly=Bonsai.Numerics" + xmlns:scr="clr-namespace:Bonsai.Scripting.Expressions;assembly=Bonsai.Scripting.Expressions" + xmlns="https://bonsai-rx.org/2018/workflow"> + <Description>Provides continuous statistics and reports current time and device synchronization state.</Description> + <Workflow> + <Nodes> + <Expression xsi:type="WorkflowInput"> + <Name>Source1</Name> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:ToArray" /> + </Expression> + <Expression xsi:type="rx:AsyncSubject"> + <Name>HeartbeatSources</Name> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:Merge" /> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:Merge" /> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:Delay"> + <rx:DueTime>PT0.2S</rx:DueTime> + </Combinator> + </Expression> + <Expression xsi:type="SubscribeSubject"> + <Name>SynchronizerEvents</Name> + </Expression> + <Expression xsi:type="harp:FilterRegister"> + <harp:FilterType>Include</harp:FilterType> + <harp:Register xsi:type="harp:TimestampSeconds" /> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:BufferTrigger"> + <rx:Count xsi:nil="true" /> + <rx:TimeSpan>PT0.4S</rx:TimeSpan> + </Combinator> + </Expression> + <Expression xsi:type="rx:SelectMany"> + <Name>UnwrapTimestamps</Name> + <Workflow> + <Nodes> + <Expression xsi:type="WorkflowInput"> + <Name>Source1</Name> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:Merge" /> + </Expression> + <Expression xsi:type="MemberSelector"> + <Selector>Seconds</Selector> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:ToList" /> + </Expression> + <Expression xsi:type="Format"> + <Format>{0}@{1}</Format> + <Selector>Value,Seconds</Selector> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:ToList" /> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:Zip" /> + </Expression> + <Expression xsi:type="WorkflowOutput" /> + </Nodes> + <Edges> + <Edge From="0" To="1" Label="Source1" /> + <Edge From="1" To="2" Label="Source1" /> + <Edge From="1" To="4" Label="Source1" /> + <Edge From="2" To="3" Label="Source1" /> + <Edge From="3" To="6" Label="Source1" /> + <Edge From="4" To="5" Label="Source1" /> + <Edge From="5" To="6" Label="Source2" /> + <Edge From="6" To="7" Label="Source1" /> + </Edges> + </Workflow> + </Expression> + <Expression xsi:type="MemberSelector"> + <Selector>Item1</Selector> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="num:DescriptiveStatistics" /> + </Expression> + <Expression xsi:type="MemberSelector"> + <Selector>Item2</Selector> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:Zip" /> + </Expression> + <Expression xsi:type="scr:ExpressionTransform"> + <scr:Expression>new( +Item1 as Stats, +Item2 as Names)</scr:Expression> + </Expression> + <Expression xsi:type="SubscribeSubject"> + <Name>HeartbeatSources</Name> + </Expression> + <Expression xsi:type="MemberSelector"> + <Selector>Length</Selector> + </Expression> + <Expression xsi:type="Combinator"> + <Combinator xsi:type="rx:WithLatestFrom" /> + </Expression> + <Expression xsi:type="scr:ExpressionTransform"> + <scr:Expression>new( +Item1.Stats.Mean as MeanRawTimestamp, +DateTime(1904, 1, 1) + TimeSpan.FromSeconds(Item1.Stats.Mean) as MeanTimestamp, +Item2 as ExpectedDeviceCount, +Item1.Stats.Count as DeviceCount, +Item1.Stats.Maximum - Item1.Stats.Minimum as MaxDifference, +string.Join("\t", Item1.Names) as Elements)</scr:Expression> + </Expression> + <Expression xsi:type="WorkflowOutput" /> + </Nodes> + <Edges> + <Edge From="0" To="1" Label="Source1" /> + <Edge From="1" To="2" Label="Source1" /> + <Edge From="2" To="3" Label="Source1" /> + <Edge From="3" To="4" Label="Source1" /> + <Edge From="4" To="5" Label="Source1" /> + <Edge From="5" To="8" Label="Source1" /> + <Edge From="6" To="7" Label="Source1" /> + <Edge From="7" To="8" Label="Source2" /> + <Edge From="8" To="9" Label="Source1" /> + <Edge From="9" To="10" Label="Source1" /> + <Edge From="9" To="12" Label="Source1" /> + <Edge From="10" To="11" Label="Source1" /> + <Edge From="11" To="13" Label="Source1" /> + <Edge From="12" To="13" Label="Source2" /> + <Edge From="13" To="14" Label="Source1" /> + <Edge From="14" To="17" Label="Source1" /> + <Edge From="15" To="16" Label="Source1" /> + <Edge From="16" To="17" Label="Source2" /> + <Edge From="17" To="18" Label="Source1" /> + <Edge From="18" To="19" Label="Source1" /> + </Edges> + </Workflow> +</WorkflowBuilder> \ No newline at end of file