diff --git a/OpenEphys.ProbeInterface.NET.sln b/OpenEphys.ProbeInterface.NET.sln
index db2d59d..6a525bb 100644
--- a/OpenEphys.ProbeInterface.NET.sln
+++ b/OpenEphys.ProbeInterface.NET.sln
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34511.84
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenEphys.ProbeInterface.NET", "OpenEphys.ProbeInterface.NET\OpenEphys.ProbeInterface.NET.csproj", "{822F3536-A4B7-4FE4-8332-A75A8458EE56}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenEphys.ProbeInterface.NET", "OpenEphys.ProbeInterface.NET\OpenEphys.ProbeInterface.NET.csproj", "{822F3536-A4B7-4FE4-8332-A75A8458EE56}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F8644FAC-94E5-4E73-B809-925ABABE35B1}"
ProjectSection(SolutionItems) = preProject
diff --git a/OpenEphys.ProbeInterface.NET/Contact.cs b/OpenEphys.ProbeInterface.NET/Contact.cs
new file mode 100644
index 0000000..b25f9bc
--- /dev/null
+++ b/OpenEphys.ProbeInterface.NET/Contact.cs
@@ -0,0 +1,72 @@
+namespace OpenEphys.ProbeInterface.NET
+{
+ ///
+ /// Struct that extends the Probeinterface specification by encapsulating all values for a single contact.
+ ///
+ public readonly struct Contact
+ {
+ ///
+ /// Gets the x-position of the contact.
+ ///
+ public float PosX { get; }
+
+ ///
+ /// Gets the y-position of the contact.
+ ///
+ public float PosY { get; }
+
+ ///
+ /// Gets the of the contact.
+ ///
+ public ContactShape Shape { get; }
+
+ ///
+ /// Gets the 's of the contact.
+ ///
+ public ContactShapeParam ShapeParams { get; }
+
+ ///
+ /// Gets the device ID of the contact.
+ ///
+ public int DeviceId { get; }
+
+ ///
+ /// Gets the contact ID of the contact.
+ ///
+ public string ContactId { get; }
+
+ ///
+ /// Gets the shank ID of the contact.
+ ///
+ public string ShankId { get; }
+
+ ///
+ /// Gets the index of the contact within the object.
+ ///
+ public int Index { get; }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// Center value of the contact on the X-axis.
+ /// Center value of the contact on the Y-axis.
+ /// The of the contact.
+ /// 's relevant to the of the contact.
+ /// The device channel index () of this contact.
+ /// The contact ID () of this contact.
+ /// The shank ID () of this contact.
+ /// The index of the contact within the context of the .
+ public Contact(float posX, float posY, ContactShape shape, ContactShapeParam shapeParam,
+ int deviceId, string contactId, string shankId, int index)
+ {
+ PosX = posX;
+ PosY = posY;
+ Shape = shape;
+ ShapeParams = shapeParam;
+ DeviceId = deviceId;
+ ContactId = contactId;
+ ShankId = shankId;
+ Index = index;
+ }
+ }
+}
diff --git a/OpenEphys.ProbeInterface.NET/ContactAnnotations.cs b/OpenEphys.ProbeInterface.NET/ContactAnnotations.cs
new file mode 100644
index 0000000..73b241e
--- /dev/null
+++ b/OpenEphys.ProbeInterface.NET/ContactAnnotations.cs
@@ -0,0 +1,25 @@
+using Newtonsoft.Json;
+
+namespace OpenEphys.ProbeInterface.NET
+{
+ ///
+ /// Class holding all of the annotations for each contact.
+ ///
+ public class ContactAnnotations
+ {
+ ///
+ /// Gets the array of strings holding annotations for each contact. Not all indices must have annotations.
+ ///
+ public string[] Annotations { get; protected set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Array of strings containing annotations for each contact. Size of the array should match the number of contacts, but they can be empty strings.
+ [JsonConstructor]
+ public ContactAnnotations(string[] contactAnnotations)
+ {
+ Annotations = contactAnnotations;
+ }
+ }
+}
diff --git a/OpenEphys.ProbeInterface.NET/ContactShape.cs b/OpenEphys.ProbeInterface.NET/ContactShape.cs
new file mode 100644
index 0000000..cf90d3d
--- /dev/null
+++ b/OpenEphys.ProbeInterface.NET/ContactShape.cs
@@ -0,0 +1,31 @@
+using System.Runtime.Serialization;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace OpenEphys.ProbeInterface.NET
+{
+ ///
+ /// Shape of the contact.
+ ///
+ [JsonConverter(typeof(StringEnumConverter))]
+ public enum ContactShape
+ {
+ ///
+ /// Circle.
+ ///
+ [EnumMember(Value = "circle")]
+ Circle = 0,
+
+ ///
+ /// Rectangle.
+ ///
+ [EnumMember(Value = "rect")]
+ Rect = 1,
+
+ ///
+ /// Square.
+ ///
+ [EnumMember(Value = "square")]
+ Square = 2,
+ }
+}
diff --git a/OpenEphys.ProbeInterface.NET/ContactShapeParam.cs b/OpenEphys.ProbeInterface.NET/ContactShapeParam.cs
new file mode 100644
index 0000000..943046b
--- /dev/null
+++ b/OpenEphys.ProbeInterface.NET/ContactShapeParam.cs
@@ -0,0 +1,63 @@
+using Newtonsoft.Json;
+
+namespace OpenEphys.ProbeInterface.NET
+{
+ ///
+ /// Class holding parameters used to draw the contact.
+ ///
+ ///
+ /// Fields are nullable, since not all fields are required depending on the shape selected.
+ ///
+ public class ContactShapeParam
+ {
+ ///
+ /// Gets the radius of the contact.
+ ///
+ ///
+ /// This is only used to draw contacts. Field can be null.
+ ///
+ public float? Radius { get; protected set; }
+
+ ///
+ /// Gets the width of the contact.
+ ///
+ ///
+ /// This is used to draw or contacts.
+ /// Field can be null.
+ ///
+ public float? Width { get; protected set; }
+
+ ///
+ /// Gets the height of the contact.
+ ///
+ ///
+ /// This is only used to draw contacts. Field can be null.
+ ///
+ public float? Height { get; protected set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Radius. Can be null.
+ /// Width. Can be null.
+ /// Height. Can be null.
+ [JsonConstructor]
+ public ContactShapeParam(float? radius = null, float? width = null, float? height = null)
+ {
+ Radius = radius;
+ Width = width;
+ Height = height;
+ }
+
+ ///
+ /// Copy constructor given an existing object.
+ ///
+ /// Existing object to be copied.
+ protected ContactShapeParam(ContactShapeParam shape)
+ {
+ Radius = shape.Radius;
+ Width = shape.Width;
+ Height = shape.Height;
+ }
+ }
+}
diff --git a/OpenEphys.ProbeInterface.NET/Probe.cs b/OpenEphys.ProbeInterface.NET/Probe.cs
new file mode 100644
index 0000000..b7a84ad
--- /dev/null
+++ b/OpenEphys.ProbeInterface.NET/Probe.cs
@@ -0,0 +1,329 @@
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+
+namespace OpenEphys.ProbeInterface.NET
+{
+ ///
+ /// Class that implements the Probe Interface specification for a Probe.
+ ///
+ public class Probe
+ {
+ ///
+ /// Gets the to use while plotting the .
+ ///
+ [XmlIgnore]
+ [JsonProperty("ndim", Required = Required.Always)]
+ public ProbeNdim NumDimensions { get; protected set; }
+
+ ///
+ /// Gets the to use while plotting the .
+ ///
+ [XmlIgnore]
+ [JsonProperty("si_units", Required = Required.Always)]
+ public ProbeSiUnits SiUnits { get; protected set; }
+
+ ///
+ /// Gets the for the .
+ ///
+ ///
+ /// Used to specify the name of the probe, and the manufacturer.
+ ///
+ [XmlIgnore]
+ [JsonProperty("annotations", Required = Required.Always)]
+ public ProbeAnnotations Annotations { get; protected set; }
+
+ ///
+ /// Gets the for the .
+ ///
+ ///
+ /// This field can be used for noting things like where it physically is within a specimen, or if it
+ /// is no longer functioning correctly.
+ ///
+ [XmlIgnore]
+ [JsonProperty("contact_annotations")]
+ public ContactAnnotations ContactAnnotations { get; protected set; }
+
+ ///
+ /// Gets the positions, specifically the center point of every contact.
+ ///
+ ///
+ /// This is a two-dimensional array of floats; the first index is the index of the contact, and
+ /// the second index is the X and Y value, respectively.
+ ///
+ [XmlIgnore]
+ [JsonProperty("contact_positions", Required = Required.Always)]
+ public float[][] ContactPositions { get; protected set; }
+
+ ///
+ /// Gets the plane axes for the contacts.
+ ///
+ [XmlIgnore]
+ [JsonProperty("contact_plane_axes")]
+ public float[][][] ContactPlaneAxes { get; protected set; }
+
+ ///
+ /// Gets the for each contact.
+ ///
+ [XmlIgnore]
+ [JsonProperty("contact_shapes", Required = Required.Always)]
+ public ContactShape[] ContactShapes { get; protected set; }
+
+ ///
+ /// Gets the parameters of the shape for each contact.
+ ///
+ ///
+ /// Depending on which
+ /// is selected, not all parameters are needed; for instance, only uses
+ /// , while just uses
+ /// .
+ ///
+ [XmlIgnore]
+ [JsonProperty("contact_shape_params", Required = Required.Always)]
+ public ContactShapeParam[] ContactShapeParams { get; protected set; }
+
+ ///
+ /// Gets the outline of the probe that represents the physical shape.
+ ///
+ [XmlIgnore]
+ [JsonProperty("probe_planar_contour")]
+ public float[][] ProbePlanarContour { get; protected set; }
+
+ ///
+ /// Gets the indices of each channel defining their recording channel number. Must be unique, except for contacts
+ /// that are set to -1 if they disabled.
+ ///
+ [XmlIgnore]
+ [JsonProperty("device_channel_indices")]
+ public int[] DeviceChannelIndices { get; internal set; }
+
+ ///
+ /// Gets the contact IDs for each channel. These do not have to be unique.
+ ///
+ [XmlIgnore]
+ [JsonProperty("contact_ids")]
+ public string[] ContactIds { get; internal set; }
+
+ ///
+ /// Gets the shank that each contact belongs to.
+ ///
+ [XmlIgnore]
+ [JsonProperty("shank_ids")]
+ public string[] ShankIds { get; internal set; }
+
+ ///
+ /// Public constructor, defined as the default Json constructor.
+ ///
+ /// Number of dimensions to use while plotting the contacts [ or ].
+ /// Real-world units to use while plotting the contacts [ or ].
+ /// Annotations for the probe.
+ /// Annotations for each contact as an array of strings.
+ /// Center position of each contact in a two-dimensional array of floats. For more info, see .
+ /// Plane axes of each contact in a three-dimensional array of floats. For more info, see .
+ /// Array of shapes for each contact.
+ /// Array of shape parameters for the each contact.
+ /// Two-dimensional array of floats (X and Y positions) defining a closed shape for a probe contour.
+ /// Array of integers containing the device channel indices for each contact. For more info, see .
+ /// Array of strings containing the contact ID for each contact. For more info, see .
+ /// Array of strings containing the shank ID for each contact. For more info, see .
+ [JsonConstructor]
+ public Probe(ProbeNdim ndim, ProbeSiUnits si_units, ProbeAnnotations annotations, ContactAnnotations contact_annotations,
+ float[][] contact_positions, float[][][] contact_plane_axes, ContactShape[] contact_shapes,
+ ContactShapeParam[] contact_shape_params, float[][] probe_planar_contour, int[] device_channel_indices,
+ string[] contact_ids, string[] shank_ids)
+ {
+ NumDimensions = ndim;
+ SiUnits = si_units;
+ Annotations = annotations;
+ ContactAnnotations = contact_annotations;
+ ContactPositions = contact_positions;
+ ContactPlaneAxes = contact_plane_axes;
+ ContactShapes = contact_shapes;
+ ContactShapeParams = contact_shape_params;
+ ProbePlanarContour = probe_planar_contour;
+ DeviceChannelIndices = device_channel_indices;
+ ContactIds = contact_ids;
+ ShankIds = shank_ids;
+ }
+
+ ///
+ /// Copy constructor given an existing object.
+ ///
+ /// Existing object to be copied.
+ protected Probe(Probe probe)
+ {
+ NumDimensions = probe.NumDimensions;
+ SiUnits = probe.SiUnits;
+ Annotations = probe.Annotations;
+ ContactAnnotations = probe.ContactAnnotations;
+ ContactPositions = probe.ContactPositions;
+ ContactPlaneAxes = probe.ContactPlaneAxes;
+ ContactShapes = probe.ContactShapes;
+ ContactShapeParams = probe.ContactShapeParams;
+ ProbePlanarContour = probe.ProbePlanarContour;
+ DeviceChannelIndices = probe.DeviceChannelIndices;
+ ContactIds = probe.ContactIds;
+ ShankIds = probe.ShankIds;
+ }
+
+ ///
+ /// Returns default array that contains the given number of channels and the corresponding shape.
+ ///
+ /// Number of contacts in a single .
+ /// The to apply to each contact.
+ /// array.
+ public static ContactShape[] DefaultContactShapes(int numberOfContacts, ContactShape contactShape)
+ {
+ ContactShape[] contactShapes = new ContactShape[numberOfContacts];
+
+ for (int i = 0; i < numberOfContacts; i++)
+ {
+ contactShapes[i] = contactShape;
+ }
+
+ return contactShapes;
+ }
+
+ ///
+ /// Returns a default contactPlaneAxes array, with each contact given the same axis; { { 1, 0 }, { 0, 1 } }
+ ///
+ ///
+ /// See Probeinterface documentation for more info.
+ ///
+ /// Number of contacts in a single .
+ /// Three-dimensional array of s.
+ public static float[][][] DefaultContactPlaneAxes(int numberOfContacts)
+ {
+ float[][][] contactPlaneAxes = new float[numberOfContacts][][];
+
+ for (int i = 0; i < numberOfContacts; i++)
+ {
+ contactPlaneAxes[i] = new float[2][] { new float[2] { 1.0f, 0.0f }, new float[2] { 0.0f, 1.0f } };
+ }
+
+ return contactPlaneAxes;
+ }
+
+ ///
+ /// Returns an array of s for a .
+ ///
+ /// Number of contacts in a single .
+ /// Radius of the contact, in units of .
+ /// array.
+ public static ContactShapeParam[] DefaultCircleParams(int numberOfContacts, float radius)
+ {
+ ContactShapeParam[] contactShapeParams = new ContactShapeParam[numberOfContacts];
+
+ for (int i = 0; i < numberOfContacts; i++)
+ {
+ contactShapeParams[i] = new ContactShapeParam(radius: radius);
+ }
+
+ return contactShapeParams;
+ }
+
+ ///
+ /// Returns an array of s for a .
+ ///
+ /// Number of contacts in a single .
+ /// Width of the contact, in units of .
+ /// array.
+ public static ContactShapeParam[] DefaultSquareParams(int numberOfContacts, float width)
+ {
+ ContactShapeParam[] contactShapeParams = new ContactShapeParam[numberOfContacts];
+
+ for (int i = 0; i < numberOfContacts; i++)
+ {
+ contactShapeParams[i] = new ContactShapeParam(width: width);
+ }
+
+ return contactShapeParams;
+ }
+
+ ///
+ /// Returns an array of s for a .
+ ///
+ /// Number of contacts in a single .
+ /// Width of the contact, in units of .
+ /// Height of the contact, in units of .
+ /// array.
+ public static ContactShapeParam[] DefaultRectParams(int numberOfContacts, float width, float height)
+ {
+ ContactShapeParam[] contactShapeParams = new ContactShapeParam[numberOfContacts];
+
+ for (int i = 0; i < numberOfContacts; i++)
+ {
+ contactShapeParams[i] = new ContactShapeParam(width: width, height: height);
+ }
+
+ return contactShapeParams;
+ }
+
+ ///
+ /// Returns a default array of sequential .
+ ///
+ /// Number of contacts in a single .
+ /// The first value of the .
+ /// A serially increasing array of .
+ public static int[] DefaultDeviceChannelIndices(int numberOfContacts, int offset)
+ {
+ int[] deviceChannelIndices = new int[numberOfContacts];
+
+ for (int i = 0; i < numberOfContacts; i++)
+ {
+ deviceChannelIndices[i] = i + offset;
+ }
+
+ return deviceChannelIndices;
+ }
+
+ ///
+ /// Returns a sequential array of .
+ ///
+ /// Number of contacts in a single .
+ /// Array of strings defining the .
+ public static string[] DefaultContactIds(int numberOfContacts)
+ {
+ string[] contactIds = new string[numberOfContacts];
+
+ for (int i = 0; i < numberOfContacts; i++)
+ {
+ contactIds[i] = i.ToString();
+ }
+
+ return contactIds;
+ }
+
+ ///
+ /// Returns an array of empty strings as the default shank ID.
+ ///
+ /// Number of contacts in a single .
+ /// Array of empty strings.
+ public static string[] DefaultShankIds(int numberOfContacts)
+ {
+ string[] contactIds = new string[numberOfContacts];
+
+ for (int i = 0; i < numberOfContacts; i++)
+ {
+ contactIds[i] = "";
+ }
+
+ return contactIds;
+ }
+
+ ///
+ /// Returns a object.
+ ///
+ /// Relative index of the contact in this .
+ /// .
+ public Contact GetContact(int index)
+ {
+ return new Contact(ContactPositions[index][0], ContactPositions[index][1], ContactShapes[index], ContactShapeParams[index],
+ DeviceChannelIndices[index], ContactIds[index], ShankIds[index], index);
+ }
+
+ ///
+ /// Gets the number of contacts within this .
+ ///
+ public int NumberOfContacts => ContactPositions.Length;
+ }
+}
diff --git a/OpenEphys.ProbeInterface.NET/ProbeAnnotations.cs b/OpenEphys.ProbeInterface.NET/ProbeAnnotations.cs
new file mode 100644
index 0000000..72f9011
--- /dev/null
+++ b/OpenEphys.ProbeInterface.NET/ProbeAnnotations.cs
@@ -0,0 +1,44 @@
+using Newtonsoft.Json;
+
+namespace OpenEphys.ProbeInterface.NET
+{
+ ///
+ /// Class holding the annotations.
+ ///
+ public class ProbeAnnotations
+ {
+ ///
+ /// Gets the name of the probe as defined by the manufacturer, or a descriptive name such as the neurological target.
+ ///
+ [JsonProperty("name")]
+ public string Name { get; protected set; }
+
+ ///
+ /// Gets the name of the manufacturer who created the probe.
+ ///
+ [JsonProperty("manufacturer")]
+ public string Manufacturer { get; protected set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// String defining the name of the probe.
+ /// String defining the manufacturer of the probe.
+ [JsonConstructor]
+ public ProbeAnnotations(string name, string manufacturer)
+ {
+ Name = name;
+ Manufacturer = manufacturer;
+ }
+
+ ///
+ /// Copy constructor that copies data from an existing object.
+ ///
+ /// Existing object, containing a and a .
+ protected ProbeAnnotations(ProbeAnnotations probeAnnotations)
+ {
+ Name = probeAnnotations.Name;
+ Manufacturer = probeAnnotations.Manufacturer;
+ }
+ }
+}
diff --git a/OpenEphys.ProbeInterface.NET/ProbeGroup.cs b/OpenEphys.ProbeInterface.NET/ProbeGroup.cs
new file mode 100644
index 0000000..5c6408f
--- /dev/null
+++ b/OpenEphys.ProbeInterface.NET/ProbeGroup.cs
@@ -0,0 +1,327 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Serialization;
+using Newtonsoft.Json;
+using System;
+
+namespace OpenEphys.ProbeInterface.NET
+{
+ ///
+ /// Abstract class that implements the Probeinterface specification in C# for .NET.
+ ///
+ public abstract class ProbeGroup
+ {
+ ///
+ /// Gets the string defining the specification of the file.
+ ///
+ ///
+ /// For Probeinterface files, this value is expected to be "probeinterface".
+ ///
+ [JsonProperty("specification", Required = Required.Always)]
+ public string Specification { get; protected set; }
+
+ ///
+ /// Gets the string defining which version of Probeinterface was used.
+ ///
+ [JsonProperty("version", Required = Required.Always)]
+ public string Version { get; protected set; }
+
+ ///
+ /// Gets an IEnumerable of probes that are present.
+ ///
+ ///
+ /// Each probe can contain multiple shanks, and each probe has a unique
+ /// contour that defines the physical representation of the probe. Contacts have several representations
+ /// for their channel number, specifically (a string that is not guaranteed to be unique) and
+ /// (guaranteed to be unique across all probes). 's can also be set to -1
+ /// to indicate that the channel was not connected or recorded from.
+ ///
+ [XmlIgnore]
+ [JsonProperty("probes", Required = Required.Always)]
+ public IEnumerable Probes { get; protected set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// String defining the parameter.
+ /// String defining the parameter.
+ /// IEnumerable of objects.
+ public ProbeGroup(string specification, string version, IEnumerable probes)
+ {
+ Specification = specification;
+ Version = version;
+ Probes = probes;
+
+ Validate();
+ }
+
+ ///
+ /// Copy constructor that takes in an existing object and copies the individual fields.
+ ///
+ ///
+ /// After copying the relevant fields, the is validated to ensure that it is compliant
+ /// with the Probeinterface specification. See for more details on what is checked.
+ ///
+ /// Existing object.
+ protected ProbeGroup(ProbeGroup probeGroup)
+ {
+ Specification = probeGroup.Specification;
+ Version = probeGroup.Version;
+ Probes = probeGroup.Probes;
+
+ Validate();
+ }
+
+ ///
+ /// Gets the number of contacts across all objects.
+ ///
+ public int NumberOfContacts => Probes.Aggregate(0, (total, next) => total + next.NumberOfContacts);
+
+ ///
+ /// Returns the 's of all contacts in all probes.
+ ///
+ ///
+ /// Note that these are not guaranteed to be unique values across probes.
+ ///
+ /// List of strings containing all contact IDs.
+ public IEnumerable GetContactIds()
+ {
+ List contactIds = new();
+
+ foreach (var probe in Probes)
+ {
+ contactIds.AddRange(probe.ContactIds.ToList());
+ }
+
+ return contactIds;
+ }
+
+ ///
+ /// Returns all objects in the .
+ ///
+ ///
+ public List GetContacts()
+ {
+ List contacts = new();
+
+ foreach (var p in Probes)
+ {
+ for (int i = 0; i < p.NumberOfContacts; i++)
+ {
+ contacts.Add(p.GetContact(i));
+ }
+ }
+
+ return contacts;
+ }
+
+ ///
+ /// Returns all 's in the .
+ ///
+ ///
+ /// Device channel indices are guaranteed to be unique, unless they are -1. Multiple contacts can be
+ /// set to -1 to indicate they are not recorded from.
+ ///
+ ///
+ public IEnumerable GetDeviceChannelIndices()
+ {
+ List deviceChannelIndices = new();
+
+ foreach (var probe in Probes)
+ {
+ deviceChannelIndices.AddRange(probe.DeviceChannelIndices.ToList());
+ }
+
+ return deviceChannelIndices;
+ }
+
+ ///
+ /// Validate that the correctly implements the Probeinterface specification.
+ ///
+ ///
+ /// Check that all necessary fields are populated (,
+ /// , ).
+ /// Check that there is at least one defined.
+ /// Check that all variables in each have the same length.
+ /// Check if are present, and generate default values
+ /// based on the index if there are no values defined.
+ /// Check if are zero-indexed, and convert to
+ /// zero-indexed if possible.
+ /// Check if are defined, and initialize empty strings
+ /// if they are not defined.
+ /// Check if are defined, and initialize default
+ /// values (using the value as the new ).
+ /// Check that all are unique across all 's,
+ /// unless the value is -1; multiple contacts can be set to -1.
+ ///
+ public void Validate()
+ {
+ if (string.IsNullOrEmpty(Specification))
+ {
+ throw new InvalidOperationException("Specification string must be defined.");
+ }
+
+ if (string.IsNullOrEmpty(Version))
+ {
+ throw new InvalidOperationException("Version string must be defined.");
+ }
+
+ if (Probes == null || Probes.Count() == 0)
+ {
+ throw new InvalidOperationException("No probes are listed, probes must be added during construction");
+ }
+
+ ValidateVariableLength();
+
+ SetDefaultContactIdsIfMissing();
+ ForceContactIdsToZeroIndexed();
+ SetEmptyShankIdsIfMissing();
+ SetDefaultDeviceChannelIndicesIfMissing();
+
+ if (!ValidateDeviceChannelIndices())
+ {
+ throw new Exception("Device channel indices are not unique across all probes.");
+ }
+ }
+
+ private void ValidateVariableLength()
+ {
+ for (int i = 0; i < Probes.Count(); i++)
+ {
+ if (Probes.ElementAt(i).NumberOfContacts != Probes.ElementAt(i).ContactPositions.Count() ||
+ Probes.ElementAt(i).NumberOfContacts != Probes.ElementAt(i).ContactPlaneAxes.Count() ||
+ Probes.ElementAt(i).NumberOfContacts != Probes.ElementAt(i).ContactShapeParams.Count() ||
+ Probes.ElementAt(i).NumberOfContacts != Probes.ElementAt(i).ContactShapes.Count())
+ {
+ throw new InvalidOperationException($"Required contact parameters are not the same length in probe {i}. " +
+ "Check positions / plane axes / shapes / shape parameters for lengths.");
+ }
+
+ if (Probes.ElementAt(i).ContactIds != null &&
+ Probes.ElementAt(i).ContactIds.Count() != Probes.ElementAt(i).NumberOfContacts)
+ {
+ throw new InvalidOperationException($"Contact IDs does not have the correct number of channels for probe {i}");
+ }
+
+ if (Probes.ElementAt(i).ShankIds != null &&
+ Probes.ElementAt(i).ShankIds.Count() != Probes.ElementAt(i).NumberOfContacts)
+ {
+ throw new InvalidOperationException($"Shank IDs does not have the correct number of channels for probe {i}");
+ }
+
+ if (Probes.ElementAt(i).DeviceChannelIndices != null &&
+ Probes.ElementAt(i).DeviceChannelIndices.Count() != Probes.ElementAt(i).NumberOfContacts)
+ {
+ throw new InvalidOperationException($"Device Channel Indices does not have the correct number of channels for probe {i}");
+ }
+ }
+ }
+
+ private void SetDefaultContactIdsIfMissing()
+ {
+ for (int i = 0; i < Probes.Count(); i++)
+ {
+ if (Probes.ElementAt(i).ContactIds == null)
+ {
+ Probes.ElementAt(i).ContactIds = Probe.DefaultContactIds(Probes.ElementAt(i).NumberOfContacts);
+ }
+ }
+ }
+
+ private void ForceContactIdsToZeroIndexed()
+ {
+ var contactIds = GetContactIds();
+ var numericIds = contactIds.Select(c => { return int.Parse(c); })
+ .ToList();
+
+ var min = numericIds.Min();
+ var max = numericIds.Max();
+
+ if (min == 1 && max == NumberOfContacts && numericIds.Count == numericIds.Distinct().Count())
+ {
+ for (int i = 0; i < Probes.Count(); i++)
+ {
+ var probe = Probes.ElementAt(i);
+ var newContactIds = probe.ContactIds.Select(c => { return (int.Parse(c) - 1).ToString(); });
+
+ for (int j = 0; j < probe.NumberOfContacts; j++)
+ {
+ probe.ContactIds.SetValue(newContactIds.ElementAt(j), j);
+ }
+ }
+ }
+ }
+
+ private void SetEmptyShankIdsIfMissing()
+ {
+ for (int i = 0; i < Probes.Count(); i++)
+ {
+ if (Probes.ElementAt(i).ShankIds == null)
+ {
+ Probes.ElementAt(i).ShankIds = Probe.DefaultShankIds(Probes.ElementAt(i).NumberOfContacts);
+ }
+ }
+ }
+
+ private void SetDefaultDeviceChannelIndicesIfMissing()
+ {
+ for (int i = 0; i < Probes.Count(); i++)
+ {
+ if (Probes.ElementAt(i).DeviceChannelIndices == null)
+ {
+ Probes.ElementAt(i).DeviceChannelIndices = new int[Probes.ElementAt(i).NumberOfContacts];
+
+ for (int j = 0; j < Probes.ElementAt(i).NumberOfContacts; j++)
+ {
+ if (int.TryParse(Probes.ElementAt(i).ContactIds[j], out int result))
+ {
+ Probes.ElementAt(i).DeviceChannelIndices[j] = result;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Validate the uniqueness of all 's across all 's.
+ ///
+ ///
+ /// All indices that are greater than or equal to 0 must be unique,
+ /// but there can be as many values equal to -1 as there are contacts. A value of -1 indicates that this contact is
+ /// not being recorded.
+ ///
+ /// True if all values not equal to -1 are unique, False if there are duplicates.
+ public bool ValidateDeviceChannelIndices()
+ {
+ var activeChannels = GetDeviceChannelIndices().Where(index => index != -1);
+ return activeChannels.Count() == activeChannels.Distinct().Count();
+ }
+
+ ///
+ /// Update the at the given probe index.
+ ///
+ ///
+ /// Device channel indices can be updated as contacts are being enabled or disabled. This is done on a
+ /// per-probe basis, where the incoming array of indices must be the same size as the original probe,
+ /// and must follow the standard for uniqueness found in .
+ ///
+ /// Zero-based index of the probe to update.
+ /// Array of .
+ ///
+ public void UpdateDeviceChannelIndices(int probeIndex, int[] deviceChannelIndices)
+ {
+ if (Probes.ElementAt(probeIndex).DeviceChannelIndices.Length != deviceChannelIndices.Length)
+ {
+ throw new ArgumentException($"Incoming device channel indices have {deviceChannelIndices.Length} contacts, " +
+ $"but the existing probe {probeIndex} has {Probes.ElementAt(probeIndex).DeviceChannelIndices.Length} contacts");
+ }
+
+ Probes.ElementAt(probeIndex).DeviceChannelIndices = deviceChannelIndices;
+
+ if (!ValidateDeviceChannelIndices())
+ {
+ throw new ArgumentException("Device channel indices are not valid. Ensure that all values are either -1 or are unique.");
+ }
+ }
+ }
+}
diff --git a/OpenEphys.ProbeInterface.NET/ProbeInterface.cs b/OpenEphys.ProbeInterface.NET/ProbeInterface.cs
deleted file mode 100644
index 140c994..0000000
--- a/OpenEphys.ProbeInterface.NET/ProbeInterface.cs
+++ /dev/null
@@ -1,1056 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Xml.Serialization;
-using System.Runtime.Serialization;
-using System.CodeDom.Compiler;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Converters;
-using System;
-
-namespace OpenEphys.ProbeInterface;
-
-///
-/// Abstract class that implements the Probeinterface specification in C# for .NET.
-///
-[GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
-public abstract class ProbeGroup
-{
- private string _specification;
- private string _version;
- private IEnumerable _probes;
-
- ///
- /// Gets the string defining the specification of the file.
- ///
- ///
- /// For Probeinterface files, this value is expected to be "probeinterface".
- ///
- [JsonProperty("specification", Required = Required.Always)]
- public string Specification
- {
- get { return _specification; }
- protected set { _specification = value; }
- }
-
- ///
- /// Gets the string defining which version of Probeinterface was used.
- ///
- [JsonProperty("version", Required = Required.Always)]
- public string Version
- {
- get { return _version; }
- protected set { _version = value; }
- }
-
- ///
- /// Gets an IEnumerable of probes that are present.
- ///
- ///
- /// Each probe can contain multiple shanks, and each probe has a unique
- /// contour that defines the physical representation of the probe. Contacts have several representations
- /// for their channel number, specifically (a string that is not guaranteed to be unique) and
- /// (guaranteed to be unique across all probes). 's can also be set to -1
- /// to indicate that the channel was not connected or recorded from.
- ///
- [XmlIgnore]
- [JsonProperty("probes", Required = Required.Always)]
- public IEnumerable Probes
- {
- get { return _probes; }
- protected set { _probes = value; }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// String defining the parameter.
- /// String defining the parameter.
- /// IEnumerable of objects.
- public ProbeGroup(string specification, string version, IEnumerable probes)
- {
- _specification = specification;
- _version = version;
- _probes = probes;
-
- Validate();
- }
-
- ///
- /// Copy constructor that takes in an existing object and copies the individual fields.
- ///
- ///
- /// After copying the relevant fields, the is validated to ensure that it is compliant
- /// with the Probeinterface specification. See for more details on what is checked.
- ///
- /// Existing object.
- protected ProbeGroup(ProbeGroup probeGroup)
- {
- _specification = probeGroup._specification;
- _version = probeGroup._version;
- _probes = probeGroup._probes;
-
- Validate();
- }
-
- ///
- /// Gets the number of contacts across all objects.
- ///
- public int NumberOfContacts
- {
- get
- {
- int numContacts = 0;
-
- foreach (var probe in _probes)
- {
- numContacts += probe.NumberOfContacts;
- }
-
- return numContacts;
- }
- }
-
- ///
- /// Returns the 's of all contacts in all probes.
- ///
- ///
- /// Note that these are not guaranteed to be unique values across probes.
- ///
- /// List of strings containing all contact IDs.
- public IEnumerable GetContactIds()
- {
- List contactIds = new();
-
- foreach (var probe in _probes)
- {
- contactIds.AddRange(probe.ContactIds.ToList());
- }
-
- return contactIds;
- }
-
- ///
- /// Returns all objects in the .
- ///
- ///
- public List GetContacts()
- {
- List contacts = new();
-
- foreach (var p in Probes)
- {
- for (int i = 0; i < p.NumberOfContacts; i++)
- {
- contacts.Add(p.GetContact(i));
- }
- }
-
- return contacts;
- }
-
- ///
- /// Returns all 's in the .
- ///
- ///
- /// Device channel indices are guaranteed to be unique, unless they are -1. Multiple contacts can be
- /// set to -1 to indicate they are not recorded from.
- ///
- ///
- public IEnumerable GetDeviceChannelIndices()
- {
- List deviceChannelIndices = new();
-
- foreach (var probe in _probes)
- {
- deviceChannelIndices.AddRange(probe.DeviceChannelIndices.ToList());
- }
-
- return deviceChannelIndices;
- }
-
- ///
- /// Validate that the correctly implements the Probeinterface specification.
- ///
- ///
- /// Check that all necessary fields are populated (,
- /// , ).
- /// Check that there is at least one defined.
- /// Check that all variables in each have the same length.
- /// Check if are present, and generate default values
- /// based on the index if there are no values defined.
- /// Check if are zero-indexed, and convert to
- /// zero-indexed if possible.
- /// Check if are defined, and initialize empty strings
- /// if they are not defined.
- /// Check if are defined, and initialize default
- /// values (using the value as the new ).
- /// Check that all are unique across all 's,
- /// unless the value is -1; multiple contacts can be set to -1.
- ///
- public void Validate()
- {
- if (_specification == null || _version == null || _probes == null)
- {
- throw new Exception("Necessary fields are null, unable to validate properly");
- }
-
- if (_probes.Count() == 0)
- {
- throw new Exception("No probes are listed, probes must be added during construction");
- }
-
- if (!ValidateVariableLength(out string result))
- {
- throw new Exception(result);
- }
-
- SetDefaultContactIdsIfMissing();
- ValidateContactIds();
- SetEmptyShankIdsIfMissing();
- SetDefaultDeviceChannelIndicesIfMissing();
-
- if (!ValidateDeviceChannelIndices())
- {
- throw new Exception("Device channel indices are not unique across all probes.");
- }
- }
-
- private bool ValidateVariableLength(out string result)
- {
- for (int i = 0; i < _probes.Count(); i++)
- {
- if (_probes.ElementAt(i).NumberOfContacts != _probes.ElementAt(i).ContactPositions.Count() ||
- _probes.ElementAt(i).NumberOfContacts != _probes.ElementAt(i).ContactPlaneAxes.Count() ||
- _probes.ElementAt(i).NumberOfContacts != _probes.ElementAt(i).ContactShapeParams.Count() ||
- _probes.ElementAt(i).NumberOfContacts != _probes.ElementAt(i).ContactShapes.Count())
- {
- result = $"Required contact parameters are not the same length in probe {i}. " +
- "Check positions / plane axes / shapes / shape parameters for lengths.";
- return false;
- }
-
- if (_probes.ElementAt(i).ContactIds != null &&
- _probes.ElementAt(i).ContactIds.Count() != _probes.ElementAt(i).NumberOfContacts)
- {
- result = $"Contact IDs does not have the correct number of channels for probe {i}";
- return false;
- }
-
- if (_probes.ElementAt(i).ShankIds != null &&
- _probes.ElementAt(i).ShankIds.Count() != _probes.ElementAt(i).NumberOfContacts)
- {
- result = $"Shank IDs does not have the correct number of channels for probe {i}";
- return false;
- }
-
- if (_probes.ElementAt(i).DeviceChannelIndices != null &&
- _probes.ElementAt(i).DeviceChannelIndices.Count() != _probes.ElementAt(i).NumberOfContacts)
- {
- result = $"Device Channel Indices does not have the correct number of channels for probe {i}";
- return false;
- }
- }
-
- result = "";
- return true;
- }
-
- private void SetDefaultContactIdsIfMissing()
- {
- int contactNum = 0;
-
- for (int i = 0; i < _probes.Count(); i++)
- {
- if (_probes.ElementAt(i).ContactIds == null)
- {
- _probes.ElementAt(i).ContactIds = Probe.DefaultContactIds(_probes.ElementAt(i).NumberOfContacts);
- }
- else
- contactNum += _probes.ElementAt(i).NumberOfContacts;
- }
- }
-
- private void ValidateContactIds()
- {
- CheckIfContactIdsAreZeroIndexed();
- }
-
- private void CheckIfContactIdsAreZeroIndexed()
- {
- var contactIds = GetContactIds();
- var numericIds = contactIds.Select(c => { return int.Parse(c); })
- .ToList();
-
- var min = numericIds.Min();
- var max = numericIds.Max();
-
- if (min == 1 && max == NumberOfContacts && numericIds.Count == numericIds.Distinct().Count())
- {
- for (int i = 0; i < _probes.Count(); i++)
- {
- var probe = _probes.ElementAt(i);
- var newContactIds = probe.ContactIds.Select(c => { return (int.Parse(c) - 1).ToString(); });
-
- for (int j = 0; j < probe.NumberOfContacts; j++)
- {
- probe.ContactIds.SetValue(newContactIds.ElementAt(j), j);
- }
- }
- }
- }
-
- private void SetEmptyShankIdsIfMissing()
- {
- for (int i = 0; i < _probes.Count(); i++)
- {
- if (_probes.ElementAt(i).ShankIds == null)
- {
- _probes.ElementAt(i).ShankIds = Probe.DefaultShankIds(_probes.ElementAt(i).NumberOfContacts);
- }
- }
- }
-
- private void SetDefaultDeviceChannelIndicesIfMissing()
- {
- for (int i = 0; i < _probes.Count(); i++)
- {
- if (_probes.ElementAt(i).DeviceChannelIndices == null)
- {
- _probes.ElementAt(i).DeviceChannelIndices = new int[_probes.ElementAt(i).NumberOfContacts];
-
- for (int j = 0; j < _probes.ElementAt(i).NumberOfContacts; j++)
- {
- if (int.TryParse(_probes.ElementAt(i).ContactIds[j], out int result))
- {
- _probes.ElementAt(i).DeviceChannelIndices[j] = result;
- }
- }
- }
- }
- }
-
- ///
- /// Validate the uniqueness of all 's across all 's.
- ///
- ///
- /// All indices that are greater than or equal to 0 must be unique,
- /// but there can be as many values equal to -1 as there are contacts. A value of -1 indicates that this contact is
- /// not being recorded.
- ///
- /// True if all values not equal to -1 are unique, False if there are duplicates.
- public bool ValidateDeviceChannelIndices()
- {
- var activeChannels = GetDeviceChannelIndices()
- .Where(index => index != -1);
-
- if (activeChannels.Count() != activeChannels.Distinct().Count())
- {
- return false;
- }
-
- return true;
- }
-
- ///
- /// Update the at the given probe index.
- ///
- ///
- /// Device channel indices can be updated as contacts are being enabled or disabled. This is done on a
- /// per-probe basis, where the incoming array of indices must be the same size as the original probe,
- /// and must follow the standard for uniqueness found in .
- ///
- /// Zero-based index of the probe to update.
- /// Array of .
- ///
- public void UpdateDeviceChannelIndices(int probeIndex, int[] deviceChannelIndices)
- {
- if (_probes.ElementAt(probeIndex).DeviceChannelIndices.Length != deviceChannelIndices.Length)
- {
- throw new ArgumentException($"Incoming device channel indices have {deviceChannelIndices.Length} contacts, " +
- $"but the existing probe {probeIndex} has {_probes.ElementAt(probeIndex).DeviceChannelIndices.Length} contacts");
- }
-
- _probes.ElementAt(probeIndex).DeviceChannelIndices = deviceChannelIndices;
-
- if (!ValidateDeviceChannelIndices())
- {
- throw new ArgumentException("Device channel indices are not valid. Ensure that all values are either -1 or are unique.");
- }
- }
-}
-
-///
-/// Class that implements the Probe Interface specification for a Probe.
-///
-[GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
-public class Probe
-{
- private ProbeNdim _numDimensions;
- private ProbeSiUnits _siUnits;
- private ProbeAnnotations _annotations;
- private ContactAnnotations _contactAnnotations;
- private float[][] _contactPositions;
- private float[][][] _contactPlaneAxes;
- private ContactShape[] _contactShapes;
- private ContactShapeParam[] _contactShapeParams;
- private float[][] _probePlanarContour;
- private int[] _deviceChannelIndices;
- private string[] _contactIds;
- private string[] _shankIds;
-
- ///
- /// Gets the to use while plotting the .
- ///
- [XmlIgnore]
- [JsonProperty("ndim", Required = Required.Always)]
- public ProbeNdim NumDimensions
- {
- get { return _numDimensions; }
- protected set { _numDimensions = value; }
- }
-
- ///
- /// Gets the to use while plotting the .
- ///
- [XmlIgnore]
- [JsonProperty("si_units", Required = Required.Always)]
- public ProbeSiUnits SiUnits
- {
- get { return _siUnits; }
- protected set { _siUnits = value; }
- }
-
- ///
- /// Gets the for the .
- ///
- ///
- /// Used to specify the name of the probe, and the manufacturer.
- ///
- [XmlIgnore]
- [JsonProperty("annotations", Required = Required.Always)]
- public ProbeAnnotations Annotations
- {
- get { return _annotations; }
- protected set { _annotations = value; }
- }
-
- ///
- /// Gets the for the .
- ///
- ///
- /// This field can be used for noting things like where it physically is within a specimen, or if it
- /// is no longer functioning correctly.
- ///
- [XmlIgnore]
- [JsonProperty("contact_annotations")]
- public ContactAnnotations ContactAnnotations
- {
- get { return _contactAnnotations; }
- protected set { _contactAnnotations = value; }
- }
-
- ///
- /// Gets the positions, specifically the center point of every contact.
- ///
- ///
- /// This is a two-dimensional array of floats; the first index is the index of the contact, and
- /// the second index is the X and Y value, respectively.
- ///
- [XmlIgnore]
- [JsonProperty("contact_positions", Required = Required.Always)]
- public float[][] ContactPositions
- {
- get { return _contactPositions; }
- protected set { _contactPositions = value; }
- }
-
- ///
- /// Gets the plane axes for the contacts.
- ///
- [XmlIgnore]
- [JsonProperty("contact_plane_axes")]
- public float[][][] ContactPlaneAxes
- {
- get { return _contactPlaneAxes; }
- protected set { _contactPlaneAxes = value; }
- }
-
- ///
- /// Gets the for each contact.
- ///
- [XmlIgnore]
- [JsonProperty("contact_shapes", Required = Required.Always)]
- public ContactShape[] ContactShapes
- {
- get { return _contactShapes; }
- protected set { _contactShapes = value; }
- }
-
- ///
- /// Gets the parameters of the shape for each contact.
- ///
- ///
- /// Depending on which
- /// is selected, not all parameters are needed; for instance, only uses
- /// , while just uses
- /// .
- ///
- [XmlIgnore]
- [JsonProperty("contact_shape_params", Required = Required.Always)]
- public ContactShapeParam[] ContactShapeParams
- {
- get { return _contactShapeParams; }
- protected set { _contactShapeParams = value; }
- }
-
- ///
- /// Gets the outline of the probe that represents the physical shape.
- ///
- [XmlIgnore]
- [JsonProperty("probe_planar_contour")]
- public float[][] ProbePlanarContour
- {
- get { return _probePlanarContour; }
- protected set { _probePlanarContour = value; }
- }
-
- ///
- /// Gets the indices of each channel defining their recording channel number. Must be unique, except for contacts
- /// that are set to -1 if they disabled.
- ///
- [XmlIgnore]
- [JsonProperty("device_channel_indices")]
- public int[] DeviceChannelIndices
- {
- get { return _deviceChannelIndices; }
- internal set { _deviceChannelIndices = value; }
- }
-
- ///
- /// Gets the contact IDs for each channel. These do not have to be unique.
- ///
- [XmlIgnore]
- [JsonProperty("contact_ids")]
- public string[] ContactIds
- {
- get { return _contactIds; }
- internal set { _contactIds = value; }
- }
-
- ///
- /// Gets the shank that each contact belongs to.
- ///
- [XmlIgnore]
- [JsonProperty("shank_ids")]
- public string[] ShankIds
- {
- get { return _shankIds; }
- internal set { _shankIds = value; }
- }
-
- ///
- /// Public constructor, defined as the default Json constructor.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- [JsonConstructor]
- public Probe(ProbeNdim ndim, ProbeSiUnits si_units, ProbeAnnotations annotations, ContactAnnotations contact_annotations,
- float[][] contact_positions, float[][][] contact_plane_axes, ContactShape[] contact_shapes,
- ContactShapeParam[] contact_shape_params, float[][] probe_planar_contour, int[] device_channel_indices,
- string[] contact_ids, string[] shank_ids)
- {
- _numDimensions = ndim;
- _siUnits = si_units;
- _annotations = annotations;
- _contactAnnotations = contact_annotations;
- _contactPositions = contact_positions;
- _contactPlaneAxes = contact_plane_axes;
- _contactShapes = contact_shapes;
- _contactShapeParams = contact_shape_params;
- _probePlanarContour = probe_planar_contour;
- _deviceChannelIndices = device_channel_indices;
- _contactIds = contact_ids;
- _shankIds = shank_ids;
- }
-
- ///
- /// Copy constructor given an existing object.
- ///
- ///
- protected Probe(Probe probe)
- {
- _numDimensions = probe._numDimensions;
- _siUnits = probe._siUnits;
- _annotations = probe._annotations;
- _contactAnnotations = probe._contactAnnotations;
- _contactPositions = probe._contactPositions;
- _contactPlaneAxes = probe._contactPlaneAxes;
- _contactShapes = probe._contactShapes;
- _contactShapeParams = probe._contactShapeParams;
- _probePlanarContour = probe._probePlanarContour;
- _deviceChannelIndices = probe._deviceChannelIndices;
- _contactIds = probe._contactIds;
- _shankIds = probe._shankIds;
- }
-
- ///
- /// Returns default array that contains the given number of channels and the corresponding shape.
- ///
- /// Number of contacts in a single .
- /// The to apply to each contact.
- /// array.
- public static ContactShape[] DefaultContactShapes(int numberOfContacts, ContactShape contactShape)
- {
- ContactShape[] contactShapes = new ContactShape[numberOfContacts];
-
- for (int i = 0; i < numberOfContacts; i++)
- {
- contactShapes[i] = contactShape;
- }
-
- return contactShapes;
- }
-
- ///
- /// Returns a default contactPlaneAxes array, with each contact given the same axis; { { 1, 0 }, { 0, 1 } }
- ///
- ///
- /// See Probeinterface documentation for more info.
- ///
- /// Number of contacts in a single .
- /// Three-dimensional array of s.
- public static float[][][] DefaultContactPlaneAxes(int numberOfContacts)
- {
- float[][][] contactPlaneAxes = new float[numberOfContacts][][];
-
- for (int i = 0; i < numberOfContacts; i++)
- {
- contactPlaneAxes[i] = new float[2][] { new float[2] { 1.0f, 0.0f }, new float[2] { 0.0f, 1.0f } };
- }
-
- return contactPlaneAxes;
- }
-
- ///
- /// Returns an array of s for a .
- ///
- /// Number of contacts in a single .
- /// Radius of the contact, in units of .
- /// array.
- public static ContactShapeParam[] DefaultCircleParams(int numberOfContacts, float radius)
- {
- ContactShapeParam[] contactShapeParams = new ContactShapeParam[numberOfContacts];
-
- for (int i = 0; i < numberOfContacts; i++)
- {
- contactShapeParams[i] = new ContactShapeParam(radius: radius);
- }
-
- return contactShapeParams;
- }
-
- ///
- /// Returns an array of s for a .
- ///
- /// Number of contacts in a single .
- /// Width of the contact, in units of .
- /// array.
- public static ContactShapeParam[] DefaultSquareParams(int numberOfContacts, float width)
- {
- ContactShapeParam[] contactShapeParams = new ContactShapeParam[numberOfContacts];
-
- for (int i = 0; i < numberOfContacts; i++)
- {
- contactShapeParams[i] = new ContactShapeParam(width: width);
- }
-
- return contactShapeParams;
- }
-
- ///
- /// Returns an array of s for a .
- ///
- /// Number of contacts in a single .
- /// Width of the contact, in units of .
- /// Height of the contact, in units of .
- /// array.
- public static ContactShapeParam[] DefaultRectParams(int numberOfContacts, float width, float height)
- {
- ContactShapeParam[] contactShapeParams = new ContactShapeParam[numberOfContacts];
-
- for (int i = 0; i < numberOfContacts; i++)
- {
- contactShapeParams[i] = new ContactShapeParam(height: height);
- }
-
- return contactShapeParams;
- }
-
- ///
- /// Returns a default array of sequential .
- ///
- /// Number of contacts in a single .
- /// The first value of the .
- /// A serially increasing array of .
- public static int[] DefaultDeviceChannelIndices(int numberOfContacts, int offset)
- {
- int[] deviceChannelIndices = new int[numberOfContacts];
-
- for (int i = 0; i < numberOfContacts; i++)
- {
- deviceChannelIndices[i] = i + offset;
- }
-
- return deviceChannelIndices;
- }
-
- ///
- /// Returns a sequential array of .
- ///
- /// Number of contacts in a single .
- /// Array of strings defining the .
- public static string[] DefaultContactIds(int numberOfContacts)
- {
- string[] contactIds = new string[numberOfContacts];
-
- for (int i = 0; i < numberOfContacts; i++)
- {
- contactIds[i] = i.ToString();
- }
-
- return contactIds;
- }
-
- ///
- /// Returns an array of empty strings as the default shank ID.
- ///
- /// Number of contacts in a single .
- /// Array of empty strings.
- public static string[] DefaultShankIds(int numberOfContacts)
- {
- string[] contactIds = new string[numberOfContacts];
-
- for (int i = 0; i < numberOfContacts; i++)
- {
- contactIds[i] = "";
- }
-
- return contactIds;
- }
-
- ///
- /// Returns a object.
- ///
- /// Relative index of the contact in this .
- /// .
- public Contact GetContact(int index)
- {
- return new Contact(ContactPositions[index][0], ContactPositions[index][1], ContactShapes[index], ContactShapeParams[index],
- DeviceChannelIndices[index], ContactIds[index], ShankIds[index], index);
- }
-
- ///
- /// Gets the number of contacts within this .
- ///
- public int NumberOfContacts => ContactPositions.Length;
-}
-
-///
-/// Number of dimensions to use while plotting a .
-///
-[GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
-public enum ProbeNdim
-{
- ///
- /// Two-dimensions.
- ///
- [EnumMemberAttribute(Value = "2")]
- Two = 2,
-
- ///
- /// Three-dimensions.
- ///
- [EnumMemberAttribute(Value = "3")]
- Three = 3,
-}
-
-///
-/// SI units for all values relating to location and position.
-///
-[GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
-[JsonConverter(typeof(StringEnumConverter))]
-public enum ProbeSiUnits
-{
- ///
- /// Millimeters [mm].
- ///
- [EnumMemberAttribute(Value = "mm")]
- mm = 0,
-
- ///
- /// Micrometers [um].
- ///
- [EnumMemberAttribute(Value = "um")]
- um = 1,
-}
-
-///
-/// Struct that extends the Probeinterface specification by encapsulating all values for a single contact.
-///
-public readonly struct Contact
-{
- ///
- /// Gets the x-position of the contact.
- ///
- public float PosX { get; }
-
- ///
- /// Gets the y-position of the contact.
- ///
- public float PosY { get; }
-
- ///
- /// Gets the of the contact.
- ///
- public ContactShape Shape { get; }
-
- ///
- /// Gets the 's of the contact.
- ///
- public ContactShapeParam ShapeParams { get; }
-
- ///
- /// Gets the device ID of the contact.
- ///
- public int DeviceId { get; }
-
- ///
- /// Gets the contact ID of the contact.
- ///
- public string ContactId { get; }
-
- ///
- /// Gets the shank ID of the contact.
- ///
- public string ShankId { get; }
-
- ///
- /// Gets the index of the contact within the object.
- ///
- public int Index { get; }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public Contact(float posX, float posY, ContactShape shape, ContactShapeParam shapeParam,
- int device_id, string contact_id, string shank_id, int index)
- {
- PosX = posX;
- PosY = posY;
- Shape = shape;
- ShapeParams = shapeParam;
- DeviceId = device_id;
- ContactId = contact_id;
- ShankId = shank_id;
- Index = index;
- }
-}
-
-///
-/// Class holding parameters used to draw the contact.
-///
-///
-/// Fields are nullable, since not all fields are required depending on the shape selected.
-///
-[GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
-public class ContactShapeParam
-{
- private float? _radius;
- private float? _width;
- private float? _height;
-
- ///
- /// Gets the radius of the contact.
- ///
- ///
- /// This is only used to draw contacts. Field can be null.
- ///
- public float? Radius
- {
- get { return _radius; }
- protected set { _radius = value; }
- }
-
- ///
- /// Gets the width of the contact.
- ///
- ///
- /// This is used to draw or contacts.
- /// Field can be null.
- ///
- public float? Width
- {
- get { return _width; }
- protected set { _width = value; }
- }
-
- ///
- /// Gets the height of the contact.
- ///
- ///
- /// This is only used to draw contacts. Field can be null.
- ///
- public float? Height
- {
- get { return _height; }
- protected set { _height = value; }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Radius. Can be null.
- /// Width. Can be null.
- /// Height. Can be null.
- [JsonConstructor]
- public ContactShapeParam(float? radius = null, float? width = null, float? height = null)
- {
- _radius = radius;
- _width = width;
- _height = height;
- }
-
- ///
- /// Copy constructor given an existing object.
- ///
- ///
- protected ContactShapeParam(ContactShapeParam shape)
- {
- _radius = shape._radius;
- _width = shape._width;
- _height = shape._height;
- }
-}
-
-///
-/// Shape of the contact.
-///
-[GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
-[JsonConverter(typeof(StringEnumConverter))]
-public enum ContactShape
-{
- ///
- /// Circle.
- ///
- [EnumMemberAttribute(Value = "circle")]
- Circle = 0,
-
- ///
- /// Rectangle.
- ///
- [EnumMemberAttribute(Value = "rect")]
- Rect = 1,
-
- ///
- /// Square.
- ///
- [EnumMemberAttribute(Value = "square")]
- Square = 2,
-}
-
-///
-/// Class holding the annotations.
-///
-[GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
-public class ProbeAnnotations
-{
- private string _name;
- private string _manufacturer;
-
- ///
- /// Gets the name of the probe as defined by the manufacturer, or a descriptive name such as the neurological target.
- ///
- [JsonProperty("name")]
- public string Name
- {
- get { return _name; }
- protected set { _name = value; }
- }
-
- ///
- /// Gets the name of the manufacturer who created the probe.
- ///
- [JsonProperty("manufacturer")]
- public string Manufacturer
- {
- get { return _manufacturer; }
- protected set { _manufacturer = value; }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- ///
- [JsonConstructor]
- public ProbeAnnotations(string name, string manufacturer)
- {
- _name = name;
- _manufacturer = manufacturer;
- }
-
- ///
- /// Copy constructor that copies data from an existing object.
- ///
- ///
- protected ProbeAnnotations(ProbeAnnotations probeAnnotations)
- {
- _name = probeAnnotations._name;
- _manufacturer = probeAnnotations._manufacturer;
- }
-}
-
-///
-/// Class holding all of the annotations for each contact.
-///
-public class ContactAnnotations
-{
- private string[] _contactAnnotations;
-
- ///
- /// Gets the array of strings holding annotations for each contact. Not all indices must have annotations.
- ///
- public string[] Annotations
- {
- get { return _contactAnnotations; }
- protected set { _contactAnnotations = value; }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- [JsonConstructor]
- public ContactAnnotations(string[] contactAnnotations)
- {
- _contactAnnotations = contactAnnotations;
- }
-}
diff --git a/OpenEphys.ProbeInterface.NET/ProbeNdim.cs b/OpenEphys.ProbeInterface.NET/ProbeNdim.cs
new file mode 100644
index 0000000..b1da56e
--- /dev/null
+++ b/OpenEphys.ProbeInterface.NET/ProbeNdim.cs
@@ -0,0 +1,22 @@
+using System.Runtime.Serialization;
+
+namespace OpenEphys.ProbeInterface.NET
+{
+ ///
+ /// Number of dimensions to use while plotting a .
+ ///
+ public enum ProbeNdim
+ {
+ ///
+ /// Two-dimensions.
+ ///
+ [EnumMember(Value = "2")]
+ Two = 2,
+
+ ///
+ /// Three-dimensions.
+ ///
+ [EnumMember(Value = "3")]
+ Three = 3,
+ }
+}
diff --git a/OpenEphys.ProbeInterface.NET/ProbeSiUnits.cs b/OpenEphys.ProbeInterface.NET/ProbeSiUnits.cs
new file mode 100644
index 0000000..c623147
--- /dev/null
+++ b/OpenEphys.ProbeInterface.NET/ProbeSiUnits.cs
@@ -0,0 +1,25 @@
+using System.Runtime.Serialization;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace OpenEphys.ProbeInterface.NET
+{
+ ///
+ /// SI units for all values relating to location and position.
+ ///
+ [JsonConverter(typeof(StringEnumConverter))]
+ public enum ProbeSiUnits
+ {
+ ///
+ /// Millimeters [mm].
+ ///
+ [EnumMember(Value = "mm")]
+ mm = 0,
+
+ ///
+ /// Micrometers [um].
+ ///
+ [EnumMember(Value = "um")]
+ um = 1,
+ }
+}