Beispiel #1
0
        private EEGDataListener GetRawDataRecordingListener()
        {
            if (!this.Settings.SaveRawData)
            {
                return(null);
            }

            StreamWriter writer;

            try
            {
                writer = new StreamWriter(
                    Path.Combine(this.Settings.OutputFolder, GetFileName(RAW_DATA_BASE_NAME, this.startTime, GUIUtils.Strings.CSV_EXTENSION)),
                    false);
            }
            catch (Exception)
            {
                GUIUtils.Alert("Failed to save raw data to " + this.Settings.OutputFolder, MessageBoxIcon.Warning);
                return(null);
            }

            var invoker = new SingleThreadedInvoker();

            return(new EEGDataListener(invoker,
                                       null,
                                       data =>
            {
                try { writer.WriteLine(data.ConcatToString(Environment.NewLine)); }
                catch (Exception) { }
            },
                                       null,
                                       () => { writer.Dispose(); invoker.Dispose(); }));
        }
Beispiel #2
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);
                            }
                    }
                }
        }
Beispiel #3
0
        private TextWriter LogExperimentAndGetLogger()
        {
            if (!this.Settings.LogExperiment)
            {
                return(null);
            }

            try
            {
                var writer = new StreamWriter(
                    Path.Combine(this.Settings.OutputFolder, GetFileName(LOG_BASE_NAME, this.startTime, GUIUtils.Strings.TEXT_EXTENSION)),
                    false);

                writer.WriteLine(string.Format(GUIUtils.Strings.LOGGING_TITLE_FORMAT, "General Settings"));
                writer.WriteLine();
                writer.WriteLine(this.Settings);
                writer.WriteLine();
                writer.WriteLine(string.Format(GUIUtils.Strings.LOGGING_TITLE_FORMAT, "First Stimulus Class"));
                writer.WriteLine();
                writer.WriteLine(this.StimulusClass1);
                writer.WriteLine();
                writer.WriteLine(string.Format(GUIUtils.Strings.LOGGING_TITLE_FORMAT, "Second Stimulus Class"));
                writer.WriteLine();
                writer.WriteLine(this.StimulusClass2);
                writer.WriteLine();
                writer.WriteLine(string.Format(GUIUtils.Strings.LOGGING_TITLE_FORMAT, "Classifiers"));
                writer.WriteLine();
                foreach (var classifier in this.ClassificationSchemes)
                {
                    writer.WriteLine(classifier);
                    writer.WriteLine();
                }
                writer.WriteLine(string.Format(GUIUtils.Strings.LOGGING_TITLE_FORMAT, "Artifact Detection"));
                writer.WriteLine();
                writer.WriteLine(this.Settings.ArtifactDetectionSettings.UseArtifactDetection
                    ? this.Settings.ArtifactDetectionSettings.PrettyPrint()
                    : "Disabled");
                writer.WriteLine();
                writer.WriteLine(string.Format(GUIUtils.Strings.LOGGING_TITLE_FORMAT, "Beginning Experiment"));
                writer.WriteLine();

                return(writer);
            }
            catch (Exception ex)
            {
                GUIUtils.Alert("Failed to log experiment to " + this.Settings.OutputFolder + ": " + ex.Message, MessageBoxIcon.Warning);
                return(null);
            }
        }
Beispiel #4
0
 //A private method for reading in stimuli, using \n as an indicator of a newline
 private IArrayView <string> ReadCompetitionStimuli(string path)
 {
     try
     {
         var lines   = File.ReadAllLines(path);
         var stimuli = lines.Select(s => s.Replace(@"\n", Environment.NewLine))
                       .ToIArray();
         return(stimuli);
     }
     catch (Exception)
     {
         GUIUtils.Alert("Failed to Read File" + path);
         return(null);
     }
 }
Beispiel #5
0
        /// <summary>
        /// Yields a sequence of views that implement the tool
        /// </summary>
        public override IEnumerator <View> GetEnumerator()
        {
            IViewResult result;

            // for each image, get the user's input
            var stimuli = this.stimulusClass.Stimuli.ToIArray();

            for (int i = 0; i < stimuli.Count; i++)
            {
                yield return(new ClassifyView(stimuli[i], this.stimulusClass, out result));

                if (BACK.Equals(result.Value))
                {
                    i = Math.Max(-1, i - 2);
                    continue;
                }
                if (SKIP.Equals(result.Value))
                {
                    continue;
                }
                stimuli[i].Subclass = (bool?)result.Value;
            }

            // a brief break
            yield return(new RestView(500));

            // offer to save
            yield return(new ChoiceView(new string[]
            {
                SAVE,
                "Don't Save"
            }, out result));

            // save
            if (SAVE.Equals(result.Value))
            {
                if (this.stimulusClass.TrySave())
                {
                    yield return(new TextView("Results saved to " + this.stimulusClass.SavePath, 2000));
                }
                else
                {
                    GUIUtils.Alert("Failed to save results to " + this.stimulusClass.SavePath, MessageBoxIcon.Error);
                }
            }
        }
Beispiel #6
0
        private TextWriter GetTrialWriter()
        {
            if (!this.Settings.SaveTrialData)
            {
                return(null);
            }

            try
            {
                return(new StreamWriter(
                           Path.Combine(this.Settings.OutputFolder, GetFileName(DATA_BASE_NAME, this.startTime, GUIUtils.Strings.CSV_EXTENSION)),
                           false));
            }
            catch (Exception)
            {
                GUIUtils.Alert("Failed to save trial data to " + this.Settings.OutputFolder, MessageBoxIcon.Warning);
                return(null);
            }
        }
Beispiel #7
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);
                        }
        }
