private void importToolStripMenuItem_Click(object sender, EventArgs e) { var fd = new OpenFileDialog { Filter = "JSON file|*.json|XML file|*.xml", Title = "Import neuropixels configuration" }; var result = fd.ShowDialog(); if (result == DialogResult.OK && fd.FileName != "") { var config_tmp = new NeuropixelsV1Configuration(); switch (fd.FilterIndex) { case 1: var json = File.ReadAllText(fd.FileName); config_tmp = JsonSerializer.Deserialize <NeuropixelsV1Configuration>(json); break; case 2: var xml = new XmlSerializer(typeof(NeuropixelsV1Configuration)); var xml_file = new FileStream(fd.FileName, FileMode.Open); config_tmp = (NeuropixelsV1Configuration)xml.Deserialize(xml_file); break; } if (config_tmp.ConfigProbeSN != Config.FlexProbeSN) { var txt = String.Format("Warning, the configuration and probe serial numbers do not match. " + "Do you wish to import the channel configuration from probe {0}?. " + "The current ADC calibration data will be preserved", config_tmp.ConfigProbeSN); result = MessageBox.Show(txt, "Serial number mismatch", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result == DialogResult.Yes) { Config.Channels = config_tmp.Channels; } } else { Config = config_tmp; // Bind the data grids dataGridView_Channels.DataSource = Config.Channels; dataGridView_ADCs.DataSource = Config.ADCs; // You need to upload these values Config.RefreshNeeded = true; } CheckStatus(); } }
// Draws the probe and returns the selected electrode indicies public List <int> DrawProbe(NeuropixelsV1Configuration config, Graphics g, Panel panel) { var selectLocations = new PointF[] { mouseLocation, selectionStart, selectionEnd, emptyPoint, new Point(panel.Size) }; g.ResetTransform(); g.TranslateTransform(translate.X, translate.Y); g.ScaleTransform(scale, scale); g.TransformPoints(CoordinateSpace.World, CoordinateSpace.Page, selectLocations); var pen = new Pen(Color.Black); var brushGrey = new SolidBrush(Color.Gray); var brushOrange = new SolidBrush(Color.Orange); var brushBlue = new SolidBrush(Color.CornflowerBlue); var brushGreen = new SolidBrush(Color.LightSeaGreen); var brushBlack = new SolidBrush(Color.Black); // 1 world unit = 1 uM const int tipLength = 175; const int pixelPitch = 20; const int pixelDiam = 12; const int shankWidth = 70; const int arrayLength = 10000; // (NeuropixelsV1Probe.ELECTRODE_COUNT + 10) * pixelPitch / 2; var active_electrodes = config.Channels.Select(x => x.ElectrodeNumber); if (!drawMaintainedSelection) { selectedElectrodes.Clear(); } int k = 0; Point mouseLoc = new Point((int)selectLocations[0].X, (int)selectLocations[0].Y); var selection = new Rectangle( (int)selectLocations[1].X, (int)selectLocations[1].Y, (int)(selectLocations[2].X - selectLocations[1].X), (int)(selectLocations[2].Y - selectLocations[1].Y)); var panelBounds = new Rectangle( (int)selectLocations[3].X, (int)selectLocations[3].Y, (int)(selectLocations[4].X - selectLocations[3].X), (int)(selectLocations[4].Y - selectLocations[3].Y) ); for (int i = 0; i < NeuropixelsV1Probe.ELECTRODE_COUNT; i++) { int sh = (k % 2) == 0 ? -pixelPitch / 4 : pixelPitch / 4; int y_pos = (i % 2) == 0 ? -pixelPitch / 2 : pixelPitch / 2; k += i % 2; var loc = new Point(tipLength + i / 2 * pixelPitch - pixelDiam / 2, sh + y_pos - pixelDiam / 2); var r = new Rectangle(loc, new Size(pixelDiam, pixelDiam)); var eLoc = new Point(r.Location.X + pixelDiam / 2, r.Location.Y + pixelDiam / 2); // If the electrode is not in the panel then ignore it if (!RectangleOverlap(r, panelBounds)) { continue; } // Draw selection boundary if (selection.Width != 0 && selection.Height != 0) { g.DrawRectangle(pen, selection); } // Draw electrode g.DrawRectangle(pen, r); // Various electrode fill options if (drawMaintainedSelection && selectedElectrodes.Contains(i)) { g.FillRectangle(brushOrange, r); } else if (!selection.IsEmpty && electrodeSelect && selection.Contains(eLoc)) { g.FillRectangle(brushOrange, r); selectedElectrodes.Add(i); multiSelect = true; } else if (r.Contains(mouseLoc) && electrodeSelect && !drawMaintainedSelection) { g.FillRectangle(brushOrange, r); selectedElectrodes.Add(i); multiSelect = false; } else if (active_electrodes.Contains(i)) { selectedElectrodes.RemoveAll(x => x == i); if (NeuropixelsV1Probe.ElectrodeToChannel(i) == NeuropixelsV1Probe.INTERNAL_REF_CHANNEL) { g.FillRectangle(brushGreen, r); } else { g.FillRectangle(brushBlue, r); } } // Electrode information var c = config.Channels[NeuropixelsV1Probe.ElectrodeToChannel(i)]; g.DrawString(i.ToString(), new Font(FontFamily.GenericSansSerif, 4, GraphicsUnit.Pixel), brushBlack, loc); var info = string.Format("Chan.: {0}\nRef.: {1}\nLFP Gain: {2}\nAP Gain: {3}\nAP Filt.: {4}\nStandby: {5}\nBank: {6}", c.Index, c.Reference, c.LFPGain, c.APGain, c.APFilter, c.Standby, c.Bank); g.DrawString(info, new Font(FontFamily.GenericSansSerif, 1, GraphicsUnit.Pixel), brushBlack, new Point(loc.X, loc.Y + 4)); } // Probe outline var tip = new Point(0, 0); var start_top = new Point(tipLength, shankWidth / 2); var end_top = new Point(arrayLength, shankWidth / 2); var start_bottom = new Point(tipLength, -shankWidth / 2); var end_bottom = new Point(arrayLength, -shankWidth / 2); g.DrawLine(pen, tip, start_top); g.DrawLine(pen, tip, start_bottom); g.DrawLine(pen, start_top, end_top); g.DrawLine(pen, start_bottom, end_bottom); // Tip reference g.FillPolygon(brushGreen, new Point[] { new Point(tip.X + 40, tip.Y), new Point(start_top.X - 10, start_top.Y - 10), new Point(start_bottom.X - 10, start_bottom.Y + 10) }); // Draw ruler var ruler_start = new Point(tip.X, start_top.Y + 10); var ruler_end = new Point(ruler_start.X + arrayLength, ruler_start.Y); g.DrawLine(pen, ruler_start, ruler_end); // Minor ticks for (var i = 0; i <= arrayLength; i += 10) { var tick_start = new Point(ruler_start.X + i, ruler_start.Y); var tick_end = new Point(ruler_start.X + i, ruler_start.Y + 4); g.DrawLine(pen, tick_start, tick_end); } // Major ticks for (var i = 0; i <= arrayLength; i += 100) { var tick_start = new Point(ruler_start.X + i, ruler_start.Y); var tick_end = new Point(ruler_start.X + i, ruler_start.Y + 12); g.DrawLine(pen, tick_start, tick_end); g.DrawString((i).ToString() + " μm", new Font(FontFamily.GenericSansSerif, 10), brushBlack, tick_end); } return(selectedElectrodes); }
public NeuropixelsV1EditorDialog(Bonsai.ONIX.NeuropixelsV1Configuration config) { InitializeComponent(); // Create a deep copy of the configuration to work with internally that won't // commit changes to config until user clicks "OK" Config = ObjectExtensions.Copy(config); // Display probe and config SNs CheckStatus(); // Recall if we need to perform a read check performSRReadCheckToolStripMenuItem.Checked = Config.PerformReadCheck; // Need to manually add the SelectedIndexChange event handler or assigning the data source will trigger it toolStripComboBoxOperationMode.ComboBox.BindingContext = this.BindingContext; toolStripComboBoxOperationMode.ComboBox.DataSource = Enum.GetValues(typeof(NeuropixelsV1Configuration.OperationMode)); toolStripComboBoxOperationMode.ComboBox.SelectedItem = Config.Mode; toolStripComboBoxOperationMode.ComboBox.SelectedIndexChanged += new EventHandler(toolStripComboBoxOperationMode_SelectedIndexChanged); var combo_col = new DataGridViewComboBoxColumn { HeaderText = "Bank", DataPropertyName = "Bank", ValueType = typeof(NeuropixelsV1Channel.ElectrodeBank), DataSource = Enum.GetValues(typeof(NeuropixelsV1Channel.ElectrodeBank)), }; dataGridView_Channels.Columns.Add(combo_col); combo_col = new DataGridViewComboBoxColumn { HeaderText = "AP Gain", DataPropertyName = "APGain", ValueType = typeof(NeuropixelsV1Channel.Gain), DataSource = Enum.GetValues(typeof(NeuropixelsV1Channel.Gain)) }; dataGridView_Channels.Columns.Add(combo_col); combo_col = new DataGridViewComboBoxColumn { HeaderText = "LFP Gain", DataPropertyName = "LFPGain", ValueType = typeof(NeuropixelsV1Channel.Gain), DataSource = Enum.GetValues(typeof(NeuropixelsV1Channel.Gain)) }; dataGridView_Channels.Columns.Add(combo_col); combo_col = new DataGridViewComboBoxColumn { HeaderText = "Reference", DataPropertyName = "Reference", ValueType = typeof(NeuropixelsV1Channel.Ref), DataSource = Enum.GetValues(typeof(NeuropixelsV1Channel.Ref)) }; dataGridView_Channels.Columns.Add(combo_col); // Immediate update dataGridView_Channels.CellEndEdit += dataGridView_Channels_CellEndEdit; // Bind the data grids dataGridView_Channels.DataSource = Config.Channels; dataGridView_ADCs.DataSource = Config.ADCs; // Drawing panel options typeof(Panel).InvokeMember("DoubleBuffered", BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, panelProbeDrawing, new object[] { true }); panelProbeDrawing.MouseWheel += panelProbeDrawing_MouseWheel; probeDrawing = new NeuropixelsV1Drawing(panelProbeDrawing); panelProbeDrawing.MouseMove += panelProbeDrawing_MouseMove; panelProbeDrawing.MouseDown += panelProbeDrawing_MouseDown; panelProbeDrawing.MouseUp += panelProbeDrawing_MouseUp; panelProbeDrawing.PreviewKeyDown += panelProbeDrawing_PreviewKeyDown; apGainToolStripComboBox.ComboBox.BindingContext = BindingContext; apGainToolStripComboBox.ComboBox.DataSource = Enum.GetValues(typeof(NeuropixelsV1Channel.Gain)); lfpGainToolStripComboBox.ComboBox.BindingContext = BindingContext; lfpGainToolStripComboBox.ComboBox.DataSource = Enum.GetValues(typeof(NeuropixelsV1Channel.Gain)); referenceToolStripComboBox.ComboBox.BindingContext = BindingContext; referenceToolStripComboBox.ComboBox.DataSource = Enum.GetValues(typeof(NeuropixelsV1Channel.Ref)); }