コード例 #1
0
        private Graph gphErr;  // error rates

        /// <summary>
        ///
        /// </summary>
        /// <param name="sd"></param>
        public ResultsForm(SessionData sd, string filename)
        {
            InitializeComponent();
            this.Text = filename;

            // create a graph for speed
            gphWpm               = new Graph();
            gphWpm.Title         = "Speed";
            gphWpm.XAxisName     = "Trial No.";
            gphWpm.YAxisName     = "WPM";
            gphWpm.XAxisTicks    = (sd.NumTrials > 1) ? sd.NumTrials - 1 : 1;
            gphWpm.XAxisDecimals = 1;
            gphWpm.YAxisDecimals = 1;
            gphWpm.Legend        = true;

            // create a graph for error rates
            gphErr               = new Graph();
            gphErr.Title         = "Error Rates";
            gphErr.XAxisName     = "Trial No.";
            gphErr.YAxisName     = "Error Rate";
            gphErr.XAxisTicks    = (sd.NumTrials > 1) ? sd.NumTrials - 1 : 1;
            gphErr.XAxisDecimals = 1;
            gphErr.YAxisDecimals = 3;
            gphErr.Legend        = true;

            // create each series we wish to graph
            Graph.Series sWpm = new Graph.Series("WPM", Color.Red, Color.Red, true, true);
            Graph.Series sAdj = new Graph.Series("AdjWPM", Color.Gray, Color.Gray, true, true);
            Graph.Series sTot = new Graph.Series("Total", Color.Red, Color.Red, true, true);
            Graph.Series sUnc = new Graph.Series("Uncorrected", Color.Gray, Color.Gray, true, true);
            Graph.Series sCor = new Graph.Series("Corrected", Color.LightGray, Color.LightGray, true, true);

            // use these lists to compute the means and stdevs for each series
            List <double> mWpm  = new List <double>();
            List <double> sdWpm = new List <double>();
            List <double> mAdj  = new List <double>();
            List <double> sdAdj = new List <double>();
            List <double> mTot  = new List <double>();
            List <double> sdTot = new List <double>();
            List <double> mUnc  = new List <double>();
            List <double> sdUnc = new List <double>();
            List <double> mCor  = new List <double>();
            List <double> sdCor = new List <double>();

            // add the points for each series
            for (int i = 0; i < sd.NumTrials; i++)
            {
                if (sd[i].NumEntries > 0)
                {
                    sWpm.AddPoint(new PointR(i + 1, sd[i].WPM));
                    mWpm.Add(sd[i].WPM);
                    sdWpm.Add(sd[i].WPM);

                    sAdj.AddPoint(new PointR(i + 1, sd[i].AdjWPM));
                    mAdj.Add(sd[i].AdjWPM);
                    sdAdj.Add(sd[i].AdjWPM);

                    sTot.AddPoint(new PointR(i + 1, sd[i].TotalErrorRate));
                    mTot.Add(sd[i].TotalErrorRate);
                    sdTot.Add(sd[i].TotalErrorRate);

                    sUnc.AddPoint(new PointR(i + 1, sd[i].UncorrectedErrorRate));
                    mUnc.Add(sd[i].UncorrectedErrorRate);
                    sdUnc.Add(sd[i].UncorrectedErrorRate);

                    sCor.AddPoint(new PointR(i + 1, sd[i].CorrectedErrorRate));
                    mCor.Add(sd[i].CorrectedErrorRate);
                    sdCor.Add(sd[i].CorrectedErrorRate);
                }
            }

            // add the means and standard deviations to the series' names
            sWpm.Name = String.Format("{0} (µ={1:f1}, σ={2:f1})", sWpm.Name, StatsEx.Mean(mWpm.ToArray()), StatsEx.StdDev(sdWpm.ToArray()));
            sAdj.Name = String.Format("{0} (µ={1:f1}, σ={2:f1})", sAdj.Name, StatsEx.Mean(mAdj.ToArray()), StatsEx.StdDev(sdAdj.ToArray()));
            sTot.Name = String.Format("{0} (µ={1:f3}, σ={2:f3})", sTot.Name, StatsEx.Mean(mTot.ToArray()), StatsEx.StdDev(sdTot.ToArray()));
            sUnc.Name = String.Format("{0} (µ={1:f3}, σ={2:f3})", sUnc.Name, StatsEx.Mean(mUnc.ToArray()), StatsEx.StdDev(sdUnc.ToArray()));
            sCor.Name = String.Format("{0} (µ={1:f3}, σ={2:f3})", sCor.Name, StatsEx.Mean(mCor.ToArray()), StatsEx.StdDev(sdCor.ToArray()));

            // add the origin point to the graphs
            Graph.Series origin = new Graph.Series(String.Empty, Color.Black, Color.Black, false, false);
            origin.AddPoint(1.0, 0.0);
            gphWpm.AddSeries(origin);
            gphErr.AddSeries(origin);

            // finally, add the series
            gphWpm.AddSeries(sWpm);
            gphWpm.AddSeries(sAdj);
            gphErr.AddSeries(sTot);
            gphErr.AddSeries(sUnc);
            gphErr.AddSeries(sCor);
        }
