Skip to content

Commit

Permalink
Move miniscope real-time properties to configuration node
Browse files Browse the repository at this point in the history
- Fixes #133
- See #114 for reasoning
  • Loading branch information
jonnew committed Jul 20, 2024
1 parent fe15000 commit 72d8e2d
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 50 deletions.
43 changes: 40 additions & 3 deletions OpenEphys.Onix/OpenEphys.Onix/ConfigureUclaMiniscopeV4Camera.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Reactive.Disposables;
using System.Reactive.Subjects;
using Bonsai;

namespace OpenEphys.Onix
{
public class ConfigureUclaMiniscopeV4Camera : SingleDeviceFactory
{
readonly BehaviorSubject<double> ledBrightness = new(0);
readonly BehaviorSubject<UclaMiniscopeV4SensorGain> sensorGain = new(UclaMiniscopeV4SensorGain.Low);
readonly BehaviorSubject<double> liquidLensVoltage = new(47); // NB: middle of range

public ConfigureUclaMiniscopeV4Camera()
: base(typeof(UclaMiniscopeV4))
{
Expand All @@ -17,11 +24,39 @@ public ConfigureUclaMiniscopeV4Camera()

[Category(ConfigurationCategory)]
[Description("Only turn on excitation LED during camera exposures.")]
public bool InterleaveLed { get; set; } = false;
public UclaMiniscopeV4FramesPerSecond FrameRate { get; set; } = UclaMiniscopeV4FramesPerSecond.Fps30Hz;

[Category(ConfigurationCategory)]
[Description("Only turn on excitation LED during camera exposures.")]
public UclaMiniscopeV4FramesPerSecond FrameRate { get; set; } = UclaMiniscopeV4FramesPerSecond.Fps30Hz;
public bool InterleaveLed { get; set; } = false;

[Description("Excitation LED brightness (0-100%).")]
[Range(0, 100)]
[Precision(1, 1)]
[Editor(DesignTypes.SliderEditor, typeof(UITypeEditor))]
public double LedBrightness
{
get => ledBrightness.Value;
set => ledBrightness.OnNext(value);
}

[Description("Camera sensor analog gain.")]
[Editor(DesignTypes.SliderEditor, typeof(UITypeEditor))]
public UclaMiniscopeV4SensorGain SensorGain
{
get => sensorGain.Value;
set => sensorGain.OnNext(value);
}

[Description("Liquid lens voltage (Volts RMS).")]
[Range(24.4, 69.7)]
[Precision(1, 1)]
[Editor(DesignTypes.SliderEditor, typeof(UITypeEditor))]
public double LiquidLensVoltage
{
get => liquidLensVoltage.Value;
set => liquidLensVoltage.OnNext(value);
}

public override IObservable<ContextTask> Process(IObservable<ContextTask> source)
{
Expand Down Expand Up @@ -66,6 +101,9 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> source
atMega.WriteByte(1, 0xFF);
});
return new CompositeDisposable(
ledBrightness.Subscribe(value => SetLedBrightness(device, value)),
sensorGain.Subscribe(value => SetSensorGain(device, value)),
liquidLensVoltage.Subscribe(value => SetLiquidLensVoltage(device, value)),
shutdown,
disposable);
});
Expand Down Expand Up @@ -160,7 +198,6 @@ internal static void SetLiquidLensVoltage(DeviceContext device, double voltage)
max14574.WriteByte(0x08, (uint)((voltage - 24.4) / 0.0445) >> 2);
max14574.WriteByte(0x09, 0x02);
}

}

static class UclaMiniscopeV4
Expand Down
Original file line number Diff line number Diff line change
@@ -1,55 +1,20 @@
using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Runtime.InteropServices;
using Bonsai;
using OpenCV.Net;