Beispiel #8
0
        private void BuildView(ClassificationScheme classificationScheme)
        {
            this.SuspendLayout();
            this.Text = classificationScheme.Settings.Name;
            var table = GUIUtils.CreateTable(new double[] { .33, .33, .33 }, Direction.Horizontal);

            // classifier
            var classifierSettings = new DerivedTypeConfigurationPanel(typeof(IClassifier), classificationScheme.Classifier);

            this.getClassifier = () => (IClassifier)classifierSettings.GetConfiguredObject();
            table.Controls.Add(classifierSettings, 0, 0);

            // general settings
            var generalSettings = new ConfigurationPanel(classificationScheme.Settings);

            table.Controls.Add(generalSettings, 1, 0);

            // bin selection
            var panel = new Panel()
            {
                Dock = DockStyle.Fill
            };

            var binList = new CheckedListBox()
            {
                Dock = DockStyle.Fill, CheckOnClick = true
            };

            binList.AddContextMenu();
            this.ToolTip.SetToolTip(binList, "Select which time bins from each trial will be used to train the classifier");
            var timeBins = GeneralClassifierSettings.MAX_BINS
                           .CountTo()
                           .Select(i => new TimeBin(i)
            {
                Checked = classificationScheme.Settings.SelectedBins.Contains(i)
            })
                           .ToIArray();

            binList.ItemCheck += (sender, args) => ((TimeBin)binList.Items[args.Index]).Checked = (args.NewValue == CheckState.Checked);
            Action <int> refreshBinList = (binWidth) =>
            {
                // ensure the right number of items
                int binCount = GeneralClassifierSettings.GetBinCount(binWidth);
                if (binList.Items.Count < binCount)
                {
                    binList.Items.AddRange(timeBins.SubView(binList.Items.Count, binCount - binList.Items.Count).ToArray());
                }
                else
                {
                    for (int i = binList.Items.Count - 1; i >= binCount; i--)
                    {
                        binList.Items.RemoveAt(i);
                    }
                }

                // ensure correct width and uncheck all
                TimeBin timeBin;
                for (int i = 0; i < binCount; i++)
                {
                    timeBin          = (TimeBin)binList.Items[i];
                    timeBin.BinWidth = binWidth;
                    binList.SetItemChecked(i, timeBin.Checked);
                }

                binList.Invalidate();
            };

            refreshBinList(classificationScheme.Settings.BinWidthMillis);
            var binWidthProp = typeof(GeneralClassifierSettings).GetProperty("BinWidthMillis");
            var nameProp     = typeof(GeneralClassifierSettings).GetProperty("Name");

            if (binWidthProp == null || nameProp == null)
            {
                throw new Exception("Failed to find properties!");
            }
            generalSettings.PropertyChanged += args =>
            {
                if (args.Property.Equals(binWidthProp))
                {
                    refreshBinList((int)args.Getter());
                }
                else if (args.Property.Equals(nameProp))
                {
                    this.Text = args.Getter().ToString();
                }
            };
            this.getSettings = () =>
            {
                var settings = (GeneralClassifierSettings)generalSettings.GetConfiguredObject();
                settings.SelectedBins = binList.CheckedIndices.Cast <int>().ToIArray();

                return(settings);
            };
            panel.Controls.Add(binList);
            panel.Controls.Add("Time Bins".ToLabel());
            var saveButton = GUIUtils.CreateFlatButton("Save", (b) =>
            {
                this.saveDialog.FileName = this.Text;
                if (this.saveDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                bool saved = this.ClassificationScheme.TrySerializeToFile(this.saveDialog.FileName);
                GUIUtils.Alert((saved ? "Saved" : "Failed to save")
                               + " classifier info to " + this.saveDialog.FileName,
                               (saved ? MessageBoxIcon.Information : MessageBoxIcon.Error));

                string directory = Path.GetDirectoryName(this.saveDialog.FileName);
                if (Directory.Exists(directory))
                {
                    this.saveDialog.InitialDirectory = directory;
                }
            });

            saveButton.Dock = DockStyle.Bottom;
            panel.Controls.Add(saveButton);
            table.Controls.Add(panel, 2, 0);

            this.Controls.Add(table);
            this.ResumeLayout(false);
        }
Beispiel #9
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);
                        }
                }
        }
Beispiel #10
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);
        }
Beispiel #11
0
        private void BuildView()
        {
            this.SuspendLayout();
            this.Text = this.StimulusClass.Settings.Name;
            var cols = GUIUtils.CreateTable(new double[] { .33, .33, .33 }, Direction.Horizontal);

            // settings
            var settingsConfig = new ConfigurationPanel(this.StimulusClass.Settings)
            {
                Dock = DockStyle.Fill
            };

            // image panel
            var imagePanel = new ImagePanel()
            {
                Dock = DockStyle.Fill
            };

            // dropdown
            var dropDown = new ComboBox()
            {
                DropDownStyle = ComboBoxStyle.DropDownList, Dock = DockStyle.Bottom
            };

            dropDown.MouseWheel += (sender, args) => ((HandledMouseEventArgs)args).Handled = true;
            dropDown.Items.Add(new DisplayPointer(() => this.StimulusClass.Settings.Answer1, true));
            dropDown.Items.Add(new DisplayPointer(() => this.StimulusClass.Settings.Answer2, false));
            dropDown.Items.Add(new DisplayPointer(GUIUtils.Strings.UNCLASSIFIED, null));

            // source folder
            var sourceFolderLink = new LinkLabel()
            {
                AutoSize = true, Text = Path.GetFileName(this.StimulusClass.SourceFolder), Dock = DockStyle.Top
            };

            sourceFolderLink.Click += (sender, args) =>
            {
                try { System.Diagnostics.Process.Start("explorer.exe", this.StimulusClass.SourceFolder); }
                catch (Exception) { GUIUtils.Alert("Failed to open " + this.StimulusClass.SourceFolder); }
            };
            this.ToolTip.SetToolTip(sourceFolderLink, "Open " + this.StimulusClass.SourceFolder);

            // image list
            var imageList = new CheckedListBox()
            {
                Dock = DockStyle.Fill
            };

            imageList.AddContextMenu();
            foreach (var stimulus in this.StimulusClass.Stimuli)
            {
                imageList.Items.Add(new StimulusItem(this.StimulusClass, stimulus), stimulus.Used);
            }
            EventHandler setImage = (sender, args) =>
            {
                if (imageList.Items.Count > 0)
                {
                    var stimulus = ((StimulusItem)(imageList.SelectedItem ?? imageList.Items[0])).Stimulus;
                    imagePanel.ImagePath = stimulus.PathOrText;
                    dropDown.Visible     = true;
                    switch (stimulus.Subclass)
                    {
                    case true: dropDown.SelectedIndex = 0; break;

                    case false: dropDown.SelectedIndex = 1; break;

                    case null: dropDown.SelectedIndex = 2; break;
                    }
                }
                else
                {
                    imagePanel.ImagePath = null;
                    dropDown.Visible     = false;
                }
            };

            setImage(imageList, EventArgs.Empty); // first set
            imageList.SelectedIndexChanged += setImage;
            settingsConfig.PropertyChanged += args =>
            {
                this.StimulusClass.Settings.SetProperty(args.Property, args.Getter());
                this.Text = this.StimulusClass.Settings.Name;
                imageList.Invalidate();

                // force a refresh
                int selectedIndex = dropDown.SelectedIndex;
                var items         = dropDown.Items.Cast <DisplayPointer>().ToArray();
                dropDown.Items.Clear();
                dropDown.Items.AddRange(items);
                dropDown.SelectedIndex = selectedIndex;
            };
            imageList.ItemCheck           += (sender, args) => ((StimulusItem)imageList.Items[args.Index]).Stimulus.Used = (args.NewValue == CheckState.Checked);
            dropDown.SelectedIndexChanged += (sender, args) =>
            {
                ((StimulusItem)(imageList.SelectedItem ?? imageList.Items[0])).Stimulus.Subclass =
                    (bool?)((DisplayPointer)dropDown.SelectedItem).Key;
                imageList.Invalidate();
            };
            this.getSelectedStimulus = () => imageList.SelectedItem == null ? null : ((StimulusItem)imageList.SelectedItem).Stimulus;

            // selection info label
            var selectionInfoLabel = new Label()
            {
                Dock = DockStyle.Bottom, AutoSize = true
            };
            PaintEventHandler updateSelectionInfoLabel = (sender, args) =>
            {
                var items = imageList.Items.Cast <StimulusItem>();
                selectionInfoLabel.Text = string.Format("{0}/{1} selected", items.Count(s => s.Stimulus.Used), imageList.Items.Count);
                if (!string.IsNullOrWhiteSpace(this.StimulusClass.Settings.Answer1) ||
                    !string.IsNullOrWhiteSpace(this.StimulusClass.Settings.Answer2))
                {
                    selectionInfoLabel.Text += string.Format(" ({0}/{1} {2}, {3}/{4} {5}, {6}/{7} {8})", items.Count(s => s.Stimulus.Subclass == true && s.Stimulus.Used),
                                                             items.Count(s => s.Stimulus.Subclass == true),
                                                             this.StimulusClass.Settings.Answer1,
                                                             items.Count(s => s.Stimulus.Subclass == false && s.Stimulus.Used),
                                                             items.Count(s => s.Stimulus.Subclass == false),
                                                             this.StimulusClass.Settings.Answer2,
                                                             items.Count(s => s.Stimulus.Subclass == null && s.Stimulus.Used),
                                                             items.Count(s => s.Stimulus.Subclass == null),
                                                             GUIUtils.Strings.UNCLASSIFIED);
                }
            };

            imageList.Paint += updateSelectionInfoLabel;
            updateSelectionInfoLabel(null, null);

            // button table
            var buttonTable = GUIUtils.CreateButtonTable(Direction.Horizontal, DockStyle.Bottom,
                                                         GUIUtils.CreateFlatButton("Classify", b =>
            {
                MainForm.Instance.Animate(new StimulusClassSetupProvider(this.StimulusClass), this.Invalidate);
            }, this.ToolTip, "Launch a tool to quickly answer this class's question for all stimuli"),
                                                         GUIUtils.CreateFlatButton("Refresh", b =>
            {
                this.StimulusClass.RefreshStimuli();
                this.Invalidate();
            }, this.ToolTip, "Reload the stimuli from the file system"),
                                                         GUIUtils.CreateFlatButton("Save", b =>
            {
                bool saved = this.StimulusClass.TrySave();
                GUIUtils.Alert((saved ? "Saved" : "Failed to save")
                               + " stimulus class info to " + this.StimulusClass.SavePath,
                               (saved ? MessageBoxIcon.Information : MessageBoxIcon.Error));
            }, this.ToolTip, "Save configuration information to " + this.StimulusClass.SavePath));

            // add all controls
            Panel panel;

            // left column
            panel = new Panel()
            {
                Dock = DockStyle.Fill
            };
            panel.Controls.Add(settingsConfig);
            panel.Controls.Add(sourceFolderLink);
            panel.Controls.Add("Folder".ToLabel());
            panel.Controls.Add(buttonTable);
            cols.Controls.Add(panel, 0, 0);

            // middle column
            panel = new Panel()
            {
                Dock = DockStyle.Fill
            };
            panel.Controls.Add(imageList);
            panel.Controls.Add(selectionInfoLabel);
            panel.Controls.Add("Stimuli".ToLabel());
            cols.Controls.Add(panel, 1, 0);

            // right column
            panel = new Panel()
            {
                Dock = DockStyle.Fill
            };
            panel.Controls.Add(imagePanel);
            panel.Controls.Add(dropDown);
            cols.Controls.Add(panel, 2, 0);

            this.Controls.Add(cols);
            this.ResumeLayout(false);
        }
