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