namespace OpenEphys.Onix
{
public class UclaMiniscopeV4CameraData : Source<UclaMiniscopeV4DataFrame>
public class UclaMiniscopeV4Camera : Source<UclaMiniscopeV4Image>
{
readonly BehaviorSubject<double> ledBrightness = new(0);
readonly BehaviorSubject<UclaMiniscopeV4SensorGain> sensorGain = new(UclaMiniscopeV4SensorGain.Low);
readonly BehaviorSubject<double> liquidLensVoltage = new(47); // NB: middle of range

[TypeConverter(typeof(UclaMiniscopeV4.NameConverter))]
public string DeviceName { get; set; }

[Description("Excitation LED brightness (0-100%).")]
[Range(0, 100)]
[Precision(1, 1)]
[Editor(DesignTypes.SliderEditor, typeof(UITypeEditor))]
public double LedBrightness
{
get => ledBrightness.Value;
set => ledBrightness.OnNext(value);
}

[Description("Camera sensor analog gain.")]
[Editor(DesignTypes.SliderEditor, typeof(UITypeEditor))]
public UclaMiniscopeV4SensorGain SensorGain
{
get => sensorGain.Value;
set => sensorGain.OnNext(value);
}

[Description("Liquid lens voltage (Volts RMS).")]
[Range(24.4, 69.7)]
[Precision(1, 1)]
[Editor(DesignTypes.SliderEditor, typeof(UITypeEditor))]
public double LiquidLensVoltage
{
get => liquidLensVoltage.Value;
set => liquidLensVoltage.OnNext(value);
}

public unsafe override IObservable<UclaMiniscopeV4DataFrame> Generate()
public unsafe override IObservable<UclaMiniscopeV4Image> Generate()
{
return Observable.Using(
() => DeviceManager.ReserveDevice(DeviceName),
Expand All @@ -58,7 +23,7 @@ public unsafe override IObservable<UclaMiniscopeV4DataFrame> Generate()
var device = deviceInfo.GetDeviceContext(typeof(UclaMiniscopeV4));
var passthrough = device.GetPassthroughDeviceContext(DS90UB9x.ID);
var scopeData = device.Context.FrameReceived.Where(frame => frame.DeviceAddress == passthrough.Address);
return Observable.Create<UclaMiniscopeV4DataFrame>(observer =>
return Observable.Create<UclaMiniscopeV4Image>(observer =>
{
var sampleIndex = 0;
var imageBuffer = new short[UclaMiniscopeV4.SensorRows * UclaMiniscopeV4.SensorColumns];
Expand All @@ -83,7 +48,7 @@ public unsafe override IObservable<UclaMiniscopeV4DataFrame> Generate()
{
var imageData = Mat.FromArray(imageBuffer, UclaMiniscopeV4.SensorRows, UclaMiniscopeV4.SensorColumns, Depth.U16, 1);
CV.ConvertScale(imageData.GetRow(0), imageData.GetRow(0), 1.0f, -32768.0f); // Get rid first row's mark bit
observer.OnNext(new UclaMiniscopeV4DataFrame(clockBuffer, hubClockBuffer, imageData.GetImage()));
observer.OnNext(new UclaMiniscopeV4Image(clockBuffer, hubClockBuffer, imageData.GetImage()));
hubClockBuffer = new ulong[UclaMiniscopeV4.SensorRows];
clockBuffer = new ulong[UclaMiniscopeV4.SensorRows];
sampleIndex = 0;
Expand All @@ -93,12 +58,7 @@ public unsafe override IObservable<UclaMiniscopeV4DataFrame> Generate()
observer.OnError,
observer.OnCompleted);

return new CompositeDisposable(
ledBrightness.Subscribe(value => ConfigureUclaMiniscopeV4Camera.SetLedBrightness(device, value)),
sensorGain.Subscribe(value => ConfigureUclaMiniscopeV4Camera.SetSensorGain(device, value)),
liquidLensVoltage.Subscribe(value => ConfigureUclaMiniscopeV4Camera.SetLiquidLensVoltage(device, value)),
scopeData.SubscribeSafe(frameObserver)
); ;
return scopeData.SubscribeSafe(frameObserver);
});
}));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

namespace OpenEphys.Onix
{
public class UclaMiniscopeV4DataFrame
public class UclaMiniscopeV4Image
{
public UclaMiniscopeV4DataFrame(ulong[] clock, ulong[] hubClock, IplImage image)
public UclaMiniscopeV4Image(ulong[] clock, ulong[] hubClock, IplImage image)
{
Clock = clock;
HubClock = hubClock;
Expand Down

0 comments on commit 72d8e2d

Please sign in to comment.