Beispiel #12
0
        /// <summary>
        /// Builds the application view for the Adaptive Application
        /// </summary>
        public void BuildAdaptiveView()
        {
            this.SuspendLayout();
            this.Text = GUIUtils.Strings.APP_NAME;
            this.Size = new System.Drawing.Size(1500, 750);

            //Settings panels
            var config = ConfigurationPanel.Create <AdaptiveSettings>();
            //var artifactConfig = ConfigurationPanel.Create<ArtifactDetectionSettings>();
            var stimulipanel = new AdaptiveSelectorPanel()
            {
                Dock = DockStyle.Fill
            };
            // classifier settings
            var classifierPanel = new ClassificationSchemePanel()
            {
                Dock = DockStyle.Fill
            };

            //Headset Connected?
            EmotivStatusCheckerPanel statusChecker = new EmotivStatusCheckerPanel()
            {
                Dock = DockStyle.Fill
            };

            // start button
            var startButton = GUIUtils.CreateFlatButton("Start Experiment", b =>
            {
                var settings = (AdaptiveSettings)config.GetConfiguredObject();
                //settings.ArtifactDetectionSettings = (ArtifactDetectionSettings)artifactConfig.GetConfiguredObject();
                settings.ArtifactDetectionSettings = (ArtifactDetectionSettings)classifierPanel.ArtifactDetectionSettings;
                var test         = this.ReadAdaptStimuli(stimulipanel.TestFile);
                var ans          = this.ReadAdaptStimuli(stimulipanel.AnsFile);
                var presentation = this.ReadCompetitionStimuli(stimulipanel.PresentationFile);
                var class1       = this.ReadCompetitionStimuli(stimulipanel.Class1File);
                var class2       = this.ReadCompetitionStimuli(stimulipanel.Class2File);
                //Make study-test pairs for practice phase
                RandomizedQueue <MCAEmotiv.GUI.Adaptive.StudyTestPair> stp = new RandomizedQueue <MCAEmotiv.GUI.Adaptive.StudyTestPair>();
                for (int i = 0; i < test.Count; i++)
                {
                    stp.Add(new MCAEmotiv.GUI.Adaptive.StudyTestPair(test[i], ans[i], i));
                }
                //To Do: Add a dialog box so that the user knows whether the headset is connected
                IEEGDataSource dataSource;
                if (statusChecker.HeadsetConnected)
                {
                    dataSource = EmotivDataSource.Instance;
                }
                else
                {
                    dataSource = new MockEEGDataSource();
                }

                var classifiers = classifierPanel.SelectedClassifiers;
                this.Animate(new AdaptiveProvider(stp, presentation, class1, class2, settings, dataSource, classifiers.Where(c => c.Settings.FeatureCount > 0).ToIArray()));
            });

            //Dialog boxes for saving and loading experiment settings
            var saveDialog = new SaveFileDialog()
            {
                Title            = "Save experiment settings",
                Filter           = "Experiment settings files|*.adaptsettings",
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
            };
            var openDialog = new OpenFileDialog()
            {
                Title            = "Select the saved experiment settings (.adaptsettings) file",
                Filter           = "Experiment settings files|*.adaptsettings",
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Multiselect      = false
            };

            // button table for saving and loading experiment settings
            var buttonTable = GUIUtils.CreateButtonTable(Direction.Horizontal, DockStyle.Fill,
                                                         GUIUtils.CreateFlatButton("Save", b =>
            {
                var settings              = (AdaptiveSettings)config.GetConfiguredObject();
                settings.TestFile         = stimulipanel.TestFile;
                settings.AnsFile          = stimulipanel.AnsFile;
                settings.PresentationFile = stimulipanel.PresentationFile;
                settings.Class1File       = stimulipanel.Class1File;
                settings.Class2File       = stimulipanel.Class2File;
                //settings.ArtifactDetectionSettings = (ArtifactDetectionSettings)artifactConfig.GetConfiguredObject();
                settings.ArtifactDetectionSettings = (ArtifactDetectionSettings)classifierPanel.ArtifactDetectionSettings;
                //ISSUE HERE
                //settings.ClassificationSettings = (ClassificationScheme) classifierPanel
                saveDialog.FileName = string.IsNullOrWhiteSpace(settings.ExperimentName) ? "my experiment" : settings.ExperimentName;
                if (saveDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                bool saved = settings.TrySerializeToFile(saveDialog.FileName);
                GUIUtils.Alert((saved ? "Saved" : "Failed to save")
                               + " experiment info to " + saveDialog.FileName,
                               (saved ? MessageBoxIcon.Information : MessageBoxIcon.Error));

                string directory = Path.GetDirectoryName(saveDialog.FileName);
                if (Directory.Exists(directory))
                {
                    saveDialog.InitialDirectory = directory;
                }
            }, null, "Save experiment configuration information"),
                                                         GUIUtils.CreateFlatButton("Load", b =>
            {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                AdaptiveSettings settings;

                if (Utils.TryDeserializeFile(openDialog.FileName, out settings))
                {
                    config.SetConfiguredObject(settings);
                    stimulipanel.TestFile         = settings.TestFile;
                    stimulipanel.AnsFile          = settings.AnsFile;
                    stimulipanel.PresentationFile = settings.PresentationFile;
                    stimulipanel.Class1File       = settings.Class1File;
                    stimulipanel.Class2File       = settings.Class2File;
                    //NEED TO DO EACH CLASSIFIERPANEL PROPERTY ONE BY ONE :(
                    //artifactConfig.SetConfiguredObject(settings.ArtifactDetectionSettings);
                    //classifierPanel.SetConfiguredObject(settings.ArtifactDetectionSettings);
                }
                else
                {
                    GUIUtils.Alert("Failed to load experiment info from " + openDialog.FileName, MessageBoxIcon.Error);
                }
            }, null, "Load a previously saved experiment settings file"));

            //Put together the GUI
            var rows = GUIUtils.CreateTable(new[] { .5, .35, .15 }, Direction.Vertical);
            var col1 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);
            var col2 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);
            var col3 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);

            //col2.Controls.Add(artifactConfig, 1, 0);
            col1.Controls.Add(startButton, 1, 0);
            col1.Controls.Add(statusChecker, 0, 0);
            col2.Controls.Add(config, 0, 0);
            col2.Controls.Add(classifierPanel, 1, 0);
            col3.Controls.Add(stimulipanel, 1, 0);
            col3.Controls.Add(buttonTable, 0, 0);
            rows.Controls.Add(col3, 0, 1);
            rows.Controls.Add(col1, 0, 2);
            rows.Controls.Add(col2, 0, 0);


            this.Controls.Add(rows);


            this.ResumeLayout(false);
        }
