/// <summary> /// Averages adjacent entries such that the result has only one entry per time bin of the specified width /// </summary> public static IArrayView <EEGDataEntry> DownSample(this IEnumerable <EEGDataEntry> entries, int binWidthMillis) { var bins = entries.BinByTime(binWidthMillis); var downSampled = Arrays.New <EEGDataEntry>(bins.Count); for (int i = 0; i < bins.Count; i++) { if (bins[i].Count == 0) { var baseEntry = downSampled[i - 1]; downSampled[i] = new EEGDataEntry(baseEntry.Marker, baseEntry.TimeStamp + binWidthMillis, baseEntry.RelativeTimeStamp + binWidthMillis, baseEntry.Data); } else { downSampled[i] = bins[i].AverageEntry(); } } return(downSampled); }
/// <summary> /// Was a stimulus showing when this entry was recorded? /// </summary> public static bool HasStimulusMarker(this EEGDataEntry entry) { return(entry.Marker != EEGDataEntry.MARKER_DEFAULT && entry.Marker != EEGDataEntry.EMO_MARKER_DEFAULT); }
/// <summary> /// Averages adjacent entries such that the result has only one entry per time bin of the specified width /// </summary> public static IArrayView<EEGDataEntry> DownSample(this IEnumerable<EEGDataEntry> entries, int binWidthMillis) { var bins = entries.BinByTime(binWidthMillis); var downSampled = Arrays.New<EEGDataEntry>(bins.Count); for (int i = 0; i < bins.Count; i++) { if (bins[i].Count == 0) { var baseEntry = downSampled[i - 1]; downSampled[i] = new EEGDataEntry(baseEntry.Marker, baseEntry.TimeStamp + binWidthMillis, baseEntry.RelativeTimeStamp + binWidthMillis, baseEntry.Data); } else downSampled[i] = bins[i].AverageEntry(); } return downSampled; }
private Example GetExample(IArrayView<EEGDataEntry> trial) { int marker = trial.FirstItem().Marker; var means = Channels.Values.Select(ch => trial.Channel(ch).Average()).ToArray(); IArrayView<EEGDataEntry> trimmedTrial = trial.DownSample(this.Settings.BinWidthMillis); if (trial.Count > this.minFeatures) trimmedTrial = trial.SubView(0, this.minFeatures); else if (trial.Count < this.minFeatures) { var defaultEntry = new EEGDataEntry(marker, 0, 0, means); trimmedTrial = Arrays.FromMap(i => i < trial.Count ? trial[i] : defaultEntry, this.minFeatures); } var features = trimmedTrial .Select(this.selectedBins) .SelectMany(e => this.Settings.SelectedChannels.Select(ch => e[ch] - means[ch.ToIndex()])); if (this.Settings.IncludeChannelMeans) features = features.Concat(this.Settings.SelectedChannels.Select(ch => means[ch.ToIndex()])); return new Example(marker, features); }
private void BuildView() { this.SuspendLayout(); var tabs = new CustomTabControl() { Dock = DockStyle.Fill }; tabs.DisplayStyleProvider = new TabStyleVisualStudioProvider(tabs) { ShowTabCloser = true }; tabs.TabClosing += (sender, args) => ((CustomTab)args.TabPage).RaiseClosingSafe(args); var startTab = new CustomTab() { Text = "Classifiers " }; // the ending space is necessary for some reason startTab.Closing += (sender, args) => { args.Cancel = true; if (GUIUtils.IsUserSure("Reset classifiers?")) { this.classifierTabs.Clear(); this.Controls.Remove(tabs); tabs.Dispose(); this.BuildView(); this.OnSizeChanged(EventArgs.Empty); } }; // classifier list var classifierList = new CheckedListBox() { Dock = DockStyle.Fill, CheckOnClick = true }; classifierList.AddContextMenu(); Action<ClassificationScheme> addClassifier = (scheme) => { // get unique name if necessary string baseName = string.IsNullOrWhiteSpace(scheme.Settings.Name) ? "new classifier" : scheme.Settings.Name; if (!this.classifierTabs.Select(ct => ct.Text).Contains(baseName)) scheme.Settings.Name = baseName; else { int i = 1; while (this.classifierTabs .Select(ct => ct.Text.ToLower()) .Contains(string.Format("{0} {1}", baseName, i))) i++; scheme.Settings.Name = string.Format("{0} {1}", baseName, i); } // create the tab var classifierTab = new ClassificationSchemeTab(scheme); classifierTab.TextChanged += (sender, args) => classifierList.Invalidate(); classifierTab.Closing += (sender, args) => { this.classifierTabs.Remove(classifierTab); classifierList.Items.Remove(classifierTab); }; this.classifierTabs.Add(classifierTab); tabs.TabPages.Add(classifierTab); classifierList.Items.Add(classifierTab, true); }; this.getSelectedClassifiers = () => classifierList.CheckedItems.Cast<ClassificationSchemeTab>().Select(cst => cst.ClassificationScheme).ToIArray(); // buttons var buttonTable = GUIUtils.CreateButtonTable(Direction.Horizontal, DockStyle.Bottom, GUIUtils.CreateFlatButton("New", (b) => { var classifier = classifierList.Items.Count > 0 ? ((ClassificationSchemeTab)(classifierList.SelectedItem ?? classifierList.Items[0])).ClassificationScheme : new ClassificationScheme(); classifier.Settings.Name = string.Empty; addClassifier(classifier); }, startTab.ToolTip, "Create a new classifier"), GUIUtils.CreateFlatButton("Load", (b) => { if (this.openDialog.ShowDialog() != DialogResult.OK) return; ClassificationScheme scheme; foreach (var path in this.openDialog.FileNames) { if (Utils.TryDeserializeFile(this.openDialog.FileName, out scheme)) addClassifier(scheme); else GUIUtils.Alert("Failed to load classifier info from " + path, MessageBoxIcon.Error); } }, startTab.ToolTip, "Load a previously saved classifier settings file")); // artifact detection config var artifactDetectionPanel = new ConfigurationPanel(this.artifactDetection); artifactDetectionPanel.PropertyChanged += args => this.artifactDetection.SetProperty(args.Property, args.Getter()); // artifact detection label var artifactDetectionLabel = new Label() { Dock = DockStyle.Bottom, TextAlign = ContentAlignment.MiddleCenter, Visible = false }; IEnumerable<EEGDataEntry> empty = new EEGDataEntry[0], entries = empty; var listener = new EEGDataListener(GUIUtils.GUIInvoker, source => artifactDetectionLabel.Visible = true, data => { if (!this.artifactDetection.UseArtifactDetection) { artifactDetectionLabel.Visible = false; entries = empty; return; } artifactDetectionLabel.Visible = true; entries = entries.Concat(data); if (data.LastItem().TimeStamp - entries.First().TimeStamp >= 500) { if (this.artifactDetection.HasMotionArtifact(entries)) { artifactDetectionLabel.Text = "Motion artifact detected!"; artifactDetectionLabel.BackColor = Color.Red; artifactDetectionLabel.ForeColor = Color.White; if (this.artifactDetection.Beep) GUIUtils.GUIInvoker.BeginInvoke(SystemSounds.Beep.Play); } else { artifactDetectionLabel.Text = "No artifacts detected"; artifactDetectionLabel.BackColor = Color.Green; artifactDetectionLabel.ForeColor = Color.Black; } entries = empty; } }, source => artifactDetectionLabel.Visible = false); // avoid using the gui invoker before the handle has been created this.HandleCreated += (sender, args) => EmotivDataSource.Instance.AddListener(listener); artifactDetectionLabel.Disposed += (sender, args) => { EmotivDataSource.Instance.RemoveListener(listener); listener.Dispose(); }; // right half var rightPanel = new Panel() { Dock = DockStyle.Fill }; rightPanel.Controls.Add(classifierList); rightPanel.Controls.Add(buttonTable); // left half var leftPanel = new Panel() { Dock = DockStyle.Fill }; leftPanel.Controls.Add(artifactDetectionPanel); leftPanel.Controls.Add(artifactDetectionLabel); var cols = GUIUtils.CreateTable(new double[] { .5, .5 }, Direction.Horizontal); cols.Controls.Add(rightPanel, 0, 0); cols.Controls.Add(leftPanel, 1, 0); startTab.Controls.Add(cols); tabs.TabPages.Add(startTab); this.Controls.Add(tabs); this.ResumeLayout(false); }