コード例 #2
0
        /// <summary>
        /// Shows all the information for a trial-level node highlighted in the treeview.
        /// </summary>
        /// <param name="node">The highlighted node in the left treeview, assumed to represent an individual trial.</param>
        private void ShowTrialInfo(TreeNode node)
        {
            //
            // Get the trial and its condition from the 'Tag' field from the selected node.
            //
            _tdata = (TrialData)node.Tag;
            _cdata = (ConditionData)node.Parent.Tag;

            //
            // Get the resampled and smoothed velocity, acceleration, and jerk profiles.
            //
            MovementData.Profiles resampled = _tdata.Movement.CreateResampledProfiles();
            MovementData.Profiles smoothed  = _tdata.Movement.CreateSmoothedProfiles();

            //
            // Clear any series in the graphs.
            //
            grfDistance.ClearSeries();
            grfVelocity.ClearSeries();
            grfAcceleration.ClearSeries();
            grfJerk.ClearSeries();

            //
            // Graph the resampled distance to the target over time.
            //
            List <PointF> rdist = new List <PointF>(resampled.Position.Count);

            for (int i = 0; i < resampled.Position.Count; i++)
            {
                long   t  = resampled.Position[i].Time - resampled.Position[0].Time;
                double dx = GeotrigEx.Distance(resampled.Position[i], _tdata.TargetCenterFromStart);
                rdist.Add(new PointF(t, (float)dx));
            }
            Graph.Series rd = new Graph.Series("resampled distance", Color.Salmon, Color.Salmon, false, true);
            rd.AddPoints(rdist);

            //
            // Graph the smoothed distance from the target over time.
            //
            List <PointF> sdist = new List <PointF>(smoothed.Position.Count);

            for (int i = 0; i < smoothed.Position.Count; i++)
            {
                long   t  = smoothed.Position[i].Time - smoothed.Position[0].Time;
                double dx = GeotrigEx.Distance(smoothed.Position[i], _tdata.TargetCenterFromStart);
                sdist.Add(new PointF(t, (float)dx));
            }
            Graph.Series sd = new Graph.Series("smoothed distance", Color.MediumBlue, Color.MediumBlue, false, true);
            sd.AddPoints(sdist);

            grfDistance.AddSeries(rd);
            grfDistance.AddSeries(sd);

            //
            // Graph the velocity.
            //
            Graph.Series rv = new Graph.Series("resampled velocity", Color.Salmon, Color.Salmon, false, true);
            rv.AddPoints(resampled.Velocity);

            Graph.Series sv = new Graph.Series("smoothed velocity", Color.MediumBlue, Color.MediumBlue, false, true);
            sv.AddPoints(smoothed.Velocity);

            grfVelocity.AddSeries(rv);
            grfVelocity.AddSeries(sv);

            //
            // Graph the acceleration.
            //
            Graph.Series aaxis = new Graph.Series("zero line", Color.Gray, Color.Gray, false, true);
            aaxis.AddPoint(0f, 0f);
            aaxis.AddPoint(resampled.Acceleration[resampled.Acceleration.Count - 1].X, 0f);

            Graph.Series ra = new Graph.Series("resampled acceleration", Color.Salmon, Color.Salmon, false, true);
            ra.AddPoints(resampled.Acceleration);

            Graph.Series sa = new Graph.Series("smoothed acceleration", Color.MediumBlue, Color.MediumBlue, false, true);
            sa.AddPoints(smoothed.Acceleration);

            grfAcceleration.AddSeries(aaxis);
            grfAcceleration.AddSeries(ra);
            grfAcceleration.AddSeries(sa);

            //
            // Graph the jerk.
            //
            Graph.Series jaxis = new Graph.Series("zero line", Color.Gray, Color.Gray, false, true);
            jaxis.AddPoint(0f, 0f);
            jaxis.AddPoint(resampled.Jerk[resampled.Jerk.Count - 1].X, 0f);

            Graph.Series rj = new Graph.Series("resampled jerk", Color.Salmon, Color.Salmon, false, true);
            rj.AddPoints(resampled.Jerk);

            Graph.Series sj = new Graph.Series("smoothed jerk", Color.MediumBlue, Color.MediumBlue, false, true);
            sj.AddPoints(smoothed.Jerk);

            grfJerk.AddSeries(jaxis);
            grfJerk.AddSeries(rj);
            grfJerk.AddSeries(sj);

            //
            // Now show the trial-level XML in the web control.
            //
            XmlTextWriter writer = null;
            string        tmpXml = String.Format("{0}{1}.xml", Path.GetTempPath(), Path.GetRandomFileName());

            try
            {
                writer            = new XmlTextWriter(tmpXml, Encoding.UTF8);
                writer.Formatting = Formatting.Indented;
                _tdata.WriteXmlHeader(writer);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                tmpXml = String.Empty;
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }
                if (tmpXml != String.Empty)
                {
                    webXml.Navigate(tmpXml);
                    rtxXml.LoadFile(tmpXml, RichTextBoxStreamType.PlainText);
                    _tmpXml.Add(tmpXml);
                }
            }

            //
            // Invalidate everything that needs to be repainted based on the node just selected.
            //
            pnlTrial.Invalidate();
            grfDistance.Invalidate();
            grfVelocity.Invalidate();
            grfAcceleration.Invalidate();
            grfJerk.Invalidate();
        }