Beispiel #13
0
        /// <summary>
        /// Builds the application view for the competition experiment
        /// </summary>
        public void BuildCompetitionExperimenterView()
        {
            this.SuspendLayout();
            this.Text = GUIUtils.Strings.APP_NAME;
            this.Size = new System.Drawing.Size(1500, 750);

            //Settings panel
            var config         = ConfigurationPanel.Create <CompetitionExperimentSettings>();
            var artifactConfig = ConfigurationPanel.Create <ArtifactDetectionSettings>();
            var stimulipanel   = new CompetitionClassSelectorPanel()
            {
                Dock = DockStyle.Fill
            };

            //Headset Connected?
            EmotivStatusCheckerPanel statusChecker = new EmotivStatusCheckerPanel()
            {
                Dock = DockStyle.Fill
            };

            // start button
            var startButton = GUIUtils.CreateFlatButton("Start Experiment", b =>
            {
                var settings = (CompetitionExperimentSettings)config.GetConfiguredObject();
                settings.ArtifactDetectionSettings = (ArtifactDetectionSettings)artifactConfig.GetConfiguredObject();
                var presentation = this.ReadCompetitionStimuli(stimulipanel.PresentationFile);
                var class1       = this.ReadCompetitionStimuli(stimulipanel.Class1File);
                var class2       = this.ReadCompetitionStimuli(stimulipanel.Class2File);
                if (presentation == null)
                {
                    return;
                }
                //To Do: Add a dialog box so that the user knows whether the headset is connected
                IEEGDataSource dataSource;
                if (statusChecker.HeadsetConnected)
                {
                    dataSource = EmotivDataSource.Instance;
                }
                else
                {
                    dataSource = new MockEEGDataSource();
                }
                this.Animate(new CompetitionExperimentProvider(presentation, class1, class2, settings, dataSource));
            });

            //Dialog boxes for saving and loading experiment settings
            var saveDialog = new SaveFileDialog()
            {
                Title            = "Save experiment settings",
                Filter           = "Experiment settings files|*.compexpsettings",
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
            };
            var openDialog = new OpenFileDialog()
            {
                Title            = "Select the saved experiment settings (.compexpsettings) file",
                Filter           = "Experiment settings files|*.compexpsettings",
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Multiselect      = false
            };

            // button table for saving and loading experiment settings
            var buttonTable = GUIUtils.CreateButtonTable(Direction.Horizontal, DockStyle.Fill,
                                                         GUIUtils.CreateFlatButton("Save", b =>
            {
                var settings = (CompetitionExperimentSettings)config.GetConfiguredObject();
                settings.PresentationFile          = stimulipanel.PresentationFile;
                settings.Class1File                = stimulipanel.Class1File;
                settings.Class2File                = stimulipanel.Class2File;
                settings.ArtifactDetectionSettings = (ArtifactDetectionSettings)artifactConfig.GetConfiguredObject();
                saveDialog.FileName                = string.IsNullOrWhiteSpace(settings.ExperimentName) ? "my experiment" : settings.ExperimentName;
                if (saveDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                bool saved = settings.TrySerializeToFile(saveDialog.FileName);
                GUIUtils.Alert((saved ? "Saved" : "Failed to save")
                               + " experiment info to " + saveDialog.FileName,
                               (saved ? MessageBoxIcon.Information : MessageBoxIcon.Error));

                string directory = Path.GetDirectoryName(saveDialog.FileName);
                if (Directory.Exists(directory))
                {
                    saveDialog.InitialDirectory = directory;
                }
            }, null, "Save experiment configuration information"),
                                                         GUIUtils.CreateFlatButton("Load", b =>
            {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                CompetitionExperimentSettings settings;

                if (Utils.TryDeserializeFile(openDialog.FileName, out settings))
                {
                    config.SetConfiguredObject(settings);
                    stimulipanel.PresentationFile = settings.PresentationFile;
                    stimulipanel.Class1File       = settings.Class1File;
                    stimulipanel.Class2File       = settings.Class2File;
                    artifactConfig.SetConfiguredObject(settings.ArtifactDetectionSettings);
                }
                else
                {
                    GUIUtils.Alert("Failed to load experiment info from " + openDialog.FileName, MessageBoxIcon.Error);
                }
            }, null, "Load a previously saved experiment settings file"));

            //Put together the GUI
            var rows = GUIUtils.CreateTable(new[] { .5, .2, .3 }, Direction.Vertical);
            var col1 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);
            var col2 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);
            var col3 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);

            col2.Controls.Add(artifactConfig, 1, 0);
            col1.Controls.Add(startButton, 1, 0);
            col1.Controls.Add(statusChecker, 0, 0);
            col2.Controls.Add(config, 0, 0);
            col3.Controls.Add(stimulipanel, 1, 0);
            col3.Controls.Add(buttonTable, 0, 0);
            rows.Controls.Add(col3, 0, 1);
            rows.Controls.Add(col1, 0, 2);
            rows.Controls.Add(col2, 0, 0);


            this.Controls.Add(rows);


            this.ResumeLayout(false);
        }
