From 2040bb65ec9a3498b779305d66570af7609cbbd5 Mon Sep 17 00:00:00 2001 From: bparks13 Date: Thu, 18 Sep 2025 16:52:16 -0400 Subject: [PATCH 1/3] Correctly handle negative minimum values --- OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs b/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs index 09fb44a9..5adf6540 100644 --- a/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs +++ b/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs @@ -1124,7 +1124,7 @@ public void MoveToVerticalPosition(float relativePosition) var minY = GetProbeBottom(zedGraphChannels.GraphPane.GraphObjList); var maxY = GetProbeTop(zedGraphChannels.GraphPane.GraphObjList); - var newMinY = (maxY - minY - currentRange) * relativePosition; + var newMinY = (maxY - minY - currentRange) * relativePosition + minY; zedGraphChannels.GraphPane.YAxis.Scale.Min = newMinY; zedGraphChannels.GraphPane.YAxis.Scale.Max = newMinY + currentRange; From 3a344cd10296b2b068378404dc604d4dc203ef1e Mon Sep 17 00:00:00 2001 From: bparks13 Date: Thu, 18 Sep 2025 16:57:24 -0400 Subject: [PATCH 2/3] Update method name to better describe what it does --- OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs | 10 +++++----- .../NeuropixelsV1ChannelConfigurationDialog.cs | 4 ++-- .../NeuropixelsV2eChannelConfigurationDialog.cs | 4 ++-- .../Rhs2116ChannelConfigurationDialog.cs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs b/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs index 5adf6540..57350e74 100644 --- a/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs +++ b/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs @@ -35,7 +35,7 @@ public ChannelConfigurationDialog(ProbeGroup probeGroup) if (probeGroup == null) { - LoadDefaultChannelLayout(); + LoadDefaultProbeGroup(); } else { @@ -68,11 +68,11 @@ public ChannelConfigurationDialog(ProbeGroup probeGroup) /// /// /// Returns an object that inherits from - internal abstract ProbeGroup DefaultChannelLayout(); + internal abstract ProbeGroup DefaultProbeGroup(); - internal virtual void LoadDefaultChannelLayout() + internal virtual void LoadDefaultProbeGroup() { - ProbeGroup = DefaultChannelLayout(); + ProbeGroup = DefaultProbeGroup(); } /// @@ -1081,7 +1081,7 @@ private void MenuItemOpenFile(object sender, EventArgs e) private void MenuItemLoadDefaultConfig(object sender, EventArgs e) { - LoadDefaultChannelLayout(); + LoadDefaultProbeGroup(); DrawProbeGroup(); UpdateFontSize(); RefreshZedGraph(); diff --git a/OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs b/OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs index 64655cd4..c65b99f9 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs +++ b/OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs @@ -49,12 +49,12 @@ public NeuropixelsV1ChannelConfigurationDialog(NeuropixelsV1ProbeConfiguration p RefreshZedGraph(); } - internal override ProbeGroup DefaultChannelLayout() + internal override ProbeGroup DefaultProbeGroup() { return new NeuropixelsV1eProbeGroup(); } - internal override void LoadDefaultChannelLayout() + internal override void LoadDefaultProbeGroup() { ProbeConfiguration = new(ProbeConfiguration.SpikeAmplifierGain, ProbeConfiguration.LfpAmplifierGain, ProbeConfiguration.Reference, ProbeConfiguration.SpikeFilter); ProbeGroup = ProbeConfiguration.ProbeGroup; diff --git a/OpenEphys.Onix1.Design/NeuropixelsV2eChannelConfigurationDialog.cs b/OpenEphys.Onix1.Design/NeuropixelsV2eChannelConfigurationDialog.cs index b9fdceaa..a6ec156f 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV2eChannelConfigurationDialog.cs +++ b/OpenEphys.Onix1.Design/NeuropixelsV2eChannelConfigurationDialog.cs @@ -44,12 +44,12 @@ public NeuropixelsV2eChannelConfigurationDialog(NeuropixelsV2QuadShankProbeConfi RefreshZedGraph(); } - internal override ProbeGroup DefaultChannelLayout() + internal override ProbeGroup DefaultProbeGroup() { return new NeuropixelsV2eProbeGroup(); } - internal override void LoadDefaultChannelLayout() + internal override void LoadDefaultProbeGroup() { ProbeConfiguration = new(ProbeConfiguration.Probe, ProbeConfiguration.Reference); ProbeGroup = ProbeConfiguration.ProbeGroup; diff --git a/OpenEphys.Onix1.Design/Rhs2116ChannelConfigurationDialog.cs b/OpenEphys.Onix1.Design/Rhs2116ChannelConfigurationDialog.cs index a3d72399..49d2785d 100644 --- a/OpenEphys.Onix1.Design/Rhs2116ChannelConfigurationDialog.cs +++ b/OpenEphys.Onix1.Design/Rhs2116ChannelConfigurationDialog.cs @@ -36,7 +36,7 @@ public Rhs2116ChannelConfigurationDialog(Rhs2116ProbeGroup probeGroup) RefreshZedGraph(); } - internal override ProbeGroup DefaultChannelLayout() + internal override ProbeGroup DefaultProbeGroup() { return new Rhs2116ProbeGroup(); } From b222087d9416853d8b138e59e7aaa145b5d4dc94 Mon Sep 17 00:00:00 2001 From: bparks13 Date: Thu, 18 Sep 2025 17:30:12 -0400 Subject: [PATCH 3/3] Add support for Neuropixels 1.0 UHD probes --- .../ChannelConfigurationDialog.cs | 36 +- OpenEphys.Onix1.Design/DesignHelper.cs | 17 + ...NeuropixelsV1ChannelConfigurationDialog.cs | 47 +- ...xelsV1ProbeConfigurationDialog.Designer.cs | 65 +- .../NeuropixelsV1ProbeConfigurationDialog.cs | 353 +- ...NeuropixelsV1ProbeConfigurationDialog.resx | 3 + OpenEphys.Onix1/NeuropixelsV1.cs | 3 +- OpenEphys.Onix1/NeuropixelsV1Electrode.cs | 6191 ++++++++++++++++- .../NeuropixelsV1ProbeConfiguration.cs | 145 +- OpenEphys.Onix1/NeuropixelsV1eProbeGroup.cs | 203 +- .../NeuropixelsV1eRegisterContext.cs | 1 - 11 files changed, 6908 insertions(+), 156 deletions(-) diff --git a/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs b/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs index 57350e74..0ee8e7d2 100644 --- a/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs +++ b/OpenEphys.Onix1.Design/ChannelConfigurationDialog.cs @@ -22,7 +22,7 @@ public abstract partial class ChannelConfigurationDialog : Form internal readonly List ReferenceContacts = new(); - internal readonly bool[] SelectedContacts = null; + internal bool[] SelectedContacts { get; private set; } = null; /// /// Constructs the dialog window using the given probe group, and plots all contacts after loading. @@ -73,6 +73,7 @@ public ChannelConfigurationDialog(ProbeGroup probeGroup) internal virtual void LoadDefaultProbeGroup() { ProbeGroup = DefaultProbeGroup(); + SelectedContacts = new bool[ProbeGroup.NumberOfContacts]; } /// @@ -432,13 +433,26 @@ internal virtual bool OpenFile() where T : ProbeGroup return false; } - if (ProbeGroup.NumberOfContacts == newConfiguration.NumberOfContacts) + bool skipContactNumberMismatchCheck = false; + + if (ProbeGroup.Probes.First().Annotations.Name != newConfiguration.Probes.First().Annotations.Name) + { + var result = MessageBox.Show($"There is a mismatch between the current probe name ({ProbeGroup.Probes.First().Annotations.Name})" + + $" and the new probe name ({newConfiguration.Probes.First().Annotations.Name}). Continue loading?", "Probe Name Mismatch", MessageBoxButtons.YesNo); + + if (result == DialogResult.No) + return false; + + skipContactNumberMismatchCheck = true; // NB: If the probe names do not match, skip the check to see if the number of contacts match. + // Example: loading a Neuropixels 1.0 probe, but the current probe is a 1.0 UHD probe. + } + + if (skipContactNumberMismatchCheck || ProbeGroup.NumberOfContacts == newConfiguration.NumberOfContacts) { newConfiguration.Validate(); ProbeGroup = newConfiguration; - DrawProbeGroup(); - RefreshZedGraph(); + SelectedContacts = new bool[ProbeGroup.NumberOfContacts]; return true; } @@ -1155,9 +1169,13 @@ internal void RefreshZedGraph() PointD clickStart = new(0.0, 0.0); + bool selectElectrodes = true; + + internal void SetSelectElectrodesStatus(bool status) => selectElectrodes = status; + private bool MouseDownEvent(ZedGraphControl sender, MouseEventArgs e) { - if (e.Button == MouseButtons.Left) + if (selectElectrodes && e.Button == MouseButtons.Left) { clickStart = TransformPixelsToCoordinates(e.Location, sender.GraphPane); } @@ -1171,6 +1189,12 @@ private bool MouseMoveEvent(ZedGraphControl sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { + if (!selectElectrodes) + { + sender.Cursor = Cursors.Arrow; + return true; + } + sender.Cursor = Cursors.Cross; if (clickStart.X == default && clickStart.Y == default) @@ -1232,7 +1256,7 @@ private bool MouseUpEvent(ZedGraphControl sender, MouseEventArgs e) { sender.Cursor = Cursors.Arrow; - if (e.Button == MouseButtons.Left) + if (selectElectrodes && e.Button == MouseButtons.Left) { if (sender.GraphPane.GraphObjList[SelectionAreaTag] is BoxObj selectionArea && selectionArea != null && ProbeGroup != null) { diff --git a/OpenEphys.Onix1.Design/DesignHelper.cs b/OpenEphys.Onix1.Design/DesignHelper.cs index e87e3ba3..c27b95e1 100644 --- a/OpenEphys.Onix1.Design/DesignHelper.cs +++ b/OpenEphys.Onix1.Design/DesignHelper.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Linq; +using System.Reflection; using System.Windows.Forms; using Newtonsoft.Json; @@ -182,5 +184,20 @@ public static void AddMenuItemsFromDialogToFileOption(this Form thisForm, Form c thisFileMenuItem.DropDownItems.Add(newChildMenuItems); } } + + internal static string GetEnumDescription(this Enum value) + { + FieldInfo field = value.GetType().GetField(value.ToString()); + if (field != null) + { + DescriptionAttribute attribute = field.GetCustomAttribute(); + if (attribute != null) + { + return attribute.Description; + } + } + + return value.ToString(); + } } } diff --git a/OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs b/OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs index c65b99f9..2a89f3ae 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs +++ b/OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Drawing; using System.Linq; using System.Windows.Forms; @@ -16,7 +17,7 @@ public partial class NeuropixelsV1ChannelConfigurationDialog : ChannelConfigurat internal event EventHandler OnZoom; internal event EventHandler OnFileLoad; - readonly IReadOnlyList ReferenceContactsList = new List { 191, 575, 959 }; + readonly IReadOnlyList ReferenceContactsNp1 = new List { 191, 575, 959 }; /// /// Public object that is modified by @@ -36,12 +37,12 @@ public NeuropixelsV1ChannelConfigurationDialog(NeuropixelsV1ProbeConfiguration p zedGraphChannels.ZoomStepFraction = 0.5; - ReferenceContacts.AddRange(ReferenceContactsList); + UpdateReferenceContacts(probeConfiguration.ProbeType); ProbeConfiguration = probeConfiguration; - ZoomInBoundaryX = 400; - ZoomInBoundaryY = 400; + ZoomInBoundaryX = 100; + ZoomInBoundaryY = 100; HighlightEnabledContacts(); UpdateContactLabels(); @@ -49,15 +50,35 @@ public NeuropixelsV1ChannelConfigurationDialog(NeuropixelsV1ProbeConfiguration p RefreshZedGraph(); } + void UpdateReferenceContacts(NeuropixelsV1ProbeType probeType) + { + ReferenceContacts.Clear(); + ReferenceContacts.AddRange(GetReferenceContacts(probeType)); + } + + List GetReferenceContacts(NeuropixelsV1ProbeType probeType) => probeType switch + { + NeuropixelsV1ProbeType.NP1 => ReferenceContactsNp1.ToList(), + NeuropixelsV1ProbeType.UHD => new List(), + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) + }; + internal override ProbeGroup DefaultProbeGroup() { - return new NeuropixelsV1eProbeGroup(); + return new NeuropixelsV1eProbeGroup(ProbeConfiguration.ProbeType); } internal override void LoadDefaultProbeGroup() { - ProbeConfiguration = new(ProbeConfiguration.SpikeAmplifierGain, ProbeConfiguration.LfpAmplifierGain, ProbeConfiguration.Reference, ProbeConfiguration.SpikeFilter); - ProbeGroup = ProbeConfiguration.ProbeGroup; + base.LoadDefaultProbeGroup(); + ProbeConfiguration = new((NeuropixelsV1eProbeGroup)ProbeGroup, + ProbeConfiguration.ProbeType, + ProbeConfiguration.SpikeAmplifierGain, + ProbeConfiguration.LfpAmplifierGain, + ProbeConfiguration.Reference, + ProbeConfiguration.SpikeFilter); + + UpdateReferenceContacts(ProbeConfiguration.ProbeType); OnFileOpenHandler(); } @@ -66,9 +87,8 @@ internal override bool OpenFile() { if (base.OpenFile()) { - ProbeConfiguration = new((NeuropixelsV1eProbeGroup)ProbeGroup, ProbeConfiguration.SpikeAmplifierGain, ProbeConfiguration.LfpAmplifierGain, ProbeConfiguration.Reference, ProbeConfiguration.SpikeFilter); - ProbeGroup = ProbeConfiguration.ProbeGroup; - + ProbeConfiguration = new((NeuropixelsV1eProbeGroup)ProbeGroup, ProbeConfiguration.ProbeType, ProbeConfiguration.SpikeAmplifierGain, ProbeConfiguration.LfpAmplifierGain, ProbeConfiguration.Reference, ProbeConfiguration.SpikeFilter); + UpdateReferenceContacts(ProbeConfiguration.ProbeType); OnFileOpenHandler(); return true; @@ -175,13 +195,14 @@ internal override void DrawScale() countMajorTicks++; } - var curve = zedGraphChannels.GraphPane.AddCurve(ScalePointsTag, pointList, Color.Black, SymbolType.None); + var curve = zedGraphChannels.GraphPane.AddCurve("", pointList, Color.Black, SymbolType.None); const float scaleBarWidth = 1; curve.Line.Width = scaleBarWidth; curve.Label.IsVisible = false; curve.Symbol.IsVisible = false; + curve.Tag = ScalePointsTag; } internal override void HighlightEnabledContacts() @@ -202,7 +223,7 @@ internal override void HighlightEnabledContacts() var contactsToEnable = contactObjects.Where(c => { var tag = c.Tag as ContactTag; - var channel = NeuropixelsV1Electrode.GetChannelNumber(tag.ContactIndex); + var channel = NeuropixelsV1Electrode.GetChannelNumber(tag.ContactIndex, ProbeConfiguration.ProbeType); return ProbeConfiguration.ChannelMap[channel].Index == tag.ContactIndex; }); @@ -232,7 +253,7 @@ internal override void UpdateContactLabels() textObjsToUpdate = textObjs.Where(c => { var tag = c.Tag as ContactTag; - var channel = NeuropixelsV1Electrode.GetChannelNumber(tag.ContactIndex); + var channel = NeuropixelsV1Electrode.GetChannelNumber(tag.ContactIndex, ProbeConfiguration.ProbeType); return ProbeConfiguration.ChannelMap[channel].Index == tag.ContactIndex; }); diff --git a/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.Designer.cs b/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.Designer.cs index 00cce85b..e0f0f84c 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.Designer.cs +++ b/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.Designer.cs @@ -41,6 +41,7 @@ private void InitializeComponent() System.Windows.Forms.Label lfpGain; System.Windows.Forms.Label apGain; System.Windows.Forms.Label invertPolarity; + System.Windows.Forms.Label labelProbeType; System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NeuropixelsV1ProbeConfigurationDialog)); this.toolStripLabelAdcCalibrationSN = new System.Windows.Forms.ToolStripStatusLabel(); this.toolStripLabelGainCalibrationSn = new System.Windows.Forms.ToolStripStatusLabel(); @@ -74,6 +75,7 @@ private void InitializeComponent() this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.buttonCancel = new System.Windows.Forms.Button(); this.buttonOkay = new System.Windows.Forms.Button(); + this.comboBoxProbeType = new System.Windows.Forms.ComboBox(); label1 = new System.Windows.Forms.Label(); label3 = new System.Windows.Forms.Label(); label4 = new System.Windows.Forms.Label(); @@ -86,6 +88,7 @@ private void InitializeComponent() lfpGain = new System.Windows.Forms.Label(); apGain = new System.Windows.Forms.Label(); invertPolarity = new System.Windows.Forms.Label(); + labelProbeType = new System.Windows.Forms.Label(); this.statusStrip1.SuspendLayout(); this.menuStrip.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout(); @@ -121,7 +124,7 @@ private void InitializeComponent() // label4 // label4.AutoSize = true; - label4.Location = new System.Drawing.Point(13, 277); + label4.Location = new System.Drawing.Point(13, 306); label4.Name = "label4"; label4.Size = new System.Drawing.Size(71, 16); label4.TabIndex = 40; @@ -130,7 +133,7 @@ private void InitializeComponent() // label2 // label2.AutoSize = true; - label2.Location = new System.Drawing.Point(13, 210); + label2.Location = new System.Drawing.Point(13, 239); label2.Name = "label2"; label2.Size = new System.Drawing.Size(71, 16); label2.TabIndex = 38; @@ -139,7 +142,7 @@ private void InitializeComponent() // labelPresets // labelPresets.AutoSize = true; - labelPresets.Location = new System.Drawing.Point(13, 405); + labelPresets.Location = new System.Drawing.Point(13, 434); labelPresets.Name = "labelPresets"; labelPresets.Size = new System.Drawing.Size(56, 32); labelPresets.TabIndex = 25; @@ -168,7 +171,7 @@ private void InitializeComponent() // spikeFilter // spikeFilter.AutoSize = true; - spikeFilter.Location = new System.Drawing.Point(13, 310); + spikeFilter.Location = new System.Drawing.Point(13, 339); spikeFilter.Name = "spikeFilter"; spikeFilter.Size = new System.Drawing.Size(77, 16); spikeFilter.TabIndex = 6; @@ -177,7 +180,7 @@ private void InitializeComponent() // Reference // Reference.AutoSize = true; - Reference.Location = new System.Drawing.Point(13, 378); + Reference.Location = new System.Drawing.Point(13, 407); Reference.Name = "Reference"; Reference.Size = new System.Drawing.Size(73, 16); Reference.TabIndex = 4; @@ -186,7 +189,7 @@ private void InitializeComponent() // lfpGain // lfpGain.AutoSize = true; - lfpGain.Location = new System.Drawing.Point(13, 244); + lfpGain.Location = new System.Drawing.Point(13, 273); lfpGain.Name = "lfpGain"; lfpGain.Size = new System.Drawing.Size(65, 16); lfpGain.TabIndex = 2; @@ -195,7 +198,7 @@ private void InitializeComponent() // apGain // apGain.AutoSize = true; - apGain.Location = new System.Drawing.Point(13, 178); + apGain.Location = new System.Drawing.Point(13, 207); apGain.Name = "apGain"; apGain.Size = new System.Drawing.Size(59, 16); apGain.TabIndex = 0; @@ -204,7 +207,7 @@ private void InitializeComponent() // invertPolarity // invertPolarity.AutoSize = true; - invertPolarity.Location = new System.Drawing.Point(13, 332); + invertPolarity.Location = new System.Drawing.Point(13, 361); invertPolarity.Name = "invertPolarity"; invertPolarity.Size = new System.Drawing.Size(55, 32); invertPolarity.TabIndex = 42; @@ -338,6 +341,8 @@ private void InitializeComponent() // panelOptions // this.panelOptions.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.panelOptions.Controls.Add(this.comboBoxProbeType); + this.panelOptions.Controls.Add(labelProbeType); this.panelOptions.Controls.Add(this.checkBoxInvertPolarity); this.panelOptions.Controls.Add(invertPolarity); this.panelOptions.Controls.Add(this.textBoxLfpCorrection); @@ -374,7 +379,7 @@ private void InitializeComponent() // checkBoxInvertPolarity // this.checkBoxInvertPolarity.AutoSize = true; - this.checkBoxInvertPolarity.Location = new System.Drawing.Point(101, 338); + this.checkBoxInvertPolarity.Location = new System.Drawing.Point(101, 367); this.checkBoxInvertPolarity.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.checkBoxInvertPolarity.Name = "checkBoxInvertPolarity"; this.checkBoxInvertPolarity.Size = new System.Drawing.Size(77, 20); @@ -386,7 +391,7 @@ private void InitializeComponent() // this.textBoxLfpCorrection.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBoxLfpCorrection.Location = new System.Drawing.Point(101, 274); + this.textBoxLfpCorrection.Location = new System.Drawing.Point(101, 303); this.textBoxLfpCorrection.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.textBoxLfpCorrection.Name = "textBoxLfpCorrection"; this.textBoxLfpCorrection.ReadOnly = true; @@ -398,7 +403,7 @@ private void InitializeComponent() // this.textBoxApCorrection.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBoxApCorrection.Location = new System.Drawing.Point(101, 207); + this.textBoxApCorrection.Location = new System.Drawing.Point(101, 236); this.textBoxApCorrection.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.textBoxApCorrection.Name = "textBoxApCorrection"; this.textBoxApCorrection.ReadOnly = true; @@ -448,7 +453,7 @@ private void InitializeComponent() // this.buttonEnableContacts.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.buttonEnableContacts.Location = new System.Drawing.Point(13, 464); + this.buttonEnableContacts.Location = new System.Drawing.Point(13, 493); this.buttonEnableContacts.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.buttonEnableContacts.Name = "buttonEnableContacts"; this.buttonEnableContacts.Size = new System.Drawing.Size(299, 44); @@ -461,7 +466,7 @@ private void InitializeComponent() // this.buttonClearSelections.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.buttonClearSelections.Location = new System.Drawing.Point(13, 512); + this.buttonClearSelections.Location = new System.Drawing.Point(13, 541); this.buttonClearSelections.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.buttonClearSelections.Name = "buttonClearSelections"; this.buttonClearSelections.Size = new System.Drawing.Size(299, 44); @@ -476,7 +481,7 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.comboBoxChannelPresets.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBoxChannelPresets.FormattingEnabled = true; - this.comboBoxChannelPresets.Location = new System.Drawing.Point(101, 411); + this.comboBoxChannelPresets.Location = new System.Drawing.Point(101, 440); this.comboBoxChannelPresets.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.comboBoxChannelPresets.Name = "comboBoxChannelPresets"; this.comboBoxChannelPresets.Size = new System.Drawing.Size(210, 24); @@ -486,7 +491,7 @@ private void InitializeComponent() // this.buttonResetZoom.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.buttonResetZoom.Location = new System.Drawing.Point(13, 562); + this.buttonResetZoom.Location = new System.Drawing.Point(13, 591); this.buttonResetZoom.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.buttonResetZoom.Name = "buttonResetZoom"; this.buttonResetZoom.Size = new System.Drawing.Size(299, 44); @@ -498,7 +503,7 @@ private void InitializeComponent() // checkBoxSpikeFilter // this.checkBoxSpikeFilter.AutoSize = true; - this.checkBoxSpikeFilter.Location = new System.Drawing.Point(101, 309); + this.checkBoxSpikeFilter.Location = new System.Drawing.Point(101, 338); this.checkBoxSpikeFilter.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.checkBoxSpikeFilter.Name = "checkBoxSpikeFilter"; this.checkBoxSpikeFilter.Size = new System.Drawing.Size(77, 20); @@ -540,7 +545,7 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.comboBoxReference.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBoxReference.FormattingEnabled = true; - this.comboBoxReference.Location = new System.Drawing.Point(101, 373); + this.comboBoxReference.Location = new System.Drawing.Point(101, 402); this.comboBoxReference.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.comboBoxReference.Name = "comboBoxReference"; this.comboBoxReference.Size = new System.Drawing.Size(210, 24); @@ -552,7 +557,7 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.comboBoxLfpGain.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBoxLfpGain.FormattingEnabled = true; - this.comboBoxLfpGain.Location = new System.Drawing.Point(101, 240); + this.comboBoxLfpGain.Location = new System.Drawing.Point(101, 269); this.comboBoxLfpGain.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.comboBoxLfpGain.Name = "comboBoxLfpGain"; this.comboBoxLfpGain.Size = new System.Drawing.Size(210, 24); @@ -564,7 +569,7 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.comboBoxApGain.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBoxApGain.FormattingEnabled = true; - this.comboBoxApGain.Location = new System.Drawing.Point(101, 174); + this.comboBoxApGain.Location = new System.Drawing.Point(101, 203); this.comboBoxApGain.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.comboBoxApGain.Name = "comboBoxApGain"; this.comboBoxApGain.Size = new System.Drawing.Size(210, 24); @@ -605,6 +610,27 @@ private void InitializeComponent() this.buttonOkay.Text = "OK"; this.buttonOkay.UseVisualStyleBackColor = true; // + // comboBoxProbeType + // + this.comboBoxProbeType.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.comboBoxProbeType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxProbeType.FormattingEnabled = true; + this.comboBoxProbeType.Location = new System.Drawing.Point(101, 170); + this.comboBoxProbeType.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.comboBoxProbeType.Name = "comboBoxProbeType"; + this.comboBoxProbeType.Size = new System.Drawing.Size(210, 24); + this.comboBoxProbeType.TabIndex = 44; + // + // labelProbeType + // + labelProbeType.AutoSize = true; + labelProbeType.Location = new System.Drawing.Point(13, 174); + labelProbeType.Name = "labelProbeType"; + labelProbeType.Size = new System.Drawing.Size(82, 16); + labelProbeType.TabIndex = 43; + labelProbeType.Text = "Probe Type:"; + // // NeuropixelsV1ProbeConfigurationDialog // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); @@ -669,5 +695,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripStatusLabel toolStripLabelAdcCalibrationSN; private System.Windows.Forms.ToolStripStatusLabel toolStripLabelGainCalibrationSn; private System.Windows.Forms.CheckBox checkBoxInvertPolarity; + private System.Windows.Forms.ComboBox comboBoxProbeType; } } diff --git a/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.cs b/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.cs index 2eb1e07f..b855c210 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.cs +++ b/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Drawing; using System.IO; using System.Linq; @@ -15,7 +16,7 @@ public partial class NeuropixelsV1ProbeConfigurationDialog : Form private NeuropixelsV1Adc[] Adcs = null; - private enum ChannelPreset + enum ChannelPresetNp1 { BankA, BankB, @@ -25,17 +26,34 @@ private enum ChannelPreset None } + enum ChannelPresetUhd + { + BankA, + BankB, + BankC, + BankD, + BankE, + BankF, + BankG, + BankH, + BankI, + BankJ, + BankK, + BankL, + BankM, + BankN, + BankO, + BankP, + None + } + /// - /// Public interface that is manipulated by - /// . + /// Gets the object. /// - /// - /// When a is passed to - /// , it is copied and stored in this - /// variable so that any modifications made to configuration settings can be easily reversed - /// by not copying the new settings back to the original instance. - /// - public NeuropixelsV1ProbeConfiguration ProbeConfiguration { get; set; } + public NeuropixelsV1ProbeConfiguration ProbeConfiguration + { + get => ChannelConfiguration.ProbeConfiguration; + } /// public bool InvertPolarity { get; set; } @@ -52,9 +70,7 @@ public NeuropixelsV1ProbeConfigurationDialog(NeuropixelsV1ProbeConfiguration pro InitializeComponent(); Shown += FormShown; - ProbeConfiguration = new(probeConfiguration); - - ChannelConfiguration = new(ProbeConfiguration) + ChannelConfiguration = new(probeConfiguration) { TopLevel = false, FormBorderStyle = FormBorderStyle.None, @@ -70,6 +86,10 @@ public NeuropixelsV1ProbeConfigurationDialog(NeuropixelsV1ProbeConfiguration pro ChannelConfiguration.OnZoom += UpdateTrackBarLocation; ChannelConfiguration.OnFileLoad += OnFileLoadEvent; + comboBoxProbeType.DataSource = Enum.GetValues(typeof(NeuropixelsV1ProbeType)); + comboBoxProbeType.SelectedItem = ProbeConfiguration.ProbeType; + comboBoxProbeType.SelectedIndexChanged += ProbeTypeIndexChanged; + comboBoxApGain.DataSource = Enum.GetValues(typeof(NeuropixelsV1Gain)); comboBoxApGain.SelectedItem = ProbeConfiguration.SpikeAmplifierGain; comboBoxApGain.SelectedIndexChanged += SpikeAmplifierGainIndexChanged; @@ -92,13 +112,72 @@ public NeuropixelsV1ProbeConfigurationDialog(NeuropixelsV1ProbeConfiguration pro textBoxGainCalibrationFile.Text = gainCalibrationFile; - comboBoxChannelPresets.DataSource = Enum.GetValues(typeof(ChannelPreset)); - CheckForExistingChannelPreset(); + comboBoxChannelPresets.DataSource = GetComboBoxChannelPresets(ProbeConfiguration.ProbeType); + CheckForExistingChannelPreset(ProbeConfiguration.ProbeType); comboBoxChannelPresets.SelectedIndexChanged += ChannelPresetIndexChanged; + ConfigureControls(ProbeConfiguration.ProbeType); + CheckStatus(); } + void UpdateProbeConfiguration() + { + ChannelConfiguration.ProbeConfiguration = new((NeuropixelsV1eProbeGroup)ChannelConfiguration.ProbeGroup, ProbeConfiguration.ProbeType, + ProbeConfiguration.SpikeAmplifierGain, ProbeConfiguration.LfpAmplifierGain, ProbeConfiguration.Reference, ProbeConfiguration.SpikeFilter); + + ChannelConfiguration.DrawProbeGroup(); + ChannelConfiguration.ResetZoom(); + ChannelConfiguration.RefreshZedGraph(); + + comboBoxChannelPresets.SelectedIndexChanged -= ChannelPresetIndexChanged; // NB: Temporarily detach handler so the loaded electrode configuration is respected + comboBoxChannelPresets.DataSource = GetComboBoxChannelPresets(ProbeConfiguration.ProbeType); + comboBoxChannelPresets.SelectedIndexChanged += ChannelPresetIndexChanged; + } + + private void ProbeTypeIndexChanged(object sender, EventArgs e) + { + var probeType = (NeuropixelsV1ProbeType)((ComboBox)sender).SelectedItem; + + if (probeType != ProbeConfiguration.ProbeType) + { + ProbeConfiguration.ProbeType = probeType; + ChannelConfiguration.LoadDefaultProbeGroup(); + UpdateProbeConfiguration(); + } + + ConfigureControls(ProbeConfiguration.ProbeType); + } + + void ConfigureControls(NeuropixelsV1ProbeType probeType) + { + if (probeType == NeuropixelsV1ProbeType.NP1) + { + buttonEnableContacts.Enabled = true; + buttonClearSelections.Enabled = true; + ChannelConfiguration.SetSelectElectrodesStatus(true); + + } + else if (probeType == NeuropixelsV1ProbeType.UHD) + { + buttonEnableContacts.Enabled = false; + buttonClearSelections.Enabled = false; + ChannelConfiguration.SetSelectElectrodesStatus(false); + } + else + throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)); + } + + static Array GetComboBoxChannelPresets(NeuropixelsV1ProbeType probeType) + { + return probeType switch + { + NeuropixelsV1ProbeType.NP1 => Enum.GetValues(typeof(ChannelPresetNp1)), + NeuropixelsV1ProbeType.UHD => Enum.GetValues(typeof(ChannelPresetUhd)), + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) + }; + } + private void InvertPolarityIndexChanged(object sender, EventArgs e) { InvertPolarity = ((CheckBox)sender).Checked; @@ -154,12 +233,29 @@ private void ReferenceIndexChanged(object sender, EventArgs e) private void ChannelPresetIndexChanged(object sender, EventArgs e) { - var channelPreset = (ChannelPreset)((ComboBox)sender).SelectedItem; + if (ProbeConfiguration.ProbeType == NeuropixelsV1ProbeType.NP1) + { + var channelPreset = (ChannelPresetNp1)((ComboBox)sender).SelectedItem; - if (channelPreset != ChannelPreset.None) + if (channelPreset != ChannelPresetNp1.None) + { + SetChannelPreset(channelPreset); + } + } + else if (ProbeConfiguration.ProbeType == NeuropixelsV1ProbeType.UHD) { - SetChannelPreset(channelPreset); + var channelPreset = (ChannelPresetUhd)((ComboBox)sender).SelectedItem; + + if (channelPreset != ChannelPresetUhd.None) + { + SetChannelPreset(channelPreset); + } } + + ChannelConfiguration.HighlightEnabledContacts(); + ChannelConfiguration.HighlightSelectedContacts(); + ChannelConfiguration.UpdateContactLabels(); + ChannelConfiguration.RefreshZedGraph(); } private void SpikeFilterIndexChanged(object sender, EventArgs e) @@ -167,81 +263,230 @@ private void SpikeFilterIndexChanged(object sender, EventArgs e) ProbeConfiguration.SpikeFilter = ((CheckBox)sender).Checked; } - private void SetChannelPreset(ChannelPreset preset) + void SetChannelPreset(ChannelPresetUhd preset) { - var probeConfiguration = ChannelConfiguration.ProbeConfiguration; - var electrodes = NeuropixelsV1eProbeGroup.ToElectrodes(ChannelConfiguration.ProbeConfiguration.ProbeGroup); + var electrodes = NeuropixelsV1eProbeGroup.ToElectrodes(ProbeConfiguration.ProbeGroup, ProbeConfiguration.ProbeType); switch (preset) { - case ChannelPreset.BankA: - probeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.A).ToArray()); + case ChannelPresetUhd.BankA: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.A).ToArray()); + break; + + case ChannelPresetUhd.BankB: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.B).ToArray()); break; - case ChannelPreset.BankB: - probeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.B).ToArray()); + case ChannelPresetUhd.BankC: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.C).ToArray()); break; - case ChannelPreset.BankC: - probeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.C || + case ChannelPresetUhd.BankD: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.D).ToArray()); + break; + + case ChannelPresetUhd.BankE: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.E).ToArray()); + break; + + case ChannelPresetUhd.BankF: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.F).ToArray()); + break; + + case ChannelPresetUhd.BankG: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.G).ToArray()); + break; + + case ChannelPresetUhd.BankH: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.H).ToArray()); + break; + + case ChannelPresetUhd.BankI: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.I).ToArray()); + break; + + case ChannelPresetUhd.BankJ: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.J).ToArray()); + break; + + case ChannelPresetUhd.BankK: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.K).ToArray()); + break; + + case ChannelPresetUhd.BankL: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.L).ToArray()); + break; + + case ChannelPresetUhd.BankM: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.M).ToArray()); + break; + + case ChannelPresetUhd.BankN: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.N).ToArray()); + break; + + case ChannelPresetUhd.BankO: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.O).ToArray()); + break; + + case ChannelPresetUhd.BankP: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.P).ToArray()); + break; + } + } + + void SetChannelPreset(ChannelPresetNp1 preset) + { + var electrodes = NeuropixelsV1eProbeGroup.ToElectrodes(ProbeConfiguration.ProbeGroup, ProbeConfiguration.ProbeType); + + switch (preset) + { + case ChannelPresetNp1.BankA: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.A).ToArray()); + break; + + case ChannelPresetNp1.BankB: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.B).ToArray()); + break; + + case ChannelPresetNp1.BankC: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.C || (e.Bank == NeuropixelsV1Bank.B && e.Index >= 576)).ToArray()); break; - case ChannelPreset.SingleColumn: - probeConfiguration.SelectElectrodes(electrodes.Where(e => (e.Index % 2 == 0 && e.Bank == NeuropixelsV1Bank.A) || + case ChannelPresetNp1.SingleColumn: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => (e.Index % 2 == 0 && e.Bank == NeuropixelsV1Bank.A) || (e.Index % 2 == 1 && e.Bank == NeuropixelsV1Bank.B)).ToArray()); break; - case ChannelPreset.Tetrodes: - probeConfiguration.SelectElectrodes(electrodes.Where(e => (e.Index % 8 < 4 && e.Bank == NeuropixelsV1Bank.A) || + case ChannelPresetNp1.Tetrodes: + ProbeConfiguration.SelectElectrodes(electrodes.Where(e => (e.Index % 8 < 4 && e.Bank == NeuropixelsV1Bank.A) || (e.Index % 8 > 3 && e.Bank == NeuropixelsV1Bank.B)).ToArray()); break; } + } - ChannelConfiguration.HighlightEnabledContacts(); - ChannelConfiguration.HighlightSelectedContacts(); - ChannelConfiguration.UpdateContactLabels(); - ChannelConfiguration.RefreshZedGraph(); + void CheckForExistingChannelPreset(NeuropixelsV1ProbeType probeType) + { + if (probeType == NeuropixelsV1ProbeType.NP1) + CheckForChannelPresetNp1(); + + else if (probeType == NeuropixelsV1ProbeType.UHD) + CheckForChannelPresetUhd(); } - private void CheckForExistingChannelPreset() + void CheckForChannelPresetNp1() { - var channelMap = ChannelConfiguration.ProbeConfiguration.ChannelMap; + var channelMap = ProbeConfiguration.ChannelMap; if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.A)) { - comboBoxChannelPresets.SelectedItem = ChannelPreset.BankA; + comboBoxChannelPresets.SelectedItem = ChannelPresetNp1.BankA; } else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.B)) { - comboBoxChannelPresets.SelectedItem = ChannelPreset.BankB; + comboBoxChannelPresets.SelectedItem = ChannelPresetNp1.BankB; } else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.C || (e.Bank == NeuropixelsV1Bank.B && e.Index >= 576))) { - comboBoxChannelPresets.SelectedItem = ChannelPreset.BankC; + comboBoxChannelPresets.SelectedItem = ChannelPresetNp1.BankC; } else if (channelMap.All(e => (e.Index % 2 == 0 && e.Bank == NeuropixelsV1Bank.A) || (e.Index % 2 == 1 && e.Bank == NeuropixelsV1Bank.B))) { - comboBoxChannelPresets.SelectedItem = ChannelPreset.SingleColumn; + comboBoxChannelPresets.SelectedItem = ChannelPresetNp1.SingleColumn; } else if (channelMap.All(e => (e.Index % 8 < 4 && e.Bank == NeuropixelsV1Bank.A) || (e.Index % 8 > 3 && e.Bank == NeuropixelsV1Bank.B))) { - comboBoxChannelPresets.SelectedItem = ChannelPreset.Tetrodes; + comboBoxChannelPresets.SelectedItem = ChannelPresetNp1.Tetrodes; } else { - comboBoxChannelPresets.SelectedItem = ChannelPreset.None; + comboBoxChannelPresets.SelectedItem = ChannelPresetNp1.None; } } + void CheckForChannelPresetUhd() + { + var channelMap = ProbeConfiguration.ChannelMap; + + if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.A)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankA; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.B)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankB; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.C)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankC; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.D)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankD; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.E)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankE; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.F)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankF; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.G)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankG; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.H)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankH; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.I)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankI; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.J)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankJ; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.K)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankK; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.L)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankL; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.M)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankM; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.N)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankN; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.O)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankO; + } + else if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.P)) + { + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.BankP; + } + else + comboBoxChannelPresets.SelectedItem = ChannelPresetUhd.None; + } + private void OnFileLoadEvent(object sender, EventArgs e) { - // NB: Ensure that the newly loaded ProbeConfiguration in the ChannelConfigurationDialog is reflected here. - ProbeConfiguration = ChannelConfiguration.ProbeConfiguration; - CheckForExistingChannelPreset(); + ProbeConfiguration.ProbeType = NeuropixelsV1eProbeGroup.GetProbeTypeFromProbeName(ChannelConfiguration.ProbeGroup.Probes.First().Annotations.Name); + comboBoxProbeType.SelectedItem = ProbeConfiguration.ProbeType; + UpdateProbeConfiguration(); + ConfigureControls(ProbeConfiguration.ProbeType); + CheckForExistingChannelPreset(ProbeConfiguration.ProbeType); } private void CheckStatus() @@ -317,22 +562,22 @@ private void CheckStatus() panelProbe.Visible = adcCalibration.HasValue && gainCorrection.HasValue; - if (toolStripAdcCalSN.Text == NoFileSelected) + if (toolStripAdcCalSN.Text == NoFileSelected) toolStripLabelAdcCalibrationSN.Image = Properties.Resources.StatusWarningImage; - else if (toolStripAdcCalSN.Text == InvalidFile) + else if (toolStripAdcCalSN.Text == InvalidFile) toolStripLabelAdcCalibrationSN.Image = Properties.Resources.StatusCriticalImage; else if (toolStripGainCalSN.Text != NoFileSelected && toolStripGainCalSN.Text != InvalidFile && toolStripAdcCalSN.Text != toolStripGainCalSN.Text) toolStripLabelAdcCalibrationSN.Image = Properties.Resources.StatusBlockedImage; - else + else toolStripLabelAdcCalibrationSN.Image = Properties.Resources.StatusReadyImage; - if (toolStripGainCalSN.Text == NoFileSelected) + if (toolStripGainCalSN.Text == NoFileSelected) toolStripLabelGainCalibrationSn.Image = Properties.Resources.StatusWarningImage; - else if (toolStripGainCalSN.Text == InvalidFile) + else if (toolStripGainCalSN.Text == InvalidFile) toolStripLabelGainCalibrationSn.Image = Properties.Resources.StatusCriticalImage; else if (toolStripAdcCalSN.Text != NoFileSelected && toolStripAdcCalSN.Text != InvalidFile && toolStripAdcCalSN.Text != toolStripGainCalSN.Text) toolStripLabelGainCalibrationSn.Image = Properties.Resources.StatusBlockedImage; - else + else toolStripLabelGainCalibrationSn.Image = Properties.Resources.StatusReadyImage; } @@ -432,14 +677,14 @@ private void ViewAdcs_Click(object sender, EventArgs e) private void EnableSelectedContacts() { - var electrodes = NeuropixelsV1eProbeGroup.ToElectrodes(ChannelConfiguration.ProbeConfiguration.ProbeGroup); + var electrodes = NeuropixelsV1eProbeGroup.ToElectrodes(ProbeConfiguration.ProbeGroup, ProbeConfiguration.ProbeType); var selectedElectrodes = electrodes.Where((e, ind) => ChannelConfiguration.SelectedContacts[ind]) .ToArray(); ChannelConfiguration.EnableElectrodes(selectedElectrodes); - CheckForExistingChannelPreset(); + CheckForExistingChannelPreset(ProbeConfiguration.ProbeType); } private void DeselectContacts() diff --git a/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.resx b/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.resx index 9282f66e..93ee7a05 100644 --- a/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.resx +++ b/OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.resx @@ -162,6 +162,9 @@ 473, 17 + + False + 25 diff --git a/OpenEphys.Onix1/NeuropixelsV1.cs b/OpenEphys.Onix1/NeuropixelsV1.cs index 3ba94fa4..d766c9d5 100644 --- a/OpenEphys.Onix1/NeuropixelsV1.cs +++ b/OpenEphys.Onix1/NeuropixelsV1.cs @@ -29,6 +29,7 @@ static class NeuropixelsV1 public const int AdcCount = 32; public const int ChannelCount = 384; public const int ElectrodeCount = 960; + public const int ElectrodeCountUHD = 6144; public const int FrameWords = 40; internal static BitArray MakeShankBits(NeuropixelsV1ProbeConfiguration configuration) @@ -81,7 +82,7 @@ internal static BitArray[] MakeConfigBits(NeuropixelsV1ProbeConfiguration probeC new(BaseConfigurationBitCount, false) }; // Ch 1, 3, 5, ... // create base shift-register bit arrays - for (int i = 0; i < NeuropixelsV1.ChannelCount; i++) + for (int i = 0; i < ChannelCount; i++) { var configIdx = i % 2; diff --git a/OpenEphys.Onix1/NeuropixelsV1Electrode.cs b/OpenEphys.Onix1/NeuropixelsV1Electrode.cs index 61a291d9..f5385a9f 100644 --- a/OpenEphys.Onix1/NeuropixelsV1Electrode.cs +++ b/OpenEphys.Onix1/NeuropixelsV1Electrode.cs @@ -1,4 +1,5 @@ -using System.Drawing; +using System.ComponentModel; +using System.Drawing; namespace OpenEphys.Onix1 { @@ -12,18 +13,25 @@ public class NeuropixelsV1Electrode : Electrode /// public NeuropixelsV1Bank Bank { get; private set; } + /// + /// Gets the column index of this electrode. + /// + public int ColumnIndex { get; private set; } + /// /// Initializes a new instance of using the given index. /// /// Integer defining the zero-indexed position of the electrode in the probe. - public NeuropixelsV1Electrode(int index) + /// The of the current probe. + public NeuropixelsV1Electrode(int index, NeuropixelsV1ProbeType probeType) { Index = index; Shank = 0; IntraShankElectrodeIndex = index; Bank = (NeuropixelsV1Bank)(index / NeuropixelsV1.ChannelCount); - Channel = GetChannelNumber(index); - var position = NeuropixelsV1eProbeGroup.DefaultContactPosition(index); + ColumnIndex = GetColumnIndex(index, probeType); + Channel = GetChannelNumber(index, probeType); + var position = NeuropixelsV1eProbeGroup.DefaultContactPosition(index, probeType); Position = new PointF(position[0], position[1]); } @@ -31,10 +39,6181 @@ public NeuropixelsV1Electrode(int index) /// Static method returning the channel number of a given electrode. /// /// Integer defining the index of the electrode in the probe. + /// The of the current probe. /// An integer between 0 and 383 defining the channel number. - public static int GetChannelNumber(int electrodeIndex) + public static int GetChannelNumber(int electrodeIndex, NeuropixelsV1ProbeType probeType) { - return electrodeIndex % NeuropixelsV1.ChannelCount; + return probeType switch + { + NeuropixelsV1ProbeType.NP1 => electrodeIndex % NeuropixelsV1.ChannelCount, + NeuropixelsV1ProbeType.UHD => channelOrder[electrodeIndex], + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) + }; } + + internal static int GetColumnIndex(int electrodeIndex, NeuropixelsV1ProbeType probeType) + { + var numColumns = NeuropixelsV1eProbeGroup.GetNumberOfColumns(probeType); + + if (probeType == NeuropixelsV1ProbeType.NP1) + { + return electrodeIndex % numColumns; + } + else if (probeType == NeuropixelsV1ProbeType.UHD) + { + int[] columnOrder = { 0, 7, 1, 6, 2, 5, 3, 4 }; + + return columnOrder[electrodeIndex % numColumns]; + } + else + throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)); + } + + static readonly int[] channelOrder = { + 0, + 2, + 32, + 34, + 63, + 61, + 31, + 29, + 4, + 6, + 36, + 38, + 59, + 57, + 27, + 25, + 8, + 10, + 40, + 42, + 55, + 53, + 23, + 21, + 12, + 14, + 44, + 46, + 51, + 49, + 19, + 17, + 16, + 18, + 48, + 50, + 47, + 45, + 15, + 13, + 20, + 22, + 52, + 54, + 43, + 41, + 11, + 9, + 24, + 26, + 56, + 58, + 39, + 37, + 7, + 5, + 28, + 30, + 60, + 62, + 35, + 33, + 3, + 1, + 64, + 66, + 96, + 98, + 127, + 125, + 95, + 93, + 68, + 70, + 100, + 102, + 123, + 121, + 91, + 89, + 72, + 74, + 104, + 106, + 119, + 117, + 87, + 85, + 76, + 78, + 108, + 110, + 115, + 113, + 83, + 81, + 80, + 82, + 112, + 114, + 111, + 109, + 79, + 77, + 84, + 86, + 116, + 118, + 107, + 105, + 75, + 73, + 88, + 90, + 120, + 122, + 103, + 101, + 71, + 69, + 92, + 94, + 124, + 126, + 99, + 97, + 67, + 65, + 128, + 130, + 160, + 162, + 191, + 189, + 159, + 157, + 132, + 134, + 164, + 166, + 187, + 185, + 155, + 153, + 136, + 138, + 168, + 170, + 183, + 181, + 151, + 149, + 140, + 142, + 172, + 174, + 179, + 177, + 147, + 145, + 144, + 146, + 176, + 178, + 175, + 173, + 143, + 141, + 148, + 150, + 180, + 182, + 171, + 169, + 139, + 137, + 152, + 154, + 184, + 186, + 167, + 165, + 135, + 133, + 156, + 158, + 188, + 190, + 163, + 161, + 131, + 129, + 192, + 194, + 224, + 226, + 255, + 253, + 223, + 221, + 196, + 198, + 228, + 230, + 251, + 249, + 219, + 217, + 200, + 202, + 232, + 234, + 247, + 245, + 215, + 213, + 204, + 206, + 236, + 238, + 243, + 241, + 211, + 209, + 208, + 210, + 240, + 242, + 239, + 237, + 207, + 205, + 212, + 214, + 244, + 246, + 235, + 233, + 203, + 201, + 216, + 218, + 248, + 250, + 231, + 229, + 199, + 197, + 220, + 222, + 252, + 254, + 227, + 225, + 195, + 193, + 256, + 258, + 288, + 290, + 319, + 317, + 287, + 285, + 260, + 262, + 292, + 294, + 315, + 313, + 283, + 281, + 264, + 266, + 296, + 298, + 311, + 309, + 279, + 277, + 268, + 270, + 300, + 302, + 307, + 305, + 275, + 273, + 272, + 274, + 304, + 306, + 303, + 301, + 271, + 269, + 276, + 278, + 308, + 310, + 299, + 297, + 267, + 265, + 280, + 282, + 312, + 314, + 295, + 293, + 263, + 261, + 284, + 286, + 316, + 318, + 291, + 289, + 259, + 257, + 320, + 322, + 352, + 354, + 383, + 381, + 351, + 349, + 324, + 326, + 356, + 358, + 379, + 377, + 347, + 345, + 328, + 330, + 360, + 362, + 375, + 373, + 343, + 341, + 332, + 334, + 364, + 366, + 371, + 369, + 339, + 337, + 336, + 338, + 368, + 370, + 367, + 365, + 335, + 333, + 340, + 342, + 372, + 374, + 363, + 361, + 331, + 329, + 344, + 346, + 376, + 378, + 359, + 357, + 327, + 325, + 348, + 350, + 380, + 382, + 355, + 353, + 323, + 321, + 32, + 34, + 0, + 2, + 31, + 29, + 63, + 61, + 36, + 38, + 4, + 6, + 27, + 25, + 59, + 57, + 40, + 42, + 8, + 10, + 23, + 21, + 55, + 53, + 44, + 46, + 12, + 14, + 19, + 17, + 51, + 49, + 48, + 50, + 16, + 18, + 15, + 13, + 47, + 45, + 52, + 54, + 20, + 22, + 11, + 9, + 43, + 41, + 56, + 58, + 24, + 26, + 7, + 5, + 39, + 37, + 60, + 62, + 28, + 30, + 3, + 1, + 35, + 33, + 96, + 98, + 64, + 66, + 95, + 93, + 127, + 125, + 100, + 102, + 68, + 70, + 91, + 89, + 123, + 121, + 104, + 106, + 72, + 74, + 87, + 85, + 119, + 117, + 108, + 110, + 76, + 78, + 83, + 81, + 115, + 113, + 112, + 114, + 80, + 82, + 79, + 77, + 111, + 109, + 116, + 118, + 84, + 86, + 75, + 73, + 107, + 105, + 120, + 122, + 88, + 90, + 71, + 69, + 103, + 101, + 124, + 126, + 92, + 94, + 67, + 65, + 99, + 97, + 160, + 162, + 128, + 130, + 159, + 157, + 191, + 189, + 164, + 166, + 132, + 134, + 155, + 153, + 187, + 185, + 168, + 170, + 136, + 138, + 151, + 149, + 183, + 181, + 172, + 174, + 140, + 142, + 147, + 145, + 179, + 177, + 176, + 178, + 144, + 146, + 143, + 141, + 175, + 173, + 180, + 182, + 148, + 150, + 139, + 137, + 171, + 169, + 184, + 186, + 152, + 154, + 135, + 133, + 167, + 165, + 188, + 190, + 156, + 158, + 131, + 129, + 163, + 161, + 224, + 226, + 192, + 194, + 223, + 221, + 255, + 253, + 228, + 230, + 196, + 198, + 219, + 217, + 251, + 249, + 232, + 234, + 200, + 202, + 215, + 213, + 247, + 245, + 236, + 238, + 204, + 206, + 211, + 209, + 243, + 241, + 240, + 242, + 208, + 210, + 207, + 205, + 239, + 237, + 244, + 246, + 212, + 214, + 203, + 201, + 235, + 233, + 248, + 250, + 216, + 218, + 199, + 197, + 231, + 229, + 252, + 254, + 220, + 222, + 195, + 193, + 227, + 225, + 288, + 290, + 256, + 258, + 287, + 285, + 319, + 317, + 292, + 294, + 260, + 262, + 283, + 281, + 315, + 313, + 296, + 298, + 264, + 266, + 279, + 277, + 311, + 309, + 300, + 302, + 268, + 270, + 275, + 273, + 307, + 305, + 304, + 306, + 272, + 274, + 271, + 269, + 303, + 301, + 308, + 310, + 276, + 278, + 267, + 265, + 299, + 297, + 312, + 314, + 280, + 282, + 263, + 261, + 295, + 293, + 316, + 318, + 284, + 286, + 259, + 257, + 291, + 289, + 352, + 354, + 320, + 322, + 351, + 349, + 383, + 381, + 356, + 358, + 324, + 326, + 347, + 345, + 379, + 377, + 360, + 362, + 328, + 330, + 343, + 341, + 375, + 373, + 364, + 366, + 332, + 334, + 339, + 337, + 371, + 369, + 368, + 370, + 336, + 338, + 335, + 333, + 367, + 365, + 372, + 374, + 340, + 342, + 331, + 329, + 363, + 361, + 376, + 378, + 344, + 346, + 327, + 325, + 359, + 357, + 380, + 382, + 348, + 350, + 323, + 321, + 355, + 353, + 0, + 2, + 32, + 34, + 63, + 61, + 31, + 29, + 4, + 6, + 36, + 38, + 59, + 57, + 27, + 25, + 8, + 10, + 40, + 42, + 55, + 53, + 23, + 21, + 12, + 14, + 44, + 46, + 51, + 49, + 19, + 17, + 16, + 18, + 48, + 50, + 47, + 45, + 15, + 13, + 20, + 22, + 52, + 54, + 43, + 41, + 11, + 9, + 24, + 26, + 56, + 58, + 39, + 37, + 7, + 5, + 28, + 30, + 60, + 62, + 35, + 33, + 3, + 1, + 64, + 66, + 96, + 98, + 127, + 125, + 95, + 93, + 68, + 70, + 100, + 102, + 123, + 121, + 91, + 89, + 72, + 74, + 104, + 106, + 119, + 117, + 87, + 85, + 76, + 78, + 108, + 110, + 115, + 113, + 83, + 81, + 80, + 82, + 112, + 114, + 111, + 109, + 79, + 77, + 84, + 86, + 116, + 118, + 107, + 105, + 75, + 73, + 88, + 90, + 120, + 122, + 103, + 101, + 71, + 69, + 92, + 94, + 124, + 126, + 99, + 97, + 67, + 65, + 128, + 130, + 160, + 162, + 191, + 189, + 159, + 157, + 132, + 134, + 164, + 166, + 187, + 185, + 155, + 153, + 136, + 138, + 168, + 170, + 183, + 181, + 151, + 149, + 140, + 142, + 172, + 174, + 179, + 177, + 147, + 145, + 144, + 146, + 176, + 178, + 175, + 173, + 143, + 141, + 148, + 150, + 180, + 182, + 171, + 169, + 139, + 137, + 152, + 154, + 184, + 186, + 167, + 165, + 135, + 133, + 156, + 158, + 188, + 190, + 163, + 161, + 131, + 129, + 192, + 194, + 224, + 226, + 255, + 253, + 223, + 221, + 196, + 198, + 228, + 230, + 251, + 249, + 219, + 217, + 200, + 202, + 232, + 234, + 247, + 245, + 215, + 213, + 204, + 206, + 236, + 238, + 243, + 241, + 211, + 209, + 208, + 210, + 240, + 242, + 239, + 237, + 207, + 205, + 212, + 214, + 244, + 246, + 235, + 233, + 203, + 201, + 216, + 218, + 248, + 250, + 231, + 229, + 199, + 197, + 220, + 222, + 252, + 254, + 227, + 225, + 195, + 193, + 256, + 258, + 288, + 290, + 319, + 317, + 287, + 285, + 260, + 262, + 292, + 294, + 315, + 313, + 283, + 281, + 264, + 266, + 296, + 298, + 311, + 309, + 279, + 277, + 268, + 270, + 300, + 302, + 307, + 305, + 275, + 273, + 272, + 274, + 304, + 306, + 303, + 301, + 271, + 269, + 276, + 278, + 308, + 310, + 299, + 297, + 267, + 265, + 280, + 282, + 312, + 314, + 295, + 293, + 263, + 261, + 284, + 286, + 316, + 318, + 291, + 289, + 259, + 257, + 320, + 322, + 352, + 354, + 383, + 381, + 351, + 349, + 324, + 326, + 356, + 358, + 379, + 377, + 347, + 345, + 328, + 330, + 360, + 362, + 375, + 373, + 343, + 341, + 332, + 334, + 364, + 366, + 371, + 369, + 339, + 337, + 336, + 338, + 368, + 370, + 367, + 365, + 335, + 333, + 340, + 342, + 372, + 374, + 363, + 361, + 331, + 329, + 344, + 346, + 376, + 378, + 359, + 357, + 327, + 325, + 348, + 350, + 380, + 382, + 355, + 353, + 323, + 321, + 32, + 34, + 0, + 2, + 31, + 29, + 63, + 61, + 36, + 38, + 4, + 6, + 27, + 25, + 59, + 57, + 40, + 42, + 8, + 10, + 23, + 21, + 55, + 53, + 44, + 46, + 12, + 14, + 19, + 17, + 51, + 49, + 48, + 50, + 16, + 18, + 15, + 13, + 47, + 45, + 52, + 54, + 20, + 22, + 11, + 9, + 43, + 41, + 56, + 58, + 24, + 26, + 7, + 5, + 39, + 37, + 60, + 62, + 28, + 30, + 3, + 1, + 35, + 33, + 96, + 98, + 64, + 66, + 95, + 93, + 127, + 125, + 100, + 102, + 68, + 70, + 91, + 89, + 123, + 121, + 104, + 106, + 72, + 74, + 87, + 85, + 119, + 117, + 108, + 110, + 76, + 78, + 83, + 81, + 115, + 113, + 112, + 114, + 80, + 82, + 79, + 77, + 111, + 109, + 116, + 118, + 84, + 86, + 75, + 73, + 107, + 105, + 120, + 122, + 88, + 90, + 71, + 69, + 103, + 101, + 124, + 126, + 92, + 94, + 67, + 65, + 99, + 97, + 160, + 162, + 128, + 130, + 159, + 157, + 191, + 189, + 164, + 166, + 132, + 134, + 155, + 153, + 187, + 185, + 168, + 170, + 136, + 138, + 151, + 149, + 183, + 181, + 172, + 174, + 140, + 142, + 147, + 145, + 179, + 177, + 176, + 178, + 144, + 146, + 143, + 141, + 175, + 173, + 180, + 182, + 148, + 150, + 139, + 137, + 171, + 169, + 184, + 186, + 152, + 154, + 135, + 133, + 167, + 165, + 188, + 190, + 156, + 158, + 131, + 129, + 163, + 161, + 224, + 226, + 192, + 194, + 223, + 221, + 255, + 253, + 228, + 230, + 196, + 198, + 219, + 217, + 251, + 249, + 232, + 234, + 200, + 202, + 215, + 213, + 247, + 245, + 236, + 238, + 204, + 206, + 211, + 209, + 243, + 241, + 240, + 242, + 208, + 210, + 207, + 205, + 239, + 237, + 244, + 246, + 212, + 214, + 203, + 201, + 235, + 233, + 248, + 250, + 216, + 218, + 199, + 197, + 231, + 229, + 252, + 254, + 220, + 222, + 195, + 193, + 227, + 225, + 288, + 290, + 256, + 258, + 287, + 285, + 319, + 317, + 292, + 294, + 260, + 262, + 283, + 281, + 315, + 313, + 296, + 298, + 264, + 266, + 279, + 277, + 311, + 309, + 300, + 302, + 268, + 270, + 275, + 273, + 307, + 305, + 304, + 306, + 272, + 274, + 271, + 269, + 303, + 301, + 308, + 310, + 276, + 278, + 267, + 265, + 299, + 297, + 312, + 314, + 280, + 282, + 263, + 261, + 295, + 293, + 316, + 318, + 284, + 286, + 259, + 257, + 291, + 289, + 352, + 354, + 320, + 322, + 351, + 349, + 383, + 381, + 356, + 358, + 324, + 326, + 347, + 345, + 379, + 377, + 360, + 362, + 328, + 330, + 343, + 341, + 375, + 373, + 364, + 366, + 332, + 334, + 339, + 337, + 371, + 369, + 368, + 370, + 336, + 338, + 335, + 333, + 367, + 365, + 372, + 374, + 340, + 342, + 331, + 329, + 363, + 361, + 376, + 378, + 344, + 346, + 327, + 325, + 359, + 357, + 380, + 382, + 348, + 350, + 323, + 321, + 355, + 353, + 2, + 0, + 34, + 32, + 61, + 63, + 29, + 31, + 6, + 4, + 38, + 36, + 57, + 59, + 25, + 27, + 10, + 8, + 42, + 40, + 53, + 55, + 21, + 23, + 14, + 12, + 46, + 44, + 49, + 51, + 17, + 19, + 18, + 16, + 50, + 48, + 45, + 47, + 13, + 15, + 22, + 20, + 54, + 52, + 41, + 43, + 9, + 11, + 26, + 24, + 58, + 56, + 37, + 39, + 5, + 7, + 30, + 28, + 62, + 60, + 33, + 35, + 1, + 3, + 66, + 64, + 98, + 96, + 125, + 127, + 93, + 95, + 70, + 68, + 102, + 100, + 121, + 123, + 89, + 91, + 74, + 72, + 106, + 104, + 117, + 119, + 85, + 87, + 78, + 76, + 110, + 108, + 113, + 115, + 81, + 83, + 82, + 80, + 114, + 112, + 109, + 111, + 77, + 79, + 86, + 84, + 118, + 116, + 105, + 107, + 73, + 75, + 90, + 88, + 122, + 120, + 101, + 103, + 69, + 71, + 94, + 92, + 126, + 124, + 97, + 99, + 65, + 67, + 130, + 128, + 162, + 160, + 189, + 191, + 157, + 159, + 134, + 132, + 166, + 164, + 185, + 187, + 153, + 155, + 138, + 136, + 170, + 168, + 181, + 183, + 149, + 151, + 142, + 140, + 174, + 172, + 177, + 179, + 145, + 147, + 146, + 144, + 178, + 176, + 173, + 175, + 141, + 143, + 150, + 148, + 182, + 180, + 169, + 171, + 137, + 139, + 154, + 152, + 186, + 184, + 165, + 167, + 133, + 135, + 158, + 156, + 190, + 188, + 161, + 163, + 129, + 131, + 194, + 192, + 226, + 224, + 253, + 255, + 221, + 223, + 198, + 196, + 230, + 228, + 249, + 251, + 217, + 219, + 202, + 200, + 234, + 232, + 245, + 247, + 213, + 215, + 206, + 204, + 238, + 236, + 241, + 243, + 209, + 211, + 210, + 208, + 242, + 240, + 237, + 239, + 205, + 207, + 214, + 212, + 246, + 244, + 233, + 235, + 201, + 203, + 218, + 216, + 250, + 248, + 229, + 231, + 197, + 199, + 222, + 220, + 254, + 252, + 225, + 227, + 193, + 195, + 258, + 256, + 290, + 288, + 317, + 319, + 285, + 287, + 262, + 260, + 294, + 292, + 313, + 315, + 281, + 283, + 266, + 264, + 298, + 296, + 309, + 311, + 277, + 279, + 270, + 268, + 302, + 300, + 305, + 307, + 273, + 275, + 274, + 272, + 306, + 304, + 301, + 303, + 269, + 271, + 278, + 276, + 310, + 308, + 297, + 299, + 265, + 267, + 282, + 280, + 314, + 312, + 293, + 295, + 261, + 263, + 286, + 284, + 318, + 316, + 289, + 291, + 257, + 259, + 322, + 320, + 354, + 352, + 381, + 383, + 349, + 351, + 326, + 324, + 358, + 356, + 377, + 379, + 345, + 347, + 330, + 328, + 362, + 360, + 373, + 375, + 341, + 343, + 334, + 332, + 366, + 364, + 369, + 371, + 337, + 339, + 338, + 336, + 370, + 368, + 365, + 367, + 333, + 335, + 342, + 340, + 374, + 372, + 361, + 363, + 329, + 331, + 346, + 344, + 378, + 376, + 357, + 359, + 325, + 327, + 350, + 348, + 382, + 380, + 353, + 355, + 321, + 323, + 34, + 32, + 2, + 0, + 29, + 31, + 61, + 63, + 38, + 36, + 6, + 4, + 25, + 27, + 57, + 59, + 42, + 40, + 10, + 8, + 21, + 23, + 53, + 55, + 46, + 44, + 14, + 12, + 17, + 19, + 49, + 51, + 50, + 48, + 18, + 16, + 13, + 15, + 45, + 47, + 54, + 52, + 22, + 20, + 9, + 11, + 41, + 43, + 58, + 56, + 26, + 24, + 5, + 7, + 37, + 39, + 62, + 60, + 30, + 28, + 1, + 3, + 33, + 35, + 98, + 96, + 66, + 64, + 93, + 95, + 125, + 127, + 102, + 100, + 70, + 68, + 89, + 91, + 121, + 123, + 106, + 104, + 74, + 72, + 85, + 87, + 117, + 119, + 110, + 108, + 78, + 76, + 81, + 83, + 113, + 115, + 114, + 112, + 82, + 80, + 77, + 79, + 109, + 111, + 118, + 116, + 86, + 84, + 73, + 75, + 105, + 107, + 122, + 120, + 90, + 88, + 69, + 71, + 101, + 103, + 126, + 124, + 94, + 92, + 65, + 67, + 97, + 99, + 162, + 160, + 130, + 128, + 157, + 159, + 189, + 191, + 166, + 164, + 134, + 132, + 153, + 155, + 185, + 187, + 170, + 168, + 138, + 136, + 149, + 151, + 181, + 183, + 174, + 172, + 142, + 140, + 145, + 147, + 177, + 179, + 178, + 176, + 146, + 144, + 141, + 143, + 173, + 175, + 182, + 180, + 150, + 148, + 137, + 139, + 169, + 171, + 186, + 184, + 154, + 152, + 133, + 135, + 165, + 167, + 190, + 188, + 158, + 156, + 129, + 131, + 161, + 163, + 226, + 224, + 194, + 192, + 221, + 223, + 253, + 255, + 230, + 228, + 198, + 196, + 217, + 219, + 249, + 251, + 234, + 232, + 202, + 200, + 213, + 215, + 245, + 247, + 238, + 236, + 206, + 204, + 209, + 211, + 241, + 243, + 242, + 240, + 210, + 208, + 205, + 207, + 237, + 239, + 246, + 244, + 214, + 212, + 201, + 203, + 233, + 235, + 250, + 248, + 218, + 216, + 197, + 199, + 229, + 231, + 254, + 252, + 222, + 220, + 193, + 195, + 225, + 227, + 290, + 288, + 258, + 256, + 285, + 287, + 317, + 319, + 294, + 292, + 262, + 260, + 281, + 283, + 313, + 315, + 298, + 296, + 266, + 264, + 277, + 279, + 309, + 311, + 302, + 300, + 270, + 268, + 273, + 275, + 305, + 307, + 306, + 304, + 274, + 272, + 269, + 271, + 301, + 303, + 310, + 308, + 278, + 276, + 265, + 267, + 297, + 299, + 314, + 312, + 282, + 280, + 261, + 263, + 293, + 295, + 318, + 316, + 286, + 284, + 257, + 259, + 289, + 291, + 354, + 352, + 322, + 320, + 349, + 351, + 381, + 383, + 358, + 356, + 326, + 324, + 345, + 347, + 377, + 379, + 362, + 360, + 330, + 328, + 341, + 343, + 373, + 375, + 366, + 364, + 334, + 332, + 337, + 339, + 369, + 371, + 370, + 368, + 338, + 336, + 333, + 335, + 365, + 367, + 374, + 372, + 342, + 340, + 329, + 331, + 361, + 363, + 378, + 376, + 346, + 344, + 325, + 327, + 357, + 359, + 382, + 380, + 350, + 348, + 321, + 323, + 353, + 355, + 2, + 0, + 34, + 32, + 61, + 63, + 29, + 31, + 6, + 4, + 38, + 36, + 57, + 59, + 25, + 27, + 10, + 8, + 42, + 40, + 53, + 55, + 21, + 23, + 14, + 12, + 46, + 44, + 49, + 51, + 17, + 19, + 18, + 16, + 50, + 48, + 45, + 47, + 13, + 15, + 22, + 20, + 54, + 52, + 41, + 43, + 9, + 11, + 26, + 24, + 58, + 56, + 37, + 39, + 5, + 7, + 30, + 28, + 62, + 60, + 33, + 35, + 1, + 3, + 66, + 64, + 98, + 96, + 125, + 127, + 93, + 95, + 70, + 68, + 102, + 100, + 121, + 123, + 89, + 91, + 74, + 72, + 106, + 104, + 117, + 119, + 85, + 87, + 78, + 76, + 110, + 108, + 113, + 115, + 81, + 83, + 82, + 80, + 114, + 112, + 109, + 111, + 77, + 79, + 86, + 84, + 118, + 116, + 105, + 107, + 73, + 75, + 90, + 88, + 122, + 120, + 101, + 103, + 69, + 71, + 94, + 92, + 126, + 124, + 97, + 99, + 65, + 67, + 130, + 128, + 162, + 160, + 189, + 191, + 157, + 159, + 134, + 132, + 166, + 164, + 185, + 187, + 153, + 155, + 138, + 136, + 170, + 168, + 181, + 183, + 149, + 151, + 142, + 140, + 174, + 172, + 177, + 179, + 145, + 147, + 146, + 144, + 178, + 176, + 173, + 175, + 141, + 143, + 150, + 148, + 182, + 180, + 169, + 171, + 137, + 139, + 154, + 152, + 186, + 184, + 165, + 167, + 133, + 135, + 158, + 156, + 190, + 188, + 161, + 163, + 129, + 131, + 194, + 192, + 226, + 224, + 253, + 255, + 221, + 223, + 198, + 196, + 230, + 228, + 249, + 251, + 217, + 219, + 202, + 200, + 234, + 232, + 245, + 247, + 213, + 215, + 206, + 204, + 238, + 236, + 241, + 243, + 209, + 211, + 210, + 208, + 242, + 240, + 237, + 239, + 205, + 207, + 214, + 212, + 246, + 244, + 233, + 235, + 201, + 203, + 218, + 216, + 250, + 248, + 229, + 231, + 197, + 199, + 222, + 220, + 254, + 252, + 225, + 227, + 193, + 195, + 258, + 256, + 290, + 288, + 317, + 319, + 285, + 287, + 262, + 260, + 294, + 292, + 313, + 315, + 281, + 283, + 266, + 264, + 298, + 296, + 309, + 311, + 277, + 279, + 270, + 268, + 302, + 300, + 305, + 307, + 273, + 275, + 274, + 272, + 306, + 304, + 301, + 303, + 269, + 271, + 278, + 276, + 310, + 308, + 297, + 299, + 265, + 267, + 282, + 280, + 314, + 312, + 293, + 295, + 261, + 263, + 286, + 284, + 318, + 316, + 289, + 291, + 257, + 259, + 322, + 320, + 354, + 352, + 381, + 383, + 349, + 351, + 326, + 324, + 358, + 356, + 377, + 379, + 345, + 347, + 330, + 328, + 362, + 360, + 373, + 375, + 341, + 343, + 334, + 332, + 366, + 364, + 369, + 371, + 337, + 339, + 338, + 336, + 370, + 368, + 365, + 367, + 333, + 335, + 342, + 340, + 374, + 372, + 361, + 363, + 329, + 331, + 346, + 344, + 378, + 376, + 357, + 359, + 325, + 327, + 350, + 348, + 382, + 380, + 353, + 355, + 321, + 323, + 34, + 32, + 2, + 0, + 29, + 31, + 61, + 63, + 38, + 36, + 6, + 4, + 25, + 27, + 57, + 59, + 42, + 40, + 10, + 8, + 21, + 23, + 53, + 55, + 46, + 44, + 14, + 12, + 17, + 19, + 49, + 51, + 50, + 48, + 18, + 16, + 13, + 15, + 45, + 47, + 54, + 52, + 22, + 20, + 9, + 11, + 41, + 43, + 58, + 56, + 26, + 24, + 5, + 7, + 37, + 39, + 62, + 60, + 30, + 28, + 1, + 3, + 33, + 35, + 98, + 96, + 66, + 64, + 93, + 95, + 125, + 127, + 102, + 100, + 70, + 68, + 89, + 91, + 121, + 123, + 106, + 104, + 74, + 72, + 85, + 87, + 117, + 119, + 110, + 108, + 78, + 76, + 81, + 83, + 113, + 115, + 114, + 112, + 82, + 80, + 77, + 79, + 109, + 111, + 118, + 116, + 86, + 84, + 73, + 75, + 105, + 107, + 122, + 120, + 90, + 88, + 69, + 71, + 101, + 103, + 126, + 124, + 94, + 92, + 65, + 67, + 97, + 99, + 162, + 160, + 130, + 128, + 157, + 159, + 189, + 191, + 166, + 164, + 134, + 132, + 153, + 155, + 185, + 187, + 170, + 168, + 138, + 136, + 149, + 151, + 181, + 183, + 174, + 172, + 142, + 140, + 145, + 147, + 177, + 179, + 178, + 176, + 146, + 144, + 141, + 143, + 173, + 175, + 182, + 180, + 150, + 148, + 137, + 139, + 169, + 171, + 186, + 184, + 154, + 152, + 133, + 135, + 165, + 167, + 190, + 188, + 158, + 156, + 129, + 131, + 161, + 163, + 226, + 224, + 194, + 192, + 221, + 223, + 253, + 255, + 230, + 228, + 198, + 196, + 217, + 219, + 249, + 251, + 234, + 232, + 202, + 200, + 213, + 215, + 245, + 247, + 238, + 236, + 206, + 204, + 209, + 211, + 241, + 243, + 242, + 240, + 210, + 208, + 205, + 207, + 237, + 239, + 246, + 244, + 214, + 212, + 201, + 203, + 233, + 235, + 250, + 248, + 218, + 216, + 197, + 199, + 229, + 231, + 254, + 252, + 222, + 220, + 193, + 195, + 225, + 227, + 290, + 288, + 258, + 256, + 285, + 287, + 317, + 319, + 294, + 292, + 262, + 260, + 281, + 283, + 313, + 315, + 298, + 296, + 266, + 264, + 277, + 279, + 309, + 311, + 302, + 300, + 270, + 268, + 273, + 275, + 305, + 307, + 306, + 304, + 274, + 272, + 269, + 271, + 301, + 303, + 310, + 308, + 278, + 276, + 265, + 267, + 297, + 299, + 314, + 312, + 282, + 280, + 261, + 263, + 293, + 295, + 318, + 316, + 286, + 284, + 257, + 259, + 289, + 291, + 354, + 352, + 322, + 320, + 349, + 351, + 381, + 383, + 358, + 356, + 326, + 324, + 345, + 347, + 377, + 379, + 362, + 360, + 330, + 328, + 341, + 343, + 373, + 375, + 366, + 364, + 334, + 332, + 337, + 339, + 369, + 371, + 370, + 368, + 338, + 336, + 333, + 335, + 365, + 367, + 374, + 372, + 342, + 340, + 329, + 331, + 361, + 363, + 378, + 376, + 346, + 344, + 325, + 327, + 357, + 359, + 382, + 380, + 350, + 348, + 321, + 323, + 353, + 355, + 0, + 2, + 32, + 34, + 63, + 61, + 31, + 29, + 4, + 6, + 36, + 38, + 59, + 57, + 27, + 25, + 8, + 10, + 40, + 42, + 55, + 53, + 23, + 21, + 12, + 14, + 44, + 46, + 51, + 49, + 19, + 17, + 16, + 18, + 48, + 50, + 47, + 45, + 15, + 13, + 20, + 22, + 52, + 54, + 43, + 41, + 11, + 9, + 24, + 26, + 56, + 58, + 39, + 37, + 7, + 5, + 28, + 30, + 60, + 62, + 35, + 33, + 3, + 1, + 64, + 66, + 96, + 98, + 127, + 125, + 95, + 93, + 68, + 70, + 100, + 102, + 123, + 121, + 91, + 89, + 72, + 74, + 104, + 106, + 119, + 117, + 87, + 85, + 76, + 78, + 108, + 110, + 115, + 113, + 83, + 81, + 80, + 82, + 112, + 114, + 111, + 109, + 79, + 77, + 84, + 86, + 116, + 118, + 107, + 105, + 75, + 73, + 88, + 90, + 120, + 122, + 103, + 101, + 71, + 69, + 92, + 94, + 124, + 126, + 99, + 97, + 67, + 65, + 128, + 130, + 160, + 162, + 191, + 189, + 159, + 157, + 132, + 134, + 164, + 166, + 187, + 185, + 155, + 153, + 136, + 138, + 168, + 170, + 183, + 181, + 151, + 149, + 140, + 142, + 172, + 174, + 179, + 177, + 147, + 145, + 144, + 146, + 176, + 178, + 175, + 173, + 143, + 141, + 148, + 150, + 180, + 182, + 171, + 169, + 139, + 137, + 152, + 154, + 184, + 186, + 167, + 165, + 135, + 133, + 156, + 158, + 188, + 190, + 163, + 161, + 131, + 129, + 192, + 194, + 224, + 226, + 255, + 253, + 223, + 221, + 196, + 198, + 228, + 230, + 251, + 249, + 219, + 217, + 200, + 202, + 232, + 234, + 247, + 245, + 215, + 213, + 204, + 206, + 236, + 238, + 243, + 241, + 211, + 209, + 208, + 210, + 240, + 242, + 239, + 237, + 207, + 205, + 212, + 214, + 244, + 246, + 235, + 233, + 203, + 201, + 216, + 218, + 248, + 250, + 231, + 229, + 199, + 197, + 220, + 222, + 252, + 254, + 227, + 225, + 195, + 193, + 256, + 258, + 288, + 290, + 319, + 317, + 287, + 285, + 260, + 262, + 292, + 294, + 315, + 313, + 283, + 281, + 264, + 266, + 296, + 298, + 311, + 309, + 279, + 277, + 268, + 270, + 300, + 302, + 307, + 305, + 275, + 273, + 272, + 274, + 304, + 306, + 303, + 301, + 271, + 269, + 276, + 278, + 308, + 310, + 299, + 297, + 267, + 265, + 280, + 282, + 312, + 314, + 295, + 293, + 263, + 261, + 284, + 286, + 316, + 318, + 291, + 289, + 259, + 257, + 320, + 322, + 352, + 354, + 383, + 381, + 351, + 349, + 324, + 326, + 356, + 358, + 379, + 377, + 347, + 345, + 328, + 330, + 360, + 362, + 375, + 373, + 343, + 341, + 332, + 334, + 364, + 366, + 371, + 369, + 339, + 337, + 336, + 338, + 368, + 370, + 367, + 365, + 335, + 333, + 340, + 342, + 372, + 374, + 363, + 361, + 331, + 329, + 344, + 346, + 376, + 378, + 359, + 357, + 327, + 325, + 348, + 350, + 380, + 382, + 355, + 353, + 323, + 321, + 32, + 34, + 0, + 2, + 31, + 29, + 63, + 61, + 36, + 38, + 4, + 6, + 27, + 25, + 59, + 57, + 40, + 42, + 8, + 10, + 23, + 21, + 55, + 53, + 44, + 46, + 12, + 14, + 19, + 17, + 51, + 49, + 48, + 50, + 16, + 18, + 15, + 13, + 47, + 45, + 52, + 54, + 20, + 22, + 11, + 9, + 43, + 41, + 56, + 58, + 24, + 26, + 7, + 5, + 39, + 37, + 60, + 62, + 28, + 30, + 3, + 1, + 35, + 33, + 96, + 98, + 64, + 66, + 95, + 93, + 127, + 125, + 100, + 102, + 68, + 70, + 91, + 89, + 123, + 121, + 104, + 106, + 72, + 74, + 87, + 85, + 119, + 117, + 108, + 110, + 76, + 78, + 83, + 81, + 115, + 113, + 112, + 114, + 80, + 82, + 79, + 77, + 111, + 109, + 116, + 118, + 84, + 86, + 75, + 73, + 107, + 105, + 120, + 122, + 88, + 90, + 71, + 69, + 103, + 101, + 124, + 126, + 92, + 94, + 67, + 65, + 99, + 97, + 160, + 162, + 128, + 130, + 159, + 157, + 191, + 189, + 164, + 166, + 132, + 134, + 155, + 153, + 187, + 185, + 168, + 170, + 136, + 138, + 151, + 149, + 183, + 181, + 172, + 174, + 140, + 142, + 147, + 145, + 179, + 177, + 176, + 178, + 144, + 146, + 143, + 141, + 175, + 173, + 180, + 182, + 148, + 150, + 139, + 137, + 171, + 169, + 184, + 186, + 152, + 154, + 135, + 133, + 167, + 165, + 188, + 190, + 156, + 158, + 131, + 129, + 163, + 161, + 224, + 226, + 192, + 194, + 223, + 221, + 255, + 253, + 228, + 230, + 196, + 198, + 219, + 217, + 251, + 249, + 232, + 234, + 200, + 202, + 215, + 213, + 247, + 245, + 236, + 238, + 204, + 206, + 211, + 209, + 243, + 241, + 240, + 242, + 208, + 210, + 207, + 205, + 239, + 237, + 244, + 246, + 212, + 214, + 203, + 201, + 235, + 233, + 248, + 250, + 216, + 218, + 199, + 197, + 231, + 229, + 252, + 254, + 220, + 222, + 195, + 193, + 227, + 225, + 288, + 290, + 256, + 258, + 287, + 285, + 319, + 317, + 292, + 294, + 260, + 262, + 283, + 281, + 315, + 313, + 296, + 298, + 264, + 266, + 279, + 277, + 311, + 309, + 300, + 302, + 268, + 270, + 275, + 273, + 307, + 305, + 304, + 306, + 272, + 274, + 271, + 269, + 303, + 301, + 308, + 310, + 276, + 278, + 267, + 265, + 299, + 297, + 312, + 314, + 280, + 282, + 263, + 261, + 295, + 293, + 316, + 318, + 284, + 286, + 259, + 257, + 291, + 289, + 352, + 354, + 320, + 322, + 351, + 349, + 383, + 381, + 356, + 358, + 324, + 326, + 347, + 345, + 379, + 377, + 360, + 362, + 328, + 330, + 343, + 341, + 375, + 373, + 364, + 366, + 332, + 334, + 339, + 337, + 371, + 369, + 368, + 370, + 336, + 338, + 335, + 333, + 367, + 365, + 372, + 374, + 340, + 342, + 331, + 329, + 363, + 361, + 376, + 378, + 344, + 346, + 327, + 325, + 359, + 357, + 380, + 382, + 348, + 350, + 323, + 321, + 355, + 353, + 0, + 2, + 32, + 34, + 63, + 61, + 31, + 29, + 4, + 6, + 36, + 38, + 59, + 57, + 27, + 25, + 8, + 10, + 40, + 42, + 55, + 53, + 23, + 21, + 12, + 14, + 44, + 46, + 51, + 49, + 19, + 17, + 16, + 18, + 48, + 50, + 47, + 45, + 15, + 13, + 20, + 22, + 52, + 54, + 43, + 41, + 11, + 9, + 24, + 26, + 56, + 58, + 39, + 37, + 7, + 5, + 28, + 30, + 60, + 62, + 35, + 33, + 3, + 1, + 64, + 66, + 96, + 98, + 127, + 125, + 95, + 93, + 68, + 70, + 100, + 102, + 123, + 121, + 91, + 89, + 72, + 74, + 104, + 106, + 119, + 117, + 87, + 85, + 76, + 78, + 108, + 110, + 115, + 113, + 83, + 81, + 80, + 82, + 112, + 114, + 111, + 109, + 79, + 77, + 84, + 86, + 116, + 118, + 107, + 105, + 75, + 73, + 88, + 90, + 120, + 122, + 103, + 101, + 71, + 69, + 92, + 94, + 124, + 126, + 99, + 97, + 67, + 65, + 128, + 130, + 160, + 162, + 191, + 189, + 159, + 157, + 132, + 134, + 164, + 166, + 187, + 185, + 155, + 153, + 136, + 138, + 168, + 170, + 183, + 181, + 151, + 149, + 140, + 142, + 172, + 174, + 179, + 177, + 147, + 145, + 144, + 146, + 176, + 178, + 175, + 173, + 143, + 141, + 148, + 150, + 180, + 182, + 171, + 169, + 139, + 137, + 152, + 154, + 184, + 186, + 167, + 165, + 135, + 133, + 156, + 158, + 188, + 190, + 163, + 161, + 131, + 129, + 192, + 194, + 224, + 226, + 255, + 253, + 223, + 221, + 196, + 198, + 228, + 230, + 251, + 249, + 219, + 217, + 200, + 202, + 232, + 234, + 247, + 245, + 215, + 213, + 204, + 206, + 236, + 238, + 243, + 241, + 211, + 209, + 208, + 210, + 240, + 242, + 239, + 237, + 207, + 205, + 212, + 214, + 244, + 246, + 235, + 233, + 203, + 201, + 216, + 218, + 248, + 250, + 231, + 229, + 199, + 197, + 220, + 222, + 252, + 254, + 227, + 225, + 195, + 193, + 256, + 258, + 288, + 290, + 319, + 317, + 287, + 285, + 260, + 262, + 292, + 294, + 315, + 313, + 283, + 281, + 264, + 266, + 296, + 298, + 311, + 309, + 279, + 277, + 268, + 270, + 300, + 302, + 307, + 305, + 275, + 273, + 272, + 274, + 304, + 306, + 303, + 301, + 271, + 269, + 276, + 278, + 308, + 310, + 299, + 297, + 267, + 265, + 280, + 282, + 312, + 314, + 295, + 293, + 263, + 261, + 284, + 286, + 316, + 318, + 291, + 289, + 259, + 257, + 320, + 322, + 352, + 354, + 383, + 381, + 351, + 349, + 324, + 326, + 356, + 358, + 379, + 377, + 347, + 345, + 328, + 330, + 360, + 362, + 375, + 373, + 343, + 341, + 332, + 334, + 364, + 366, + 371, + 369, + 339, + 337, + 336, + 338, + 368, + 370, + 367, + 365, + 335, + 333, + 340, + 342, + 372, + 374, + 363, + 361, + 331, + 329, + 344, + 346, + 376, + 378, + 359, + 357, + 327, + 325, + 348, + 350, + 380, + 382, + 355, + 353, + 323, + 321, + 32, + 34, + 0, + 2, + 31, + 29, + 63, + 61, + 36, + 38, + 4, + 6, + 27, + 25, + 59, + 57, + 40, + 42, + 8, + 10, + 23, + 21, + 55, + 53, + 44, + 46, + 12, + 14, + 19, + 17, + 51, + 49, + 48, + 50, + 16, + 18, + 15, + 13, + 47, + 45, + 52, + 54, + 20, + 22, + 11, + 9, + 43, + 41, + 56, + 58, + 24, + 26, + 7, + 5, + 39, + 37, + 60, + 62, + 28, + 30, + 3, + 1, + 35, + 33, + 96, + 98, + 64, + 66, + 95, + 93, + 127, + 125, + 100, + 102, + 68, + 70, + 91, + 89, + 123, + 121, + 104, + 106, + 72, + 74, + 87, + 85, + 119, + 117, + 108, + 110, + 76, + 78, + 83, + 81, + 115, + 113, + 112, + 114, + 80, + 82, + 79, + 77, + 111, + 109, + 116, + 118, + 84, + 86, + 75, + 73, + 107, + 105, + 120, + 122, + 88, + 90, + 71, + 69, + 103, + 101, + 124, + 126, + 92, + 94, + 67, + 65, + 99, + 97, + 160, + 162, + 128, + 130, + 159, + 157, + 191, + 189, + 164, + 166, + 132, + 134, + 155, + 153, + 187, + 185, + 168, + 170, + 136, + 138, + 151, + 149, + 183, + 181, + 172, + 174, + 140, + 142, + 147, + 145, + 179, + 177, + 176, + 178, + 144, + 146, + 143, + 141, + 175, + 173, + 180, + 182, + 148, + 150, + 139, + 137, + 171, + 169, + 184, + 186, + 152, + 154, + 135, + 133, + 167, + 165, + 188, + 190, + 156, + 158, + 131, + 129, + 163, + 161, + 224, + 226, + 192, + 194, + 223, + 221, + 255, + 253, + 228, + 230, + 196, + 198, + 219, + 217, + 251, + 249, + 232, + 234, + 200, + 202, + 215, + 213, + 247, + 245, + 236, + 238, + 204, + 206, + 211, + 209, + 243, + 241, + 240, + 242, + 208, + 210, + 207, + 205, + 239, + 237, + 244, + 246, + 212, + 214, + 203, + 201, + 235, + 233, + 248, + 250, + 216, + 218, + 199, + 197, + 231, + 229, + 252, + 254, + 220, + 222, + 195, + 193, + 227, + 225, + 288, + 290, + 256, + 258, + 287, + 285, + 319, + 317, + 292, + 294, + 260, + 262, + 283, + 281, + 315, + 313, + 296, + 298, + 264, + 266, + 279, + 277, + 311, + 309, + 300, + 302, + 268, + 270, + 275, + 273, + 307, + 305, + 304, + 306, + 272, + 274, + 271, + 269, + 303, + 301, + 308, + 310, + 276, + 278, + 267, + 265, + 299, + 297, + 312, + 314, + 280, + 282, + 263, + 261, + 295, + 293, + 316, + 318, + 284, + 286, + 259, + 257, + 291, + 289, + 352, + 354, + 320, + 322, + 351, + 349, + 383, + 381, + 356, + 358, + 324, + 326, + 347, + 345, + 379, + 377, + 360, + 362, + 328, + 330, + 343, + 341, + 375, + 373, + 364, + 366, + 332, + 334, + 339, + 337, + 371, + 369, + 368, + 370, + 336, + 338, + 335, + 333, + 367, + 365, + 372, + 374, + 340, + 342, + 331, + 329, + 363, + 361, + 376, + 378, + 344, + 346, + 327, + 325, + 359, + 357, + 380, + 382, + 348, + 350, + 323, + 321, + 355, + 353, + 2, + 0, + 34, + 32, + 61, + 63, + 29, + 31, + 6, + 4, + 38, + 36, + 57, + 59, + 25, + 27, + 10, + 8, + 42, + 40, + 53, + 55, + 21, + 23, + 14, + 12, + 46, + 44, + 49, + 51, + 17, + 19, + 18, + 16, + 50, + 48, + 45, + 47, + 13, + 15, + 22, + 20, + 54, + 52, + 41, + 43, + 9, + 11, + 26, + 24, + 58, + 56, + 37, + 39, + 5, + 7, + 30, + 28, + 62, + 60, + 33, + 35, + 1, + 3, + 66, + 64, + 98, + 96, + 125, + 127, + 93, + 95, + 70, + 68, + 102, + 100, + 121, + 123, + 89, + 91, + 74, + 72, + 106, + 104, + 117, + 119, + 85, + 87, + 78, + 76, + 110, + 108, + 113, + 115, + 81, + 83, + 82, + 80, + 114, + 112, + 109, + 111, + 77, + 79, + 86, + 84, + 118, + 116, + 105, + 107, + 73, + 75, + 90, + 88, + 122, + 120, + 101, + 103, + 69, + 71, + 94, + 92, + 126, + 124, + 97, + 99, + 65, + 67, + 130, + 128, + 162, + 160, + 189, + 191, + 157, + 159, + 134, + 132, + 166, + 164, + 185, + 187, + 153, + 155, + 138, + 136, + 170, + 168, + 181, + 183, + 149, + 151, + 142, + 140, + 174, + 172, + 177, + 179, + 145, + 147, + 146, + 144, + 178, + 176, + 173, + 175, + 141, + 143, + 150, + 148, + 182, + 180, + 169, + 171, + 137, + 139, + 154, + 152, + 186, + 184, + 165, + 167, + 133, + 135, + 158, + 156, + 190, + 188, + 161, + 163, + 129, + 131, + 194, + 192, + 226, + 224, + 253, + 255, + 221, + 223, + 198, + 196, + 230, + 228, + 249, + 251, + 217, + 219, + 202, + 200, + 234, + 232, + 245, + 247, + 213, + 215, + 206, + 204, + 238, + 236, + 241, + 243, + 209, + 211, + 210, + 208, + 242, + 240, + 237, + 239, + 205, + 207, + 214, + 212, + 246, + 244, + 233, + 235, + 201, + 203, + 218, + 216, + 250, + 248, + 229, + 231, + 197, + 199, + 222, + 220, + 254, + 252, + 225, + 227, + 193, + 195, + 258, + 256, + 290, + 288, + 317, + 319, + 285, + 287, + 262, + 260, + 294, + 292, + 313, + 315, + 281, + 283, + 266, + 264, + 298, + 296, + 309, + 311, + 277, + 279, + 270, + 268, + 302, + 300, + 305, + 307, + 273, + 275, + 274, + 272, + 306, + 304, + 301, + 303, + 269, + 271, + 278, + 276, + 310, + 308, + 297, + 299, + 265, + 267, + 282, + 280, + 314, + 312, + 293, + 295, + 261, + 263, + 286, + 284, + 318, + 316, + 289, + 291, + 257, + 259, + 322, + 320, + 354, + 352, + 381, + 383, + 349, + 351, + 326, + 324, + 358, + 356, + 377, + 379, + 345, + 347, + 330, + 328, + 362, + 360, + 373, + 375, + 341, + 343, + 334, + 332, + 366, + 364, + 369, + 371, + 337, + 339, + 338, + 336, + 370, + 368, + 365, + 367, + 333, + 335, + 342, + 340, + 374, + 372, + 361, + 363, + 329, + 331, + 346, + 344, + 378, + 376, + 357, + 359, + 325, + 327, + 350, + 348, + 382, + 380, + 353, + 355, + 321, + 323, + 34, + 32, + 2, + 0, + 29, + 31, + 61, + 63, + 38, + 36, + 6, + 4, + 25, + 27, + 57, + 59, + 42, + 40, + 10, + 8, + 21, + 23, + 53, + 55, + 46, + 44, + 14, + 12, + 17, + 19, + 49, + 51, + 50, + 48, + 18, + 16, + 13, + 15, + 45, + 47, + 54, + 52, + 22, + 20, + 9, + 11, + 41, + 43, + 58, + 56, + 26, + 24, + 5, + 7, + 37, + 39, + 62, + 60, + 30, + 28, + 1, + 3, + 33, + 35, + 98, + 96, + 66, + 64, + 93, + 95, + 125, + 127, + 102, + 100, + 70, + 68, + 89, + 91, + 121, + 123, + 106, + 104, + 74, + 72, + 85, + 87, + 117, + 119, + 110, + 108, + 78, + 76, + 81, + 83, + 113, + 115, + 114, + 112, + 82, + 80, + 77, + 79, + 109, + 111, + 118, + 116, + 86, + 84, + 73, + 75, + 105, + 107, + 122, + 120, + 90, + 88, + 69, + 71, + 101, + 103, + 126, + 124, + 94, + 92, + 65, + 67, + 97, + 99, + 162, + 160, + 130, + 128, + 157, + 159, + 189, + 191, + 166, + 164, + 134, + 132, + 153, + 155, + 185, + 187, + 170, + 168, + 138, + 136, + 149, + 151, + 181, + 183, + 174, + 172, + 142, + 140, + 145, + 147, + 177, + 179, + 178, + 176, + 146, + 144, + 141, + 143, + 173, + 175, + 182, + 180, + 150, + 148, + 137, + 139, + 169, + 171, + 186, + 184, + 154, + 152, + 133, + 135, + 165, + 167, + 190, + 188, + 158, + 156, + 129, + 131, + 161, + 163, + 226, + 224, + 194, + 192, + 221, + 223, + 253, + 255, + 230, + 228, + 198, + 196, + 217, + 219, + 249, + 251, + 234, + 232, + 202, + 200, + 213, + 215, + 245, + 247, + 238, + 236, + 206, + 204, + 209, + 211, + 241, + 243, + 242, + 240, + 210, + 208, + 205, + 207, + 237, + 239, + 246, + 244, + 214, + 212, + 201, + 203, + 233, + 235, + 250, + 248, + 218, + 216, + 197, + 199, + 229, + 231, + 254, + 252, + 222, + 220, + 193, + 195, + 225, + 227, + 290, + 288, + 258, + 256, + 285, + 287, + 317, + 319, + 294, + 292, + 262, + 260, + 281, + 283, + 313, + 315, + 298, + 296, + 266, + 264, + 277, + 279, + 309, + 311, + 302, + 300, + 270, + 268, + 273, + 275, + 305, + 307, + 306, + 304, + 274, + 272, + 269, + 271, + 301, + 303, + 310, + 308, + 278, + 276, + 265, + 267, + 297, + 299, + 314, + 312, + 282, + 280, + 261, + 263, + 293, + 295, + 318, + 316, + 286, + 284, + 257, + 259, + 289, + 291, + 354, + 352, + 322, + 320, + 349, + 351, + 381, + 383, + 358, + 356, + 326, + 324, + 345, + 347, + 377, + 379, + 362, + 360, + 330, + 328, + 341, + 343, + 373, + 375, + 366, + 364, + 334, + 332, + 337, + 339, + 369, + 371, + 370, + 368, + 338, + 336, + 333, + 335, + 365, + 367, + 374, + 372, + 342, + 340, + 329, + 331, + 361, + 363, + 378, + 376, + 346, + 344, + 325, + 327, + 357, + 359, + 382, + 380, + 350, + 348, + 321, + 323, + 353, + 355, + 2, + 0, + 34, + 32, + 61, + 63, + 29, + 31, + 6, + 4, + 38, + 36, + 57, + 59, + 25, + 27, + 10, + 8, + 42, + 40, + 53, + 55, + 21, + 23, + 14, + 12, + 46, + 44, + 49, + 51, + 17, + 19, + 18, + 16, + 50, + 48, + 45, + 47, + 13, + 15, + 22, + 20, + 54, + 52, + 41, + 43, + 9, + 11, + 26, + 24, + 58, + 56, + 37, + 39, + 5, + 7, + 30, + 28, + 62, + 60, + 33, + 35, + 1, + 3, + 66, + 64, + 98, + 96, + 125, + 127, + 93, + 95, + 70, + 68, + 102, + 100, + 121, + 123, + 89, + 91, + 74, + 72, + 106, + 104, + 117, + 119, + 85, + 87, + 78, + 76, + 110, + 108, + 113, + 115, + 81, + 83, + 82, + 80, + 114, + 112, + 109, + 111, + 77, + 79, + 86, + 84, + 118, + 116, + 105, + 107, + 73, + 75, + 90, + 88, + 122, + 120, + 101, + 103, + 69, + 71, + 94, + 92, + 126, + 124, + 97, + 99, + 65, + 67, + 130, + 128, + 162, + 160, + 189, + 191, + 157, + 159, + 134, + 132, + 166, + 164, + 185, + 187, + 153, + 155, + 138, + 136, + 170, + 168, + 181, + 183, + 149, + 151, + 142, + 140, + 174, + 172, + 177, + 179, + 145, + 147, + 146, + 144, + 178, + 176, + 173, + 175, + 141, + 143, + 150, + 148, + 182, + 180, + 169, + 171, + 137, + 139, + 154, + 152, + 186, + 184, + 165, + 167, + 133, + 135, + 158, + 156, + 190, + 188, + 161, + 163, + 129, + 131, + 194, + 192, + 226, + 224, + 253, + 255, + 221, + 223, + 198, + 196, + 230, + 228, + 249, + 251, + 217, + 219, + 202, + 200, + 234, + 232, + 245, + 247, + 213, + 215, + 206, + 204, + 238, + 236, + 241, + 243, + 209, + 211, + 210, + 208, + 242, + 240, + 237, + 239, + 205, + 207, + 214, + 212, + 246, + 244, + 233, + 235, + 201, + 203, + 218, + 216, + 250, + 248, + 229, + 231, + 197, + 199, + 222, + 220, + 254, + 252, + 225, + 227, + 193, + 195, + 258, + 256, + 290, + 288, + 317, + 319, + 285, + 287, + 262, + 260, + 294, + 292, + 313, + 315, + 281, + 283, + 266, + 264, + 298, + 296, + 309, + 311, + 277, + 279, + 270, + 268, + 302, + 300, + 305, + 307, + 273, + 275, + 274, + 272, + 306, + 304, + 301, + 303, + 269, + 271, + 278, + 276, + 310, + 308, + 297, + 299, + 265, + 267, + 282, + 280, + 314, + 312, + 293, + 295, + 261, + 263, + 286, + 284, + 318, + 316, + 289, + 291, + 257, + 259, + 322, + 320, + 354, + 352, + 381, + 383, + 349, + 351, + 326, + 324, + 358, + 356, + 377, + 379, + 345, + 347, + 330, + 328, + 362, + 360, + 373, + 375, + 341, + 343, + 334, + 332, + 366, + 364, + 369, + 371, + 337, + 339, + 338, + 336, + 370, + 368, + 365, + 367, + 333, + 335, + 342, + 340, + 374, + 372, + 361, + 363, + 329, + 331, + 346, + 344, + 378, + 376, + 357, + 359, + 325, + 327, + 350, + 348, + 382, + 380, + 353, + 355, + 321, + 323, + 34, + 32, + 2, + 0, + 29, + 31, + 61, + 63, + 38, + 36, + 6, + 4, + 25, + 27, + 57, + 59, + 42, + 40, + 10, + 8, + 21, + 23, + 53, + 55, + 46, + 44, + 14, + 12, + 17, + 19, + 49, + 51, + 50, + 48, + 18, + 16, + 13, + 15, + 45, + 47, + 54, + 52, + 22, + 20, + 9, + 11, + 41, + 43, + 58, + 56, + 26, + 24, + 5, + 7, + 37, + 39, + 62, + 60, + 30, + 28, + 1, + 3, + 33, + 35, + 98, + 96, + 66, + 64, + 93, + 95, + 125, + 127, + 102, + 100, + 70, + 68, + 89, + 91, + 121, + 123, + 106, + 104, + 74, + 72, + 85, + 87, + 117, + 119, + 110, + 108, + 78, + 76, + 81, + 83, + 113, + 115, + 114, + 112, + 82, + 80, + 77, + 79, + 109, + 111, + 118, + 116, + 86, + 84, + 73, + 75, + 105, + 107, + 122, + 120, + 90, + 88, + 69, + 71, + 101, + 103, + 126, + 124, + 94, + 92, + 65, + 67, + 97, + 99, + 162, + 160, + 130, + 128, + 157, + 159, + 189, + 191, + 166, + 164, + 134, + 132, + 153, + 155, + 185, + 187, + 170, + 168, + 138, + 136, + 149, + 151, + 181, + 183, + 174, + 172, + 142, + 140, + 145, + 147, + 177, + 179, + 178, + 176, + 146, + 144, + 141, + 143, + 173, + 175, + 182, + 180, + 150, + 148, + 137, + 139, + 169, + 171, + 186, + 184, + 154, + 152, + 133, + 135, + 165, + 167, + 190, + 188, + 158, + 156, + 129, + 131, + 161, + 163, + 226, + 224, + 194, + 192, + 221, + 223, + 253, + 255, + 230, + 228, + 198, + 196, + 217, + 219, + 249, + 251, + 234, + 232, + 202, + 200, + 213, + 215, + 245, + 247, + 238, + 236, + 206, + 204, + 209, + 211, + 241, + 243, + 242, + 240, + 210, + 208, + 205, + 207, + 237, + 239, + 246, + 244, + 214, + 212, + 201, + 203, + 233, + 235, + 250, + 248, + 218, + 216, + 197, + 199, + 229, + 231, + 254, + 252, + 222, + 220, + 193, + 195, + 225, + 227, + 290, + 288, + 258, + 256, + 285, + 287, + 317, + 319, + 294, + 292, + 262, + 260, + 281, + 283, + 313, + 315, + 298, + 296, + 266, + 264, + 277, + 279, + 309, + 311, + 302, + 300, + 270, + 268, + 273, + 275, + 305, + 307, + 306, + 304, + 274, + 272, + 269, + 271, + 301, + 303, + 310, + 308, + 278, + 276, + 265, + 267, + 297, + 299, + 314, + 312, + 282, + 280, + 261, + 263, + 293, + 295, + 318, + 316, + 286, + 284, + 257, + 259, + 289, + 291, + 354, + 352, + 322, + 320, + 349, + 351, + 381, + 383, + 358, + 356, + 326, + 324, + 345, + 347, + 377, + 379, + 362, + 360, + 330, + 328, + 341, + 343, + 373, + 375, + 366, + 364, + 334, + 332, + 337, + 339, + 369, + 371, + 370, + 368, + 338, + 336, + 333, + 335, + 365, + 367, + 374, + 372, + 342, + 340, + 329, + 331, + 361, + 363, + 378, + 376, + 346, + 344, + 325, + 327, + 357, + 359, + 382, + 380, + 350, + 348, + 321, + 323, + 353, + 355, + }; } } diff --git a/OpenEphys.Onix1/NeuropixelsV1ProbeConfiguration.cs b/OpenEphys.Onix1/NeuropixelsV1ProbeConfiguration.cs index f1d7f1bf..27207f0f 100644 --- a/OpenEphys.Onix1/NeuropixelsV1ProbeConfiguration.cs +++ b/OpenEphys.Onix1/NeuropixelsV1ProbeConfiguration.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Linq; using System.Text; using System.Xml.Serialization; using Bonsai; @@ -26,11 +27,96 @@ public enum NeuropixelsV1Bank /// Specifies that Bank C is the current bank. /// /// - /// Bank C is defined as shank index 768 to 960 along each shank. Note that Bank C is not a full contingent - /// of 384 channels; to compensate for this, electrodes from Bank B (starting at shank index 576) are used to - /// generate a full 384 channel map. + /// + /// For Neuropixels 1.0 probes, Bank C is defined as shank index 768 to 960 along each shank. Note that + /// Bank C is not a full contingent of 384 channels; to compensate for this, electrodes from Bank B + /// (starting at shank index 576) are used to generate a full 384 channel map. + /// + /// + /// For Neuropixels 1.0 UHD probes, Bank C is shank index 768 to 1151 + /// /// - C + C, + /// + /// Specifies that Bank D of the UHD probe is the current bank. + /// + /// Bank D is defined as shank index 1152 to 1535 along each shank. + D, + /// + /// Specifies that Bank E of the UHD probe is the current bank. + /// + /// Bank E is defined as shank index 1536 to 1919 along each shank. + E, + /// + /// Specifies that Bank F of the UHD probe is the current bank. + /// + /// Bank F is defined as shank index 1920 to 2303 along each shank. + F, + /// + /// Specifies that Bank G of the UHD probe is the current bank. + /// + /// Bank G is defined as shank index 2304 to 2687 along each shank. + G, + /// + /// Specifies that Bank H of the UHD probe is the current bank. + /// + /// Bank H is defined as shank index 2688 to 3071 along each shank. + H, + /// + /// Specifies that Bank I of the UHD probe is the current bank. + /// + /// Bank I is defined as shank index 3072 to 3455 along each shank. + I, + /// + /// Specifies that Bank J of the UHD probe is the current bank. + /// + /// Bank J is defined as shank index 3456 to 3839 along each shank. + J, + /// + /// Specifies that Bank K of the UHD probe is the current bank. + /// + /// Bank K is defined as shank index 3840 to 4223 along each shank. + K, + /// + /// Specifies that Bank L of the UHD probe is the current bank. + /// + /// Bank L is defined as shank index 4224 to 4607 along each shank. + L, + /// + /// Specifies that Bank M of the UHD probe is the current bank. + /// + /// Bank M is defined as shank index 4608 to 4991 along each shank. + M, + /// + /// Specifies that Bank N of the UHD probe is the current bank. + /// + /// Bank N is defined as shank index 4992 to 5375 along each shank. + N, + /// + /// Specifies that Bank O of the UHD probe is the current bank. + /// + /// Bank O is defined as shank index 5376 to 5759 along each shank. + O, + /// + /// Specifies that Bank P of the UHD probe is the current bank. + /// + /// Bank P is defined as shank index 5760 to 6143 along each shank. + P + } + + /// + /// Specifies the current probe type. + /// + public enum NeuropixelsV1ProbeType + { + /// + /// Specifies that this is a Neuropixels 1.0 probe. + /// + NP1, + /// + /// Specifies that this is a Neuropixels 1.0 Ultra-High Density probe. + /// + UHD } /// @@ -43,25 +129,32 @@ public class NeuropixelsV1ProbeConfiguration /// public NeuropixelsV1ProbeConfiguration() { - ChannelMap = NeuropixelsV1eProbeGroup.ToChannelMap(ProbeGroup); + ChannelMap = NeuropixelsV1eProbeGroup.ToChannelMap(ProbeGroup, ProbeType); } /// /// Initializes a new instance of using default /// values and the given gain / reference / filter settings. /// + /// Desired or current . /// Desired or current for the spike-band. /// Desired or current for the LFP-band. /// Desired or current . /// Desired or current option to filer the spike-band. - public NeuropixelsV1ProbeConfiguration(NeuropixelsV1Gain spikeAmplifierGain, NeuropixelsV1Gain lfpAmplifierGain, NeuropixelsV1ReferenceSource reference, bool spikeFilter) + public NeuropixelsV1ProbeConfiguration( + NeuropixelsV1ProbeType probeType, + NeuropixelsV1Gain spikeAmplifierGain, + NeuropixelsV1Gain lfpAmplifierGain, + NeuropixelsV1ReferenceSource reference, + bool spikeFilter) { + ProbeType = probeType; + ProbeGroup = new(probeType); SpikeAmplifierGain = spikeAmplifierGain; LfpAmplifierGain = lfpAmplifierGain; Reference = reference; SpikeFilter = spikeFilter; - ProbeGroup = new(); - ChannelMap = NeuropixelsV1eProbeGroup.ToChannelMap(ProbeGroup); + ChannelMap = NeuropixelsV1eProbeGroup.ToChannelMap(ProbeGroup, ProbeType); } /// @@ -69,37 +162,51 @@ public NeuropixelsV1ProbeConfiguration(NeuropixelsV1Gain spikeAmplifierGain, Neu /// values and the given gain / reference / filter settings. /// /// Desired or current variable. + /// Desired or current . /// Desired or current for the spike-band. /// Desired or current for the LFP-band. /// Desired or current . /// Desired or current option to filer the spike-band. - public NeuropixelsV1ProbeConfiguration(NeuropixelsV1eProbeGroup probeGroup, NeuropixelsV1Gain spikeAmplifierGain, NeuropixelsV1Gain lfpAmplifierGain, NeuropixelsV1ReferenceSource reference, bool spikeFilter) + public NeuropixelsV1ProbeConfiguration( + NeuropixelsV1eProbeGroup probeGroup, + NeuropixelsV1ProbeType probeType, + NeuropixelsV1Gain spikeAmplifierGain, + NeuropixelsV1Gain lfpAmplifierGain, + NeuropixelsV1ReferenceSource reference, + bool spikeFilter) { + ProbeType = probeType; SpikeAmplifierGain = spikeAmplifierGain; LfpAmplifierGain = lfpAmplifierGain; Reference = reference; SpikeFilter = spikeFilter; - ChannelMap = NeuropixelsV1eProbeGroup.ToChannelMap(probeGroup); - ProbeGroup = new(); - ProbeGroup.UpdateDeviceChannelIndices(ChannelMap); + ProbeGroup = probeGroup; + ChannelMap = NeuropixelsV1eProbeGroup.ToChannelMap(ProbeGroup, ProbeType); } /// - /// Copy constructor initializes a new instance of using the given - /// values. + /// Copy constructor initializes a new instance of using + /// the given values. /// /// Existing instance. public NeuropixelsV1ProbeConfiguration(NeuropixelsV1ProbeConfiguration probeConfiguration) { + ProbeType = probeConfiguration.ProbeType; SpikeAmplifierGain = probeConfiguration.SpikeAmplifierGain; LfpAmplifierGain = probeConfiguration.LfpAmplifierGain; Reference = probeConfiguration.Reference; SpikeFilter = probeConfiguration.SpikeFilter; - ProbeGroup = new(); - ProbeGroup.UpdateDeviceChannelIndices(probeConfiguration.ChannelMap); - ChannelMap = NeuropixelsV1eProbeGroup.ToChannelMap(ProbeGroup); + ProbeGroup = probeConfiguration.ProbeGroup; + ChannelMap = NeuropixelsV1eProbeGroup.ToChannelMap(ProbeGroup, ProbeType); } + /// + /// Gets or sets the for this probe. + /// + [Browsable(false)] + [Description("Defines the type of probe that is being configured.")] + public NeuropixelsV1ProbeType ProbeType { get; set; } = NeuropixelsV1ProbeType.NP1; + /// /// Gets or sets the amplifier gain for the spike-band. /// @@ -181,7 +288,7 @@ public void SelectElectrodes(NeuropixelsV1Electrode[] electrodes) [XmlIgnore] [Category("Configuration")] [Description("Defines all aspects of the probe group, including probe contours, electrode size and location, enabled channels, etc.")] - public NeuropixelsV1eProbeGroup ProbeGroup { get; set; } = new(); + public NeuropixelsV1eProbeGroup ProbeGroup { get; set; } = new(NeuropixelsV1ProbeType.NP1); /// /// Gets or sets a string defining the in Base64. @@ -202,7 +309,7 @@ public string ProbeGroupString { var jsonString = Encoding.UTF8.GetString(Convert.FromBase64String(value)); ProbeGroup = JsonConvert.DeserializeObject(jsonString); - SelectElectrodes(NeuropixelsV1eProbeGroup.ToChannelMap(ProbeGroup)); + SelectElectrodes(NeuropixelsV1eProbeGroup.ToChannelMap(ProbeGroup, ProbeType)); } } } diff --git a/OpenEphys.Onix1/NeuropixelsV1eProbeGroup.cs b/OpenEphys.Onix1/NeuropixelsV1eProbeGroup.cs index ac9047f3..8fd2d6c6 100644 --- a/OpenEphys.Onix1/NeuropixelsV1eProbeGroup.cs +++ b/OpenEphys.Onix1/NeuropixelsV1eProbeGroup.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; -using OpenEphys.ProbeInterface.NET; -using Newtonsoft.Json; +using System.ComponentModel; using System.Linq; +using Newtonsoft.Json; +using OpenEphys.ProbeInterface.NET; namespace OpenEphys.Onix1 { @@ -14,27 +15,66 @@ public class NeuropixelsV1eProbeGroup : ProbeGroup /// /// Initializes a new instance of the class. /// - public NeuropixelsV1eProbeGroup() - : base("probeinterface", "0.2.21", DefaultProbes()) + public NeuropixelsV1eProbeGroup(NeuropixelsV1ProbeType probeType) + : base("probeinterface", "0.2.21", DefaultProbes(probeType)) + { + } + + internal static string Neuropixels1ProbeName = "Neuropixels 1.0"; + internal static string Neuropixels1UhdProbeName = "Neuropixels Ultra (16 banks)"; + + internal static string GetProbeName(NeuropixelsV1ProbeType probeType) { + return probeType switch + { + NeuropixelsV1ProbeType.NP1 => Neuropixels1ProbeName, + NeuropixelsV1ProbeType.UHD => Neuropixels1UhdProbeName, + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) + }; } - private static Probe[] DefaultProbes() + internal static NeuropixelsV1ProbeType GetProbeTypeFromProbeName(string probeName) + { + if (probeName == Neuropixels1ProbeName) + return NeuropixelsV1ProbeType.NP1; + + else if (probeName == Neuropixels1UhdProbeName) + return NeuropixelsV1ProbeType.UHD; + + else + throw new ArgumentException($"The name '{probeName}' does not match any known Neuropixels 1.0 probe names."); + } + + private static Probe[] DefaultProbes(NeuropixelsV1ProbeType probeType) { var probe = new Probe[1]; + var electrodeCount = probeType switch + { + NeuropixelsV1ProbeType.NP1 => NeuropixelsV1.ElectrodeCount, + NeuropixelsV1ProbeType.UHD => NeuropixelsV1.ElectrodeCountUHD, + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) + }; + + float contactSize = probeType switch + { + NeuropixelsV1ProbeType.NP1 => 12.0f, + NeuropixelsV1ProbeType.UHD => 5.0f, + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) + }; + probe[0] = new(ProbeNdim.Two, ProbeSiUnits.um, - new ProbeAnnotations("Neuropixels 1.0", "IMEC"), + new ProbeAnnotations(GetProbeName(probeType), "IMEC"), null, - DefaultContactPositions(NeuropixelsV1.ElectrodeCount), - Probe.DefaultContactPlaneAxes(NeuropixelsV1.ElectrodeCount), - Probe.DefaultContactShapes(NeuropixelsV1.ElectrodeCount, ContactShape.Square), - Probe.DefaultSquareParams(NeuropixelsV1.ElectrodeCount, 12.0f), - DefaultProbePlanarContour(), - DefaultDeviceChannelIndices(NeuropixelsV1.ChannelCount, NeuropixelsV1.ElectrodeCount), - Probe.DefaultContactIds(NeuropixelsV1.ElectrodeCount), - DefaultShankIds(NeuropixelsV1.ElectrodeCount)); + DefaultContactPositions(electrodeCount, probeType), + Probe.DefaultContactPlaneAxes(electrodeCount), + Probe.DefaultContactShapes(electrodeCount, ContactShape.Square), + Probe.DefaultSquareParams(electrodeCount, contactSize), + DefaultProbePlanarContour(probeType), + DefaultDeviceChannelIndices(NeuropixelsV1.ChannelCount, electrodeCount, probeType), + Probe.DefaultContactIds(electrodeCount), + DefaultShankIds(electrodeCount)); return probe; } @@ -64,15 +104,26 @@ public NeuropixelsV1eProbeGroup(NeuropixelsV1eProbeGroup probeGroup) { } + internal static float[][] DefaultContactPositions(NeuropixelsV1ProbeType probeType) + { + return probeType switch + { + NeuropixelsV1ProbeType.NP1 => DefaultContactPositions(NeuropixelsV1.ElectrodeCount, probeType), + NeuropixelsV1ProbeType.UHD => DefaultContactPositions(NeuropixelsV1.ElectrodeCountUHD, probeType), + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) + }; + } + /// /// Generates a 2D array of default contact positions based on the given number of channels. /// /// Value defining the number of contacts to create positions for. + /// The of the current probe. /// /// 2D array of floats [N x 2], where the first dimension is the contact index [N] and the second dimension [2] /// contains the X and Y values, respectively. /// - public static float[][] DefaultContactPositions(int numberOfContacts) + public static float[][] DefaultContactPositions(int numberOfContacts, NeuropixelsV1ProbeType probeType) { if (numberOfContacts % 2 != 0) { @@ -83,7 +134,7 @@ public static float[][] DefaultContactPositions(int numberOfContacts) for (int i = 0; i < numberOfContacts; i++) { - contactPositions[i] = DefaultContactPosition(i); + contactPositions[i] = DefaultContactPosition(i, probeType); } return contactPositions; @@ -94,35 +145,110 @@ public static float[][] DefaultContactPositions(int numberOfContacts) /// Generates a float array containing the X and Y position of a single contact. /// /// Index of the contact. + /// The of the current probe. /// A float array of size [2 x 1] with the X and Y coordinates, respectively. - public static float[] DefaultContactPosition(int index) + public static float[] DefaultContactPosition(int index, NeuropixelsV1ProbeType probeType) { - return new float[2] { ContactPositionX(index), index / 2 * 20 + 170 }; + return new float[2] { ContactPositionX(index, probeType), ContactPositionY(index, probeType) }; } - private static float ContactPositionX(int index) => (index % 4) switch + static int GetSiteSpacing(NeuropixelsV1ProbeType probeType) => probeType switch + { + NeuropixelsV1ProbeType.NP1 => 20, + NeuropixelsV1ProbeType.UHD => 6, + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) + }; + + internal static int GetNumberOfColumns(NeuropixelsV1ProbeType probeType) => probeType switch { - 0 => 27.0f, - 1 => 59.0f, - 2 => 11.0f, - 3 => 43.0f, - _ => throw new ArgumentException("Invalid index given.") + NeuropixelsV1ProbeType.NP1 => 2, + NeuropixelsV1ProbeType.UHD => 8, + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) }; + static float ContactPositionY(int index, NeuropixelsV1ProbeType probeType) + { + int numColumns = GetNumberOfColumns(probeType); + int siteSpacing = GetSiteSpacing(probeType); + + const int shankOffsetY = 170; + + return probeType switch + { + NeuropixelsV1ProbeType.NP1 => index / numColumns * siteSpacing + shankOffsetY, + NeuropixelsV1ProbeType.UHD => (index - (index % numColumns)) * siteSpacing / numColumns, + _ => throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)) + }; + } + + static float ContactPositionX(int index, NeuropixelsV1ProbeType probeType) + { + if (probeType == NeuropixelsV1ProbeType.NP1) + { + return (index % 4) switch + { + 0 => 27.0f, + 1 => 59.0f, + 2 => 11.0f, + 3 => 43.0f, + _ => throw new ArgumentException("Invalid index given.") + }; + } + else if (probeType == NeuropixelsV1ProbeType.UHD) + { + var columnIndex = NeuropixelsV1Electrode.GetColumnIndex(index, probeType); + + return columnIndex * GetSiteSpacing(probeType); + } + else + throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)); + } + + /// /// Generates a default planar contour for the probe, based on the given probe index /// /// - public static float[][] DefaultProbePlanarContour() + public static float[][] DefaultProbePlanarContour(NeuropixelsV1ProbeType probeType) { float[][] probePlanarContour = new float[6][]; - probePlanarContour[0] = new float[2] { 0f, 155f }; - probePlanarContour[1] = new float[2] { 35f, 0f }; - probePlanarContour[2] = new float[2] { 70f, 155f }; - probePlanarContour[3] = new float[2] { 70f, 9770f }; - probePlanarContour[4] = new float[2] { 0f, 9770f }; - probePlanarContour[5] = new float[2] { 0f, 155f }; + if (probeType == NeuropixelsV1ProbeType.NP1) + { + const float shankTipY = 0f; + const float shankBaseY = 155f; + const float shankLengthY = 9770f; + const float shankBaseX = 0f; + const float shankTipX = 35f; + const float shankLengthX = 70f; + + probePlanarContour[0] = new float[2] { shankBaseX, shankBaseY }; + probePlanarContour[1] = new float[2] { shankTipX, shankTipY }; + probePlanarContour[2] = new float[2] { shankLengthX, shankBaseY }; + probePlanarContour[3] = new float[2] { shankLengthX, shankLengthY }; + probePlanarContour[4] = new float[2] { shankBaseX, shankLengthY }; + probePlanarContour[5] = new float[2] { shankBaseX, shankBaseY }; + } + else if (probeType == NeuropixelsV1ProbeType.UHD) + { + const float shankTipY = -186f; + const float shankBaseY = -11f; + const float shankLengthY = 9989f; + const float shankBaseX = -14f; + const float shankTipX = 21f; + const float shankLengthX = 56f; + + probePlanarContour[0] = new float[2] { shankBaseX, shankBaseY }; + probePlanarContour[1] = new float[2] { shankTipX, shankTipY }; + probePlanarContour[2] = new float[2] { shankLengthX, shankBaseY }; + probePlanarContour[3] = new float[2] { shankLengthX, shankLengthY }; + probePlanarContour[4] = new float[2] { shankBaseX, shankLengthY }; + probePlanarContour[5] = new float[2] { shankBaseX, shankBaseY }; + } + else + { + throw new InvalidEnumArgumentException(nameof(NeuropixelsV1ProbeType)); + } return probePlanarContour; } @@ -133,14 +259,15 @@ public static float[][] DefaultProbePlanarContour() /// /// Number of contacts that are connected for recording /// Total number of physical contacts on the probe + /// The of the current probe. /// - public static int[] DefaultDeviceChannelIndices(int channelCount, int electrodeCount) + public static int[] DefaultDeviceChannelIndices(int channelCount, int electrodeCount, NeuropixelsV1ProbeType probeType = NeuropixelsV1ProbeType.NP1) { int[] deviceChannelIndices = new int[electrodeCount]; for (int i = 0; i < channelCount; i++) { - deviceChannelIndices[i] = i; + deviceChannelIndices[i] = NeuropixelsV1Electrode.GetChannelNumber(i, probeType); } for (int i = channelCount; i < electrodeCount; i++) @@ -192,8 +319,9 @@ internal void UpdateDeviceChannelIndices(NeuropixelsV1Electrode[] channelMap) /// Convert a object to a list of electrodes, which only includes currently enabled electrodes /// /// A object + /// The of the current probe. /// List of 's that are enabled - public static NeuropixelsV1Electrode[] ToChannelMap(NeuropixelsV1eProbeGroup probeGroup) + public static NeuropixelsV1Electrode[] ToChannelMap(NeuropixelsV1eProbeGroup probeGroup, NeuropixelsV1ProbeType probeType) { var enabledContacts = probeGroup.GetContacts().Where(c => c.DeviceId != -1); @@ -204,7 +332,7 @@ public static NeuropixelsV1Electrode[] ToChannelMap(NeuropixelsV1eProbeGroup pro $"index >= 0."); } - return enabledContacts.Select(c => new NeuropixelsV1Electrode(c.Index)) + return enabledContacts.Select(c => new NeuropixelsV1Electrode(c.Index, probeType)) .OrderBy(e => e.Channel) .ToArray(); } @@ -213,14 +341,15 @@ public static NeuropixelsV1Electrode[] ToChannelMap(NeuropixelsV1eProbeGroup pro /// Convert a ProbeInterface object to a list of electrodes, which includes all possible electrodes. /// /// A object. + /// The of the current probe. /// List of electrodes. - public static List ToElectrodes(NeuropixelsV1eProbeGroup probeGroup) + public static List ToElectrodes(NeuropixelsV1eProbeGroup probeGroup, NeuropixelsV1ProbeType probeType) { List electrodes = new(); foreach (var c in probeGroup.GetContacts()) { - electrodes.Add(new NeuropixelsV1Electrode(c.Index)); + electrodes.Add(new NeuropixelsV1Electrode(c.Index, probeType)); } return electrodes; diff --git a/OpenEphys.Onix1/NeuropixelsV1eRegisterContext.cs b/OpenEphys.Onix1/NeuropixelsV1eRegisterContext.cs index 345c90a6..5b99cdde 100644 --- a/OpenEphys.Onix1/NeuropixelsV1eRegisterContext.cs +++ b/OpenEphys.Onix1/NeuropixelsV1eRegisterContext.cs @@ -71,7 +71,6 @@ public NeuropixelsV1eRegisterContext(DeviceContext deviceContext, uint i2cAddres // Create Configuration bit arrays ShankConfig = NeuropixelsV1.MakeShankBits(probeConfiguration); BaseConfigs = NeuropixelsV1.MakeConfigBits(probeConfiguration, Adcs); - } public void InitializeProbe()