-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Merge pull request #214 from open-ephys/issue-88
Add configuration GUI for NeuropixelsV2e
Showing
41 changed files
with
13,674 additions
and
175 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
.vs/ | ||
.vs*/ | ||
/artifacts/ | ||
.bonsai/Packages/ | ||
.bonsai/*.exe | ||
.bonsai/*.exe.settings | ||
.bonsai/*.exe.WebView2/ | ||
.bonsai/*.exe.WebView2/ | ||
*.user |
194 changes: 194 additions & 0 deletions
194
OpenEphys.Onix1.Design/ChannelConfigurationDialog.Designer.cs
Oops, something went wrong.
1,191 changes: 1,191 additions & 0 deletions
1,191
OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs
Large diffs are not rendered by default.
Oops, something went wrong.
1,778 changes: 1,778 additions & 0 deletions
1,778
OpenEphys.Onix1.Design/ChannelConfigurationDialog.resx
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using System; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Public class used to create tags for contacts in their respective GUIs. | ||
/// </summary> | ||
public class ContactTag | ||
{ | ||
const string ContactStringFormat = "Probe_{0}-Contact_{1}"; | ||
const string TextStringFormat = "TextProbe_{0}-Contact_{1}"; | ||
|
||
/// <summary> | ||
/// Gets the probe index of this contact. | ||
/// </summary> | ||
public int ProbeIndex { get; } | ||
|
||
/// <summary> | ||
/// Gets the contact index of this contact. | ||
/// </summary> | ||
public int ContactIndex { get; } | ||
|
||
/// <summary> | ||
/// Gets the string defining the probe and contact index for this contact. | ||
/// </summary> | ||
public string ContactString => GetContactString(ProbeIndex, ContactIndex); | ||
|
||
/// <summary> | ||
/// Gets the string defining the probe and contact index of a text object for this contact. | ||
/// </summary> | ||
public string TextString => GetTextString(ProbeIndex, ContactIndex); | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="ContactTag"/> class with the given indices. | ||
/// </summary> | ||
/// <param name="probeIndex">Index of the probe for this contact.</param> | ||
/// <param name="contactIndex">Index of the contact for this contact.</param> | ||
public ContactTag(int probeIndex, int contactIndex) | ||
{ | ||
ProbeIndex = probeIndex; | ||
ContactIndex = contactIndex; | ||
} | ||
|
||
static string GetContactString(int probeNumber, int contactNumber) | ||
{ | ||
return string.Format(ContactStringFormat, probeNumber, contactNumber); | ||
} | ||
|
||
static string GetTextString(int probeNumber, int contactNumber) | ||
{ | ||
return string.Format(TextStringFormat, probeNumber, contactNumber); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Windows.Forms; | ||
using Newtonsoft.Json; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
static class DesignHelper | ||
{ | ||
public static T DeserializeString<T>(string channelLayout) | ||
{ | ||
return JsonConvert.DeserializeObject<T>(channelLayout); | ||
} | ||
|
||
public static void SerializeObject(object _object, string filepath) | ||
{ | ||
var stringJson = JsonConvert.SerializeObject(_object, Formatting.Indented); | ||
|
||
File.WriteAllText(filepath, stringJson); | ||
} | ||
|
||
public static IEnumerable<Control> GetAllControls(this Control root) | ||
{ | ||
var stack = new Stack<Control>(); | ||
stack.Push(root); | ||
|
||
while (stack.Any()) | ||
{ | ||
var next = stack.Pop(); | ||
foreach (Control child in next.Controls) | ||
stack.Push(child); | ||
yield return next; | ||
} | ||
} | ||
|
||
public static IEnumerable<Control> GetTopLevelControls(this Control root) | ||
{ | ||
var stack = new Stack<Control>(); | ||
stack.Push(root); | ||
|
||
if (stack.Any()) | ||
{ | ||
var next = stack.Pop(); | ||
foreach (Control child in next.Controls) | ||
{ | ||
yield return child; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Given two forms, take all menu items that are in the "File" MenuItem of the child form, and copy them directly to the | ||
/// "File" MenuItem for the parent form | ||
/// </summary> | ||
/// <param name="thisForm"></param> | ||
/// <param name="childForm"></param> | ||
public static void AddMenuItemsFromDialogToFileOption(this Form thisForm, Form childForm) | ||
{ | ||
const string FileString = "File"; | ||
|
||
if (childForm != null) | ||
{ | ||
var childMenuStrip = childForm.GetAllControls() | ||
.OfType<MenuStrip>() | ||
.FirstOrDefault() ?? throw new InvalidOperationException($"There are no menu strips in any child controls of the {childForm.Text} dialog."); | ||
|
||
var thisMenuStrip = thisForm.GetTopLevelControls() | ||
.OfType<MenuStrip>() | ||
.FirstOrDefault() ?? throw new InvalidOperationException($"There are no menu strips at the top level of the {thisForm.Text} dialog to pull out."); | ||
|
||
ToolStripMenuItem existingMenuItem = null; | ||
|
||
foreach (ToolStripMenuItem menuItem in thisMenuStrip.Items) | ||
{ | ||
if (menuItem.Text == FileString) | ||
{ | ||
existingMenuItem = menuItem; | ||
} | ||
} | ||
|
||
foreach (ToolStripMenuItem menuItem in childMenuStrip.Items) | ||
{ | ||
if (menuItem.Text == FileString) | ||
{ | ||
while (menuItem.DropDownItems.Count > 0) | ||
{ | ||
existingMenuItem.DropDownItems.Add(menuItem.DropDownItems[0]); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Given two forms, take all menu items that are in the "File" MenuItem of the child form, and copy them to the | ||
/// sub-menu name given, nested under the "File" MenuItem for the parent form | ||
/// </summary> | ||
/// <param name="thisForm"></param> | ||
/// <param name="childForm"></param> | ||
/// <param name="subMenuName"></param> | ||
public static void AddMenuItemsFromDialogToFileOption(this Form thisForm, Form childForm, string subMenuName) | ||
{ | ||
const string FileString = "File"; | ||
|
||
if (childForm != null) | ||
{ | ||
var childMenuStrip = childForm.GetAllControls() | ||
.OfType<MenuStrip>() | ||
.First() ?? throw new InvalidOperationException($"There are no menu strips in any child controls of the {childForm.Text} dialog."); | ||
|
||
var thisMenuStrip = thisForm.GetTopLevelControls() | ||
.OfType<MenuStrip>() | ||
.FirstOrDefault() ?? throw new InvalidOperationException($"There are no menu strips at the top level of the {thisForm.Text} dialog to pull out."); | ||
|
||
ToolStripMenuItem thisFileMenuItem = null; | ||
|
||
foreach (ToolStripMenuItem menuItem in thisMenuStrip.Items) | ||
{ | ||
if (menuItem.Text == FileString) | ||
{ | ||
thisFileMenuItem = menuItem; | ||
} | ||
} | ||
|
||
ToolStripMenuItem newChildMenuItems = new() | ||
{ | ||
Text = subMenuName | ||
}; | ||
|
||
foreach (ToolStripMenuItem childItem in childMenuStrip.Items) | ||
{ | ||
if (childItem.Text == FileString) | ||
{ | ||
while (childItem.DropDownItems.Count > 0) | ||
{ | ||
newChildMenuItems.DropDownItems.Add(childItem.DropDownItems[0]); | ||
} | ||
} | ||
} | ||
|
||
thisFileMenuItem.DropDownItems.Add(newChildMenuItems); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.Windows.Forms; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Abstract form that implements a very basic GUI consisting of a single property grid and | ||
/// two buttons (OK / Cancel). | ||
/// </summary> | ||
public abstract partial class GenericDeviceDialog : Form | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of <see cref="GenericDeviceDialog"/>. | ||
/// </summary> | ||
public GenericDeviceDialog() | ||
{ | ||
InitializeComponent(); | ||
} | ||
|
||
private void ButtonClick(object sender, System.EventArgs e) | ||
{ | ||
if (sender is Button button) | ||
{ | ||
if (button.Name == nameof(buttonOK)) | ||
{ | ||
DialogResult = DialogResult.OK; | ||
} | ||
else if (button.Name == nameof(buttonCancel)) | ||
{ | ||
DialogResult = DialogResult.Cancel; | ||
} | ||
} | ||
} | ||
} | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
39 changes: 39 additions & 0 deletions
39
OpenEphys.Onix1.Design/NeuropixelsV2eBno055Dialog.Designer.cs
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using System; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Partial class to create a GUI for <see cref="ConfigureNeuropixelsV2eBno055"/>. | ||
/// </summary> | ||
public partial class NeuropixelsV2eBno055Dialog : GenericDeviceDialog | ||
{ | ||
/// <summary> | ||
/// Gets or sets the <see cref="ConfigureNeuropixelsV2eBno055"/> object attached to | ||
/// the property grid. | ||
/// </summary> | ||
public ConfigureNeuropixelsV2eBno055 ConfigureNode | ||
{ | ||
get => (ConfigureNeuropixelsV2eBno055)propertyGrid.SelectedObject; | ||
set => propertyGrid.SelectedObject = value; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of <see cref="NeuropixelsV2eBno055Dialog"/> with the given | ||
/// <see cref="ConfigureNeuropixelsV2eBno055"/> object. | ||
/// </summary> | ||
/// <param name="configureNode">A <see cref="ConfigureNeuropixelsV2eBno055"/> object that contains configuration settings.</param> | ||
public NeuropixelsV2eBno055Dialog(ConfigureNeuropixelsV2eBno055 configureNode) | ||
{ | ||
InitializeComponent(); | ||
Shown += FormShown; | ||
|
||
ConfigureNode = new(configureNode); | ||
} | ||
|
||
private void FormShown(object sender, EventArgs e) | ||
{ | ||
if (!TopLevel) | ||
{ | ||
splitContainer1.Panel2Collapsed = true; | ||
splitContainer1.Panel2.Hide(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using System; | ||
using System.ComponentModel; | ||
using Bonsai.Design; | ||
using System.Windows.Forms; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Class that opens a new dialog for a <see cref="ConfigureNeuropixelsV2eBno055"/>. | ||
/// </summary> | ||
public class NeuropixelsV2eBno055Editor : WorkflowComponentEditor | ||
{ | ||
/// <inheritdoc/> | ||
public override bool EditComponent(ITypeDescriptorContext context, object component, IServiceProvider provider, IWin32Window owner) | ||
{ | ||
if (provider != null) | ||
{ | ||
var editorState = (IWorkflowEditorState)provider.GetService(typeof(IWorkflowEditorState)); | ||
if (editorState != null && !editorState.WorkflowRunning && component is ConfigureNeuropixelsV2eBno055 configureBno055) | ||
{ | ||
using var editorDialog = new NeuropixelsV2eBno055Dialog(configureBno055); | ||
|
||
if (editorDialog.ShowDialog() == DialogResult.OK) | ||
{ | ||
configureBno055.Enable = editorDialog.ConfigureNode.Enable; | ||
|
||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
OpenEphys.Onix1.Design/NeuropixelsV2eChannelConfigurationDialog.Designer.cs
Oops, something went wrong.
262 changes: 262 additions & 0 deletions
262
OpenEphys.Onix1.Design/NeuropixelsV2eChannelConfigurationDialog.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Drawing; | ||
using System.Linq; | ||
using System.Windows.Forms; | ||
using OpenEphys.ProbeInterface.NET; | ||
using ZedGraph; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Partial class to create a channel configuration GUI for <see cref="ConfigureNeuropixelsV2e"/>. | ||
/// </summary> | ||
public partial class NeuropixelsV2eChannelConfigurationDialog : ChannelConfigurationDialog | ||
{ | ||
internal event EventHandler OnZoom; | ||
internal event EventHandler OnFileLoad; | ||
|
||
/// <summary> | ||
/// Public <see cref="NeuropixelsV2QuadShankProbeConfiguration"/> object that is manipulated by | ||
/// <see cref="NeuropixelsV2eChannelConfigurationDialog"/>. | ||
/// </summary> | ||
public NeuropixelsV2QuadShankProbeConfiguration ProbeConfiguration; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of <see cref="NeuropixelsV2eChannelConfigurationDialog"/>. | ||
/// </summary> | ||
/// <param name="probeConfiguration">A <see cref="NeuropixelsV2QuadShankProbeConfiguration"/> object holding the current configuration settings.</param> | ||
public NeuropixelsV2eChannelConfigurationDialog(NeuropixelsV2QuadShankProbeConfiguration probeConfiguration) | ||
: base(probeConfiguration.ChannelConfiguration) | ||
{ | ||
zedGraphChannels.ZoomButtons = MouseButtons.None; | ||
zedGraphChannels.ZoomButtons2 = MouseButtons.None; | ||
|
||
zedGraphChannels.ZoomStepFraction = 0.5; | ||
|
||
ProbeConfiguration = probeConfiguration; | ||
|
||
ZoomInBoundaryX = 600; | ||
ZoomInBoundaryY = 600; | ||
|
||
HighlightEnabledContacts(); | ||
UpdateContactLabels(); | ||
RefreshZedGraph(); | ||
} | ||
|
||
internal override ProbeGroup DefaultChannelLayout() | ||
{ | ||
return new NeuropixelsV2eProbeGroup(); | ||
} | ||
|
||
internal override void LoadDefaultChannelLayout() | ||
{ | ||
ProbeConfiguration = new(ProbeConfiguration.Probe, ProbeConfiguration.Reference); | ||
ChannelConfiguration = ProbeConfiguration.ChannelConfiguration; | ||
|
||
DrawProbeGroup(); | ||
RefreshZedGraph(); | ||
|
||
OnFileOpenHandler(); | ||
} | ||
|
||
internal override void OpenFile<T>() | ||
{ | ||
var newConfiguration = OpenAndParseConfigurationFile<NeuropixelsV2eProbeGroup>(); | ||
|
||
if (newConfiguration == null) | ||
{ | ||
return; | ||
} | ||
|
||
if (ProbeConfiguration.ChannelConfiguration.NumberOfContacts == newConfiguration.NumberOfContacts) | ||
{ | ||
newConfiguration.Validate(); | ||
|
||
ProbeConfiguration = new(newConfiguration, ProbeConfiguration.Reference, ProbeConfiguration.Probe); | ||
ChannelConfiguration = ProbeConfiguration.ChannelConfiguration; | ||
|
||
DrawProbeGroup(); | ||
RefreshZedGraph(); | ||
} | ||
else | ||
{ | ||
throw new InvalidOperationException($"Number of contacts does not match; expected {ProbeConfiguration.ChannelConfiguration.NumberOfContacts} contacts" + | ||
$", but found {newConfiguration.NumberOfContacts} contacts"); | ||
} | ||
|
||
OnFileOpenHandler(); | ||
} | ||
|
||
private void OnFileOpenHandler() | ||
{ | ||
OnFileLoad?.Invoke(this, EventArgs.Empty); | ||
} | ||
|
||
internal override void ZoomEvent(ZedGraphControl sender, ZoomState oldState, ZoomState newState) | ||
{ | ||
base.ZoomEvent(sender, oldState, newState); | ||
|
||
UpdateFontSize(); | ||
DrawScale(); | ||
RefreshZedGraph(); | ||
|
||
OnZoomHandler(); | ||
} | ||
|
||
private void OnZoomHandler() | ||
{ | ||
OnZoom?.Invoke(this, EventArgs.Empty); | ||
} | ||
|
||
internal override void DrawScale() | ||
{ | ||
if (ProbeConfiguration == null) | ||
return; | ||
|
||
const string ScalePointsTag = "scale_points"; | ||
const string ScaleTextTag = "scale_text"; | ||
|
||
zedGraphChannels.GraphPane.GraphObjList.RemoveAll(obj => obj is TextObj && obj.Tag is string tag && tag == ScaleTextTag); | ||
zedGraphChannels.GraphPane.CurveList.RemoveAll(curve => curve.Tag is string tag && tag == ScalePointsTag); | ||
|
||
const int MajorTickIncrement = 100; | ||
const int MajorTickLength = 10; | ||
const int MinorTickIncrement = 10; | ||
const int MinorTickLength = 5; | ||
|
||
if (ProbeConfiguration.ChannelConfiguration.Probes.ElementAt(0).SiUnits != ProbeSiUnits.um) | ||
{ | ||
MessageBox.Show("Warning: Expected ProbeGroup units to be in microns, but it is in millimeters. Scale might not be accurate."); | ||
} | ||
|
||
var fontSize = CalculateFontSize(); | ||
|
||
var zoomedOut = fontSize <= 2; | ||
|
||
fontSize = zoomedOut ? 8 : fontSize * 4; | ||
var majorTickOffset = MajorTickLength + CalculateScaleRange(zedGraphChannels.GraphPane.XAxis.Scale) * 0.015; | ||
majorTickOffset = majorTickOffset > 50 ? 50 : majorTickOffset; | ||
|
||
var x = GetProbeContourMaxX(zedGraphChannels.GraphPane.GraphObjList) + 50; | ||
var minY = GetProbeContourMinY(zedGraphChannels.GraphPane.GraphObjList); | ||
var maxY = GetProbeContourMaxY(zedGraphChannels.GraphPane.GraphObjList); | ||
|
||
PointPairList pointList = new(); | ||
|
||
var countMajorTicks = 0; | ||
|
||
for (int i = (int)minY; i < maxY; i += MajorTickIncrement) | ||
{ | ||
PointPair majorTickLocation = new(x + majorTickOffset, minY + MajorTickIncrement * countMajorTicks); | ||
|
||
pointList.Add(new PointPair(x, minY + MajorTickIncrement * countMajorTicks)); | ||
pointList.Add(majorTickLocation); | ||
pointList.Add(new PointPair(x, minY + MajorTickIncrement * countMajorTicks)); | ||
|
||
if (!zoomedOut || i % (5 * MajorTickIncrement) == 0) | ||
{ | ||
TextObj textObj = new($"{i} µm\n", majorTickLocation.X + 5, majorTickLocation.Y, CoordType.AxisXYScale, AlignH.Left, AlignV.Center) | ||
{ | ||
Tag = ScaleTextTag, | ||
}; | ||
textObj.FontSpec.Border.IsVisible = false; | ||
textObj.FontSpec.Size = fontSize; | ||
zedGraphChannels.GraphPane.GraphObjList.Add(textObj); | ||
} | ||
|
||
if (!zoomedOut) | ||
{ | ||
var countMinorTicks = 1; | ||
|
||
for (int j = i + MinorTickIncrement; j < i + MajorTickIncrement && i + MinorTickIncrement * countMinorTicks < maxY; j += MinorTickIncrement) | ||
{ | ||
pointList.Add(new PointPair(x, minY + MajorTickIncrement * countMajorTicks + MinorTickIncrement * countMinorTicks)); | ||
pointList.Add(new PointPair(x + MinorTickLength, minY + MajorTickIncrement * countMajorTicks + MinorTickIncrement * countMinorTicks)); | ||
pointList.Add(new PointPair(x, minY + MajorTickIncrement * countMajorTicks + MinorTickIncrement * countMinorTicks)); | ||
|
||
countMinorTicks++; | ||
} | ||
} | ||
|
||
countMajorTicks++; | ||
} | ||
|
||
var curve = zedGraphChannels.GraphPane.AddCurve(ScalePointsTag, pointList, Color.Black, SymbolType.None); | ||
|
||
const float scaleBarWidth = 1; | ||
|
||
curve.Line.Width = scaleBarWidth; | ||
curve.Label.IsVisible = false; | ||
curve.Symbol.IsVisible = false; | ||
} | ||
|
||
internal override void HighlightEnabledContacts() | ||
{ | ||
if (ProbeConfiguration == null || ProbeConfiguration.ChannelMap == null) | ||
return; | ||
|
||
var contactObjects = zedGraphChannels.GraphPane.GraphObjList.OfType<BoxObj>() | ||
.Where(c => c is not PolyObj); | ||
|
||
var enabledContacts = contactObjects.Where(c => c.Fill.Color == EnabledContactFill); | ||
|
||
foreach (var contact in enabledContacts) | ||
{ | ||
contact.Fill.Color = DisabledContactFill; | ||
} | ||
|
||
var contactsToEnable = contactObjects.Where(c => | ||
{ | ||
var tag = c.Tag as ContactTag; | ||
var channel = NeuropixelsV2QuadShankElectrode.GetChannelNumber(tag.ContactIndex); | ||
return ProbeConfiguration.ChannelMap[channel].Index == tag.ContactIndex; | ||
}); | ||
|
||
foreach (var contact in contactsToEnable) | ||
{ | ||
var tag = (ContactTag)contact.Tag; | ||
|
||
contact.Fill.Color = ReferenceContacts.Any(x => x == tag.ContactIndex) ? ReferenceContactFill : EnabledContactFill; | ||
} | ||
} | ||
|
||
internal override void UpdateContactLabels() | ||
{ | ||
if (ProbeConfiguration.ChannelConfiguration == null) | ||
return; | ||
|
||
var textObjs = zedGraphChannels.GraphPane.GraphObjList.OfType<TextObj>() | ||
.Where(t => t.Tag is ContactTag); | ||
|
||
var textObjsToUpdate = textObjs.Where(t => t.FontSpec.FontColor != DisabledContactTextColor); | ||
|
||
foreach (var textObj in textObjsToUpdate) | ||
{ | ||
textObj.FontSpec.FontColor = DisabledContactTextColor; | ||
} | ||
|
||
textObjsToUpdate = textObjs.Where(c => | ||
{ | ||
var tag = c.Tag as ContactTag; | ||
var channel = NeuropixelsV2QuadShankElectrode.GetChannelNumber(tag.ContactIndex); | ||
return ProbeConfiguration.ChannelMap[channel].Index == tag.ContactIndex; | ||
}); | ||
|
||
foreach (var textObj in textObjsToUpdate) | ||
{ | ||
textObj.FontSpec.FontColor = EnabledContactTextColor; | ||
} | ||
} | ||
|
||
internal override string ContactString(int deviceChannelIndex, int index) | ||
{ | ||
return index.ToString(); | ||
} | ||
|
||
internal void EnableElectrodes(List<NeuropixelsV2QuadShankElectrode> electrodes) | ||
{ | ||
ProbeConfiguration.SelectElectrodes(electrodes); | ||
} | ||
} | ||
} |
167 changes: 167 additions & 0 deletions
167
OpenEphys.Onix1.Design/NeuropixelsV2eDialog.Designer.cs
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Windows.Forms; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Partial class to create a GUI for <see cref="ConfigureNeuropixelsV2e"/>. | ||
/// </summary> | ||
public partial class NeuropixelsV2eDialog : Form | ||
{ | ||
readonly IReadOnlyList<NeuropixelsV2eProbeConfigurationDialog> ProbeConfigurations; | ||
|
||
/// <summary> | ||
/// Public <see cref="ConfigureNeuropixelsV2e"/> object that is manipulated by | ||
/// <see cref="NeuropixelsV2eDialog"/>. | ||
/// </summary> | ||
public ConfigureNeuropixelsV2e ConfigureNode { get; set; } | ||
|
||
/// <summary> | ||
/// Initializes a new instance of <see cref="NeuropixelsV2eDialog"/>. | ||
/// </summary> | ||
/// <param name="configureNode">A <see cref="ConfigureNeuropixelsV2e"/> object holding the current configuration settings.</param> | ||
public NeuropixelsV2eDialog(ConfigureNeuropixelsV2e configureNode) | ||
{ | ||
InitializeComponent(); | ||
Shown += FormShown; | ||
|
||
ConfigureNode = new(configureNode); | ||
|
||
ProbeConfigurations = new List<NeuropixelsV2eProbeConfigurationDialog> | ||
{ | ||
new(ConfigureNode.ProbeConfigurationA, ConfigureNode.GainCalibrationFileA) | ||
{ | ||
TopLevel = false, | ||
FormBorderStyle = FormBorderStyle.None, | ||
Dock = DockStyle.Fill, | ||
Parent = this, | ||
Tag = NeuropixelsV2Probe.ProbeA | ||
}, | ||
new(ConfigureNode.ProbeConfigurationB, ConfigureNode.GainCalibrationFileB) | ||
{ | ||
TopLevel = false, | ||
FormBorderStyle = FormBorderStyle.None, | ||
Dock = DockStyle.Fill, | ||
Parent = this, | ||
Tag = NeuropixelsV2Probe.ProbeB | ||
} | ||
}; | ||
|
||
foreach (var channelConfiguration in ProbeConfigurations) | ||
{ | ||
string probeName = GetProbeName((NeuropixelsV2Probe)channelConfiguration.Tag); | ||
|
||
tabControlProbe.TabPages.Add(probeName, probeName); | ||
tabControlProbe.TabPages[probeName].Controls.Add(channelConfiguration); | ||
this.AddMenuItemsFromDialogToFileOption(channelConfiguration, probeName); | ||
} | ||
} | ||
|
||
private string GetProbeName(NeuropixelsV2Probe probe) | ||
{ | ||
return probe switch | ||
{ | ||
NeuropixelsV2Probe.ProbeA => "Probe A", | ||
NeuropixelsV2Probe.ProbeB => "Probe B", | ||
_ => throw new ArgumentException("Invalid probe was specified.") | ||
}; | ||
} | ||
|
||
private int GetProbeIndex(NeuropixelsV2Probe probe) | ||
{ | ||
return probe == NeuropixelsV2Probe.ProbeA ? 0 : 1; | ||
} | ||
|
||
private void FormShown(object sender, EventArgs e) | ||
{ | ||
if (!TopLevel) | ||
{ | ||
splitContainer1.Panel2Collapsed = true; | ||
splitContainer1.Panel2.Hide(); | ||
|
||
menuStrip.Visible = false; | ||
} | ||
|
||
foreach (var channelConfiguration in ProbeConfigurations) | ||
{ | ||
channelConfiguration.Show(); | ||
} | ||
} | ||
|
||
internal void ButtonClick(object sender, EventArgs e) | ||
{ | ||
if (sender is Button button && button != null) | ||
{ | ||
if (button.Name == nameof(buttonOkay)) | ||
{ | ||
SaveVariables(); | ||
|
||
DialogResult = DialogResult.OK; | ||
} | ||
else if (button.Name == nameof(buttonCancel)) | ||
{ | ||
DialogResult = DialogResult.Cancel; | ||
} | ||
} | ||
} | ||
|
||
internal void SaveVariables() | ||
{ | ||
ConfigureNode.ProbeConfigurationA = ProbeConfigurations[GetProbeIndex(NeuropixelsV2Probe.ProbeA)].ProbeConfiguration; | ||
ConfigureNode.ProbeConfigurationB = ProbeConfigurations[GetProbeIndex(NeuropixelsV2Probe.ProbeB)].ProbeConfiguration; | ||
|
||
ConfigureNode.GainCalibrationFileA = ProbeConfigurations[GetProbeIndex(NeuropixelsV2Probe.ProbeA)].textBoxProbeCalibrationFile.Text; | ||
ConfigureNode.GainCalibrationFileB = ProbeConfigurations[GetProbeIndex(NeuropixelsV2Probe.ProbeB)].textBoxProbeCalibrationFile.Text; | ||
} | ||
} | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using System; | ||
using System.ComponentModel; | ||
using System.Windows.Forms; | ||
using Bonsai.Design; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Class that opens a new dialog for a <see cref="ConfigureNeuropixelsV2e"/>. | ||
/// </summary> | ||
public class NeuropixelsV2eEditor : WorkflowComponentEditor | ||
{ | ||
/// <inheritdoc/> | ||
public override bool EditComponent(ITypeDescriptorContext context, object component, IServiceProvider provider, IWin32Window owner) | ||
{ | ||
if (provider != null) | ||
{ | ||
var editorState = (IWorkflowEditorState)provider.GetService(typeof(IWorkflowEditorState)); | ||
if (editorState != null && !editorState.WorkflowRunning && component is ConfigureNeuropixelsV2e configureNeuropixelsV2e) | ||
{ | ||
using var editorDialog = new NeuropixelsV2eDialog(configureNeuropixelsV2e); | ||
|
||
if (editorDialog.ShowDialog() == DialogResult.OK) | ||
{ | ||
configureNeuropixelsV2e.Enable = editorDialog.ConfigureNode.Enable; | ||
configureNeuropixelsV2e.GainCalibrationFileA = editorDialog.ConfigureNode.GainCalibrationFileA; | ||
configureNeuropixelsV2e.GainCalibrationFileB = editorDialog.ConfigureNode.GainCalibrationFileB; | ||
configureNeuropixelsV2e.ProbeConfigurationA = editorDialog.ConfigureNode.ProbeConfigurationA; | ||
configureNeuropixelsV2e.ProbeConfigurationB = editorDialog.ConfigureNode.ProbeConfigurationB; | ||
|
||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
} |
211 changes: 211 additions & 0 deletions
211
OpenEphys.Onix1.Design/NeuropixelsV2eHeadstageDialog.Designer.cs
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
using System.Windows.Forms; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Partial class to create a GUI for <see cref="ConfigureNeuropixelsV2eHeadstage"/>. | ||
/// </summary> | ||
public partial class NeuropixelsV2eHeadstageDialog : Form | ||
{ | ||
/// <summary> | ||
/// A <see cref="NeuropixelsV2eDialog"/> that configures a <see cref="ConfigureNeuropixelsV2e"/>. | ||
/// </summary> | ||
public readonly NeuropixelsV2eDialog DialogNeuropixelsV2e; | ||
|
||
/// <summary> | ||
/// A <see cref="NeuropixelsV2eBno055Dialog"/> that configures a <see cref="ConfigureNeuropixelsV2eBno055"/>. | ||
/// </summary> | ||
public readonly NeuropixelsV2eBno055Dialog DialogBno055; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of a <see cref="NeuropixelsV2eHeadstageDialog"/>. | ||
/// </summary> | ||
/// <param name="configureNeuropixelsV2e">Configuration settings for a <see cref="ConfigureNeuropixelsV2e"/>.</param> | ||
/// <param name="configureBno055">Configuration settings for a <see cref="ConfigureNeuropixelsV2eBno055"/>.</param> | ||
public NeuropixelsV2eHeadstageDialog(ConfigureNeuropixelsV2e configureNeuropixelsV2e, ConfigureNeuropixelsV2eBno055 configureBno055) | ||
{ | ||
InitializeComponent(); | ||
|
||
DialogNeuropixelsV2e = new(configureNeuropixelsV2e) | ||
{ | ||
TopLevel = false, | ||
FormBorderStyle = FormBorderStyle.None, | ||
Dock = DockStyle.Fill, | ||
Parent = this | ||
}; | ||
|
||
panelNeuropixelsV2e.Controls.Add(DialogNeuropixelsV2e); | ||
this.AddMenuItemsFromDialogToFileOption(DialogNeuropixelsV2e, "NeuropixelsV2e"); | ||
DialogNeuropixelsV2e.Show(); | ||
|
||
DialogBno055 = new(configureBno055) | ||
{ | ||
TopLevel = false, | ||
FormBorderStyle = FormBorderStyle.None, | ||
Dock = DockStyle.Fill, | ||
Parent = this | ||
}; | ||
|
||
panelBno055.Controls.Add(DialogBno055); | ||
DialogBno055.Show(); | ||
DialogBno055.Invalidate(); | ||
} | ||
|
||
private void ButtonClick(object sender, System.EventArgs e) | ||
{ | ||
if (sender is Button button && button != null) | ||
{ | ||
if (button.Name == nameof(buttonOkay)) | ||
{ | ||
DialogNeuropixelsV2e.SaveVariables(); | ||
|
||
DialogResult = DialogResult.OK; | ||
} | ||
} | ||
} | ||
} | ||
} |
1,778 changes: 1,778 additions & 0 deletions
1,778
OpenEphys.Onix1.Design/NeuropixelsV2eHeadstageDialog.resx
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using Bonsai.Design; | ||
using System.ComponentModel; | ||
using System.Windows.Forms; | ||
using System; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Class that opens a new dialog for a <see cref="ConfigureNeuropixelsV2eHeadstage"/>. | ||
/// </summary> | ||
public class NeuropixelsV2eHeadstageEditor : WorkflowComponentEditor | ||
{ | ||
/// <inheritdoc/> | ||
public override bool EditComponent(ITypeDescriptorContext context, object component, IServiceProvider provider, IWin32Window owner) | ||
{ | ||
if (provider != null) | ||
{ | ||
var editorState = (IWorkflowEditorState)provider.GetService(typeof(IWorkflowEditorState)); | ||
if (editorState != null && !editorState.WorkflowRunning && component is ConfigureNeuropixelsV2eHeadstage configureHeadstage) | ||
{ | ||
using var editorDialog = new NeuropixelsV2eHeadstageDialog(configureHeadstage.NeuropixelsV2e, configureHeadstage.Bno055); | ||
|
||
if (editorDialog.ShowDialog() == DialogResult.OK) | ||
{ | ||
configureHeadstage.Bno055.Enable = editorDialog.DialogBno055.ConfigureNode.Enable; | ||
|
||
configureHeadstage.NeuropixelsV2e.Enable = editorDialog.DialogNeuropixelsV2e.ConfigureNode.Enable; | ||
configureHeadstage.NeuropixelsV2e.ProbeConfigurationA = editorDialog.DialogNeuropixelsV2e.ConfigureNode.ProbeConfigurationA; | ||
configureHeadstage.NeuropixelsV2e.ProbeConfigurationB = editorDialog.DialogNeuropixelsV2e.ConfigureNode.ProbeConfigurationB; | ||
configureHeadstage.NeuropixelsV2e.GainCalibrationFileA = editorDialog.DialogNeuropixelsV2e.ConfigureNode.GainCalibrationFileA; | ||
configureHeadstage.NeuropixelsV2e.GainCalibrationFileB = editorDialog.DialogNeuropixelsV2e.ConfigureNode.GainCalibrationFileB; | ||
|
||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
} |
435 changes: 435 additions & 0 deletions
435
OpenEphys.Onix1.Design/NeuropixelsV2eProbeConfigurationDialog.Designer.cs
Large diffs are not rendered by default.
Oops, something went wrong.
619 changes: 619 additions & 0 deletions
619
OpenEphys.Onix1.Design/NeuropixelsV2eProbeConfigurationDialog.cs
Large diffs are not rendered by default.
Oops, something went wrong.
1,796 changes: 1,796 additions & 0 deletions
1,796
OpenEphys.Onix1.Design/NeuropixelsV2eProbeConfigurationDialog.resx
Large diffs are not rendered by default.
Oops, something went wrong.
57 changes: 57 additions & 0 deletions
57
OpenEphys.Onix1.Design/NeuropixelsV2eProbeConfigurationEditor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using System; | ||
using System.ComponentModel; | ||
using System.Drawing.Design; | ||
using System.Windows.Forms; | ||
using System.Windows.Forms.Design; | ||
using Bonsai.Design; | ||
|
||
namespace OpenEphys.Onix1.Design | ||
{ | ||
/// <summary> | ||
/// Class that opens a new dialog for a <see cref="NeuropixelsV2QuadShankProbeConfiguration"/>. | ||
/// </summary> | ||
public class NeuropixelsV2eProbeConfigurationEditor : UITypeEditor | ||
{ | ||
/// <inheritdoc/> | ||
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) | ||
{ | ||
return UITypeEditorEditStyle.Modal; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) | ||
{ | ||
if (provider != null) | ||
{ | ||
var editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService)); | ||
var editorState = (IWorkflowEditorState)provider.GetService(typeof(IWorkflowEditorState)); | ||
|
||
if (editorService != null && editorState != null && !editorState.WorkflowRunning && | ||
value is NeuropixelsV2QuadShankProbeConfiguration configuration) | ||
{ | ||
var instance = (ConfigureNeuropixelsV2e)context.Instance; | ||
|
||
var calibrationFile = configuration.Probe == NeuropixelsV2Probe.ProbeA ? instance.GainCalibrationFileA : instance.GainCalibrationFileB; | ||
|
||
using var editorDialog = new NeuropixelsV2eProbeConfigurationDialog(configuration, calibrationFile); | ||
|
||
if (editorDialog.ShowDialog() == DialogResult.OK) | ||
{ | ||
if (configuration.Probe == NeuropixelsV2Probe.ProbeA) | ||
{ | ||
instance.GainCalibrationFileA = editorDialog.textBoxProbeCalibrationFile.Text; | ||
} | ||
else | ||
{ | ||
instance.GainCalibrationFileB = editorDialog.textBoxProbeCalibrationFile.Text; | ||
} | ||
|
||
return editorDialog.ProbeConfiguration; | ||
} | ||
} | ||
} | ||
|
||
return base.EditValue(context, provider, value); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<root> | ||
<!-- | ||
Microsoft ResX Schema | ||
Version 2.0 | ||
The primary goals of this format is to allow a simple XML format | ||
that is mostly human readable. The generation and parsing of the | ||
various data types are done through the TypeConverter classes | ||
associated with the data types. | ||
Example: | ||
... ado.net/XML headers & schema ... | ||
<resheader name="resmimetype">text/microsoft-resx</resheader> | ||
<resheader name="version">2.0</resheader> | ||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | ||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | ||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | ||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | ||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | ||
<value>[base64 mime encoded serialized .NET Framework object]</value> | ||
</data> | ||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | ||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | ||
<comment>This is a comment</comment> | ||
</data> | ||
There are any number of "resheader" rows that contain simple | ||
name/value pairs. | ||
Each data row contains a name, and value. The row also contains a | ||
type or mimetype. Type corresponds to a .NET class that support | ||
text/value conversion through the TypeConverter architecture. | ||
Classes that don't support this are serialized and stored with the | ||
mimetype set. | ||
The mimetype is used for serialized objects, and tells the | ||
ResXResourceReader how to depersist the object. This is currently not | ||
extensible. For a given mimetype the value must be set accordingly: | ||
Note - application/x-microsoft.net.object.binary.base64 is the format | ||
that the ResXResourceWriter will generate, however the reader can | ||
read any of the formats listed below. | ||
mimetype: application/x-microsoft.net.object.binary.base64 | ||
value : The object must be serialized with | ||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | ||
: and then encoded with base64 encoding. | ||
mimetype: application/x-microsoft.net.object.soap.base64 | ||
value : The object must be serialized with | ||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter | ||
: and then encoded with base64 encoding. | ||
mimetype: application/x-microsoft.net.object.bytearray.base64 | ||
value : The object must be serialized into a byte array | ||
: using a System.ComponentModel.TypeConverter | ||
: and then encoded with base64 encoding. | ||
--> | ||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | ||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | ||
<xsd:element name="root" msdata:IsDataSet="true"> | ||
<xsd:complexType> | ||
<xsd:choice maxOccurs="unbounded"> | ||
<xsd:element name="metadata"> | ||
<xsd:complexType> | ||
<xsd:sequence> | ||
<xsd:element name="value" type="xsd:string" minOccurs="0" /> | ||
</xsd:sequence> | ||
<xsd:attribute name="name" use="required" type="xsd:string" /> | ||
<xsd:attribute name="type" type="xsd:string" /> | ||
<xsd:attribute name="mimetype" type="xsd:string" /> | ||
<xsd:attribute ref="xml:space" /> | ||
</xsd:complexType> | ||
</xsd:element> | ||
<xsd:element name="assembly"> | ||
<xsd:complexType> | ||
<xsd:attribute name="alias" type="xsd:string" /> | ||
<xsd:attribute name="name" type="xsd:string" /> | ||
</xsd:complexType> | ||
</xsd:element> | ||
<xsd:element name="data"> | ||
<xsd:complexType> | ||
<xsd:sequence> | ||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | ||
</xsd:sequence> | ||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | ||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | ||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | ||
<xsd:attribute ref="xml:space" /> | ||
</xsd:complexType> | ||
</xsd:element> | ||
<xsd:element name="resheader"> | ||
<xsd:complexType> | ||
<xsd:sequence> | ||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||
</xsd:sequence> | ||
<xsd:attribute name="name" type="xsd:string" use="required" /> | ||
</xsd:complexType> | ||
</xsd:element> | ||
</xsd:choice> | ||
</xsd:complexType> | ||
</xsd:element> | ||
</xsd:schema> | ||
<resheader name="resmimetype"> | ||
<value>text/microsoft-resx</value> | ||
</resheader> | ||
<resheader name="version"> | ||
<value>2.0</value> | ||
</resheader> | ||
<resheader name="reader"> | ||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||
</resheader> | ||
<resheader name="writer"> | ||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||
</resheader> | ||
</root> |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using System.Drawing; | ||
using System.Xml.Serialization; | ||
|
||
namespace OpenEphys.Onix1 | ||
{ | ||
/// <summary> | ||
/// Abstract base class for describing a single electrode. | ||
/// </summary> | ||
public abstract class Electrode | ||
{ | ||
/// <summary> | ||
/// Gets the index of the electrode (the electrode "number") within | ||
/// the context of the entire probe. | ||
/// </summary> | ||
[XmlIgnore] | ||
public int Index { get; internal set; } | ||
|
||
/// <summary> | ||
/// Gets the shank this electrode belongs to. | ||
/// </summary> | ||
[XmlIgnore] | ||
public int Shank { get; internal set; } | ||
|
||
/// <summary> | ||
/// Gets the index of the electrode within the context of <see cref="Shank"/>. | ||
/// </summary> | ||
[XmlIgnore] | ||
public int IntraShankElectrodeIndex { get; internal set; } | ||
|
||
/// <summary> | ||
/// Gets the electrical channel that this electrode is mapped to. | ||
/// </summary> | ||
[XmlIgnore] | ||
public int Channel { get; internal set; } | ||
|
||
/// <summary> | ||
/// Gets the location of the electrode in two-dimensional space in arbitrary units. | ||
/// </summary> | ||
[XmlIgnore] | ||
public PointF Position { get; internal set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.