コード例 #3
0
        /// <summary>
        /// Handles the Load event for the form. Loads the data from the model into the graph control, and
        /// displays the model terms in the read-only textbox.
        /// </summary>
        /// <param name="sender">The sender of this event.</param>
        /// <param name="e">The arguments for this event.</param>
        private void ModelForm_Load(object sender, EventArgs e)
        {
            //
            // Ask the session instance to build a Fitts' law model.
            //
            Model fm = _sdata.BuildModel();

            fm.RoundTerms(4);         // round for display

            if (_sdata.MTPct == null) // regular Fitts experiment
            {
                PointF min = PointF.Empty;
                PointF max = PointF.Empty;

                //
                // Add the (IDe, MTe) points for plotting.
                //
                Graph.Series s1 = new Graph.Series("Fitts model 1D points", Color.Tomato, Color.Tomato, true, false);
                s1.AddPoints(fm.FittsPts_1d); // add the points to the series
                grfFitts1D.AddSeries(s1);     // add the series to the graph
                if (s1.NumPoints > 1)
                {
                    RectangleF   r  = s1.DomainRange;                                       // get the domain and range of the first series
                    Graph.Series s3 = new Graph.Series("Fitts model 1D line", Color.OrangeRed, Color.OrangeRed, false, true);
                    s3.AddPoint(0f, (float)fm.Fitts_a_1d);                                  // y-intercept
                    s3.AddPoint(r.Right, (float)(fm.Fitts_b_1d * r.Right + fm.Fitts_a_1d)); // rightmost point
                    grfFitts1D.AddSeries(s3);
                    min = s3[0];
                    max = s3[1];
                }

                if (_sdata.Is2D)
                {
                    Graph.Series s2 = new Graph.Series("Fitts model 2D points", Color.Tomato, Color.Tomato, true, false);
                    s2.AddPoints(fm.FittsPts_2d);
                    grfFitts2D.AddSeries(s2);
                    if (s2.NumPoints > 1)
                    {
                        RectangleF   r  = s2.DomainRange;                                       // get the domain and range of the first series
                        Graph.Series s4 = new Graph.Series("Fitts model 2D line", Color.OrangeRed, Color.OrangeRed, false, true);
                        s4.AddPoint(0f, (float)fm.Fitts_a_2d);                                  // y-intercept
                        s4.AddPoint(r.Right, (float)(fm.Fitts_b_2d * r.Right + fm.Fitts_a_2d)); // rightmost point
                        grfFitts2D.AddSeries(s4);
                        min.X = Math.Min(min.X, s4[0].X);
                        min.Y = Math.Min(min.Y, s4[0].Y);
                        max.X = Math.Max(max.X, s4[1].X);
                        max.Y = Math.Max(max.Y, s4[1].Y);
                    }
                }

                // add a series to ensure both graphs display at the same scale for better comparisons
                Graph.Series s5 = new Graph.Series("Fitts min-max", Color.Black, Color.Black, false, false);
                s5.AddPoint(min);
                s5.AddPoint(max);
                grfFitts1D.AddSeries(s5);
                grfFitts2D.AddSeries(s5);

                //
                // Fill the text box with the Fitts' law model parameters.
                //
                txtFitts1D.Text =
                    String.Format("Fitts' Law - Univariate for Subject {0}\r\n", _sdata.Subject) +
                    String.Format("N = {0}\r\n", fm.N) +
                    String.Format("MTavg = {0} ms\r\n", fm.MTe) +
                    String.Format("Error% = {0}\r\n", fm.ErrorPct) +

                    String.Format("MT(1d) = {0} + {1} * ID\r\n", fm.Fitts_a_1d, fm.Fitts_b_1d) +
                    String.Format("TP_avg(1d) = {0} bits/s\r\n", fm.Fitts_TP_avg_1d) +
                    String.Format("TP_inv(1d) = {0} bits/s\r\n", fm.Fitts_TP_inv_1d) +

                    String.Format("a(1d) = {0} ms\r\n", fm.Fitts_a_1d) +
                    String.Format("b(1d) = {0} ms/bit\r\n", fm.Fitts_b_1d) +
                    String.Format("r(1d) = {0}\r\n", fm.Fitts_r_1d);

                if (_sdata.Is2D)
                {
                    txtFitts2D.Text =
                        String.Format("Fitts' Law - Bivariate for Subject {0}\r\n", _sdata.Subject) +
                        String.Format("N = {0}\r\n", fm.N) +
                        String.Format("MTavg = {0} ms\r\n", fm.MTe) +
                        String.Format("Error% = {0}\r\n", fm.ErrorPct) +

                        String.Format("MT(2d) = {0} + {1} * ID\r\n", fm.Fitts_a_2d, fm.Fitts_b_2d) +
                        String.Format("TP_avg(2d) = {0} bits/s\r\n", fm.Fitts_TP_avg_2d) +
                        String.Format("TP_inv(2d) = {0} bits/s\r\n", fm.Fitts_TP_inv_2d) +

                        String.Format("a(2d) = {0} ms\r\n", fm.Fitts_a_2d) +
                        String.Format("b(2d) = {0} ms/bit\r\n", fm.Fitts_b_2d) +
                        String.Format("r(2d) = {0}\r\n", fm.Fitts_r_2d);
                }
                else
                {
                    tabModel.TabPages.RemoveAt(1);                       // remove the Fitts' law 2D tab
                }
                tabModel.TabPages.RemoveAt(tabModel.TabPages.Count - 1); // remove the Error model 2D tab
                tabModel.TabPages.RemoveAt(tabModel.TabPages.Count - 1); // remove the Error model 1D tab
            }
            else // metronome experiment
            {
                //
                // Add the diagonal line for easy visual model comparisons.
                //
                Graph.Series s0 = new Graph.Series("Diagonal", Color.LightGray, Color.LightGray, false, true);
                s0.AddPoint(0f, 0f);
                s0.AddPoint(1f, 1f);
                grfErrors1D.AddSeries(s0);
                grfErrors2D.AddSeries(s0);

                //
                // Add the (predicted error rate, observed error rate) points for plotting.
                //
                Graph.Series s1 = new Graph.Series("Error model 1D points", Color.Tomato, Color.Tomato, true, false);
                s1.AddPoints(fm.ErrorPts_1d);
                grfErrors1D.AddSeries(s1);
                if (s1.NumPoints > 1)
                {
                    RectangleF   r  = s1.DomainRange;
                    Graph.Series s3 = new Graph.Series("Error model 1D line", Color.OrangeRed, Color.OrangeRed, false, true);
                    s3.AddPoint(0f, (float)fm.Error_b_1d);  // y-intercept
                    s3.AddPoint(r.Right, (float)(fm.Error_m_1d * r.Right + fm.Error_b_1d));
                    grfErrors1D.AddSeries(s3);
                }

                if (_sdata.Is2D)
                {
                    Graph.Series s2 = new Graph.Series("Error model 2D points", Color.Tomato, Color.Tomato, true, false);
                    s2.AddPoints(fm.ErrorPts_2d);
                    grfErrors2D.AddSeries(s2);
                    if (s2.NumPoints > 1)
                    {
                        RectangleF   r  = s2.DomainRange;
                        Graph.Series s4 = new Graph.Series("Error model 2D line", Color.OrangeRed, Color.OrangeRed, false, true);
                        s4.AddPoint(0f, (float)fm.Error_b_2d);  // y-intercept
                        s4.AddPoint(r.Right, (float)(fm.Error_m_2d * r.Right + fm.Error_b_2d));
                        grfErrors2D.AddSeries(s4);
                    }
                }

                //
                // Fill the text box with the Error model parameters.
                //
                txtErrors1D.Text =
                    String.Format("Pointing Error Model - Univariate for Subject {0}\r\n", _sdata.Subject) +
                    String.Format("N = {0}\r\n", fm.N) +
                    String.Format("MTavg = {0} ms\r\n", fm.MTe) +
                    String.Format("Error% = {0}\r\n", fm.ErrorPct) +

                    String.Format("Predicted(1d) = 1 - erf[(2.066 * W/A * (2^((MT-{0})/{1}) - 1)) / sqrt(2)]\r\n", fm.Fitts_a_1d, fm.Fitts_b_1d) +
                    String.Format("Observed(1d) = {0} * Predicted + {1}\r\n", fm.Error_m_1d, fm.Error_b_1d) +
                    String.Format("m(1d) = {0}\r\n", fm.Error_m_1d) +
                    String.Format("b(1d) = {0}\r\n", fm.Error_b_1d) +
                    String.Format("r(1d) = {0}\r\n", fm.Error_r_1d);

                if (_sdata.Is2D)
                {
                    txtErrors2D.Text =
                        String.Format("Pointing Error Model - Bivariate for Subject {0}\r\n", _sdata.Subject) +
                        String.Format("N = {0}\r\n", fm.N) +
                        String.Format("MTavg = {0} ms\r\n", fm.MTe) +
                        String.Format("Error% = {0}\r\n", fm.ErrorPct) +

                        String.Format("Predicted(2d) = 1 - erf[(2.066 * W/A * (2^((MT-{0})/{1}) - 1)) / sqrt(2)]\r\n", fm.Fitts_a_2d, fm.Fitts_b_2d) +
                        String.Format("Observed(2d) = {0} * Predicted + {1}\r\n", fm.Error_m_2d, fm.Error_b_2d) +
                        String.Format("m(2d) = {0}\r\n", fm.Error_m_2d) +
                        String.Format("b(2d) = {0}\r\n", fm.Error_b_2d) +
                        String.Format("r(2d) = {0}\r\n", fm.Error_r_2d);
                }
                else
                {
                    tabModel.TabPages.RemoveAt(3); // remove the Error model 2D tab
                }
                tabModel.TabPages.RemoveAt(0);     // remove the Fitts' law 1D tab
                tabModel.TabPages.RemoveAt(0);     // remove the Fitts' law 2D tab
            }
        }