Exemple #1
0
        /// <summary>
        /// The enumerator implementation
        /// </summary>
        public override IEnumerator <View> GetEnumerator()
        {
            IViewResult result;

            using (var logWriter = new StreamWriter(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "compexp_log_" + settings.SubjectName + DateTime.Now.ToString("MM dd yyyy H mm ss") + ".txt")))
                using (var dataWriter = new StreamWriter(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "compexp_" + settings.SubjectName + DateTime.Now.ToString("MM dd yyyy H mm ss") + ".csv")))
                {
                    for (int i = 0; i < 2; i++)
                    {
                        yield return(new ChoiceView(new string[]
                        {
                            "Ready for Study Phase"
                        }, out result));

                        //Present half the stimuli for study
                        for (int j = 0 + i * (presentation.Count / 2); j < (presentation.Count / 2) * (i + 1); j++)
                        {
                            yield return(new TextView(presentation[j], this.settings.PresentationTime, GUIUtils.Constants.DISPLAY_FONT_LARGE));

                            yield return(new RestView(this.settings.RestTime));
                        }

                        //Begin the practice phase
                        yield return(new ChoiceView(new string[]
                        {
                            "Start EEG Recording"
                        }, out result)
                        {
                            Text = "Click When Ready"
                        });

                        var connected = true; // assume it's connected
                        using (var invoker = new SingleThreadedInvoker())
                            using (var connectionListener = new EEGDataListener(invoker, s => connected = true, null, s => connected = false))
                            {
                                // listen for a broken connection
                                this.dataSource.AddListener(connectionListener);
                                foreach (var view in this.GetViews(invoker, logWriter, dataWriter, i))
                                {
                                    if (connected)
                                    {
                                        yield return(view);
                                    }
                                    else
                                    {
                                        GUIUtils.Alert("Lost connection to headset!");
                                        break;
                                    }
                                }

                                this.dataSource.RemoveListener(connectionListener);
                            }
                    }
                }
        }
Exemple #2
0
        //Generates the views by calling RunTrial
        private IEnumerable <View> GetViews(ISynchronizeInvoke invoker, StreamWriter logWriter, StreamWriter dataWriter, int round)
        {
            //Get a block of stimuli
            //var blocks = this.GetBlocks(this.class1, new Random())
            //    .Zip(this.GetBlocks(this.class2, new Random()), (b1, b2) => new[] { new { stimuli = b1, cls = 1 }, new { stimuli = b2, cls = 2 } })
            //    .SelectMany(x => x);
            //int blockCount = 1;

            var currentTrialEntries = new List <EEGDataEntry>();

            //To do: Save the date/time earlier and use it for both this and the dataWriter. Put it in GetEnumerator and pass to GetViews
            using (var artifactListener = new EEGDataListener(invoker, null, data =>
            {
                foreach (var entry in data)
                {
                    if (entry.HasStimulusMarker())
                    {
                        lock (currentTrialEntries)
                        {
                            currentTrialEntries.Add(entry);
                        }
                    }
                }
            }, null))
            {
                this.dataSource.AddListener(artifactListener);
                //Display each block of stimuli
                for (int j = 0 + round * (settings.NumBlocks); j < (settings.NumBlocks) * (round + 1); j++)
                {
                    logWriter.WriteLine("Current Class: {0}, Block Number: {1}", (j % 2 + 1), j);
                    //yield return new TextView("Current Class: " + block.cls, 2500, GUIUtils.Constants.DISPLAY_FONT_LARGE);
                    IViewResult result;

                    yield return(new ChoiceView(new string[]
                    {
                        "Ready for next block"
                    }, out result));

                    int limit = blocks[j].Count;
                    for (int k = 0; k < limit; k++)
                    {
                        foreach (var view in RunTrial(blocks[j].RemoveRandom(), (j % 2 + 1), dataWriter, logWriter, currentTrialEntries))
                        {
                            yield return(view);
                        }
                    }
                    //blockCount++;
                }
                logWriter.WriteLine("Phase {0} Concluded.", round + 1);
            }
        }