Beispiel #14
0
        /// <summary>
        /// Builds the application view for the User Control Vocabulary Application
        /// </summary>
        public void BuildUserCtrlView()
        {
            this.SuspendLayout();
            this.Text = GUIUtils.Strings.APP_NAME;
            this.Size = new System.Drawing.Size(1500, 750);

            //Settings panel
            var config       = ConfigurationPanel.Create <UserCtrlSettings>();
            var stimulipanel = new UserCtrlSelectorPanel()
            {
                Dock = DockStyle.Fill
            };

            // start button
            var startButton = GUIUtils.CreateFlatButton("Start Experiment", b =>
            {
                var settings     = (UserCtrlSettings)config.GetConfiguredObject();
                var presentation = this.ReadUserStimuli(stimulipanel.PresentationFile);
                var test         = this.ReadUserStimuli(stimulipanel.TestFile);
                var ans          = this.ReadUserStimuli(stimulipanel.AnsFile);
                var comp         = this.ReadCompetitionStimuli(stimulipanel.CompFile);
                var class1       = this.ReadCompetitionStimuli(stimulipanel.Class1File);
                var class2       = this.ReadCompetitionStimuli(stimulipanel.Class2File);
                //Make study-test pairs for the practice phase
                RandomizedQueue <MCAEmotiv.GUI.UserControlVocab.StudyTestPair> stp = new RandomizedQueue <MCAEmotiv.GUI.UserControlVocab.StudyTestPair>();
                for (int i = 0; i < test.Count; i++)
                {
                    stp.Add(new MCAEmotiv.GUI.UserControlVocab.StudyTestPair(test[i], ans[i], i));
                }
                if (presentation == null)
                {
                    return;
                }
                this.Animate(new UserCtrlProvider(presentation, comp, class1, class2, stp, settings));
            });

            //Dialog boxes for saving and loading experiment settings
            var saveDialog = new SaveFileDialog()
            {
                Title            = "Save experiment settings",
                Filter           = "Experiment settings files|*.usersettings",
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
            };
            var openDialog = new OpenFileDialog()
            {
                Title            = "Select the saved experiment settings (.usersettings) file",
                Filter           = "Experiment settings files|*.usersettings",
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Multiselect      = false
            };

            // button table for saving and loading experiment settings
            var buttonTable = GUIUtils.CreateButtonTable(Direction.Horizontal, DockStyle.Fill,
                                                         GUIUtils.CreateFlatButton("Save", b =>
            {
                var settings = (UserCtrlSettings)config.GetConfiguredObject();
                settings.PresentationFile = stimulipanel.PresentationFile;
                settings.TestFile         = stimulipanel.TestFile;
                settings.AnsFile          = stimulipanel.AnsFile;
                settings.CompFile         = stimulipanel.CompFile;
                settings.Class1File       = stimulipanel.Class1File;
                settings.Class2File       = stimulipanel.Class2File;
                saveDialog.FileName       = string.IsNullOrWhiteSpace(settings.ExperimentName) ? "my experiment" : settings.ExperimentName;
                if (saveDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                bool saved = settings.TrySerializeToFile(saveDialog.FileName);
                GUIUtils.Alert((saved ? "Saved" : "Failed to save")
                               + " experiment info to " + saveDialog.FileName,
                               (saved ? MessageBoxIcon.Information : MessageBoxIcon.Error));

                string directory = Path.GetDirectoryName(saveDialog.FileName);
                if (Directory.Exists(directory))
                {
                    saveDialog.InitialDirectory = directory;
                }
            }, null, "Save experiment configuration information"),
                                                         GUIUtils.CreateFlatButton("Load", b =>
            {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                UserCtrlSettings settings;

                if (Utils.TryDeserializeFile(openDialog.FileName, out settings))
                {
                    config.SetConfiguredObject(settings);
                    stimulipanel.PresentationFile = settings.PresentationFile;
                    stimulipanel.TestFile         = settings.TestFile;
                    stimulipanel.AnsFile          = settings.AnsFile;
                    stimulipanel.CompFile         = settings.CompFile;
                    stimulipanel.Class1File       = settings.Class1File;
                    stimulipanel.Class2File       = settings.Class2File;
                }
                else
                {
                    GUIUtils.Alert("Failed to load experiment info from " + openDialog.FileName, MessageBoxIcon.Error);
                }
            }, null, "Load a previously saved experiment settings file"));


            //Put together the GUI
            var rows = GUIUtils.CreateTable(new[] { .5, .35, .15 }, Direction.Vertical);
            var col3 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);

            col3.Controls.Add(stimulipanel, 1, 0);
            col3.Controls.Add(buttonTable, 0, 0);
            rows.Controls.Add(col3, 0, 1);
            rows.Controls.Add(startButton, 0, 2);
            rows.Controls.Add(config, 0, 0);


            this.Controls.Add(rows);


            this.ResumeLayout(false);
        }
