Skip to content
Open
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
66 changes: 27 additions & 39 deletions OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,25 @@ namespace OpenEphys.Onix1.Design
/// Within, there are a number of useful methods for initializing, resizing, and drawing channels.
/// Each device must implement their own ChannelConfigurationDialog.
/// </summary>
public partial class ChannelConfigurationDialog : Form
public abstract partial class ChannelConfigurationDialog : Form
{
internal event EventHandler OnResizeZedGraph;
internal event EventHandler OnDrawProbeGroup;

ProbeGroup probeGroup;

internal ProbeGroup ProbeGroup
{
get => probeGroup;
set
{
probeGroup = value;
SelectedContacts = new bool[probeGroup.NumberOfContacts];
}
}
internal virtual ProbeGroup ProbeGroup { get; set; }

internal readonly List<int> ReferenceContacts = new();

internal bool[] SelectedContacts { get; private set; } = null;

[Obsolete("Designer only.", true)]
ChannelConfigurationDialog()
{
InitializeComponent();
}

/// <summary>
/// Constructs the dialog window using the given probe group, and plots all contacts after loading.
/// Constructs the dialog window.
/// </summary>
/// <param name="probeGroup">Channel configuration given as a <see cref="ProbeInterface.NET.ProbeGroup"/></param>
public ChannelConfigurationDialog(ProbeGroup probeGroup)
public ChannelConfigurationDialog()
{
InitializeComponent();
Shown += FormShown;

if (probeGroup == null)
{
LoadDefaultChannelLayout();
}
else
{
ProbeGroup = probeGroup;
}

ReferenceContacts = new List<int>();

zedGraphChannels.MouseDownEvent += MouseDownEvent;
Expand All @@ -81,6 +55,17 @@ public ChannelConfigurationDialog(ProbeGroup probeGroup)
{
pane.Chart.Fill = new Fill(Color.WhiteSmoke);
}
}

/// <summary>
/// Constructs the dialog window using the given probe group, and plots all contacts after loading.
/// </summary>
/// <param name="probeGroup">Channel configuration given as a <see cref="ProbeInterface.NET.ProbeGroup"/></param>
public ChannelConfigurationDialog(ProbeGroup probeGroup)
: this()
{
ProbeGroup = probeGroup;
ResizeSelectedContacts();

DrawProbeGroup();
RefreshZedGraph();
Expand All @@ -107,6 +92,12 @@ internal virtual ProbeGroup DefaultChannelLayout()
internal virtual void LoadDefaultChannelLayout()
{
ProbeGroup = DefaultChannelLayout();
ResizeSelectedContacts();
}

internal void ResizeSelectedContacts()
{
SelectedContacts = new bool[ProbeGroup.NumberOfContacts];
}

/// <summary>
Expand Down Expand Up @@ -296,25 +287,21 @@ internal virtual bool OpenFile(Type type)
return false;
}

internal bool ValidateProbeGroup(ProbeGroup newConfiguration)
internal void ValidateProbeGroup(ProbeGroup newConfiguration)
{
if (newConfiguration == null)
{
return false;
throw new ArgumentNullException($"{nameof(newConfiguration)} is null, {nameof(ProbeGroup)} is invalid.");
}

if (ProbeGroup.NumberOfContacts == newConfiguration.NumberOfContacts)
{
newConfiguration.Validate();

return true;
}
else
{
MessageBox.Show($"Error: Number of contacts does not match; expected {ProbeGroup.NumberOfContacts} contacts" +
$", but found {newConfiguration.NumberOfContacts} contacts", "Contact Number Mismatch");

return false;
throw new ArgumentException($"Number of contacts does not match; expected {ProbeGroup.NumberOfContacts} contacts" +
$", but found {newConfiguration.NumberOfContacts} contacts. Double check that the correct file is chosen.");
}
}

Expand All @@ -334,8 +321,9 @@ internal ProbeGroup OpenAndParseConfigurationFile(Type type)
try
{
var newConfiguration = ProbeInterfaceHelper.LoadExternalProbeInterfaceFile(ofd.FileName, type);
ValidateProbeGroup(newConfiguration);

return ValidateProbeGroup(newConfiguration) ? newConfiguration : null;
return newConfiguration;
}
catch (Exception ex)
{
Expand Down
3 changes: 3 additions & 0 deletions OpenEphys.Onix1.Design/INeuropixelsV2ProbeInfo.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;

namespace OpenEphys.Onix1.Design
{
interface INeuropixelsV2ProbeInfo
{
public IEnumerable<NeuropixelsV2Electrode> Electrodes { get; }

Array GetReferenceEnumValues();

Array GetComboBoxChannelPresets();
Expand Down
20 changes: 11 additions & 9 deletions OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ public partial class NeuropixelsV1ChannelConfigurationDialog : ChannelConfigurat
/// </summary>
public NeuropixelsV1ProbeConfiguration ProbeConfiguration { get; set; }

internal override ProbeGroup ProbeGroup
{
get => ProbeConfiguration.ProbeGroup;
set => ProbeConfiguration.ProbeGroup = value as NeuropixelsV1eProbeGroup ?? throw new ArgumentNullException($"Invalid probe group given; expected type {ProbeConfiguration.ProbeGroup.GetType()}, but found type {value.GetType()}");
}

/// <summary>
/// Initializes a new instance of <see cref="NeuropixelsV1ChannelConfigurationDialog"/>.
/// </summary>
/// <param name="probeConfiguration">A <see cref="NeuropixelsV1ProbeConfiguration"/> object holding the current configuration settings.</param>
public NeuropixelsV1ChannelConfigurationDialog(NeuropixelsV1ProbeConfiguration probeConfiguration)
: base(probeConfiguration.ProbeGroup)
: base()
{
zedGraphChannels.ZoomButtons = MouseButtons.None;
zedGraphChannels.ZoomButtons2 = MouseButtons.None;
Expand All @@ -38,10 +44,9 @@ public NeuropixelsV1ChannelConfigurationDialog(NeuropixelsV1ProbeConfiguration p
ReferenceContacts.AddRange(ReferenceContactsList);

ProbeConfiguration = new(probeConfiguration);
ResizeSelectedContacts();

HighlightEnabledContacts();
UpdateContactLabels();
DrawScale();
DrawProbeGroup();
RefreshZedGraph();
}

Expand All @@ -53,7 +58,6 @@ internal override ProbeGroup DefaultChannelLayout()
internal override void LoadDefaultChannelLayout()
{
ProbeConfiguration.ProbeGroup = new();
ProbeGroup = ProbeConfiguration.ProbeGroup;

OnFileOpenHandler();
}
Expand All @@ -62,7 +66,6 @@ internal override bool OpenFile(Type type)
{
if (base.OpenFile(type))
{
ProbeConfiguration.ProbeGroup = (NeuropixelsV1eProbeGroup)ProbeGroup;
OnFileOpenHandler();

return true;
Expand All @@ -73,6 +76,8 @@ internal override bool OpenFile(Type type)

private void OnFileOpenHandler()
{
ResizeSelectedContacts();

OnFileLoad?.Invoke(this, EventArgs.Empty);
}

Expand Down Expand Up @@ -142,9 +147,6 @@ internal override void HighlightEnabledContacts()

internal override void UpdateContactLabels()
{
if (ProbeConfiguration.ProbeGroup == null)
return;

var textObjs = zedGraphChannels.GraphPane.GraphObjList.OfType<TextObj>()
.Where(t => t.Tag is ContactTag);

Expand Down
2 changes: 1 addition & 1 deletion OpenEphys.Onix1.Design/NeuropixelsV2QuadShankInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ enum QuadShankChannelPreset
None
}

IEnumerable<NeuropixelsV2Electrode> Electrodes { get; init; }
public IEnumerable<NeuropixelsV2Electrode> Electrodes { get; init; }

public NeuropixelsV2QuadShankInfo(NeuropixelsV2QuadShankProbeConfiguration probeConfiguration)
{
Expand Down
78 changes: 78 additions & 0 deletions OpenEphys.Onix1.Design/NeuropixelsV2SingleShankInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace OpenEphys.Onix1.Design
{
internal class NeuropixelsV2SingleShankInfo : INeuropixelsV2ProbeInfo
{
const int BankDStartIndex = 896;

enum SingleShankChannelPreset
{
BankA,
BankB,
BankC,
BankD,
None
}

public IEnumerable<NeuropixelsV2Electrode> Electrodes { get; init; }

public NeuropixelsV2SingleShankInfo(NeuropixelsV2SingleShankProbeConfiguration probeConfiguration)
{
Electrodes = probeConfiguration.ProbeGroup.ToElectrodes();
}

public Array GetReferenceEnumValues()
{
return Enum.GetValues(typeof(NeuropixelsV2SingleShankReference));
}

public Array GetComboBoxChannelPresets()
{
return Enum.GetValues(typeof(SingleShankChannelPreset));
}

public Enum CheckForExistingChannelPreset(NeuropixelsV2Electrode[] channelMap)
{
if (channelMap.All(e => e.Bank == NeuropixelsV2Bank.A))
{
return SingleShankChannelPreset.BankA;
}
else if (channelMap.All(e => e.Bank == NeuropixelsV2Bank.B))
{
return SingleShankChannelPreset.BankB;
}
else if (channelMap.All(e => e.Bank == NeuropixelsV2Bank.C))
{
return SingleShankChannelPreset.BankC;
}
else if (channelMap.All(e => e.Bank == NeuropixelsV2Bank.D ||
(e.Bank == NeuropixelsV2Bank.C && e.Index >= BankDStartIndex)))
{
return SingleShankChannelPreset.BankD;
}
else
{
return SingleShankChannelPreset.None;
}
}

public NeuropixelsV2Electrode[] GetChannelPreset(Enum channelPreset)
{
var preset = (SingleShankChannelPreset)channelPreset;

return preset switch
{
SingleShankChannelPreset.BankA => Electrodes.Where(e => e.Bank == NeuropixelsV2Bank.A).ToArray(),
SingleShankChannelPreset.BankB => Electrodes.Where(e => e.Bank == NeuropixelsV2Bank.B).ToArray(),
SingleShankChannelPreset.BankC => Electrodes.Where(e => e.Bank == NeuropixelsV2Bank.C).ToArray(),
SingleShankChannelPreset.BankD => Electrodes.Where(e => e.Bank == NeuropixelsV2Bank.D || (e.Bank == NeuropixelsV2Bank.C && e.Index >= BankDStartIndex)).ToArray(),
SingleShankChannelPreset.None => Array.Empty<NeuropixelsV2Electrode>(),
_ => throw new InvalidEnumArgumentException($"Unknown value of {nameof(SingleShankChannelPreset)}: {channelPreset}")
};
}
}
}
29 changes: 14 additions & 15 deletions OpenEphys.Onix1.Design/NeuropixelsV2eChannelConfigurationDialog.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using OpenEphys.ProbeInterface.NET;
using ZedGraph;
Expand All @@ -15,44 +14,43 @@ public partial class NeuropixelsV2eChannelConfigurationDialog : ChannelConfigura
internal event EventHandler OnZoom;
internal event EventHandler OnFileLoad;

internal NeuropixelsV2ProbeConfiguration ProbeConfiguration;
internal NeuropixelsV2ProbeConfiguration ProbeConfiguration { get; set; }

readonly Func<int, int> GetChannelNumberFunc;
internal override ProbeGroup ProbeGroup
{
get => ProbeConfiguration.ProbeGroup;
set => ProbeConfiguration.ProbeGroup = value as NeuropixelsV2eProbeGroup ?? throw new ArgumentNullException($"Invalid probe group given; expected type {ProbeConfiguration.ProbeGroup.GetType()}, but found type {value.GetType()}");
}

/// <summary>
/// Initializes a new instance of <see cref="NeuropixelsV2eChannelConfigurationDialog"/>.
/// </summary>
/// <param name="probeConfiguration">A <see cref="NeuropixelsV2ProbeConfiguration"/> object holding the current configuration settings.</param>
public NeuropixelsV2eChannelConfigurationDialog(NeuropixelsV2ProbeConfiguration probeConfiguration)
: base(probeConfiguration.ProbeGroup.Clone())
: base()
{
zedGraphChannels.ZoomButtons = MouseButtons.None;
zedGraphChannels.ZoomButtons2 = MouseButtons.None;

zedGraphChannels.ZoomStepFraction = 0.5;

ProbeConfiguration = probeConfiguration.Clone();
ProbeConfiguration.ProbeGroup = (NeuropixelsV2eProbeGroup)ProbeGroup;
ResizeSelectedContacts();

GetChannelNumberFunc = ProbeConfiguration.ChannelMap[0].GetChannelNumberFunc();

HighlightEnabledContacts();
UpdateContactLabels();
DrawScale();
DrawProbeGroup();
RefreshZedGraph();
}

internal override ProbeGroup DefaultChannelLayout()
{
return Activator.CreateInstance(ProbeConfiguration.ProbeGroup.GetType()) as NeuropixelsV2eProbeGroup ?? throw new InvalidOperationException("Could not create new probe group of type " + ProbeConfiguration.ProbeGroup.GetType().Name);
return Activator.CreateInstance(ProbeConfiguration.ProbeGroup.GetType()) as NeuropixelsV2eProbeGroup ?? throw new NullReferenceException("Could not create new probe group of type " + ProbeConfiguration.ProbeGroup.GetType().Name);
}

internal override void LoadDefaultChannelLayout()
{
try
{
ProbeConfiguration.ProbeGroup = DefaultChannelLayout() as NeuropixelsV2eProbeGroup;
ProbeGroup = ProbeConfiguration.ProbeGroup;
}
catch (InvalidOperationException ex)
{
Expand All @@ -67,7 +65,6 @@ internal override bool OpenFile(Type type)
{
if (base.OpenFile(type))
{
ProbeConfiguration.ProbeGroup = (NeuropixelsV2eProbeGroup)ProbeGroup;
OnFileOpenHandler();

return true;
Expand All @@ -78,6 +75,8 @@ internal override bool OpenFile(Type type)

private void OnFileOpenHandler()
{
ResizeSelectedContacts();

OnFileLoad?.Invoke(this, EventArgs.Empty);
}

Expand Down Expand Up @@ -133,7 +132,7 @@ internal override void HighlightEnabledContacts()
var contactsToEnable = contactObjects.Where(c =>
{
var tag = c.Tag as ContactTag;
var channel = GetChannelNumberFunc(tag.ContactIndex);
var channel = ProbeConfiguration.GetChannelNumber(tag.ContactIndex);
return channelMap[channel].Index == tag.ContactIndex;
});

Expand Down Expand Up @@ -165,7 +164,7 @@ internal override void UpdateContactLabels()
textObjsToUpdate = textObjs.Where(c =>
{
var tag = c.Tag as ContactTag;
var channel = GetChannelNumberFunc(tag.ContactIndex);
var channel = ProbeConfiguration.GetChannelNumber(tag.ContactIndex);
return channelMap[channel].Index == tag.ContactIndex;
});

Expand Down
Loading