Exemple #3
0
        //Generates the views by calling RunTrial
        private IEnumerable <View> GetCompViews(ISynchronizeInvoke invoker, StreamWriter logWriter, StreamWriter dataWriter)
        {
            var currentCompTrialEntries = new List <EEGDataEntry>();

            using (var compartifactListener = new EEGDataListener(invoker, null, data =>
            {
                foreach (var entry in data)
                {
                    if (entry.HasStimulusMarker())
                    {
                        lock (currentCompTrialEntries)
                        {
                            currentCompTrialEntries.Add(entry);
                        }
                    }
                }
            }, null))
            {
                this.dataSource.AddListener(compartifactListener);
                //Display each block of stimuli
                for (int j = 0; j < settings.NumBlocks * 2; j++)
                {
                    logWriter.WriteLine("Current Class: {0}, Block Number: {1}", (j % 2 + 1), j);
                    //yield return new TextView("Current Class: " + block.cls, 2500, GUIUtils.Constants.DISPLAY_FONT_LARGE);
                    IViewResult result;

                    yield return(new ChoiceView(new string[]
                    {
                        "Ready for next block"
                    }, out result));

                    int limit = blocks[j].Count;
                    for (int k = 0; k < limit; k++)
                    {
                        foreach (var view in RunCompTrial(blocks[j].RemoveRandom(), (j % 2 + 1), dataWriter, logWriter, currentCompTrialEntries))
                        {
                            yield return(view);
                        }
                    }
                }
                logWriter.WriteLine("Training Phase Concluded.");
            }
        }
Exemple #4
0
        /// <summary>
        /// Yields the experiment as a sequence of views
        /// </summary>
        public override IEnumerator <View> GetEnumerator()
        {
            // wait to begin
            yield return(new ChoiceView(new string[] { "Click anywhere to begin" }));

            var connected = new VolatileBool(true); // assume it's connected

            using (var invoker = new SingleThreadedInvoker())
                using (var connectionListener = new EEGDataListener(invoker, s => connected.value = true, null, s => connected.value = false))
                    using (var logger = this.LogExperimentAndGetLogger()) // log the experiment
                        using (var trialLogger = this.GetTrialWriter())   // logs each trial
                        {
                            // create the runtime
                            var runtime = new Runtime(this)
                            {
                                Classifiers = this.ClassificationSchemes.Select(cs => new ClassifierManager(cs)).ToIArray(),
                                Logger      = logger,
                                TrialLogger = trialLogger,
                            };

                            // listen for a broken connection
                            this.DataSource.AddListener(connectionListener);

                            foreach (var view in this.GetViews(runtime))
                            {
                                if (connected.value)
                                {
                                    yield return(view);
                                }
                                else
                                {
                                    GUIUtils.Alert(runtime.LogLine("Lost connection to headset!"));
                                    break;
                                }
                            }

                            this.DataSource.RemoveListener(connectionListener);
                        }
        }