Beispiel #15
0
        /// <summary>
        /// Builds the application view for the False Adaptive Application
        /// </summary>
        public void BuildFAdaptView()
        {
            this.SuspendLayout();
            this.Text = GUIUtils.Strings.APP_NAME;
            this.Size = new System.Drawing.Size(1500, 750);

            //Settings panels
            var config         = ConfigurationPanel.Create <FalseAdaptSettings>();
            var artifactConfig = ConfigurationPanel.Create <ArtifactDetectionSettings>();
            var stimulipanel   = new FalseAdaptSelectorPanel()
            {
                Dock = DockStyle.Fill
            };

            //Headset Connected?
            EmotivStatusCheckerPanel statusChecker = new EmotivStatusCheckerPanel()
            {
                Dock = DockStyle.Fill
            };

            // start button
            var startButton = GUIUtils.CreateFlatButton("Start Experiment", b =>
            {
                var settings = (FalseAdaptSettings)config.GetConfiguredObject();
                settings.ArtifactDetectionSettings = (ArtifactDetectionSettings)artifactConfig.GetConfiguredObject();
                var presentation = this.ReadFAStimuli(stimulipanel.PresentationFile);
                var comp         = this.ReadCompetitionStimuli(stimulipanel.CompFile);
                var class1       = this.ReadCompetitionStimuli(stimulipanel.Class1File);
                var class2       = this.ReadCompetitionStimuli(stimulipanel.Class2File);
                var study        = this.ReadUserStimuli(stimulipanel.StudyFile);
                //Make study-test pairs for practice phase
                RandomizedQueue <StudyTestTuple> stt = new RandomizedQueue <StudyTestTuple>();
                for (int i = 0; i < presentation.Count; i++)
                {
                    if (presentation[i] == "5")
                    {
                        stt.Add(new StudyTestTuple(presentation[i + 1], presentation[i + 1], true));
                    }
                    if (presentation[i] == "7")
                    {
                        stt.Add(new StudyTestTuple(presentation[i + 1], presentation[i + 2], false));
                    }
                }

                this.Animate(new FalseAdaptProvider(stt, comp, class1, class2, study, settings));
            });

            //Dialog boxes for saving and loading experiment settings
            var saveDialog = new SaveFileDialog()
            {
                Title            = "Save experiment settings",
                Filter           = "Experiment settings files|*.fasettings",
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
            };
            var openDialog = new OpenFileDialog()
            {
                Title            = "Select the saved experiment settings (.fasettings) file",
                Filter           = "Experiment settings files|*.fasettings",
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Multiselect      = false
            };

            // button table for saving and loading experiment settings
            var buttonTable = GUIUtils.CreateButtonTable(Direction.Horizontal, DockStyle.Fill,
                                                         GUIUtils.CreateFlatButton("Save", b =>
            {
                var settings = (FalseAdaptSettings)config.GetConfiguredObject();
                settings.PresentationFile          = stimulipanel.PresentationFile;
                settings.StudyFile                 = stimulipanel.StudyFile;
                settings.CompFile                  = stimulipanel.CompFile;
                settings.Class1File                = stimulipanel.Class1File;
                settings.Class2File                = stimulipanel.Class2File;
                settings.ArtifactDetectionSettings = (ArtifactDetectionSettings)artifactConfig.GetConfiguredObject();
                saveDialog.FileName                = string.IsNullOrWhiteSpace(settings.ExperimentName) ? "my experiment" : settings.ExperimentName;
                if (saveDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                bool saved = settings.TrySerializeToFile(saveDialog.FileName);
                GUIUtils.Alert((saved ? "Saved" : "Failed to save")
                               + " experiment info to " + saveDialog.FileName,
                               (saved ? MessageBoxIcon.Information : MessageBoxIcon.Error));

                string directory = Path.GetDirectoryName(saveDialog.FileName);
                if (Directory.Exists(directory))
                {
                    saveDialog.InitialDirectory = directory;
                }
            }, null, "Save experiment configuration information"),
                                                         GUIUtils.CreateFlatButton("Load", b =>
            {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                FalseAdaptSettings settings;

                if (Utils.TryDeserializeFile(openDialog.FileName, out settings))
                {
                    config.SetConfiguredObject(settings);
                    stimulipanel.PresentationFile = settings.PresentationFile;
                    stimulipanel.StudyFile        = settings.StudyFile;
                    stimulipanel.CompFile         = settings.CompFile;
                    stimulipanel.Class1File       = settings.Class1File;
                    stimulipanel.Class2File       = settings.Class2File;
                    artifactConfig.SetConfiguredObject(settings.ArtifactDetectionSettings);
                }
                else
                {
                    GUIUtils.Alert("Failed to load experiment info from " + openDialog.FileName, MessageBoxIcon.Error);
                }
            }, null, "Load a previously saved experiment settings file"));

            //Put together the GUI
            var rows = GUIUtils.CreateTable(new[] { .5, .3, .2 }, Direction.Vertical);
            var col1 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);
            var col2 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);
            var col3 = GUIUtils.CreateTable(new[] { .5, .5 }, Direction.Horizontal);

            col2.Controls.Add(artifactConfig, 1, 0);
            col1.Controls.Add(startButton, 1, 0);
            col1.Controls.Add(statusChecker, 0, 0);
            col2.Controls.Add(config, 0, 0);
            col3.Controls.Add(stimulipanel, 1, 0);
            col3.Controls.Add(buttonTable, 0, 0);
            rows.Controls.Add(col3, 0, 1);
            rows.Controls.Add(col1, 0, 2);
            rows.Controls.Add(col2, 0, 0);


            this.Controls.Add(rows);


            this.ResumeLayout(false);
        }
Beispiel #16
0
        /// <summary>
        /// The enumerator implementation
        /// </summary>
        public override IEnumerator <View> GetEnumerator()
        {
            IViewResult result;
            Random      numgen = new Random();
            int         a, b;
            RandomizedQueue <string> pres     = new RandomizedQueue <string>();
            RandomizedQueue <string> usedPres = new RandomizedQueue <string>();

            pres.AddRange(presentation);
            using (var logWriter = new StreamWriter(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "krmon_log_" + settings.SubjectName + "_" + DateTime.Now.ToString("MM dd yyyy H mm ss") + ".txt")))
                using (var anslog = new StreamWriter(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "krmon_anslog_" + settings.SubjectName + "_" + DateTime.Now.ToString("MM dd yyyy H mm ss") + ".txt")))
                    using (var dataWriter = new StreamWriter(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "krmon_data_" + settings.SubjectName + "_" + DateTime.Now.ToString("MM dd yyyy H mm ss") + ".csv")))
                    {
                        //Alternating Study and Test Phases
                        for (int i = 0; i < settings.NumRounds; i++)
                        {
                            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, this.settings.PresentationTime, GUIUtils.Constants.DISPLAY_FONT_LARGE));

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

                                usedPres.Add(stimulus);
                            }
                            pres.AddRange(usedPres);
                            usedPres.Clear();

                            a = numgen.Next(4, 13);
                            b = numgen.Next(4, 13);

                            yield return(new VocabView(string.Format("{0} x {1} = {2}", a, b, a * b), "Verify", settings.DisplayTime, settings.DelayTime, true, anslog, out result));

                            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, anslog, logWriter, dataWriter, i, pres))
                                    {
                                        if (connected)
                                        {
                                            yield return(view);
                                        }
                                        else
                                        {
                                            GUIUtils.Alert("Lost connection to headset!");
                                            break;
                                        }
                                    }

                                    this.dataSource.RemoveListener(connectionListener);
                                }
                        }
                    }
        }
