Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 106 additions & 2 deletions OpenEphys.Onix1/ConfigureRhs2116Trigger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Reactive.Disposables;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Bonsai;
using Newtonsoft.Json;
Expand Down Expand Up @@ -44,7 +45,7 @@ public ConfigureRhs2116Trigger(ConfigureRhs2116Trigger rhs2116Trigger)
DeviceAddress = rhs2116Trigger.DeviceAddress;
DeviceName = rhs2116Trigger.DeviceName;
TriggerSource = rhs2116Trigger.TriggerSource;
ProbeGroup = rhs2116Trigger.ProbeGroup;
ProbeGroup = rhs2116Trigger.ProbeGroup.Clone();
Armed = rhs2116Trigger.Armed;
StimulusSequence = new(rhs2116Trigger.StimulusSequence);
}
Expand Down Expand Up @@ -76,13 +77,116 @@ public ConfigureRhs2116Trigger(ConfigureRhs2116Trigger rhs2116Trigger)
[Description("Specifies whether the trigger source is local or external.")]
public Rhs2116TriggerSource TriggerSource { get; set; } = Rhs2116TriggerSource.Local;

Task<Rhs2116ProbeGroup> probeGroupTask = null;

Rhs2116ProbeGroup probeGroup = null;

/// <summary>
/// Gets or sets the <see cref="Rhs2116ProbeGroup"/> channel configuration.
/// </summary>
[XmlIgnore]
[Category(ConfigurationCategory)]
[Description("Defines the channel configuration")]
public Rhs2116ProbeGroup ProbeGroup { get; set; } = new();
[Browsable(false)]
[Externalizable(false)]
public Rhs2116ProbeGroup ProbeGroup
{
get
{
if (probeGroup == null)
{
try
{
probeGroup = probeGroupTask?.Result ?? new Rhs2116ProbeGroup();
}
catch (AggregateException ae)
{
probeGroup = new();
throw new InvalidOperationException($"There was an error loading the ProbeInterface file, loading the default configuration instead.\n\nError: {ae.InnerException.Message}", ae.InnerException);
}
}

return probeGroup;
}
set => probeGroup = value;
}

string probeInterfaceFileName;

/// <summary>
/// Gets or sets the file path where the ProbeInterface configuration will be saved.
/// </summary>
/// <remarks>
/// If left empty, the ProbeInterface configuration will not be saved.
/// </remarks>
[XmlIgnore]
[Category(ConfigurationCategory)]
[Description("File path to where the ProbeInterface file will be saved for this probe. If the file exists, it will be overwritten.")]
[FileNameFilter(ProbeInterfaceHelper.ProbeInterfaceFileNameFilter)]
[Editor("Bonsai.Design.SaveFileNameEditor, Bonsai.Design", DesignTypes.UITypeEditor)]
public string ProbeInterfaceFileName
{
get => probeInterfaceFileName;
set => probeInterfaceFileName = value;
}

/// <summary>
/// Gets or sets the ProbeInterface file name, loading the given file asynchronously when set.
/// </summary>
[XmlIgnore]
[Browsable(false)]
[Externalizable(false)]
public string ProbeInterfaceLoadFileName
{
get => probeInterfaceFileName;
set
{
probeInterfaceFileName = value;
probeGroupTask = Task.Run(() =>
{
if (string.IsNullOrEmpty(probeInterfaceFileName))
return new Rhs2116ProbeGroup();

return ProbeInterfaceHelper.LoadExternalProbeInterfaceFile<Rhs2116ProbeGroup>(probeInterfaceFileName);
});
}
}

/// <summary>
/// Gets or sets a string defining the path to an external ProbeInterface JSON file.
/// This variable is needed to properly save a workflow in Bonsai, but it is not
/// directly accessible in the Bonsai editor.
/// </summary>
/// <remarks>
/// [Obsolete]. Cannot tag this property with the Obsolete attribute due to https://github.com/dotnet/runtime/issues/100453
/// </remarks>
[Browsable(false)]
[Externalizable(false)]
[XmlElement(nameof(ProbeInterfaceFileName))]
public string ProbeInterfaceFileNameSerialize
{
get
{
if (string.IsNullOrEmpty(ProbeInterfaceFileName))
return "";

if (probeGroup != null)
ProbeInterfaceHelper.SaveExternalProbeInterfaceFile(ProbeGroup, ProbeInterfaceFileName);

return ProbeInterfaceFileName;
}
set => ProbeInterfaceLoadFileName = value;
}

/// <summary>
/// Prevent the ProbeGroup property from being serialized.
/// </summary>
/// <returns>False</returns>
[Obsolete]
public bool ShouldSerializeProbeGroupString()
{
return false;
}

/// <summary>
/// Gets or sets if trigger is armed.
Expand Down
7 changes: 6 additions & 1 deletion OpenEphys.Onix1/Rhs2116ProbeGroup.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using OpenEphys.ProbeInterface.NET;

Expand Down Expand Up @@ -82,6 +82,11 @@ public Rhs2116ProbeGroup(Rhs2116ProbeGroup probeGroup)
{
}

internal Rhs2116ProbeGroup Clone()
{
return new Rhs2116ProbeGroup(Specification, Version, Probes.Select(probe => new Probe(probe)).ToArray());
}

internal static ContactAnnotations DefaultContactAnnotations(int numberOfChannels, int probeIndex)
{
string[] contactAnnotations = new string[numberOfChannels];
Expand Down