Exemple #5
0
        /// <summary>
        /// The enumerator implementation
        /// </summary>
        public override IEnumerator <View> GetEnumerator()
        {
            IViewResult result;
            Random      numgen = new Random();
            RandomizedQueue <StudyTestPair> study = new RandomizedQueue <StudyTestPair>();
            RandomizedQueue <StudyTestPair> quiz  = new RandomizedQueue <StudyTestPair>();
            RandomizedQueue <StudyTestPair> done  = new RandomizedQueue <StudyTestPair>();
            string filename = "adapt_data_" + settings.SubjectName + "_" + DateTime.Now.ToString("MM dd yyyy H mm ss") + ".csv";

            using (var logWriter = new StreamWriter(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "adapt_log_" + settings.SubjectName + "_" + DateTime.Now.ToString("MM dd yyyy H mm ss") + ".txt")))
                //If using MATLAB reference, the datawriter path must match the location of your MATLAB code
                using (var dataWriter = new StreamWriter(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), filename)))
                {
                    yield return(new ChoiceView(new string[]
                    {
                        "Ready for Training Study Phase"
                    }, out result));

                    //Present competition stimuli for study
                    for (int j = 0; j < presentation.Count; j++)
                    {
                        yield return(new TextView(presentation[j], this.settings.PresentationTime, GUIUtils.Constants.DISPLAY_FONT_LARGE));

                        yield return(new RestView(this.settings.RestTime));
                    }

                    //Begin the practice phase
                    yield return(new ChoiceView(new string[]
                    {
                        "Start Training EEG Recording"
                    }, out result)
                    {
                        Text = "Click When Ready"
                    });

                    var compconnected = true; // assume it's connected
                    using (var compinvoker = new SingleThreadedInvoker())
                        using (var compconnectionListener = new EEGDataListener(compinvoker, s => compconnected = true, null, s => compconnected = false))
                        {
                            // listen for a broken connection
                            this.dataSource.AddListener(compconnectionListener);
                            foreach (var view in this.GetCompViews(compinvoker, logWriter, dataWriter))
                            {
                                if (compconnected)
                                {
                                    yield return(view);
                                }
                                else
                                {
                                    GUIUtils.Alert("Lost connection to headset!");
                                    break;
                                }
                            }

                            this.dataSource.RemoveListener(compconnectionListener);
                        }

                    //Check that the person has sufficient training data
                    if (numArt1 > 24 || numArt2 > 24)
                    {
                        yield return(new TextView("Error: Weeping Angel", settings.InstructionTime, GUIUtils.Constants.DISPLAY_FONT_LARGE));
                    }

                    //MATLAB REFERENCE
                    //matlab.Execute("cd c:\\Users\\Nicole\\Documents\\Matlab\\Thesis\\Adapt");
                    //matlab.Execute("classifier = wekacomptrain('"+ filename + "');");

                    yield return(new ChoiceView(new string[]
                    {
                        "Start Study Phase"
                    }, out result)
                    {
                        Text = "Click When Ready"
                    });

                    while (pres.Count > 0)
                    {
                        var stimulus = pres.RemoveRandom();
                        yield return(new TextView(stimulus.test + "\n" + stimulus.answer, this.settings.PresentationTime, GUIUtils.Constants.DISPLAY_FONT_LARGE));

                        yield return(new RestView(this.settings.RestTime));

                        quiz.Add(stimulus);
                    }

                    yield return(new ChoiceView(new string[]
                    {
                        "Start Test Phase"
                    }, out result)
                    {
                        Text = "Click When Ready"
                    });

                    var connected = true; // assume it's connected
                    using (var invoker = new SingleThreadedInvoker())
                        using (var connectionListener = new EEGDataListener(invoker, s => connected = true, null, s => connected = false))
                        {
                            // listen for a broken connection
                            this.dataSource.AddListener(connectionListener);
                            foreach (var view in this.GetViews(invoker, logWriter, dataWriter, study, quiz, done, numgen))
                            {
                                if (connected)
                                {
                                    yield return(view);
                                }
                                else
                                {
                                    GUIUtils.Alert("Lost connection to headset!");
                                    break;
                                }
                            }

                            this.dataSource.RemoveListener(connectionListener);
                        }
                }
        }
