From a46d06703f86af984f57752d180c5980a2752f69 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Wed, 17 Jul 2024 09:26:06 +0100 Subject: [PATCH 1/9] Refactor vision operators into separate packages --- src/Aeon.Acquisition/Aeon.Acquisition.csproj | 10 +--- src/Aeon.Acquisition/ObservableExtensions.cs | 40 -------------- src/Aeon.Environment/Aeon.Environment.csproj | 4 +- src/Aeon.Foraging/Aeon.Foraging.csproj | 2 +- src/Aeon.Tests/Aeon.Tests.csproj | 3 ++ src/Aeon.Tests/AssertWorkflow.cs | 2 +- src/Aeon.Tests/OperatorTests.cs | 9 ++++ src/Aeon.Video/Aeon.Video.csproj | 30 +++++++++++ .../CameraController.bonsai | 0 .../FileVideoSource.bonsai | 2 +- .../LogVideo.bonsai | 0 src/Aeon.Video/ObservableExtensions.cs | 52 +++++++++++++++++++ src/Aeon.Video/Properties/AssemblyInfo.cs | 6 +++ src/Aeon.Video/Properties/launchSettings.json | 10 ++++ .../PylonCapture.cs | 2 +- .../PylonVideoSource.bonsai | 2 +- .../SpinnakerCapture.cs | 2 +- .../SpinnakerVideoSource.bonsai | 2 +- .../VideoController.bonsai | 2 +- .../VideoControllerType.cs | 2 +- .../VideoDataFrame.cs | 2 +- .../VideoFileCapture.cs | 2 +- .../Aeon.Vision.Sleap.csproj | 25 +++++++++ .../CreatePoseTrackingMetadata.cs | 2 +- .../FormatPose.cs | 2 +- .../LogPoseTracking.bonsai | 2 +- .../PoseTracking.bonsai | 2 +- .../Properties/AssemblyInfo.cs | 6 +++ .../Properties/launchSettings.json | 10 ++++ .../ActivityTracking.bonsai | 0 src/Aeon.Vision/Aeon.Vision.csproj | 25 +++++++++ .../DistanceFromPoint.cs | 2 +- .../FormatBinaryRegions.cs | 2 +- .../PositionTracking.bonsai | 2 +- src/Aeon.Vision/Properties/AssemblyInfo.cs | 6 +++ .../Properties/launchSettings.json | 10 ++++ .../RegionContainsPoint.cs | 2 +- .../RegionTracking.bonsai | 2 +- .../TakeLargestRegions.cs | 6 +-- src/Aeon.sln | 20 ++++++- 40 files changed, 238 insertions(+), 74 deletions(-) create mode 100644 src/Aeon.Video/Aeon.Video.csproj rename src/{Aeon.Acquisition => Aeon.Video}/CameraController.bonsai (100%) rename src/{Aeon.Acquisition => Aeon.Video}/FileVideoSource.bonsai (96%) rename src/{Aeon.Acquisition => Aeon.Video}/LogVideo.bonsai (100%) create mode 100644 src/Aeon.Video/ObservableExtensions.cs create mode 100644 src/Aeon.Video/Properties/AssemblyInfo.cs create mode 100644 src/Aeon.Video/Properties/launchSettings.json rename src/{Aeon.Acquisition => Aeon.Video}/PylonCapture.cs (97%) rename src/{Aeon.Acquisition => Aeon.Video}/PylonVideoSource.bonsai (95%) rename src/{Aeon.Acquisition => Aeon.Video}/SpinnakerCapture.cs (99%) rename src/{Aeon.Acquisition => Aeon.Video}/SpinnakerVideoSource.bonsai (97%) rename src/{Aeon.Acquisition => Aeon.Video}/VideoController.bonsai (99%) rename src/{Aeon.Acquisition => Aeon.Video}/VideoControllerType.cs (75%) rename src/{Aeon.Acquisition => Aeon.Video}/VideoDataFrame.cs (96%) rename src/{Aeon.Acquisition => Aeon.Video}/VideoFileCapture.cs (99%) create mode 100644 src/Aeon.Vision.Sleap/Aeon.Vision.Sleap.csproj rename src/{Aeon.Acquisition => Aeon.Vision.Sleap}/CreatePoseTrackingMetadata.cs (99%) rename src/{Aeon.Acquisition => Aeon.Vision.Sleap}/FormatPose.cs (99%) rename src/{Aeon.Acquisition => Aeon.Vision.Sleap}/LogPoseTracking.bonsai (97%) rename src/{Aeon.Acquisition => Aeon.Vision.Sleap}/PoseTracking.bonsai (97%) create mode 100644 src/Aeon.Vision.Sleap/Properties/AssemblyInfo.cs create mode 100644 src/Aeon.Vision.Sleap/Properties/launchSettings.json rename src/{Aeon.Acquisition => Aeon.Vision}/ActivityTracking.bonsai (100%) create mode 100644 src/Aeon.Vision/Aeon.Vision.csproj rename src/{Aeon.Acquisition => Aeon.Vision}/DistanceFromPoint.cs (98%) rename src/{Aeon.Acquisition => Aeon.Vision}/FormatBinaryRegions.cs (98%) rename src/{Aeon.Acquisition => Aeon.Vision}/PositionTracking.bonsai (98%) create mode 100644 src/Aeon.Vision/Properties/AssemblyInfo.cs create mode 100644 src/Aeon.Vision/Properties/launchSettings.json rename src/{Aeon.Acquisition => Aeon.Vision}/RegionContainsPoint.cs (98%) rename src/{Aeon.Acquisition => Aeon.Vision}/RegionTracking.bonsai (96%) rename src/{Aeon.Acquisition => Aeon.Vision}/TakeLargestRegions.cs (96%) diff --git a/src/Aeon.Acquisition/Aeon.Acquisition.csproj b/src/Aeon.Acquisition/Aeon.Acquisition.csproj index 354f117..58651f0 100644 --- a/src/Aeon.Acquisition/Aeon.Acquisition.csproj +++ b/src/Aeon.Acquisition/Aeon.Acquisition.csproj @@ -17,22 +17,14 @@ - - - - - - - - - + diff --git a/src/Aeon.Acquisition/ObservableExtensions.cs b/src/Aeon.Acquisition/ObservableExtensions.cs index c0a10ad..ce4498f 100644 --- a/src/Aeon.Acquisition/ObservableExtensions.cs +++ b/src/Aeon.Acquisition/ObservableExtensions.cs @@ -9,46 +9,6 @@ namespace Aeon.Acquisition { public static class ObservableExtensions { - public static IObservable FillGaps(this IObservable source, Func gapSelector) - { - return FillGaps(source, value => value, gapSelector); - } - - public static IObservable FillGaps( - this IObservable source, - Func counterSelector, - Func gapSelector) - { - return Observable.Create(observer => - { - bool hasPrevious = false; - TCounter previousCounter = default; - var gapObserver = Observer.Create(value => - { - var counter = counterSelector(value); - if (hasPrevious) - { - var missing = gapSelector(previousCounter, counter); - if (missing < 0) - { - observer.OnError(new InvalidOperationException( - $"Negative gap sizes are not allowed.\n Previous counter: {previousCounter}\n Current counter: {counter}")); - } - - while (missing > 0) - { - observer.OnNext(default); - missing--; - } - } - observer.OnNext(value); - previousCounter = counter; - hasPrevious = true; - }); - return source.SubscribeSafe(gapObserver); - }); - } - public static IObservable MergeUnit(this IObservable source, IObservable other) { return source.Select(x => Unit.Default).Merge(other.Select(x => Unit.Default)); diff --git a/src/Aeon.Environment/Aeon.Environment.csproj b/src/Aeon.Environment/Aeon.Environment.csproj index 7f73a17..fc66d73 100644 --- a/src/Aeon.Environment/Aeon.Environment.csproj +++ b/src/Aeon.Environment/Aeon.Environment.csproj @@ -6,7 +6,7 @@ Provides reactive modules for controlling and monitoring Project Aeon environments. Bonsai Rx Project Aeon Environment net472 - 0.1.0 + 0.2.0 @@ -16,6 +16,8 @@ + + diff --git a/src/Aeon.Foraging/Aeon.Foraging.csproj b/src/Aeon.Foraging/Aeon.Foraging.csproj index 44e8401..5060a1c 100644 --- a/src/Aeon.Foraging/Aeon.Foraging.csproj +++ b/src/Aeon.Foraging/Aeon.Foraging.csproj @@ -6,7 +6,7 @@ Provides acquisition and control modules for Project Aeon foraging experiments. Bonsai Rx Project Aeon Foraging net472 - 0.1.2 + 0.2.0 diff --git a/src/Aeon.Tests/Aeon.Tests.csproj b/src/Aeon.Tests/Aeon.Tests.csproj index fcd9983..9da55c6 100644 --- a/src/Aeon.Tests/Aeon.Tests.csproj +++ b/src/Aeon.Tests/Aeon.Tests.csproj @@ -24,6 +24,9 @@ + + + diff --git a/src/Aeon.Tests/AssertWorkflow.cs b/src/Aeon.Tests/AssertWorkflow.cs index 4a80e0c..b7628b5 100644 --- a/src/Aeon.Tests/AssertWorkflow.cs +++ b/src/Aeon.Tests/AssertWorkflow.cs @@ -4,7 +4,7 @@ using System.IO; using Bonsai.Expressions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Aeon.Acquisition; +using Aeon.Video; using System; namespace Aeon.Tests diff --git a/src/Aeon.Tests/OperatorTests.cs b/src/Aeon.Tests/OperatorTests.cs index 3789e1b..fb6fb5b 100644 --- a/src/Aeon.Tests/OperatorTests.cs +++ b/src/Aeon.Tests/OperatorTests.cs @@ -1,6 +1,9 @@ using Aeon.Acquisition; using Aeon.Environment; using Aeon.Foraging; +using Aeon.Video; +using Aeon.Vision; +using Aeon.Vision.Sleap; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Aeon.Tests @@ -14,9 +17,15 @@ public void Build_Workflows() var acquisition = typeof(GroupByTime).Assembly; var environment = typeof(EnvironmentState).Assembly; var foraging = typeof(WheelDisplacement).Assembly; + var video = typeof(VideoDataFrame).Assembly; + var vision = typeof(DistanceFromPoint).Assembly; + var sleap = typeof(FormatPose).Assembly; AssertWorkflow.CanBuildEmbeddedResources(acquisition); AssertWorkflow.CanBuildEmbeddedResources(environment); AssertWorkflow.CanBuildEmbeddedResources(foraging); + AssertWorkflow.CanBuildEmbeddedResources(video); + AssertWorkflow.CanBuildEmbeddedResources(vision); + AssertWorkflow.CanBuildEmbeddedResources(sleap); } } } diff --git a/src/Aeon.Video/Aeon.Video.csproj b/src/Aeon.Video/Aeon.Video.csproj new file mode 100644 index 0000000..6347327 --- /dev/null +++ b/src/Aeon.Video/Aeon.Video.csproj @@ -0,0 +1,30 @@ + + + + true + Project Aeon - Video + Provides reactive modules for video acquisition in Project Aeon experiments. + Bonsai Rx Project Aeon Video + net472 + 0.1.0 + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Aeon.Acquisition/CameraController.bonsai b/src/Aeon.Video/CameraController.bonsai similarity index 100% rename from src/Aeon.Acquisition/CameraController.bonsai rename to src/Aeon.Video/CameraController.bonsai diff --git a/src/Aeon.Acquisition/FileVideoSource.bonsai b/src/Aeon.Video/FileVideoSource.bonsai similarity index 96% rename from src/Aeon.Acquisition/FileVideoSource.bonsai rename to src/Aeon.Video/FileVideoSource.bonsai index db5b8c5..6ac140b 100644 --- a/src/Aeon.Acquisition/FileVideoSource.bonsai +++ b/src/Aeon.Video/FileVideoSource.bonsai @@ -1,7 +1,7 @@  diff --git a/src/Aeon.Acquisition/LogVideo.bonsai b/src/Aeon.Video/LogVideo.bonsai similarity index 100% rename from src/Aeon.Acquisition/LogVideo.bonsai rename to src/Aeon.Video/LogVideo.bonsai diff --git a/src/Aeon.Video/ObservableExtensions.cs b/src/Aeon.Video/ObservableExtensions.cs new file mode 100644 index 0000000..484b8f1 --- /dev/null +++ b/src/Aeon.Video/ObservableExtensions.cs @@ -0,0 +1,52 @@ +using System; +using System.Linq; +using System.Reactive; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using Bonsai.Harp; + +namespace Aeon.Video +{ + public static class ObservableExtensions + { + public static IObservable FillGaps(this IObservable source, Func gapSelector) + { + return FillGaps(source, value => value, gapSelector); + } + + public static IObservable FillGaps( + this IObservable source, + Func counterSelector, + Func gapSelector) + { + return Observable.Create(observer => + { + bool hasPrevious = false; + TCounter previousCounter = default; + var gapObserver = Observer.Create(value => + { + var counter = counterSelector(value); + if (hasPrevious) + { + var missing = gapSelector(previousCounter, counter); + if (missing < 0) + { + observer.OnError(new InvalidOperationException( + $"Negative gap sizes are not allowed.\n Previous counter: {previousCounter}\n Current counter: {counter}")); + } + + while (missing > 0) + { + observer.OnNext(default); + missing--; + } + } + observer.OnNext(value); + previousCounter = counter; + hasPrevious = true; + }); + return source.SubscribeSafe(gapObserver); + }); + } + } +} diff --git a/src/Aeon.Video/Properties/AssemblyInfo.cs b/src/Aeon.Video/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b5f6d0d --- /dev/null +++ b/src/Aeon.Video/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using Bonsai; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: XmlNamespacePrefix("clr-namespace:Aeon.Video", "aeon-video")] diff --git a/src/Aeon.Video/Properties/launchSettings.json b/src/Aeon.Video/Properties/launchSettings.json new file mode 100644 index 0000000..b48bcfa --- /dev/null +++ b/src/Aeon.Video/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "Bonsai": { + "commandName": "Executable", + "executablePath": "$(registry:HKEY_CURRENT_USER\\Software\\Bonsai Foundation\\Bonsai@InstallDir)Bonsai.exe", + "commandLineArgs": "--lib:\"$(TargetDir).\"", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/src/Aeon.Acquisition/PylonCapture.cs b/src/Aeon.Video/PylonCapture.cs similarity index 97% rename from src/Aeon.Acquisition/PylonCapture.cs rename to src/Aeon.Video/PylonCapture.cs index 8c6709e..83ec4f5 100644 --- a/src/Aeon.Acquisition/PylonCapture.cs +++ b/src/Aeon.Video/PylonCapture.cs @@ -6,7 +6,7 @@ using Bonsai.Harp; using Basler.Pylon; -namespace Aeon.Acquisition +namespace Aeon.Video { [Description("Configures and initializes a Pylon camera for triggered acquisition.")] public class PylonCapture : Bonsai.Pylon.PylonCapture diff --git a/src/Aeon.Acquisition/PylonVideoSource.bonsai b/src/Aeon.Video/PylonVideoSource.bonsai similarity index 95% rename from src/Aeon.Acquisition/PylonVideoSource.bonsai rename to src/Aeon.Video/PylonVideoSource.bonsai index 185d78b..2b4e6db 100644 --- a/src/Aeon.Acquisition/PylonVideoSource.bonsai +++ b/src/Aeon.Video/PylonVideoSource.bonsai @@ -1,7 +1,7 @@  diff --git a/src/Aeon.Acquisition/SpinnakerCapture.cs b/src/Aeon.Video/SpinnakerCapture.cs similarity index 99% rename from src/Aeon.Acquisition/SpinnakerCapture.cs rename to src/Aeon.Video/SpinnakerCapture.cs index bda960c..31bba45 100644 --- a/src/Aeon.Acquisition/SpinnakerCapture.cs +++ b/src/Aeon.Video/SpinnakerCapture.cs @@ -6,7 +6,7 @@ using SpinnakerNET; using Bonsai.Harp; -namespace Aeon.Acquisition +namespace Aeon.Video { [Description("Configures and initializes a Spinnaker camera for triggered acquisition.")] public class SpinnakerCapture : Bonsai.Spinnaker.SpinnakerCapture diff --git a/src/Aeon.Acquisition/SpinnakerVideoSource.bonsai b/src/Aeon.Video/SpinnakerVideoSource.bonsai similarity index 97% rename from src/Aeon.Acquisition/SpinnakerVideoSource.bonsai rename to src/Aeon.Video/SpinnakerVideoSource.bonsai index 3b98612..351eb1d 100644 --- a/src/Aeon.Acquisition/SpinnakerVideoSource.bonsai +++ b/src/Aeon.Video/SpinnakerVideoSource.bonsai @@ -2,7 +2,7 @@ > diff --git a/src/Aeon.Vision.Sleap/Aeon.Vision.Sleap.csproj b/src/Aeon.Vision.Sleap/Aeon.Vision.Sleap.csproj new file mode 100644 index 0000000..810817e --- /dev/null +++ b/src/Aeon.Vision.Sleap/Aeon.Vision.Sleap.csproj @@ -0,0 +1,25 @@ + + + + true + Project Aeon - SLEAP + Provides reactive modules for SLEAP based pose estimation used for Project Aeon experiments. + Bonsai Rx Project Aeon Vision Sleap + net472 + 0.1.0 + + + + + + + + + + + + + + + + diff --git a/src/Aeon.Acquisition/CreatePoseTrackingMetadata.cs b/src/Aeon.Vision.Sleap/CreatePoseTrackingMetadata.cs similarity index 99% rename from src/Aeon.Acquisition/CreatePoseTrackingMetadata.cs rename to src/Aeon.Vision.Sleap/CreatePoseTrackingMetadata.cs index 1625889..72171d0 100644 --- a/src/Aeon.Acquisition/CreatePoseTrackingMetadata.cs +++ b/src/Aeon.Vision.Sleap/CreatePoseTrackingMetadata.cs @@ -5,7 +5,7 @@ using System.Reactive.Linq; using Bonsai; -namespace Aeon.Acquisition +namespace Aeon.Vision.Sleap { [Description("Initializes a pose tracking metadata object from the specified model path.")] public class CreatePoseTrackingMetadata : Source diff --git a/src/Aeon.Acquisition/FormatPose.cs b/src/Aeon.Vision.Sleap/FormatPose.cs similarity index 99% rename from src/Aeon.Acquisition/FormatPose.cs rename to src/Aeon.Vision.Sleap/FormatPose.cs index f1e1403..a2dd3d0 100644 --- a/src/Aeon.Acquisition/FormatPose.cs +++ b/src/Aeon.Vision.Sleap/FormatPose.cs @@ -6,7 +6,7 @@ using Bonsai.Sleap; using Bonsai.Harp; -namespace Aeon.Acquisition +namespace Aeon.Vision.Sleap { [Combinator] [Description("Converts a timestamped pose collection into a sequence of Harp messages.")] diff --git a/src/Aeon.Acquisition/LogPoseTracking.bonsai b/src/Aeon.Vision.Sleap/LogPoseTracking.bonsai similarity index 97% rename from src/Aeon.Acquisition/LogPoseTracking.bonsai rename to src/Aeon.Vision.Sleap/LogPoseTracking.bonsai index 8f205aa..2bc3a52 100644 --- a/src/Aeon.Acquisition/LogPoseTracking.bonsai +++ b/src/Aeon.Vision.Sleap/LogPoseTracking.bonsai @@ -1,7 +1,7 @@  diff --git a/src/Aeon.Acquisition/PoseTracking.bonsai b/src/Aeon.Vision.Sleap/PoseTracking.bonsai similarity index 97% rename from src/Aeon.Acquisition/PoseTracking.bonsai rename to src/Aeon.Vision.Sleap/PoseTracking.bonsai index 849f6e5..52c1a03 100644 --- a/src/Aeon.Acquisition/PoseTracking.bonsai +++ b/src/Aeon.Vision.Sleap/PoseTracking.bonsai @@ -1,7 +1,7 @@  + + + true + Project Aeon - Tracking + Provides reactive modules for computer vision used for Project Aeon experiments. + Bonsai Rx Project Aeon Vision + net472 + 0.1.0 + + + + + + + + + + + + + + + + diff --git a/src/Aeon.Acquisition/DistanceFromPoint.cs b/src/Aeon.Vision/DistanceFromPoint.cs similarity index 98% rename from src/Aeon.Acquisition/DistanceFromPoint.cs rename to src/Aeon.Vision/DistanceFromPoint.cs index 127f292..1aa7ed1 100644 --- a/src/Aeon.Acquisition/DistanceFromPoint.cs +++ b/src/Aeon.Vision/DistanceFromPoint.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Reactive.Linq; -namespace Aeon.Acquisition +namespace Aeon.Vision { [Combinator] [Description("Computes the distance from every component in the sequence to a point.")] diff --git a/src/Aeon.Acquisition/FormatBinaryRegions.cs b/src/Aeon.Vision/FormatBinaryRegions.cs similarity index 98% rename from src/Aeon.Acquisition/FormatBinaryRegions.cs rename to src/Aeon.Vision/FormatBinaryRegions.cs index e17c5c2..3608e3a 100644 --- a/src/Aeon.Acquisition/FormatBinaryRegions.cs +++ b/src/Aeon.Vision/FormatBinaryRegions.cs @@ -6,7 +6,7 @@ using Bonsai.Vision; using Bonsai.Harp; -namespace Aeon.Acquisition +namespace Aeon.Vision { [Combinator] [Description("Converts timestamped binary regions into a sequence of Harp messages.")] diff --git a/src/Aeon.Acquisition/PositionTracking.bonsai b/src/Aeon.Vision/PositionTracking.bonsai similarity index 98% rename from src/Aeon.Acquisition/PositionTracking.bonsai rename to src/Aeon.Vision/PositionTracking.bonsai index 514dee1..f6b158d 100644 --- a/src/Aeon.Acquisition/PositionTracking.bonsai +++ b/src/Aeon.Vision/PositionTracking.bonsai @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cv="clr-namespace:Bonsai.Vision;assembly=Bonsai.Vision" xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core" - xmlns:aeon="clr-namespace:Aeon.Acquisition;assembly=Aeon.Acquisition" + xmlns:aeon="clr-namespace:Aeon.Vision;assembly=Aeon.Vision" xmlns:harp="clr-namespace:Bonsai.Harp;assembly=Bonsai.Harp" xmlns="https://bonsai-rx.org/2018/workflow"> Extracts information on the largest binary blob in the input image. diff --git a/src/Aeon.Vision/Properties/AssemblyInfo.cs b/src/Aeon.Vision/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..28f1234 --- /dev/null +++ b/src/Aeon.Vision/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using Bonsai; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: XmlNamespacePrefix("clr-namespace:Aeon.Vision", "aeon-vision")] diff --git a/src/Aeon.Vision/Properties/launchSettings.json b/src/Aeon.Vision/Properties/launchSettings.json new file mode 100644 index 0000000..b48bcfa --- /dev/null +++ b/src/Aeon.Vision/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "Bonsai": { + "commandName": "Executable", + "executablePath": "$(registry:HKEY_CURRENT_USER\\Software\\Bonsai Foundation\\Bonsai@InstallDir)Bonsai.exe", + "commandLineArgs": "--lib:\"$(TargetDir).\"", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/src/Aeon.Acquisition/RegionContainsPoint.cs b/src/Aeon.Vision/RegionContainsPoint.cs similarity index 98% rename from src/Aeon.Acquisition/RegionContainsPoint.cs rename to src/Aeon.Vision/RegionContainsPoint.cs index ed4b393..4ed4a95 100644 --- a/src/Aeon.Acquisition/RegionContainsPoint.cs +++ b/src/Aeon.Vision/RegionContainsPoint.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Reactive.Linq; -namespace Aeon.Acquisition +namespace Aeon.Vision { [Combinator] [Description("Generates boolean values indicating whether each point in the sequence is inside a region of interest.")] diff --git a/src/Aeon.Acquisition/RegionTracking.bonsai b/src/Aeon.Vision/RegionTracking.bonsai similarity index 96% rename from src/Aeon.Acquisition/RegionTracking.bonsai rename to src/Aeon.Vision/RegionTracking.bonsai index 9520a8b..e882bd6 100644 --- a/src/Aeon.Acquisition/RegionTracking.bonsai +++ b/src/Aeon.Vision/RegionTracking.bonsai @@ -1,7 +1,7 @@  diff --git a/src/Aeon.Acquisition/TakeLargestRegions.cs b/src/Aeon.Vision/TakeLargestRegions.cs similarity index 96% rename from src/Aeon.Acquisition/TakeLargestRegions.cs rename to src/Aeon.Vision/TakeLargestRegions.cs index a52f2ef..85d6d2f 100644 --- a/src/Aeon.Acquisition/TakeLargestRegions.cs +++ b/src/Aeon.Vision/TakeLargestRegions.cs @@ -1,4 +1,4 @@ -using Bonsai; +using Bonsai; using System; using System.ComponentModel; using System.Linq; @@ -6,7 +6,7 @@ using Bonsai.Vision; using OpenCV.Net; -namespace Aeon.Acquisition +namespace Aeon.Vision { [Combinator] [Description("Takes the N-largest binary regions.")] @@ -33,4 +33,4 @@ public IObservable Process(IObservable Date: Wed, 17 Jul 2024 09:38:57 +0100 Subject: [PATCH 2/9] Update environment and remove obsolete scripts --- .bonsai/Bonsai.config | 59 +++++ bonsai/NuGet.Config => .bonsai/NuGet.config | 2 - .bonsai/Setup.cmd | 4 + .bonsai/Setup.ps1 | 21 ++ bonsai/Bonsai.config | 123 ----------- bonsai/setup.cmd | 1 - bonsai/setup.ps1 | 10 - calibration/calibcamera.py | 66 ------ calibration/metadata.py | 65 ------ .../calib.io_checker_420x594_13x9_40.pdf | Bin 21140 -> 0 bytes .../calib.io_checker_85.6x53.98_9x13_5.pdf | Bin 8040 -> 0 bytes python/requirements.txt | 4 - python/setup.cmd | 1 - python/setup.ps1 | 9 - workflows/CalibrateArenaMask.bonsai | 157 ------------- workflows/CalibrateArenaMask.bonsai.layout | 208 ------------------ workflows/TestSynchronizer.bonsai | 35 --- workflows/TestSynchronizer.bonsai.layout | 42 ---- 18 files changed, 84 insertions(+), 723 deletions(-) create mode 100644 .bonsai/Bonsai.config rename bonsai/NuGet.Config => .bonsai/NuGet.config (69%) create mode 100644 .bonsai/Setup.cmd create mode 100644 .bonsai/Setup.ps1 delete mode 100644 bonsai/Bonsai.config delete mode 100644 bonsai/setup.cmd delete mode 100644 bonsai/setup.ps1 delete mode 100644 calibration/calibcamera.py delete mode 100644 calibration/metadata.py delete mode 100644 calibration/targets/calib.io_checker_420x594_13x9_40.pdf delete mode 100644 calibration/targets/calib.io_checker_85.6x53.98_9x13_5.pdf delete mode 100644 python/requirements.txt delete mode 100644 python/setup.cmd delete mode 100644 python/setup.ps1 delete mode 100644 workflows/CalibrateArenaMask.bonsai delete mode 100644 workflows/CalibrateArenaMask.bonsai.layout delete mode 100644 workflows/TestSynchronizer.bonsai delete mode 100644 workflows/TestSynchronizer.bonsai.layout diff --git a/.bonsai/Bonsai.config b/.bonsai/Bonsai.config new file mode 100644 index 0000000..ac40c8a --- /dev/null +++ b/.bonsai/Bonsai.config @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bonsai/NuGet.Config b/.bonsai/NuGet.config similarity index 69% rename from bonsai/NuGet.Config rename to .bonsai/NuGet.config index 81b34d6..97e8b73 100644 --- a/bonsai/NuGet.Config +++ b/.bonsai/NuGet.config @@ -4,7 +4,5 @@ - - diff --git a/.bonsai/Setup.cmd b/.bonsai/Setup.cmd new file mode 100644 index 0000000..92d983d --- /dev/null +++ b/.bonsai/Setup.cmd @@ -0,0 +1,4 @@ +@echo off +pushd %~dp0 +powershell -ExecutionPolicy Bypass -File ./Setup.ps1 +popd \ No newline at end of file diff --git a/.bonsai/Setup.ps1 b/.bonsai/Setup.ps1 new file mode 100644 index 0000000..01cfba6 --- /dev/null +++ b/.bonsai/Setup.ps1 @@ -0,0 +1,21 @@ +Push-Location $PSScriptRoot +if (!(Test-Path "./Bonsai.exe")) { + $release = "https://github.com/bonsai-rx/bonsai/releases/latest/download/Bonsai.zip" + $configPath = "./Bonsai.config" + if (Test-Path $configPath) { + [xml]$config = Get-Content $configPath + $bootstrapper = $config.PackageConfiguration.Packages.Package.where{$_.id -eq 'Bonsai'} + if ($bootstrapper) { + $version = $bootstrapper.version + $release = "https://github.com/bonsai-rx/bonsai/releases/download/$version/Bonsai.zip" + } + } + Invoke-WebRequest $release -OutFile "temp.zip" + Move-Item -Path "NuGet.config" "temp.config" -ErrorAction SilentlyContinue + Expand-Archive "temp.zip" -DestinationPath "." -Force + Move-Item -Path "temp.config" "NuGet.config" -Force -ErrorAction SilentlyContinue + Remove-Item -Path "temp.zip" + Remove-Item -Path "Bonsai32.exe" +} +& .\Bonsai.exe --no-editor +Pop-Location \ No newline at end of file diff --git a/bonsai/Bonsai.config b/bonsai/Bonsai.config deleted file mode 100644 index 4caead7..0000000 --- a/bonsai/Bonsai.config +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/bonsai/setup.cmd b/bonsai/setup.cmd deleted file mode 100644 index 3c53f3a..0000000 --- a/bonsai/setup.cmd +++ /dev/null @@ -1 +0,0 @@ -powershell -ExecutionPolicy Bypass -File .\setup.ps1 \ No newline at end of file diff --git a/bonsai/setup.ps1 b/bonsai/setup.ps1 deleted file mode 100644 index 235aafc..0000000 --- a/bonsai/setup.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -if (!(Test-Path "./Bonsai.exe")) { - & dotnet build ../src/Aeon.sln --configuration Release - Invoke-WebRequest "https://github.com/bonsai-rx/bonsai/releases/download/2.7-rc1/Bonsai.zip" -OutFile "temp.zip" - Move-Item -Path "NuGet.config" "temp.config" - Expand-Archive "temp.zip" -DestinationPath "." -Force - Move-Item -Path "temp.config" "NuGet.config" -Force - Remove-Item -Path "temp.zip" - Remove-Item -Path "Bonsai32.exe" -} -& .\Bonsai.exe --no-editor \ No newline at end of file diff --git a/calibration/calibcamera.py b/calibration/calibcamera.py deleted file mode 100644 index 9adfa1c..0000000 --- a/calibration/calibcamera.py +++ /dev/null @@ -1,66 +0,0 @@ -import os -import cv2 -import glob -import numpy as np -import matplotlib.pyplot as plt -import argparse - -parser = argparse.ArgumentParser(description="Camera checkerboard calibration. Assumes a checkerboard with 8x12 inner corners.") -parser.add_argument('dname', type=str, help="The path to a folder with checkerboard images to use for camera calibration.") -args = parser.parse_args() - -patternsize = (8, 12) -pattern = np.zeros((1, patternsize[0] * patternsize[1], 3), np.float32) -pattern[0,:,:2] = np.mgrid[0:patternsize[0], 0:patternsize[1]].T.reshape(-1, 2) -criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) - -objectPoints = [] -imagePoints = [] -fnames = glob.glob(args.dname + '/*.png') -for fname in fnames: - print("Processing {0}...".format(os.path.split(fname)[-1]), end=" ") - img = cv2.imread(fname) - gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - - flags = cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE - ret, corners = cv2.findChessboardCorners(gray, patternsize, flags) - print("Success" if ret else "Not found!") - - if ret: - corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) - objectPoints.append(pattern) - imagePoints.append(corners) - - img = cv2.drawChessboardCorners(img, patternsize, corners, ret) - - plt.imshow(img) - plt.draw() - plt.waitforbuttonpress(timeout=0.1) - -print("Calibrating camera with {0} points from {1} images...".format( - np.prod(np.array(imagePoints).shape) // 2, - len(imagePoints))) -ret, intrinsics, distortion, rvecs, tvecs = cv2.calibrateCamera( - objectPoints, imagePoints, gray.shape[::-1], None, None) -print("Reprojection error: {0}".format(ret)) - -fname = "{0}.yml".format(os.path.split(args.dname)[-1]) -print("Writing calibration file {0}...".format(fname)) -flags = cv2.FILE_STORAGE_FORMAT_YAML + cv2.FILE_STORAGE_WRITE -f = cv2.FileStorage(args.dname + '/' + fname,flags) -f.write('image_width', img.shape[1]) -f.write('image_height', img.shape[0]) -f.write('camera_matrix', intrinsics) -f.write('distortion_coefficients', distortion) -f.write('reprojection_error', ret) -f.release() - -for i,fname in enumerate(fnames): - print("Undistorting {0}...".format(os.path.split(fname)[-1])) - img = cv2.imread(fname) - img = cv2.drawChessboardCorners(img, patternsize, imagePoints[i], True) - - uimg = cv2.undistort(img, intrinsics, distortion) - plt.imshow(uimg) - plt.draw() - plt.waitforbuttonpress(timeout=0.1) \ No newline at end of file diff --git a/calibration/metadata.py b/calibration/metadata.py deleted file mode 100644 index 3e2a545..0000000 --- a/calibration/metadata.py +++ /dev/null @@ -1,65 +0,0 @@ -from pathlib import Path -from lxml import etree -from git import Repo -import argparse -import json -import sys - -parser = argparse.ArgumentParser(description="Exports device and experiment metadata for the specified workflow file.") -parser.add_argument('workflow', type=str, help="The path to the workflow file used for data acquisition.") -parser.add_argument('--indent', type=int, help="The optional indent level for JSON pretty printing.") -parser.add_argument('--allow-dirty', action="store_true", help="Optionally allow exporting metadata for modified repositories.") -parser.add_argument('--output', type=str, help="The optional path to the exported JSON file.") -args = parser.parse_args() -dname = Path(__file__).parent - -repo = Repo(dname.parent) -if not args.allow_dirty and (repo.is_dirty() or len(repo.untracked_files) > 0): - parser.error("all modifications to the acquisition repository must be committed before exporting metadata") - -ns = { - 'x' : 'https://bonsai-rx.org/2018/workflow', - 'xsi' : 'http://www.w3.org/2001/XMLSchema-instance' -} - -def recursive_dict(element): - return etree.QName(element).localname, \ - dict(map(recursive_dict, element)) or element.text - -def list_metadata(elements, key, **kwargs): - metadata = [] - for x in elements: - elem_metadata = {} - elem_metadata = (recursive_dict(x)[1]) - elem_metadata.update(kwargs) - elem_metadata['Name'] = elem_metadata.pop(key, key) - metadata.append(elem_metadata) - return metadata - -root = etree.parse(args.workflow) -workflow = root.xpath('/x:WorkflowBuilder/x:Workflow/x:Nodes', namespaces=ns)[0] -hardware = workflow.xpath('./x:Expression[@xsi:type="GroupWorkflow" and ./x:Name[text()="Hardware"]]/x:Workflow/x:Nodes', namespaces=ns)[0] - -video_controllers = hardware.xpath('./x:Expression[@Path="Aeon.Acquisition:VideoController.bonsai"]', namespaces=ns) -video_sources = hardware.xpath('./x:Expression[@Path="Aeon.Acquisition:VideoSource.bonsai"]', namespaces=ns) -audio_sources = hardware.xpath('./x:Expression[@Path="Aeon.Acquisition:AudioSource.bonsai"]', namespaces=ns) -patches = hardware.xpath('./x:Expression[@Path="Aeon.Acquisition:PatchController.bonsai"]', namespaces=ns) -weight_scales = hardware.xpath('./x:Expression[@Path="Aeon.Acquisition:WeightScale.bonsai"]', namespaces=ns) -position_tracking = hardware.xpath('./x:Expression[@Path="Aeon.Acquisition:PositionTracking.bonsai"]', namespaces=ns) - -metadata = { - 'Workflow' : args.workflow, - 'Revision' : repo.head.commit.hexsha, - 'Devices' : list_metadata(video_controllers, 'VideoController', Type='VideoController') + - list_metadata(video_sources, 'FrameEvents', Type='VideoSource') + - list_metadata(audio_sources, 'AudioAmbient', Type='AudioSource') + - list_metadata(patches, 'PatchEvents', Type='Patch') + - list_metadata(weight_scales, 'WeightEvents', Type='WeightScale') + - list_metadata(position_tracking, 'TrackingEvents', Type='PositionTracking') -} - -if args.output: - with open(args.output, "w") as outfile: - json.dump(metadata, outfile, indent=args.indent) -else: - json.dump(metadata, sys.stdout, indent=args.indent) \ No newline at end of file diff --git a/calibration/targets/calib.io_checker_420x594_13x9_40.pdf b/calibration/targets/calib.io_checker_420x594_13x9_40.pdf deleted file mode 100644 index 256f653b374d5a7c035d3cb2a5d5b7563aef4b4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21140 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 diff --git a/calibration/targets/calib.io_checker_85.6x53.98_9x13_5.pdf b/calibration/targets/calib.io_checker_85.6x53.98_9x13_5.pdf deleted file mode 100644 index dcf9721f8f899f5be5048f333fd7f6ea9cc121cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8040 zcmai3Wn5I-y9ViIB$N<_ZkPdP2#4;HE-7J1iGiV0N6S+C z;5p}i&%O78!hBfeLLzp+s~vxw78oc1JE zLgZ?C?-;<+Zhk2)lcZ!H!793l&hOhe(Bn`P^bDlfj2?XHx3tst+iUuFW}4Z#cBX0D z@(YvSzDsADE5C29Mt`@q{knXipH}8ET6Ve3@j~qT&(rl6ziuVWe%C*LF+AV)LVTWU zW%RPyANGQBY~Ugw_+#!&#$Gu3t@roi&IcRwpD)%3SlX__uzq5JJ%c; zW)jiB&VY*u;j>$E3q!Rsoi8NZk8y5Ntx))2>+i6t-EfYs$^(T6tCE%h?SQee1Dpt} zAAu6~v*+5vg8>hvl5P(H6}#6cCzrPE3#OUwO4oJ-k}2sH6wH17i)N&fKA&{3m41z~ zqS@z~Nqvbq;BmX-SMVxL&cziL)FEt!Xj_Lo#dmE)+*>KXYqH_@Gpm@6`c*WvLNiqX#Yn|z+`~4nPv>&Isrk)$? z20d4&Z!h^7qp*@S{gA49No2mUWmEbCA$-*i&ZQZ=D-)~y{*cg_>lv_=Z{D&5YjGZZ zdPy1E4-Ah&`Z6s}{Yg>4xzEweOk3$MP6++!j(yZgibcOPC%ww%WoXkwGVNn=tY|9C-Ll0isrJ?lIyUs)9gd$Dv-9CDop{2gd;K`*y`PdjNS(jlz70IlJvjld z1?KiT^>U4>Ul3pUo6HWW?u7)5-fnwJ;MSAcWvUvkgl^E=XGe%MoA&XTJ(024mXZoQ z$EChUKBGppudgzi{}pQ}xU6UL2HauV3huIGYgYsEZGsHuxR%svq(8`xr zM%rPQ{bf#6itY}y6X^2QGt(SXOb6T7_<8l2ulCr{hE|STrt)}b^eL$2nUu|q423tw zh@8*jT1Vp%wEBa}a~b>jvw5#&@?>6+P+)7S+`Fi6C*Pi1Vx;&KFXfZGRxUSpojv@Z zQ(?m)yz!wXU44AfU=E9LO@PUR;fp1Cy0cmA1H%ynY?u>I@x3QsX)bg@oE~lce+#9e+1Y zu1JE*oTA?d^k-hwz%%Cu%n+*k2{>SXcEg-B0=XaO30Bd)I}v zRi0_IbGtNdkG=e)jNyWSrz}*Q`XMa(f;zEiW-lDS@I4waatM!djF*pNZXF*ZHe#$d zCFgQ~`}O@89)WijwYZvcp&&-WM-eY_-}*_dKFZ*;_mE(9Dz+55R01Hcz+$1p3IA}3 zLzSUrbo90SBfCXt{GDw719!>E7z_M10fM$Q5Q*X|oJjI*L%`@islm=?ZMQ5l>e1QK>?-a*Y ztHx>4Z9-*)Fl++5iEAk0oD#MbLu%?+kQknmn9AVR-jsRCBM|x03pU1Aa;>@8B1^lF zkl4YS31TFakgV1j{oxcOd9BXd+O7XR)j7hlm{fq|SkXNgGI6hJlE0?sKq`-yT9dy- z`9w6EX}_w)t2*@K>O=i-Ku!UzhQ-xkr>+m{i$x5sA@ee($h}8|suo zU1H!9Ei!QKVyCz`cNL~+r`pk9upem2bn6Y-!2=8tK@MI?9R8FdvO2DZeK7$!jbKIr ze_V)3gwFxy@yx4d!CuW@so+J7<>}G6+j=R{lA)AWT;cr%j|+I{tGb?^Rr6C_cbfBW zf5P_sb%jrg?r>btlCJmhxh`=|Y3kzSLk`2P%4WakfH$e7b$ym89XwrrP{yChKmlg1 z?4#lc&MAt7^xh|#()_hBNrTYySAmal3Xts>o#UROT4dp6w!!?ZH_YOt+`b&DS~^3d z!8>|dEnQ=0RJyd>!{=1nkI>ubd?Sf=Fgdrs51^r0CV5LT0x5wEzpqwD(s$E5uPsxU zNJr2U)I;8xtOWRNe^nVgKFA+YOQhbuTE^p%dMowwBX9rNa|PKWbG$}5z|j%!XhqVr zc)PrBGeBjDx7D;x)I*-z$i!&z^u zEp}FdkhLoHh!0IFr2veI^{YNmSwO`ScmAou&CUP`7y0Ui>@7RngSLgRb;qFhi3F+x zQ4G8Ur-Ayf+CO{6;J@m+$0IDjN*U-ljplgaHGk>%v>vPev@Bydb-$e3*UoR=25tY| zSui67bOxhKhdg3?Ex5(W+4YP&i;%?WTNGzz6jfm4mpNWVmKLL`Ygbh`kVP>H4@5zH zey@BSKT7+Q@FcLLpt2zz7;nuP8fb=|m(b{$^J%8m*S%3i`r_iviqV(q6qv4(y!9=% zML`OQv=nZ_bE7xFRi{OtEL?{U(~mBg0@JAIqek!WtY$^P@~-9a&q) ztkdx15vvn>6hdSn+B4>|<hcs+qasyH@+ZV(v7k^p>Y8+lNeuf(-4j zB^Okhb}pOyGC$w@{Q9seYBv6d0z}tx5iM~&*+rUhR~{GyJ<>175(=L)S@v&MfTu=l z+>aiHZ;54}FQ+n;I)3iWl5_ZFIGp39#l)3HEJ4ZT@uD+aMG?Inrmw0}l2`#c z@xqH-oS7LZTRP=$lZ=_>%(k0=65}$tcp4u=xO#pyF1ItMV%=b|H?9s63{@)BQCw4g zwimw&2x0qWpgHwwqFnR?k$EBOnW5pD2*A|EJ2L{1aJUX^I*(+AZO}(M& zQ84cgYici!#^yj%tA|b6d1)1Fu9=QO6u%}_>ZrCLikT@T?tT|zKcNi{{F(q)?hxcp z5DBkKB?^P{J zNmJo8nqz))K(ZebPM;^Qx`~sORHs7^5G8#3Td7dxL(Ur#_?Xsv;;xnr3k`XIAqzEs*uuSK?6_ue3=J$C*!%k}f7K+oy z?eP%Wh(W@wl=Q>hw)Ruk2e12t2pmc>!n&&&a~!$81JZ&P8|Mf^WTba>6*WX{Mqn;o z;ebdEi(G8Mkhl0_>R%5RRQhI5k%4vQyf{YrSa-cn(tg)#rm)XASi8a(?LnQ%Qu zx%|E7ySQ`h}d?=yFN*nvYQR?4W*6jg#pg1rM&l#*S}&)2}Otw$n$ z#N5v?n~hgPDOhwki~2w*%RQ#R>tuE^bF||^Tabc~O5vH;!%rbk!{sz}M9lcNHsn7x zGUa!F@Rl#=W|}29ey`nTv3owZ>KsrN3rb;0r``9%=MlRd`bZ1ddfSFv*M@z5Z63@P z?`zrp=wM74)88l5_BHY`$vCQ;-w-JFof zA=tQ41bYt;^Z{Z(N{@)$bLzy7ma~A(BgAG(noeTuv823o(CQqGq{L}OO);S%CD0BG z@jjZzF3*ArBAaG7D>={LuC>UViqAy zi#Y+9z4=2+OqewL@A%jY9)8SOLo+1%Rlpdim3K_Gu)BUu*lX*RzEw$MS_KPV>(=uX zr(-kQBAxijFke@M-RN|Q5gMqgqt_y7BP688zm`bwts=SQJtsOH%*o*~wT7Utx5KEh zoGi9I)GsSx)|F&ZBNkm{FsE{4?1@Q*d1!?T9{Xb2+!-L7C@Y{iqz_L}qvvIOdL>>Q zGJ4x%)6%Bp)2bsrH?4m_{Fj-xtL9WEH zspdGn6*K-6Y2&~aL9Ch9-NZV-!^!gH_b=IR_{ON|2uNnpIVa^5tvaK&OQZM$6F3;Q zB_!!OaTptqNk`Uq5Gh_iFoHHeET5|PdmPuZO+0z4gS(sZW}c}yX?R}KLsOO}jzq|C z_qC=rQH)2?CcFaScfd+ms86~s{n5z)tSXV0ED$okYjf_(T{TEm$~Mrj$& zV?IRyOZbV^qoi0x>}vV*!Gy0t#LL1sp~&(Wf2W1E_UlfH$?)gJy}}y|`m4i~DVgk; zuBW%VqK6i5=p}#NAJY))dsYOKZKQZv)Ok$A2&v+%kznZ6Ga z(inSUfOiio-GMANMe^&$8=qTIN%FyE`iRRTKQ&Kj7^VTi@V3VL5BJ_Hi#>%`@Fg0> zI}Q?|4~bEYk&m}4aL&dqkCHIOs)Vj8^r`&8QNJ4+DY0}~`gOBG!}JggLP*anRk>&em-<;%E~XO z!e^*W7RTOiGq4yj#BkX>&UN8OhzRz0Pt2;#tJkP~>$3}zY2`Oq>nG)WQKLw~?D;(> zYA`Iz-#9xo_z`n0L33xRNiO$7{W_8BxOeXr7f;(JmcO1;yXhC zg1A=6Nsq&!LYsbzo-WurTLH?9cFR0d*#&hvaNYdJ`o&*P3vWHfv!^$`-e`MzJX~b3=ECkEhSjqp6HMN6}?0kG8xRm8$FMUtsYu{id$&8iA*Z12lvtfXM4q6v| z?I?$kkp0Lq40!9TSu)>p3G)8M8aUp267X)2Qdv*^t;~YWXw`j^YbH#*N++$O2wJeH^>UAbp&FCe91k=N`6&^aoSlqI8zp`vNNAS>=+uZ)i9#3X)v0(d;aQr$yq-cf zPJ0DJ9}dxv3KxN!pi8e`l6y6M6r&p_jHJ!3d~xpF3l}OQB;%Cm7xcVoc;J9Iatbi6 zHjH>$Cv{l^aGBbOo&7D#Zc*3#UQE<>y@6SBxSX;kyLaJ|hr%K5NyuKGt<;=0UU8+^ zxWcF$pKQrbKe{xq3wjZtnHS zuL+%V%7Ls%dS1n3;|u5|U>`Lr$28@hi+?V<#MI1z#O`TxPo`4#R?c^YZJqJSuv^MP z(6fVqMv~A$e{b_0qUi9Zf)91Yj9r3uc5;TCG~6qa7i+AvOEu3BnJ=I7jFC8VdK$RB z;LL2AlW+b~Bx`ldKTGqljW^8u!Dd!S5JmwjG@_cwb0TwT`IiEWT!IlO~bs67*ej)kUdLyBAN|C;1Y?UrGH z-I-Wl0)8OZdb7jj^5DE&Mw9oNcq%Sr`eN;!6og$8;lplDd7F}h~mhcw%`miv)`e1cW!%37{1Z8>lE14N{a-AKQjivu7h z4b;4n_lKriTt|I!4m&oa8dC4kwYfdk>iQ}c{Qf)F^#(RaPOH)mn*DX=7QC0u@dx>< z>aycv((Vl`1ax`+a6cy5!=%uwKBrpPnB;tIz~qiuuI0Mc%XM-txF0IxXXFURC1DQ%Wy+S{gx33 zBQun5lVE7nD8LHiE*GE6^5>zf%eu{o|1cMaJ0|PNaPx$obah&1hWmaFG-u;;SHW;S zUUXN1+PgCl7=KLbRn)f}^n-x2oye?wdLIy@Q&R*n0uZHbF&XFT?&>(Zq?wBYX$k#8 zICQUYCi}box*WlCQMs3(N5I?pS1D&1PZ8eZcwoNg6N}$RqUIC2Eln*GbV)us4*N!> zJaD(4nspxt;A$3%dik!d+zdKTW+Cp*%7iq?ey);9CB@#%sm$Q>VHoar%NmN{+|yw1 z9>Rsox3ebgDm}Bd6xar>mEL4#U|D7X?Ag#Ju^M_}$7VEZh14Dl1t&w*&s@<{!duHcg`xi7oI5cRDMs=E(SXspCl#A{Gs1f1y6#h7y{g6{b}3{hlJ9pL@2FrH zrG5Tl?dRwb?|n-Ir>ji~(`j2EE!Y3{9*;Jgjwy=3CuW^obxZd_baTsn=3{FQm}l@Y zwK1Xypt&@!;uuQWwmdoAy&@&t&a3A=^B^hGQ}?L~dj{OPPVAi2URP=BUB&|4`fIRv z3Qs)7M>ct%ZVda?drbjNALd%3U)s7%JKR60vx|38ZbYV1$N4i$VlCFNbF4 zHtQPSx$0Skx*P@Jdher0hKj$?_EqW;?aN~tdkR_2H|E4{UgvRq)-cTiOp71@D~qJ5 z$2$14v{zHPNDJ11nOq-Db*Eu0iQy_D9X3wv#^@F?m*v_A62KVavt6oXej1QT;)l=q8ovkg58F`Vbv)T#^mV9xES% ztN63!99&t&ooLvG5at1&@aM<9VI7S(FVashqz2s#cTBaoStFNg>Zh0Xf)C~x2*!Ud zxY8aL)Q5u_4;lqY4z44dGG1K~3+6fPp90PkQpu$&Ec1BwXWQO|aPOg&gj3^--vlOZ zw@8u{vPi^6n9Ybd#nDA*w}5SyOCEHN8W%1ToQl&<>|>EUs+h+bcq7xU3P0|BcOyjF zkP#;)ZZgmU*3!TC&nebtp>-K3sqoopMFV4a+kb6znl z2zi!f{oq!(Q;O!txALvcj=Xv~wsGFA?4{iqkyR1$1$%+_vxXj_k?+1ygTJZ-FZ)4+ zZ%($M>(BBf7>p}OLNA@$dA508bCRf=3>foA;wdYKrw)wg?szzy+s+1(FO89wzi*-} zo#{M)9NB=w%&5WB#`%&XA`|vNt%4f2B;`kFW!kp{ZKoT(GGDf+TT&Q@cm7v}e>2CGUNe1O5 zYvo}Fx6)FOz61Yij8DtT72%GATe$-7#-sJGHt!nvN6!53HeK)T@~PNax}w^-n}pVX zYIncu`db>>I; zpg#R&Q6Rr8>U?MKFkzH0Y6}Vey;0a*ECDIhH&l+h4gLS}+|_{c6G8=qqLTBA{Gkco zpK|RGPO^8jVwV-=2l0bJ!u%jG1R^K^;R1o#Kp>8PjY#NUBl>H`GUjgP4hWk+&EL_= z^=~5mH~qYjR@V3+pfEnF?!Olh3V{effY!jjF(CmF6w~e&(CI%I7$Wk2Fpw~+g8%6U zLKXYJF(D8X#mN8ZCnN~@zkWi3s6YK5KR2Ygor4wfj~=dV=VOH``HnkU2!tE(uJOMJ huHkyDq)|1UX4oACeu diff --git a/python/requirements.txt b/python/requirements.txt deleted file mode 100644 index 8e36a5f..0000000 --- a/python/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -matplotlib~=3.4.3 -opencv-python~=4.5.3 -lxml>=4.9.1 -GitPython~=3.1.24 \ No newline at end of file diff --git a/python/setup.cmd b/python/setup.cmd deleted file mode 100644 index 3c53f3a..0000000 --- a/python/setup.cmd +++ /dev/null @@ -1 +0,0 @@ -powershell -ExecutionPolicy Bypass -File .\setup.ps1 \ No newline at end of file diff --git a/python/setup.ps1 b/python/setup.ps1 deleted file mode 100644 index 8d124fa..0000000 --- a/python/setup.ps1 +++ /dev/null @@ -1,9 +0,0 @@ -if (!(Test-Path "./winpython")) { - Invoke-WebRequest "https://github.com/winpython/winpython/releases/download/4.3.20210620/Winpython64-3.9.5.0dot.exe" -OutFile "temp.exe" - $process = Start-Process "temp.exe" "-y" -PassThru - $process.WaitForExit() - Rename-Item -Path "WPy64-3950" -NewName "winpython" - Remove-Item -Path "temp.exe" -} - -cmd.exe /c '.\winpython\scripts\env.bat && pip install -r requirements.txt' \ No newline at end of file diff --git a/workflows/CalibrateArenaMask.bonsai b/workflows/CalibrateArenaMask.bonsai deleted file mode 100644 index 11eaf0c..0000000 --- a/workflows/CalibrateArenaMask.bonsai +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - COM3 - 50 - 125 - - - 21053810 - 4 - 1 - GlobalTrigger - FrameTop - GlobalTriggerFrequency - - - Value.Image - - - TopView - - - - Source1 - - - - - - - - - - - 92 - 255 - Binary - - - - - External - ChainApproxNone - - 0 - 0 - - 400000 - - - - - - 1 - -1 - - - - - - - - 159 - 471 - - - 219 - 480 - - - 216 - 516 - - - 240 - 518 - - - 238 - 540 - - - 215 - 541 - - - 214 - 574 - - - 148 - 574 - - - - Binary - - 0 - 0 - 0 - 0 - - - - - - - - - - None - false - - - - - - - - mask.png - None - - - - - PT1S - PT0S - - - - StartCameras - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/workflows/CalibrateArenaMask.bonsai.layout b/workflows/CalibrateArenaMask.bonsai.layout deleted file mode 100644 index b5c0fd6..0000000 --- a/workflows/CalibrateArenaMask.bonsai.layout +++ /dev/null @@ -1,208 +0,0 @@ - - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - false - - 130 - 130 - - - 336 - 65 - - Normal - Bonsai.Design.ObjectTextVisualizer - - - - - - true - - -15 - 712 - - - 1203 - 746 - - Normal - Bonsai.Vision.Design.IplImageVisualizer - - - - - 5 - - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - true - - 270 - 535 - - - 778 - 648 - - Normal - Bonsai.Vision.Design.IplImageVisualizer - - - - - - true - - 1405 - 290 - - - 336 - 279 - - Normal - Bonsai.Vision.Design.ContoursVisualizer - - - - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - true - - 1125 - 691 - - - 336 - 279 - - Normal - Bonsai.Vision.Design.IplImageVisualizer - - - - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - \ No newline at end of file diff --git a/workflows/TestSynchronizer.bonsai b/workflows/TestSynchronizer.bonsai deleted file mode 100644 index 24cb123..0000000 --- a/workflows/TestSynchronizer.bonsai +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - PT1S - PT3S - - - - SynchronizeTimestamp - - - - Active - true - On - On - Disable - false - COM6 - - - - - - - - - \ No newline at end of file diff --git a/workflows/TestSynchronizer.bonsai.layout b/workflows/TestSynchronizer.bonsai.layout deleted file mode 100644 index d7fa003..0000000 --- a/workflows/TestSynchronizer.bonsai.layout +++ /dev/null @@ -1,42 +0,0 @@ - - - - true - - 0 - 0 - - - 0 - 0 - - Normal - Bonsai.Design.ObjectTextVisualizer - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - - false - - 0 - 0 - - - 0 - 0 - - Normal - - \ No newline at end of file From edf113951f0d0f89d52db78e60e1046a7893498a Mon Sep 17 00:00:00 2001 From: glopesdev Date: Wed, 17 Jul 2024 09:39:20 +0100 Subject: [PATCH 3/9] Use local environment for debugging local builds --- src/Aeon.Acquisition/Properties/launchSettings.json | 2 +- src/Aeon.Database/Properties/launchSettings.json | 2 +- src/Aeon.Environment/Properties/launchSettings.json | 2 +- src/Aeon.Foraging/Properties/launchSettings.json | 2 +- src/Aeon.Video/Properties/launchSettings.json | 2 +- src/Aeon.Vision.Sleap/Properties/launchSettings.json | 2 +- src/Aeon.Vision/Properties/launchSettings.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Aeon.Acquisition/Properties/launchSettings.json b/src/Aeon.Acquisition/Properties/launchSettings.json index b48bcfa..766d23b 100644 --- a/src/Aeon.Acquisition/Properties/launchSettings.json +++ b/src/Aeon.Acquisition/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(registry:HKEY_CURRENT_USER\\Software\\Bonsai Foundation\\Bonsai@InstallDir)Bonsai.exe", + "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Database/Properties/launchSettings.json b/src/Aeon.Database/Properties/launchSettings.json index b48bcfa..766d23b 100644 --- a/src/Aeon.Database/Properties/launchSettings.json +++ b/src/Aeon.Database/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(registry:HKEY_CURRENT_USER\\Software\\Bonsai Foundation\\Bonsai@InstallDir)Bonsai.exe", + "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Environment/Properties/launchSettings.json b/src/Aeon.Environment/Properties/launchSettings.json index b48bcfa..766d23b 100644 --- a/src/Aeon.Environment/Properties/launchSettings.json +++ b/src/Aeon.Environment/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(registry:HKEY_CURRENT_USER\\Software\\Bonsai Foundation\\Bonsai@InstallDir)Bonsai.exe", + "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Foraging/Properties/launchSettings.json b/src/Aeon.Foraging/Properties/launchSettings.json index b48bcfa..766d23b 100644 --- a/src/Aeon.Foraging/Properties/launchSettings.json +++ b/src/Aeon.Foraging/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(registry:HKEY_CURRENT_USER\\Software\\Bonsai Foundation\\Bonsai@InstallDir)Bonsai.exe", + "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Video/Properties/launchSettings.json b/src/Aeon.Video/Properties/launchSettings.json index b48bcfa..766d23b 100644 --- a/src/Aeon.Video/Properties/launchSettings.json +++ b/src/Aeon.Video/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(registry:HKEY_CURRENT_USER\\Software\\Bonsai Foundation\\Bonsai@InstallDir)Bonsai.exe", + "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Vision.Sleap/Properties/launchSettings.json b/src/Aeon.Vision.Sleap/Properties/launchSettings.json index b48bcfa..766d23b 100644 --- a/src/Aeon.Vision.Sleap/Properties/launchSettings.json +++ b/src/Aeon.Vision.Sleap/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(registry:HKEY_CURRENT_USER\\Software\\Bonsai Foundation\\Bonsai@InstallDir)Bonsai.exe", + "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Vision/Properties/launchSettings.json b/src/Aeon.Vision/Properties/launchSettings.json index b48bcfa..766d23b 100644 --- a/src/Aeon.Vision/Properties/launchSettings.json +++ b/src/Aeon.Vision/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(registry:HKEY_CURRENT_USER\\Software\\Bonsai Foundation\\Bonsai@InstallDir)Bonsai.exe", + "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } From bd49525eeea57ce9f09d0d64f24813882d491434 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Wed, 17 Jul 2024 09:54:13 +0100 Subject: [PATCH 4/9] Update dependencies and unify versioning scheme --- src/Aeon.Acquisition/Aeon.Acquisition.csproj | 12 +++++------- src/Aeon.Database/Aeon.Database.csproj | 5 ++--- src/Aeon.Environment/Aeon.Environment.csproj | 3 +-- src/Aeon.Foraging/Aeon.Foraging.csproj | 3 +-- src/Aeon.Tests/Aeon.Tests.csproj | 8 ++++---- src/Aeon.Video/Aeon.Video.csproj | 3 +-- src/Aeon.Vision.Sleap/Aeon.Vision.Sleap.csproj | 1 - src/Aeon.Vision/Aeon.Vision.csproj | 3 +-- src/Directory.Build.props | 1 + 9 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/Aeon.Acquisition/Aeon.Acquisition.csproj b/src/Aeon.Acquisition/Aeon.Acquisition.csproj index 58651f0..cc043b1 100644 --- a/src/Aeon.Acquisition/Aeon.Acquisition.csproj +++ b/src/Aeon.Acquisition/Aeon.Acquisition.csproj @@ -5,8 +5,6 @@ A package providing common acquisition and control functionality for all Project Aeon experiments. Bonsai Rx Project Aeon Acquisition net472 - 0.6.0 - @@ -14,14 +12,14 @@ - + - + - - + + - + diff --git a/src/Aeon.Database/Aeon.Database.csproj b/src/Aeon.Database/Aeon.Database.csproj index 9fdcbc2..c3bcf5b 100644 --- a/src/Aeon.Database/Aeon.Database.csproj +++ b/src/Aeon.Database/Aeon.Database.csproj @@ -5,7 +5,6 @@ Provides querying and schema functionality for Project Aeon databases. Bonsai Rx Project Aeon Database net472 - 0.1.0 @@ -14,8 +13,8 @@ - - + + diff --git a/src/Aeon.Environment/Aeon.Environment.csproj b/src/Aeon.Environment/Aeon.Environment.csproj index fc66d73..cbd6ec2 100644 --- a/src/Aeon.Environment/Aeon.Environment.csproj +++ b/src/Aeon.Environment/Aeon.Environment.csproj @@ -6,7 +6,6 @@ Provides reactive modules for controlling and monitoring Project Aeon environments. Bonsai Rx Project Aeon Environment net472 - 0.2.0 @@ -15,7 +14,7 @@ - + diff --git a/src/Aeon.Foraging/Aeon.Foraging.csproj b/src/Aeon.Foraging/Aeon.Foraging.csproj index 5060a1c..3efd0c4 100644 --- a/src/Aeon.Foraging/Aeon.Foraging.csproj +++ b/src/Aeon.Foraging/Aeon.Foraging.csproj @@ -6,7 +6,6 @@ Provides acquisition and control modules for Project Aeon foraging experiments. Bonsai Rx Project Aeon Foraging net472 - 0.2.0 @@ -15,7 +14,7 @@ - + diff --git a/src/Aeon.Tests/Aeon.Tests.csproj b/src/Aeon.Tests/Aeon.Tests.csproj index 9da55c6..1c7cd4f 100644 --- a/src/Aeon.Tests/Aeon.Tests.csproj +++ b/src/Aeon.Tests/Aeon.Tests.csproj @@ -11,10 +11,10 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Aeon.Video/Aeon.Video.csproj b/src/Aeon.Video/Aeon.Video.csproj index 6347327..5dcb6cc 100644 --- a/src/Aeon.Video/Aeon.Video.csproj +++ b/src/Aeon.Video/Aeon.Video.csproj @@ -6,7 +6,6 @@ Provides reactive modules for video acquisition in Project Aeon experiments. Bonsai Rx Project Aeon Video net472 - 0.1.0 @@ -20,7 +19,7 @@ - + diff --git a/src/Aeon.Vision.Sleap/Aeon.Vision.Sleap.csproj b/src/Aeon.Vision.Sleap/Aeon.Vision.Sleap.csproj index 810817e..3eaf9f8 100644 --- a/src/Aeon.Vision.Sleap/Aeon.Vision.Sleap.csproj +++ b/src/Aeon.Vision.Sleap/Aeon.Vision.Sleap.csproj @@ -6,7 +6,6 @@ Provides reactive modules for SLEAP based pose estimation used for Project Aeon experiments. Bonsai Rx Project Aeon Vision Sleap net472 - 0.1.0 diff --git a/src/Aeon.Vision/Aeon.Vision.csproj b/src/Aeon.Vision/Aeon.Vision.csproj index 6326ab5..0b1d5ab 100644 --- a/src/Aeon.Vision/Aeon.Vision.csproj +++ b/src/Aeon.Vision/Aeon.Vision.csproj @@ -6,7 +6,6 @@ Provides reactive modules for computer vision used for Project Aeon experiments. Bonsai Rx Project Aeon Vision net472 - 0.1.0 @@ -15,7 +14,7 @@ - + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 09d06be..d0bdcf6 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -12,6 +12,7 @@ icon.png true git + 0.7.0 9.0 strict From 158a9bb1ff40d9e0cce286155f8dcea5e729bde4 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Wed, 17 Jul 2024 10:18:08 +0100 Subject: [PATCH 5/9] Use artifacts output layout for all projects --- src/.editorconfig => .editorconfig | 0 .gitignore | 28 ++++--------------- src/Aeon.sln => Aeon.sln | 16 +++++------ ...ctory.Build.props => Directory.Build.props | 2 +- src/NuGet.config => NuGet.config | 0 .../Properties/launchSettings.json | 2 +- .../Properties/launchSettings.json | 2 +- .../Properties/launchSettings.json | 2 +- .../Properties/launchSettings.json | 2 +- src/Aeon.Video/Properties/launchSettings.json | 2 +- .../Properties/launchSettings.json | 2 +- .../Properties/launchSettings.json | 2 +- 12 files changed, 21 insertions(+), 39 deletions(-) rename src/.editorconfig => .editorconfig (100%) rename src/Aeon.sln => Aeon.sln (85%) rename src/Directory.Build.props => Directory.Build.props (93%) rename src/NuGet.config => NuGet.config (100%) diff --git a/src/.editorconfig b/.editorconfig similarity index 100% rename from src/.editorconfig rename to .editorconfig diff --git a/.gitignore b/.gitignore index 613d6c8..f331238 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,5 @@ -# State recovery files -~* - -# Bonsai scripting and environment files -.vs -bin -obj -Packages -*.bin -*.avi -*.dll -*.exe -*.exe.settings -SessionSummary - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# Environments -.venv -winpython \ No newline at end of file +.vs/ +/artifacts/ +.bonsai/Packages/ +.bonsai/*.exe +.bonsai/*.exe.settings diff --git a/src/Aeon.sln b/Aeon.sln similarity index 85% rename from src/Aeon.sln rename to Aeon.sln index cbd0b4a..0135b79 100644 --- a/src/Aeon.sln +++ b/Aeon.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32825.248 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Acquisition", "Aeon.Acquisition\Aeon.Acquisition.csproj", "{5F8F4AF8-7C4C-436F-A74E-4BE82A4526F6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Acquisition", "src\Aeon.Acquisition\Aeon.Acquisition.csproj", "{5F8F4AF8-7C4C-436F-A74E-4BE82A4526F6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Tests", "Aeon.Tests\Aeon.Tests.csproj", "{235C151D-1507-4EDA-8BE9-79FA24EE858E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Tests", "src\Aeon.Tests\Aeon.Tests.csproj", "{235C151D-1507-4EDA-8BE9-79FA24EE858E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FB666352-C351-407B-9BF6-AA5DDC6C9DD5}" ProjectSection(SolutionItems) = preProject @@ -14,17 +14,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution NuGet.config = NuGet.config EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Database", "Aeon.Database\Aeon.Database.csproj", "{D99F92A5-E825-4CDC-A7EB-849E860FB5B7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Database", "src\Aeon.Database\Aeon.Database.csproj", "{D99F92A5-E825-4CDC-A7EB-849E860FB5B7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Foraging", "Aeon.Foraging\Aeon.Foraging.csproj", "{2C814742-0F6D-40DC-B9B7-C54BDB95EE7F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Foraging", "src\Aeon.Foraging\Aeon.Foraging.csproj", "{2C814742-0F6D-40DC-B9B7-C54BDB95EE7F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Environment", "Aeon.Environment\Aeon.Environment.csproj", "{49FC1C61-791E-41CF-BB7C-C2AC26AFAFE3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aeon.Environment", "src\Aeon.Environment\Aeon.Environment.csproj", "{49FC1C61-791E-41CF-BB7C-C2AC26AFAFE3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aeon.Video", "Aeon.Video\Aeon.Video.csproj", "{1D11793E-85E9-473C-8EF6-F4BD4B249E30}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aeon.Video", "src\Aeon.Video\Aeon.Video.csproj", "{1D11793E-85E9-473C-8EF6-F4BD4B249E30}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aeon.Vision", "Aeon.Vision\Aeon.Vision.csproj", "{709D0302-5A4F-4F76-8596-41B74DF3B3E9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aeon.Vision", "src\Aeon.Vision\Aeon.Vision.csproj", "{709D0302-5A4F-4F76-8596-41B74DF3B3E9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aeon.Vision.Sleap", "Aeon.Vision.Sleap\Aeon.Vision.Sleap.csproj", "{0D9D431D-EA23-4610-B262-313A48BFE34B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aeon.Vision.Sleap", "src\Aeon.Vision.Sleap\Aeon.Vision.Sleap.csproj", "{0D9D431D-EA23-4610-B262-313A48BFE34B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Directory.Build.props b/Directory.Build.props similarity index 93% rename from src/Directory.Build.props rename to Directory.Build.props index d0bdcf6..e23b04b 100644 --- a/src/Directory.Build.props +++ b/Directory.Build.props @@ -7,8 +7,8 @@ https://github.com/SainsburyWellcomeCentre/aeon_acquisition.git true snupkg - ..\bin\$(Configuration) LICENSE + true icon.png true git diff --git a/src/NuGet.config b/NuGet.config similarity index 100% rename from src/NuGet.config rename to NuGet.config diff --git a/src/Aeon.Acquisition/Properties/launchSettings.json b/src/Aeon.Acquisition/Properties/launchSettings.json index 766d23b..11dbb0a 100644 --- a/src/Aeon.Acquisition/Properties/launchSettings.json +++ b/src/Aeon.Acquisition/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", + "executablePath": "$(SolutionDir).bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Database/Properties/launchSettings.json b/src/Aeon.Database/Properties/launchSettings.json index 766d23b..11dbb0a 100644 --- a/src/Aeon.Database/Properties/launchSettings.json +++ b/src/Aeon.Database/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", + "executablePath": "$(SolutionDir).bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Environment/Properties/launchSettings.json b/src/Aeon.Environment/Properties/launchSettings.json index 766d23b..11dbb0a 100644 --- a/src/Aeon.Environment/Properties/launchSettings.json +++ b/src/Aeon.Environment/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", + "executablePath": "$(SolutionDir).bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Foraging/Properties/launchSettings.json b/src/Aeon.Foraging/Properties/launchSettings.json index 766d23b..11dbb0a 100644 --- a/src/Aeon.Foraging/Properties/launchSettings.json +++ b/src/Aeon.Foraging/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", + "executablePath": "$(SolutionDir).bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Video/Properties/launchSettings.json b/src/Aeon.Video/Properties/launchSettings.json index 766d23b..11dbb0a 100644 --- a/src/Aeon.Video/Properties/launchSettings.json +++ b/src/Aeon.Video/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", + "executablePath": "$(SolutionDir).bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Vision.Sleap/Properties/launchSettings.json b/src/Aeon.Vision.Sleap/Properties/launchSettings.json index 766d23b..11dbb0a 100644 --- a/src/Aeon.Vision.Sleap/Properties/launchSettings.json +++ b/src/Aeon.Vision.Sleap/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", + "executablePath": "$(SolutionDir).bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } diff --git a/src/Aeon.Vision/Properties/launchSettings.json b/src/Aeon.Vision/Properties/launchSettings.json index 766d23b..11dbb0a 100644 --- a/src/Aeon.Vision/Properties/launchSettings.json +++ b/src/Aeon.Vision/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Bonsai": { "commandName": "Executable", - "executablePath": "$(SolutionDir)../.bonsai/Bonsai.exe", + "executablePath": "$(SolutionDir).bonsai/Bonsai.exe", "commandLineArgs": "--lib:\"$(TargetDir).\"", "nativeDebugging": true } From 59461af833f2994e535aeab34a3318a3d043d3ef Mon Sep 17 00:00:00 2001 From: glopesdev Date: Wed, 17 Jul 2024 10:56:18 +0100 Subject: [PATCH 6/9] Update build CI to use modern dotnet tooling --- .github/workflows/ci-audit.yml | 42 ++++++++++++++++++++-------------- Directory.Build.props | 1 - 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci-audit.yml b/.github/workflows/ci-audit.yml index cf6d2ed..0eef9a7 100644 --- a/.github/workflows/ci-audit.yml +++ b/.github/workflows/ci-audit.yml @@ -6,28 +6,36 @@ on: pull_request: branches: [ main ] workflow_dispatch: - +env: + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_GENERATE_ASPNET_CERTIFICATE: false + ContinuousIntegrationBuild: true jobs: audit: - runs-on: windows-latest + strategy: + fail-fast: false + matrix: + configuration: [debug, release] + os: [ubuntu-latest, windows-latest] + runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v2.3.4 - - - name: Setup MSBuild - uses: microsoft/setup-msbuild@v1 + uses: actions/checkout@v4 - - name: Setup VSTest - uses: darenm/Setup-VSTest@v1 - - - name: Setup NuGet - uses: NuGet/setup-nuget@v1.0.5 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.x - - name: Restore NuGet Packages - run: nuget restore src/Aeon.sln + - name: Restore + run: dotnet restore - - name: Build Project - run: msbuild src/Aeon.sln /p:Configuration=Release + - name: Build + run: dotnet build --no-restore --configuration ${{ matrix.configuration }} + + - name: Pack + run: dotnet pack --no-restore --no-build --configuration ${{ matrix.configuration }} - - name: Run Tests - run: vstest.console.exe src/Aeon.Tests/bin/Release/net472/Aeon.Tests.dll \ No newline at end of file + - name: Test + run: dotnet test --no-restore --no-build --configuration ${{ matrix.configuration }} \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index e23b04b..41ae192 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,7 +5,6 @@ Copyright © 2023-2024 University College London https://sainsburywellcomecentre.github.io/aeon_docs https://github.com/SainsburyWellcomeCentre/aeon_acquisition.git - true snupkg LICENSE true From bf672da8821fbf90264aea33d42a9bc2ad5c710c Mon Sep 17 00:00:00 2001 From: glopesdev Date: Wed, 17 Jul 2024 11:32:40 +0100 Subject: [PATCH 7/9] Exclude driver dependent tests from linux run --- .github/workflows/ci-audit.yml | 7 +++++-- src/Aeon.Tests/OperatorTests.cs | 9 +++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-audit.yml b/.github/workflows/ci-audit.yml index 0eef9a7..a4f6e74 100644 --- a/.github/workflows/ci-audit.yml +++ b/.github/workflows/ci-audit.yml @@ -18,6 +18,9 @@ jobs: matrix: configuration: [debug, release] os: [ubuntu-latest, windows-latest] + include: + - os: ubuntu-latest + test-filter: --filter TestCategory!=DriverDependent runs-on: ${{ matrix.os }} steps: - name: Checkout @@ -35,7 +38,7 @@ jobs: run: dotnet build --no-restore --configuration ${{ matrix.configuration }} - name: Pack - run: dotnet pack --no-restore --no-build --configuration ${{ matrix.configuration }} + run: dotnet pack --no-build --configuration ${{ matrix.configuration }} - name: Test - run: dotnet test --no-restore --no-build --configuration ${{ matrix.configuration }} \ No newline at end of file + run: dotnet test --no-build --configuration ${{ matrix.configuration }} ${{ matrix.test-filter }} \ No newline at end of file diff --git a/src/Aeon.Tests/OperatorTests.cs b/src/Aeon.Tests/OperatorTests.cs index fb6fb5b..99a15a6 100644 --- a/src/Aeon.Tests/OperatorTests.cs +++ b/src/Aeon.Tests/OperatorTests.cs @@ -17,15 +17,20 @@ public void Build_Workflows() var acquisition = typeof(GroupByTime).Assembly; var environment = typeof(EnvironmentState).Assembly; var foraging = typeof(WheelDisplacement).Assembly; - var video = typeof(VideoDataFrame).Assembly; var vision = typeof(DistanceFromPoint).Assembly; var sleap = typeof(FormatPose).Assembly; AssertWorkflow.CanBuildEmbeddedResources(acquisition); AssertWorkflow.CanBuildEmbeddedResources(environment); AssertWorkflow.CanBuildEmbeddedResources(foraging); - AssertWorkflow.CanBuildEmbeddedResources(video); AssertWorkflow.CanBuildEmbeddedResources(vision); AssertWorkflow.CanBuildEmbeddedResources(sleap); } + + [TestMethod, TestCategory("DriverDependent")] + public void Build_DriverDependentWorkflows() + { + var video = typeof(VideoDataFrame).Assembly; + AssertWorkflow.CanBuildEmbeddedResources(video); + } } } From f17ce9828571fe11c8ff3c60b3b52c20683852d8 Mon Sep 17 00:00:00 2001 From: glopesdev Date: Wed, 17 Jul 2024 14:30:39 +0100 Subject: [PATCH 8/9] Internalize local extension methods --- src/Aeon.Acquisition/ObservableExtensions.cs | 2 +- src/Aeon.Database/DataReaderExtensions.cs | 2 +- src/Aeon.Video/ObservableExtensions.cs | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Aeon.Acquisition/ObservableExtensions.cs b/src/Aeon.Acquisition/ObservableExtensions.cs index ce4498f..d52e9d4 100644 --- a/src/Aeon.Acquisition/ObservableExtensions.cs +++ b/src/Aeon.Acquisition/ObservableExtensions.cs @@ -7,7 +7,7 @@ namespace Aeon.Acquisition { - public static class ObservableExtensions + internal static class ObservableExtensions { public static IObservable MergeUnit(this IObservable source, IObservable other) { diff --git a/src/Aeon.Database/DataReaderExtensions.cs b/src/Aeon.Database/DataReaderExtensions.cs index f1c2c41..c369cdc 100644 --- a/src/Aeon.Database/DataReaderExtensions.cs +++ b/src/Aeon.Database/DataReaderExtensions.cs @@ -4,7 +4,7 @@ namespace Aeon.Database { - public static class DataReaderExtensions + internal static class DataReaderExtensions { public static IEnumerable GetRecords(this MySqlDataReader reader) { diff --git a/src/Aeon.Video/ObservableExtensions.cs b/src/Aeon.Video/ObservableExtensions.cs index 484b8f1..8cfd2b2 100644 --- a/src/Aeon.Video/ObservableExtensions.cs +++ b/src/Aeon.Video/ObservableExtensions.cs @@ -1,13 +1,10 @@ using System; -using System.Linq; using System.Reactive; -using System.Reactive.Disposables; using System.Reactive.Linq; -using Bonsai.Harp; namespace Aeon.Video { - public static class ObservableExtensions + internal static class ObservableExtensions { public static IObservable FillGaps(this IObservable source, Func gapSelector) { From f0c0966e1c415211dc39950d98e6deb080625c9b Mon Sep 17 00:00:00 2001 From: glopesdev Date: Wed, 17 Jul 2024 14:39:25 +0100 Subject: [PATCH 9/9] Rename test methods to clarify their actual scope --- src/Aeon.Tests/AssertWorkflow.cs | 2 +- src/Aeon.Tests/OperatorTests.cs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Aeon.Tests/AssertWorkflow.cs b/src/Aeon.Tests/AssertWorkflow.cs index b7628b5..785169e 100644 --- a/src/Aeon.Tests/AssertWorkflow.cs +++ b/src/Aeon.Tests/AssertWorkflow.cs @@ -11,7 +11,7 @@ namespace Aeon.Tests { public static class AssertWorkflow { - public static void CanBuildEmbeddedResources(Assembly assembly) + public static void CanLoadEmbeddedResources(Assembly assembly) { foreach (var name in assembly.GetManifestResourceNames()) { diff --git a/src/Aeon.Tests/OperatorTests.cs b/src/Aeon.Tests/OperatorTests.cs index 99a15a6..aac16b2 100644 --- a/src/Aeon.Tests/OperatorTests.cs +++ b/src/Aeon.Tests/OperatorTests.cs @@ -12,25 +12,25 @@ namespace Aeon.Tests public class OperatorTests { [TestMethod] - public void Build_Workflows() + public void Load_Workflows() { var acquisition = typeof(GroupByTime).Assembly; var environment = typeof(EnvironmentState).Assembly; var foraging = typeof(WheelDisplacement).Assembly; var vision = typeof(DistanceFromPoint).Assembly; var sleap = typeof(FormatPose).Assembly; - AssertWorkflow.CanBuildEmbeddedResources(acquisition); - AssertWorkflow.CanBuildEmbeddedResources(environment); - AssertWorkflow.CanBuildEmbeddedResources(foraging); - AssertWorkflow.CanBuildEmbeddedResources(vision); - AssertWorkflow.CanBuildEmbeddedResources(sleap); + AssertWorkflow.CanLoadEmbeddedResources(acquisition); + AssertWorkflow.CanLoadEmbeddedResources(environment); + AssertWorkflow.CanLoadEmbeddedResources(foraging); + AssertWorkflow.CanLoadEmbeddedResources(vision); + AssertWorkflow.CanLoadEmbeddedResources(sleap); } [TestMethod, TestCategory("DriverDependent")] - public void Build_DriverDependentWorkflows() + public void Load_DriverDependentWorkflows() { var video = typeof(VideoDataFrame).Assembly; - AssertWorkflow.CanBuildEmbeddedResources(video); + AssertWorkflow.CanLoadEmbeddedResources(video); } } }