Beispiel #17
0
        private void BuildView()
        {
            this.SuspendLayout();
            this.StimulusClass1 = this.StimulusClass2 = null;

            // tab control
            var tabs = new CustomTabControl()
            {
                Dock = DockStyle.Fill
            };

            tabs.DisplayStyleProvider = new TabStyleVisualStudioProvider(tabs)
            {
                ShowTabCloser = true
            };
            tabs.TabClosing += (sender, args) => ((CustomTab)args.TabPage).RaiseClosingSafe(args);

            // start tab
            var startTab = new CustomTab()
            {
                Text = "Classes"
            };

            // columns
            var cols = GUIUtils.CreateTable(new double[] { .33, .33, .33 }, Direction.Horizontal);

            // image config
            var imageConfig = ConfigurationPanel.Create <ImageDisplaySettings>();

            // image panel
            var imagePanel = new ImagePanel()
            {
                Dock = DockStyle.Fill, UseNativeSize = false
            };
            bool cycle = true;
            var  rand  = new Random();
            Func <StimulusClass, string> getImageForClass = stimulusClass =>
            {
                var tab = this.stimulusClassTabs.First(t => t.StimulusClass == stimulusClass);
                if (tab.StimulusClass.Stimuli.Count == 0)
                {
                    return(null);
                }
                if (!((ImageDisplaySettings)imageConfig.GetConfiguredObject()).CycleThroughImages)
                {
                    return((tab.SelectedStimulus ?? tab.StimulusClass.Stimuli.First()).PathOrText);
                }
                return(tab.StimulusClass.Stimuli.ElementAt(rand.Next(tab.StimulusClass.Stimuli.Count)).PathOrText);
            };
            Action setImage = () =>
            {
                imagePanel.ImagePath = this.StimulusClass1 == null
                    ? null
                    : getImageForClass(this.StimulusClass1);
                imagePanel.SecondaryImagePath = this.StimulusClass2 == null
                    ? null
                    : getImageForClass(this.StimulusClass2);
            };

            setImage();
            var timer = new Timer()
            {
                Interval = 2500, Enabled = true
            };

            timer.Tick += (sender, args) =>
            {
                // just return if we're not cycling to avoid flicker
                if (!cycle && !timer.Enabled)
                {
                    return;
                }

                // if the form is valid, set a new image
                var activeTextBox = this.FindForm().ActiveControl as TextBox;
                if (activeTextBox == null || activeTextBox.IsValid())
                {
                    setImage();
                }
            };
            Action <ImageDisplaySettings> configurePanel = settings =>
            {
                imagePanel.Configure(settings);
                if (settings.CycleThroughImages != cycle)
                {
                    cycle = settings.CycleThroughImages;
                    setImage();
                }
                this.ImageDisplaySettings = settings;
            };

            configurePanel((ImageDisplaySettings)imageConfig.GetConfiguredObject());
            imageConfig.PropertyChanged += args => configurePanel((ImageDisplaySettings)imageConfig.GetConfiguredObject());

            // class list
            var classList = new CheckedListBox()
            {
                Dock = DockStyle.Fill, AllowDrop = true, CheckOnClick = true
            };

            classList.AddContextMenu();
            ItemCheckEventHandler refreshSelectedClasses = (sender, args) =>
            {
                // get the list of checked indices, including the possibly not-yet-changed item
                List <int> checkedIndices = classList.CheckedIndices.Cast <int>().ToList();
                if (args != null)
                {
                    if (args.NewValue == CheckState.Checked)
                    {
                        checkedIndices.Add(args.Index);
                        checkedIndices.Sort();
                    }
                    else
                    {
                        checkedIndices.Remove(args.Index);
                    }
                }

                this.StimulusClass1 = this.StimulusClass2 = null;
                if (checkedIndices.Count > 0)
                {
                    this.StimulusClass1 = ((StimulusClassTab)classList.Items[checkedIndices[0]]).StimulusClass;
                    if (checkedIndices.Count > 1)
                    {
                        this.StimulusClass2 = ((StimulusClassTab)classList.Items[checkedIndices[1]]).StimulusClass;
                    }
                }
                setImage();
            };
            Action <string> addClass = path =>
            {
                StimulusClass stimulusClass;
                if (!StimulusClass.TryLoad(path, out stimulusClass))
                {
                    GUIUtils.Alert("Failed to load stimulus class from " + path, MessageBoxIcon.Error);
                }
                else if (this.stimulusClassTabs
                         .Count(tp => tp.StimulusClass.SourceFolder.Equals(path, StringComparison.OrdinalIgnoreCase) ||
                                tp.StimulusClass.SavePath.Equals(path, StringComparison.OrdinalIgnoreCase)) > 0)
                {
                    GUIUtils.Alert("A class from " + path + " is already loaded!", MessageBoxIcon.Exclamation);
                }
                else
                {
                    // get a unique marker unless this was the load of a saved class
                    if (!File.Exists(stimulusClass.SavePath))
                    {
                        stimulusClass.Settings.Marker = this.stimulusClassTabs.Count == 0
                            ? 1
                            : this.stimulusClassTabs.Max(s => s.StimulusClass.Settings.Marker) + 1;
                    }
                    var classTab = new StimulusClassTab(stimulusClass);
                    classTab.TextChanged += (sender, args) => classList.Invalidate();
                    classTab.Closing     += (sender, args) =>
                    {
                        this.stimulusClassTabs.Remove(classTab);
                        classList.Items.Remove(classTab);
                        refreshSelectedClasses(classList, null);
                    };

                    this.stimulusClassTabs.Add(classTab);
                    tabs.TabPages.Add(classTab);
                    classList.Items.Add(classTab, true);
                    refreshSelectedClasses(classList, null);
                }
            };

            classList.ItemCheck += refreshSelectedClasses;
            classList.DragEnter += (sender, args) =>
            {
                if (args.Data.GetDataPresent(DataFormats.FileDrop, false) &&
                    ((string[])args.Data.GetData(DataFormats.FileDrop)).Where(StimulusClass.IsValidLoadPath).Count() > 0)
                {
                    args.Effect = DragDropEffects.All;
                }
            };
            classList.DragDrop += (sender, args) =>
            {
                // check that the form is in a valid state
                var activeTextBox = this.FindForm().ActiveControl as TextBox;
                if (activeTextBox != null && !activeTextBox.IsValid())
                {
                    GUIUtils.Alert("All entered data must be valid in order for drag and drop to be enabled", MessageBoxIcon.Error);
                    return;
                }

                string[] data = (string[])args.Data.GetData(DataFormats.FileDrop);

                foreach (string path in data.Where(StimulusClass.IsValidLoadPath))
                {
                    addClass(path);
                }
            };

            // button table
            var buttonTable = GUIUtils.CreateButtonTable(Direction.Horizontal, DockStyle.Bottom,
                                                         GUIUtils.CreateFlatButton("New", b =>
            {
                if (this.folderDialog.ShowDialog() == DialogResult.OK)
                {
                    addClass(this.folderDialog.SelectedPath);
                }
            }, startTab.ToolTip, "Create a new stimulus class from a folder of images"),
                                                         GUIUtils.CreateFlatButton("Load", b =>
            {
                if (this.fileDialog.ShowDialog() == DialogResult.OK)
                {
                    addClass(this.fileDialog.FileName);
                }
            }, startTab.ToolTip, "Load a previously saved stimulus class settings file"));

            startTab.Closing += (sender, args) =>
            {
                args.Cancel = true;
                if (GUIUtils.IsUserSure("Reset stimulus classes?"))
                {
                    this.stimulusClassTabs.Clear();
                    this.Controls.Remove(tabs);
                    tabs.Dispose();
                    timer.Enabled = false;
                    timer.Dispose();
                    this.BuildView();
                    this.OnSizeChanged(EventArgs.Empty);
                }
            };

            // add all controls

            // left column
            var panel = new Panel()
            {
                Dock = DockStyle.Fill
            };

            panel.Controls.Add(classList);
            panel.Controls.Add(buttonTable);
            cols.Controls.Add(panel, 0, 0);

            // middle column
            cols.Controls.Add(imageConfig, 1, 0);

            // right column
            cols.Controls.Add(imagePanel, 2, 0);

            startTab.Controls.Add(cols);
            tabs.Controls.Add(startTab);
            this.Controls.Add(tabs);

            this.ResumeLayout(false);
        }