Exemple #6
0
        private IEnumerable <View> GetViews(ISynchronizeInvoke invoker, StreamWriter logWriter, StreamWriter dataWriter, RandomizedQueue <StudyTestPair> study,
                                            RandomizedQueue <StudyTestPair> quiz, RandomizedQueue <StudyTestPair> done, Random numgen)
        {
            var currentTrialEntries = new List <EEGDataEntry>();

            using (var artifactListener = new EEGDataListener(invoker, null, data =>
            {
                foreach (var entry in data)
                {
                    if (entry.HasStimulusMarker())
                    {
                        lock (currentTrialEntries)
                        {
                            currentTrialEntries.Add(entry);
                        }
                    }
                }
            }, null))
            {
                this.dataSource.AddListener(artifactListener);
                for (int index = 0; index < settings.NumRounds; index++)
                {
                    double        rand = numgen.NextDouble();
                    StudyTestPair stim;
                    if (rand < .39)
                    {
                        if (!study.IsEmpty())
                        {
                            stim = study.RemoveRandom();
                            quiz.Add(stim);
                            logWriter.WriteLine("5");
                            logWriter.WriteLine(stim.test + "\\n" + stim.answer);
                            yield return(new RestView(this.settings.BlinkTime));

                            yield return(new TextView(stim.test + "\n" + stim.answer, this.settings.PresentationTime, GUIUtils.Constants.DISPLAY_FONT_LARGE));
                        }
                        else if (!quiz.IsEmpty())
                        {
                            stim = quiz.RemoveRandom();
                            logWriter.WriteLine("7");
                            logWriter.WriteLine(stim.test);
                            logWriter.WriteLine(stim.answer);
                            foreach (var view in RunTrial(index, stim, dataWriter, logWriter, currentTrialEntries, study, quiz, done))
                            {
                                yield return(view);
                            }
                        }
                        else
                        {
                            stim = done.RemoveRandom();
                            logWriter.WriteLine("7");
                            logWriter.WriteLine(stim.test);
                            logWriter.WriteLine(stim.answer);
                            foreach (var view in RunTrial(index, stim, dataWriter, logWriter, currentTrialEntries, study, quiz, done))
                            {
                                yield return(view);
                            }
                        }
                    }
                    else if (rand < .99)
                    {
                        if (!quiz.IsEmpty())
                        {
                            stim = quiz.RemoveRandom();
                            logWriter.WriteLine("7");
                            logWriter.WriteLine(stim.test);
                            logWriter.WriteLine(stim.answer);
                            foreach (var view in RunTrial(index, stim, dataWriter, logWriter, currentTrialEntries, study, quiz, done))
                            {
                                yield return(view);
                            }
                        }
                        else if (!study.IsEmpty())
                        {
                            stim = study.RemoveRandom();
                            quiz.Add(stim);
                            logWriter.WriteLine("5");
                            logWriter.WriteLine(stim.test + "\\n" + stim.answer);
                            yield return(new RestView(this.settings.BlinkTime));

                            yield return(new TextView(stim.test + "\n" + stim.answer, this.settings.PresentationTime, GUIUtils.Constants.DISPLAY_FONT_LARGE));
                        }
                        else
                        {
                            stim = done.RemoveRandom();
                            logWriter.WriteLine("7");
                            logWriter.WriteLine(stim.test);
                            logWriter.WriteLine(stim.answer);
                            foreach (var view in RunTrial(index, stim, dataWriter, logWriter, currentTrialEntries, study, quiz, done))
                            {
                                yield return(view);
                            }
                        }
                    }
                    else
                    {
                        if (!done.IsEmpty())
                        {
                            stim = done.RemoveRandom();
                            logWriter.WriteLine("7");
                            logWriter.WriteLine(stim.test);
                            logWriter.WriteLine(stim.answer);
                            foreach (var view in RunTrial(index, stim, dataWriter, logWriter, currentTrialEntries, study, quiz, done))
                            {
                                yield return(view);
                            }
                        }
                        else if (!quiz.IsEmpty())
                        {
                            stim = quiz.RemoveRandom();
                            logWriter.WriteLine("7");
                            logWriter.WriteLine(stim.test);
                            logWriter.WriteLine(stim.answer);
                            foreach (var view in RunTrial(index, stim, dataWriter, logWriter, currentTrialEntries, study, quiz, done))
                            {
                                yield return(view);
                            }
                        }
                        else
                        {
                            stim = study.RemoveRandom();
                            quiz.Add(stim);
                            logWriter.WriteLine("5");
                            logWriter.WriteLine(stim.test + "\\n" + stim.answer);
                            yield return(new RestView(this.settings.BlinkTime));

                            yield return(new TextView(stim.test + "\n" + stim.answer, this.settings.PresentationTime, GUIUtils.Constants.DISPLAY_FONT_LARGE));
                        }
                    }
                }
            }
        }
Exemple #7
0
        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);
        }