From 82e6c032e0d13bda18fd9f504956dd45b75c3c0d Mon Sep 17 00:00:00 2001 From: bruno-f-cruz <7049351+bruno-f-cruz@users.noreply.github.com> Date: Thu, 2 Jul 2026 10:33:26 -0700 Subject: [PATCH 1/2] Add basic hardware quality control assurance to workflow --- .bonsai/Bonsai.config | 9 + src/Extensions/HardwareQA.bonsai | 660 ++++++++++++++++++++++++ src/Extensions/MessageBox.cs | 76 +++ src/Extensions/ValidateClkOutput.bonsai | 141 +++++ src/main.bonsai | 21 +- 5 files changed, 897 insertions(+), 10 deletions(-) create mode 100644 src/Extensions/HardwareQA.bonsai create mode 100644 src/Extensions/MessageBox.cs create mode 100644 src/Extensions/ValidateClkOutput.bonsai diff --git a/.bonsai/Bonsai.config b/.bonsai/Bonsai.config index e5893024..7e42dc58 100644 --- a/.bonsai/Bonsai.config +++ b/.bonsai/Bonsai.config @@ -11,6 +11,7 @@ + @@ -50,6 +51,8 @@ + + @@ -87,6 +90,7 @@ + @@ -130,6 +134,7 @@ + @@ -166,6 +171,7 @@ + @@ -211,6 +217,9 @@ + + + diff --git a/src/Extensions/HardwareQA.bonsai b/src/Extensions/HardwareQA.bonsai new file mode 100644 index 00000000..ea23e8c8 --- /dev/null +++ b/src/Extensions/HardwareQA.bonsai @@ -0,0 +1,660 @@ + + + + + + HardwareChecks + + + + ProtocolValidation + + + + PreSession + + + + + Cameras + + + + TriggeredCamerasStream + + + CheckDroppedFrames + + + + Source1 + + + + 1 + + + + InputSequence + + + InputSequence + + + + + + Value.ChunkData + + + FrameID + + + + 1 + + + + + 1 + + + + + 0 + + + + + + + Source1 + + + + + + + + + + InputSequence + + + Key + + + + + + Item2 + + + + + + + + + + + + + + + + + + + + + + + + + + Camera {0} dropped frame detected during pre-session! + it + + + + + + it + + + + Dropped frame detected during pre-session! + + + + StartExperiment + + + + + + TriggeredCameraController + + + Cameras + + + + + + CheckCameraSettings + + + + Source1 + + + + 1 + + + + ThisCamera + + + ThisCamera + + + Value.Exposure + + + TriggeredCameraController + + + FrameRate + + + Value + + + + + + ((1.0 / Item2) * 1000000) < double(Item1) + 1000 + + + + + + Source1 + + + + + + + + + + + 1 + + + + ThisCamera + + + Key + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Camera {0} exposure setting not compatible with requested frame rate! + it + + + + + + it + + + + + + + + TriggeredCameraController + + + FrameRate.HasValue + + + + + + + Source1 + + + + + + + + + + + TriggeredCameraControl must specify a valid FrameRate property! + + + + + + + + + + + + + + + + + + + + + + + + + + + GitRepository + + + + + ../. + + + + + false + + + + + SessionSchema + + + AllowDirtyRepo + + + + + + AllowDirty? + Item2 ? False : Item1 + + + + + + Source1 + + + + + + + + + + + Repository is not clean! Please discard all local changes. + + + + + + + + + + + + + + + + + + + + + + + CameraChecks + + + + TriggeredCamerasStream + + + OnlineQC + + + + Source1 + + + + 1 + + + + InputSequence + + + InputSequence + + + + + + Value.ChunkData + + + Timestamp + + + + 1 + + + + + 1E-09 + + + + Seconds + + + + 1 + + + + + + + + + + + + + + + 0.0005 + + + + + + + Source1 + + + + + + + + + + + TaskPoolScheduler + + + + + + + + PT0S + PT10S + + + + + + + MakeUI + + + + InputSequence + + + Key + + + Camera {0} out-of-alignment qc was triggered. + it + + + + + + + + + + Warning + Exclamation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SessionSchema + + + SkipHardwareValidation + + + + + + + Source1 + + + + + + + + + + + + + + PT2S + + + + + + + FilterErrors + + + + Source1 + + + Kind + + + + OnError + + + + + + + + + + + + + Exception + + + + + + + + Error + Hand + + + + CloseWorkflow + + + + Source1 + + + + EndExperiment + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Extensions/MessageBox.cs b/src/Extensions/MessageBox.cs new file mode 100644 index 00000000..854f3d20 --- /dev/null +++ b/src/Extensions/MessageBox.cs @@ -0,0 +1,76 @@ +using Bonsai; +using System; +using System.ComponentModel; +using System.Reactive.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +[Combinator] +[Description("Creates a custom message box dialog window.")] +[WorkflowElementCategory(ElementCategory.Sink)] +public class MessageBox +{ + private string text = ""; + public string Text + { + get { return text; } + set { text = value; } + } + + private string title = "Warning"; + public string Title + { + get { return title; } + set { title = value; } + } + + private MessageBoxIcon messageBoxIcon = MessageBoxIcon.Warning; + public MessageBoxIcon MessageBoxIcon + { + get { return messageBoxIcon; } + set { messageBoxIcon = value; } + } + + private class Win32Window : IWin32Window + { + private readonly IntPtr handle; + public Win32Window(IntPtr handle) { this.handle = handle; } + public IntPtr Handle { get { return handle; } } + } + + public IObservable Process(IObservable source) + { + var hwnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; + var owner = new Win32Window(hwnd); + + var capturedText = text; + var capturedTitle = title; + var capturedIcon = messageBoxIcon; + + return source.Select(value => + { + var task = new Task(() => + System.Windows.Forms.MessageBox.Show(owner, capturedText, capturedTitle, MessageBoxButtons.OK, capturedIcon)); + task.Start(); + return value; + }); + } + + public IObservable Process(IObservable source) + { + var hwnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; + var owner = new Win32Window(hwnd); + + var capturedText = text; + var capturedTitle = title; + var capturedIcon = messageBoxIcon; + + return source.Select(ex => + { + var task = new Task(() => + System.Windows.Forms.MessageBox.Show(owner, ex.ToString(), capturedTitle, MessageBoxButtons.OK, capturedIcon)); + task.Start(); + return ex; + }); + } +} diff --git a/src/Extensions/ValidateClkOutput.bonsai b/src/Extensions/ValidateClkOutput.bonsai new file mode 100644 index 00000000..8fb7b47c --- /dev/null +++ b/src/Extensions/ValidateClkOutput.bonsai @@ -0,0 +1,141 @@ + + + + + + ValidateClkOutput + + + + RigSchema + + + HarpClockGenerator.ConnectedClockOutputs + + + + + + OutputChannel + TargetDevice + + + + 1 + + + + ExpectedDevices + + + HarpWhiteRabbitEvents + + + + + + Read + + None + + + + HarpWhiteRabbitCommands + + + + + + Item1 + + + ExpectedDevices + + + + + + + + + + + + + + Source1 + + + MissingChannels + + + Count + + + + 0 + + + + + + + + + + + + + + Error raised while validating the Harp Clock Output: +{0} + it + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main.bonsai b/src/main.bonsai index 579c4274..e5825026 100644 --- a/src/main.bonsai +++ b/src/main.bonsai @@ -395,6 +395,7 @@ + @@ -462,22 +463,22 @@ - - + - - - - - - - - + + + + + + + + + \ No newline at end of file From eb8d23f5031eae3eabf34242dc5a79ecc8de00ff Mon Sep 17 00:00:00 2001 From: bruno-f-cruz <7049351+bruno-f-cruz@users.noreply.github.com> Date: Thu, 2 Jul 2026 10:59:46 -0700 Subject: [PATCH 2/2] Remove shaders dependency --- src/Extensions/HardwareQA.bonsai | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Extensions/HardwareQA.bonsai b/src/Extensions/HardwareQA.bonsai index ea23e8c8..4fda0594 100644 --- a/src/Extensions/HardwareQA.bonsai +++ b/src/Extensions/HardwareQA.bonsai @@ -6,7 +6,6 @@ xmlns:p1="clr-namespace:AllenNeuralDynamics.Core;assembly=AllenNeuralDynamics.Core" xmlns:scr="clr-namespace:Bonsai.Scripting.Expressions;assembly=Bonsai.Scripting.Expressions" xmlns:p2="clr-namespace:AllenNeuralDynamics.VersionControl;assembly=AllenNeuralDynamics.VersionControl" - xmlns:gl="clr-namespace:Bonsai.Shaders;assembly=Bonsai.Shaders" xmlns:p3="clr-namespace:AllenNeuralDynamics.Core.Design;assembly=AllenNeuralDynamics.Core.Design" xmlns:p4="clr-namespace:System.Reactive;assembly=System.Reactive.Core" xmlns:io="clr-namespace:Bonsai.IO;assembly=Bonsai.System" @@ -457,9 +456,9 @@ - - PT0S - PT10S + + PT0S + PT10S @@ -564,8 +563,8 @@ - - PT2S + + PT2S