Beispiel #18
0
        /// <summary>
        /// Builds the application view
        /// </summary>
        public void BuildExperimenterView()
        {
            this.SuspendLayout();
            this.Text = GUIUtils.Strings.APP_NAME;
            this.Size = new System.Drawing.Size(1500, 750);

            // experiment settings
            var experimentPanel = new ExperimentPanel()
            {
                Dock = DockStyle.Fill
            };

            // classifier settings
            var classifierPanel = new ClassificationSchemePanel()
            {
                Dock = DockStyle.Fill
            };

            // stimulus class settings
            var stimulusClassPanel = new StimulusClassPanel()
            {
                Dock = DockStyle.Fill
            };

            // status checker
            var statusChecker = new EmotivStatusCheckerPanel()
            {
                Dock = DockStyle.Fill
            };

            // start button
            var startButton = GUIUtils.CreateFlatButton("Start Experiment", b =>
            {
                var experimentSettings = experimentPanel.ExperimentSettings;
                experimentSettings.ImageDisplaySettings      = stimulusClassPanel.ImageDisplaySettings;
                experimentSettings.ArtifactDetectionSettings = classifierPanel.ArtifactDetectionSettings;

                // check stimulus classes
                if (stimulusClassPanel.StimulusClass1 == null || stimulusClassPanel.StimulusClass2 == null)
                {
                    GUIUtils.Alert("Two stimulus classes must be selected", MessageBoxIcon.Error);
                    return;
                }

                if (stimulusClassPanel.StimulusClass1.UsedStimuli(experimentSettings.QuestionMode).IsEmpty() ||
                    stimulusClassPanel.StimulusClass2.UsedStimuli(experimentSettings.QuestionMode).IsEmpty())
                {
                    GUIUtils.Alert("Each stimulus class must have at least one valid stimulus for the selected question mode", MessageBoxIcon.Error);
                    return;
                }

                if (stimulusClassPanel.StimulusClass1.Settings.Marker == stimulusClassPanel.StimulusClass2.Settings.Marker)
                {
                    GUIUtils.Alert("The two selected stimulus classes must have different marker values", MessageBoxIcon.Error);
                    return;
                }

                // check classifiers
                var classifiers = classifierPanel.SelectedClassifiers;
                foreach (var classifier in classifiers)
                {
                    if (classifier.Settings.FeatureCount <= 0 &&
                        !GUIUtils.IsUserSure("Classifier " + classifier.Settings.Name + " has no features. Continue without this classifier?"))
                    {
                        return;
                    }
                }

                // check headset
                if (!statusChecker.HeadsetConnected &&
                    !GUIUtils.IsUserSure("The Emotiv headset is not connected: run experiment with mock headset (generates random data for testing purposes)?"))
                {
                    return;
                }

                this.Animate(new ExperimentProvider(experimentSettings,
                                                    stimulusClassPanel.StimulusClass1,
                                                    stimulusClassPanel.StimulusClass2,
                                                    classifiers.Where(c => c.Settings.FeatureCount > 0).ToIArray(),
                                                    statusChecker.HeadsetConnected
                        ? EmotivDataSource.Instance
                        : this.mockDataSource ?? (this.mockDataSource = new MockEEGDataSource())));
            });

            // add all controls
            var rows = GUIUtils.CreateTable(new double[] { .5, .5 }, Direction.Vertical);

            // top row
            var topCols = GUIUtils.CreateTable(new double[] { .25, .75 }, Direction.Horizontal);

            topCols.Controls.Add(experimentPanel, 0, 0);
            topCols.Controls.Add(classifierPanel, 1, 0);
            rows.Controls.Add(topCols, 0, 0);

            // bottom row
            var bottomCols = GUIUtils.CreateTable(new double[] { .75, .25 }, Direction.Horizontal);

            bottomCols.Controls.Add(stimulusClassPanel, 0, 0);
            var bottomRightTable = GUIUtils.CreateTable(new double[] { .6, .4 }, Direction.Vertical);

            bottomRightTable.Controls.Add(statusChecker, 0, 0);
            bottomRightTable.Controls.Add(startButton, 0, 1);
            bottomCols.Controls.Add(bottomRightTable, 1, 0);
            rows.Controls.Add(bottomCols, 0, 1);

            this.Controls.Add(rows);
            this.ResumeLayout(false);
        }
Beispiel #19
0
        private void BuildView()
        {
            // config panel
            var config = ConfigurationPanel.Create <ExperimentSettings>();

            // output folder
            var outputLabel = "Data Output Folder".ToLabel(DockStyle.Bottom);
            var outputLink  = new LinkLabel()
            {
                Text = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), Dock = DockStyle.Bottom
            };

            outputLink.Click += (sender, args) =>
            {
                if (this.folderDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                outputLink.Text = this.folderDialog.SelectedPath;
            };
            this.getExperimentSettings = () =>
            {
                var settings = (ExperimentSettings)config.GetConfiguredObject();
                settings.OutputFolder = outputLink.Text;

                return(settings);
            };

            // button table
            var buttonTable = GUIUtils.CreateButtonTable(Direction.Horizontal, DockStyle.Bottom,
                                                         GUIUtils.CreateFlatButton("Save", b =>
            {
                var settings             = this.ExperimentSettings;
                this.saveDialog.FileName = string.IsNullOrWhiteSpace(settings.ExperimentName) ? "my experiment" : settings.ExperimentName;
                if (this.saveDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                bool saved = settings.TrySerializeToFile(this.saveDialog.FileName);
                GUIUtils.Alert((saved ? "Saved" : "Failed to save")
                               + " experiment info to " + this.saveDialog.FileName,
                               (saved ? MessageBoxIcon.Information : MessageBoxIcon.Error));

                string directory = Path.GetDirectoryName(this.saveDialog.FileName);
                if (Directory.Exists(directory))
                {
                    this.saveDialog.InitialDirectory = directory;
                }
            }, this.toolTip, "Save experiment configuration information"),
                                                         GUIUtils.CreateFlatButton("Load", b =>
            {
                if (this.openDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                ExperimentSettings settings;
                foreach (var path in this.openDialog.FileNames)
                {
                    if (Utils.TryDeserializeFile(this.openDialog.FileName, out settings))
                    {
                        config.SetConfiguredObject(settings);
                    }
                    else
                    {
                        GUIUtils.Alert("Failed to load experiment info from " + path, MessageBoxIcon.Error);
                    }
                }
            }, this.toolTip, "Load a previously saved experiment settings file"));

            // add all controls
            this.Controls.Add(config);
            this.Controls.Add(outputLabel);
            this.Controls.Add(outputLink);
            this.Controls.Add(buttonTable);
        }