Example #1
0
 private void OnPointsAdded(SeriesEx series)
 {
     if (PointsAdded != null)
     {
         PointsAdded(series);
     }
 }
Example #2
0
        /// <summary>
        /// Retrieves absolute range from all points.
        /// </summary>
        private int[] GetVisiblePointsRange(SeriesEx series)
        {
            // two shortcuts
            ChartArea area = WrappedChart.ChartAreas[0];

            // these are the X-Values of the zoomed portion:
            double minX = area.AxisX.ScaleView.ViewMinimum;
            double maxX = area.AxisX.ScaleView.ViewMaximum;

            double minPointsX = series.Points.Items.Min((point) => point.X);
            double maxPointX  = series.Points.Items.Max((point) => point.X);

            double size = maxPointX - minPointsX;

            if (size <= minX || size <= maxX)
            {
                return new int[] { -1, -1 }
            }
            ;
            else
            {
                return new int[] { (int)Math.Ceiling((minX / size) * series.Points.Items.Count), (int)Math.Ceiling((maxX / size) * series.Points.Items.Count) }
            };
        }
    }
        /// <summary>
        /// Writes all or part of this data object to XML. If this data object owns other
        /// data objects that will also be written, this method may leave some XML elements
        /// open, which will be closed with a later call to <i>WriteXmlFooter</i>.
        /// </summary>
        /// <param name="writer">An open XML writer. The writer will be left open by this method
        /// after writing.</param>
        /// <returns>Returns <b>true</b> if successful; <b>false</b> otherwise.</returns>
        public bool WriteXmlHeader(XmlTextWriter writer)
        {
            writer.WriteStartElement("Movement");
            writer.WriteAttributeString("count", XmlConvert.ToString(_moves.Count));
            writer.WriteAttributeString("travel", XmlConvert.ToString(Math.Round(this.Travel, 4)));
            writer.WriteAttributeString("duration", XmlConvert.ToString(this.Duration));

            // write out the submovement information
            Profiles resampled = CreateResampledProfiles();

            if (resampled.IsEmpty) // this can happen if the trial is terminated prematurely
            {
                writer.WriteAttributeString("submovements", XmlConvert.ToString(0));
                writer.WriteAttributeString("maxVelocity", PointF.Empty.ToString());
                writer.WriteAttributeString("maxAcceleration", PointF.Empty.ToString());
                writer.WriteAttributeString("maxJerk", PointF.Empty.ToString());
            }
            else
            {
                int nsub = GetNumSubmovements(); // from smoothed velocity profile
                int vidx = SeriesEx.Max(resampled.Velocity, 0, -1);
                int aidx = SeriesEx.Max(resampled.Acceleration, 0, -1);
                int jidx = SeriesEx.Max(resampled.Jerk, 0, -1);

                writer.WriteAttributeString("submovements", XmlConvert.ToString(nsub));
                writer.WriteAttributeString("maxVelocity", resampled.Velocity[vidx].ToString());
                writer.WriteAttributeString("maxAcceleration", resampled.Acceleration[aidx].ToString());
                writer.WriteAttributeString("maxJerk", resampled.Jerk[jidx].ToString());
            }

            // write out all of MacKenzie's path analysis measures
            PathAnalyses analyses = DoPathAnalyses(_owner.Start, _owner.TargetCenterFromStart);

            writer.WriteAttributeString("taskAxisCrossings", XmlConvert.ToString(analyses.TaskAxisCrossings));
            writer.WriteAttributeString("movementDirectionChanges", XmlConvert.ToString(analyses.MovementDirectionChanges));
            writer.WriteAttributeString("orthogonalDirectionChanges", XmlConvert.ToString(analyses.OrthogonalDirectionChanges));
            writer.WriteAttributeString("movementVariability", XmlConvert.ToString(Math.Round(analyses.MovementVariability, 4)));
            writer.WriteAttributeString("movementError", XmlConvert.ToString(Math.Round(analyses.MovementError, 4)));
            writer.WriteAttributeString("movementOffset", XmlConvert.ToString(Math.Round(analyses.MovementOffset, 4)));

            // write out all the mouse move points that make up this trial
            int i = 0;

            foreach (TimePointF pt in _moves)
            {
                writer.WriteStartElement("move");
                writer.WriteAttributeString("index", XmlConvert.ToString(i++));
                writer.WriteAttributeString("point", pt.ToString());
                writer.WriteEndElement(); // </move>
            }

            writer.WriteEndElement(); // </Movement>

            return(true);
        }
Example #4
0
        public SeriesEx Add(String name)
        {
            SeriesEx s = collection.FirstOrDefault(x => name.Equals(x.WrappedSeries.Name));

            if (s == null)
            {
                s              = new SeriesEx(WrappedCollection.Add(name));
                s.PointsAdded += PointsAddedHandler;
                collection.Add(s);
            }
            return(s);
        }
Example #5
0
        public void Add(SeriesEx series)
        {
            SeriesEx s = collection.FirstOrDefault(x => series.WrappedSeries.Name.Equals(x.WrappedSeries.Name));

            if (s == null)
            {
                collection.Add(series);
                WrappedCollection.Add(series.WrappedSeries);
                series.PointsAdded += PointsAddedHandler;
                OnPointsAdded(series); // force update
            }
        }
Example #6
0
        public List<double> Vector;        // vector representation -- for Protractor

        /// <summary>
        /// Constructor of a unistroke gesture. A unistroke is comprised of a set of points drawn
        /// out over time in a sequence.
        /// </summary>
        /// <param name="name">The name of the unistroke gesture.</param>
        /// <param name="timepoints">The array of points supplied for this unistroke.</param>
        public Unistroke(string name, List<TimePointF> timepoints)
        {
            this.Name = name;
            this.RawPoints = new List<TimePointF>(timepoints); // copy (saved for drawing)
            double I = GeotrigEx.PathLength(timepoints) / (Recognizer.NumPoints - 1); // interval distance between points
            this.Points = TimePointF.ConvertList(SeriesEx.ResampleInSpace(timepoints, I));
            double radians = GeotrigEx.Angle(GeotrigEx.Centroid(this.Points), this.Points[0], false);
            this.Points = GeotrigEx.RotatePoints(this.Points, -radians);
            this.Points = GeotrigEx.ScaleTo(this.Points, Recognizer.SquareSize);
            this.Points = GeotrigEx.TranslateTo(this.Points, Recognizer.Origin, true);
            this.Vector = Vectorize(this.Points); // vectorize resampled points (for Protractor)
        }
        /// <summary>
        /// Calculates the number of submovements in this movement. The number of submovements is defined
        /// by the number of velocity peaks in the smoothed velocity profile. The profile is obtained after
        /// resampling at 100 Hz and smoothing using a Gaussian convolution filter with a standard deviation
        /// of 3.
        /// </summary>
        /// <returns>The number of submovements defined by peaks in the smoothed velocity profile.</returns>
        public int GetNumSubmovements()
        {
            Profiles smoothed = CreateSmoothedProfiles();

            if (smoothed.IsEmpty)
            {
                return(-1);
            }

            int[] maxima = SeriesEx.Maxima(smoothed.Velocity, 0, -1);
            return(maxima.Length);
        }
        /// <summary>
        /// Temporally resamples the movement at 100 Hz, and then produces the position, velocity, acceleration,
        /// and jerk profiles that accompany it. Note that the position profile are TimePoints, and the derivative
        /// profiles are PointF time series.
        /// </summary>
        /// <returns>The velocity, acceleration, and jerk submovement profiles from the resampled movement.</returns>
        public Profiles CreateResampledProfiles()
        {
            if (_moves.Count == 0)
            {
                return(Profiles.Empty);
            }

            // Resampled position, velocity, acceleration, jerk
            Profiles resampled;

            resampled.Position     = SeriesEx.ResampleInTime(_moves, Hertz);
            resampled.Velocity     = SeriesEx.Derivative(resampled.Position);
            resampled.Acceleration = SeriesEx.Derivative(resampled.Velocity);
            resampled.Jerk         = SeriesEx.Derivative(resampled.Acceleration);

            return(resampled);
        }
Example #9
0
 private void Generate()
 {
     PointF[][] pts = new PointF[12][];
     chartEx.Series.Clear();
     for (int i = 0; i < seriesAmount; i++)
     {
         SeriesEx s = new SeriesEx(i.ToString());
         s.WrappedSeries.ChartType = SeriesChartType.Line;
         chartEx.Series.Add(s);
         s.WrappedSeries.Enabled = enabledSeries[i];
         if (enabledSeries[i])
         {
             pts[i] = GetFunc(i).CreatePoints(pointsAmount, pointsRange, 0, (i + 1) * 10, time);
             s.Points.AddRange(pts[i]);
         }
     }
 }
Example #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="timepoints"></param>
        /// <param name="protractor">false</param>
        /// <returns></returns>
        public NBestList Recognize(List <TimePointF> timepoints, bool protractor)       // candidate points
        {
            double        I       = GeotrigEx.PathLength(timepoints) / (NumPoints - 1); // interval distance between points
            List <PointF> points  = TimePointF.ConvertList(SeriesEx.ResampleInSpace(timepoints, I));
            double        radians = GeotrigEx.Angle(GeotrigEx.Centroid(points), points[0], false);

            points = GeotrigEx.RotatePoints(points, -radians);
            points = GeotrigEx.ScaleTo(points, SquareSize);
            points = GeotrigEx.TranslateTo(points, Origin, true);
            List <double> vector = Unistroke.Vectorize(points); // candidate's vector representation

            NBestList nbest = new NBestList();

            foreach (Unistroke u in _gestures.Values)
            {
                if (protractor) // Protractor extension by Yang Li (CHI 2010)
                {
                    double[] best  = OptimalCosineDistance(u.Vector, vector);
                    double   score = 1.0 / best[0];
                    nbest.AddResult(u.Name, score, best[0], best[1]); // name, score, distance, angle
                }
                else // original $1 angular invariance search -- Golden Section Search (GSS)
                {
                    double[] best = GoldenSectionSearch(
                        points,                                 // to rotate
                        u.Points,                               // to match
                        GeotrigEx.Degrees2Radians(-45.0),       // lbound
                        GeotrigEx.Degrees2Radians(+45.0),       // ubound
                        GeotrigEx.Degrees2Radians(2.0)          // threshold
                        );

                    double score = 1.0 - best[0] / HalfDiagonal;
                    nbest.AddResult(u.Name, score, best[0], best[1]); // name, score, distance, angle
                }
            }
            nbest.SortDescending(); // sort descending by score so that nbest[0] is best result
            return(nbest);
        }
Example #11
0
        // Main approximation methods

        private void ZoomApproximation(SeriesEx s)
        {
            if (!ApproximationEnabled)
            {
                return;
            }
            if (!s.WrappedSeries.Enabled)
            {
                return;
            }
            List <PointF> storedPoints = s.Points.Items;

            if (storedPoints.Count > MaxRenderedPoints)
            {
                int[] actualIndexes = GetVisiblePointsRange(s);
                if (actualIndexes[0] >= 0 && actualIndexes[1] >= 0)
                {
                    int           actualPointsCount = actualIndexes[1] - actualIndexes[0];
                    List <PointF> res = ApproximateSeries(s, storedPoints, actualIndexes);
                    s.WrappedSeries.Points.DataBindXY(res, "X", res, "Y");
                }
            }
        }
Example #12
0
        private List <PointF> ApproximateSeries(SeriesEx series, List <PointF> candidatePoints, int[] detailedRange = null)
        {
            List <PointF> resultPoints       = new List <PointF>();
            int           detailedRangeWidth = ((detailedRange != null && detailedRange.Length == 2) ? detailedRange[1] - detailedRange[0] : 0);

            if (ApproximationEnabled && candidatePoints.Count > MaxRenderedPoints)
            {
                if (detailedRangeWidth == 0)
                {
                    resultPoints = SelectionMethod.Select(candidatePoints, MaxRenderedPoints);
                    if (resultPoints.Count > MaxRenderedPoints) // ensure the Selector gives us allowed number of points.
                    {
                        resultPoints = resultPoints.Take(MaxRenderedPoints).ToList();
                    }
                    if (UseDashLines)
                    {
                        series.WrappedSeries.BorderDashStyle = ChartDashStyle.Dash;
                    }
                }
                else
                {
                    this.detailedRange = detailedRange;
                    resultPoints.Add(candidatePoints.First());
                    resultPoints.AddRange(ApproximateSeries(series, candidatePoints.GetRange(detailedRange[0], detailedRangeWidth)));
                    resultPoints.Add(candidatePoints.Last());
                }
            }
            else
            {
                resultPoints.AddRange(candidatePoints);
                if (UseDashLines)
                {
                    series.WrappedSeries.BorderDashStyle = ChartDashStyle.Solid;
                }
            }
            return(resultPoints);
        }
Example #13
0
 private List <PointF> ApproximateSeries(SeriesEx series, int[] detailedRanges = null)
 {
     return(ApproximateSeries(series, series.Points.Items, detailedRanges));
 }
Example #14
0
        /// <summary>
        /// Performs any analyses on this data object and writes the results to a space-delimitted
        /// file for subsequent copy-and-pasting into a spreadsheet like Microsoft Excel or SAS JMP.
        /// </summary>
        /// <param name="writer">An open stream writer pointed to a text file. The writer will be closed by
        /// this method after writing.</param>
        /// <returns>True if writing is successful; false otherwise.</returns>
        public bool WriteResultsToTxt(StreamWriter writer)
        {
            bool success = true;

            try
            {
                // write an identifying title for this file.
                writer.WriteLine("FittsStudy log analysis results for '{0}' on {1} at {2}. FittsStudy.exe version: {3}.\r\n",
                                 this.FilenameBase + ".xml", // Note: ((FileStream) writer.BaseStream).Name holds the file path.
                                 DateTime.Now.ToLongDateString(),
                                 DateTime.Now.ToLongTimeString(),
                                 Assembly.GetExecutingAssembly().GetName().Version);

                // write the column headers with comma separation -- see Columns.txt
                writer.WriteLine("Subject,Circular?,Block,Condition,Trial,Practice?,Metronome?,MT%,MTPred,MT,a(given),b(given),A,W,ID,axis,angle,ae(1d),dx(1d),ae(2d),dx(2d),Ae(1d),SD(1d),We(1d),IDe(1d),TP(1d),Ae(2d),SD(2d),We(2d),IDe(2d),TP(2d),MTe,MTRatio,MeanMTe,MeanMTe(sx),MeanMTe(tx),Entries,Overshoots,Error?,Errors,Errors(sx),Errors(tx),Error%,Error%(sx),Error%(tx),SpatialOutlier?,TemporalOutlier?,SpatialOutliers,TemporalOutliers,StartX,StartY,EndX,EndY,TargetX,TargetY,Travel,Duration,Submovements,MaxVelocity,MaxAcceleration,MaxJerk,tMaxVelocity,tMaxAcceleration,tMaxJerk,TAC,MDC,ODC,MV,ME,MO,N,Fitts_TP_avg(1d),Fitts_TP_inv(1d),Fitts_a(1d),Fitts_b(1d),Fitts_r(1d),Fitts_TP_avg(2d),Fitts_TP_inv(2d),Fitts_a(2d),Fitts_b(2d),Fitts_r(2d),Error_m(1d),Error_b(1d),Error_r(1d),Error_m(2d),Error_b(2d),Error_r(2d)");

                // pre-compute session-level values here
                Model fm = this.BuildModel();
                fm.RoundTerms(4);

                // now iterate through all of the conditions
                for (int i = 0; i < _conditions.Count; i++)
                {
                    // get the condition and pre-compute any condition-level values here. we could
                    // compute them again and again while writing each trial, but that is inefficient.
                    ConditionData cd = _conditions[i];

                    double cAe_1d  = Math.Round(cd.GetAe(false), 4);
                    double cSD_1d  = Math.Round(cd.GetSD(false), 4);
                    double cWe_1d  = Math.Round(cd.GetWe(false), 4);
                    double cIDe_1d = Math.Round(cd.GetIDe(false), 4);
                    double cTP_1d  = Math.Round(cd.GetTP(false), 4);

                    double cAe_2d  = Math.Round(cd.GetAe(true), 4);
                    double cSD_2d  = Math.Round(cd.GetSD(true), 4);
                    double cWe_2d  = Math.Round(cd.GetWe(true), 4);
                    double cIDe_2d = Math.Round(cd.GetIDe(true), 4);
                    double cTP_2d  = Math.Round(cd.GetTP(true), 4);

                    long meanMTe    = cd.GetMTe(ExcludeOutliersType.None);
                    long meanMTe_sx = cd.GetMTe(ExcludeOutliersType.Spatial);
                    long meanMTe_tx = cd.GetMTe(ExcludeOutliersType.Temporal);

                    int errors    = cd.GetNumErrors(ExcludeOutliersType.None);
                    int errors_sx = cd.GetNumErrors(ExcludeOutliersType.Spatial);
                    int errors_tx = cd.GetNumErrors(ExcludeOutliersType.Temporal);

                    double errorPct    = Math.Round(cd.GetErrorRate(ExcludeOutliersType.None), 4);
                    double errorPct_sx = Math.Round(cd.GetErrorRate(ExcludeOutliersType.Spatial), 4);
                    double errorPct_tx = Math.Round(cd.GetErrorRate(ExcludeOutliersType.Temporal), 4);

                    int nSpatialOutliers  = cd.NumSpatialOutliers;
                    int nTemporalOutliers = cd.NumTemporalOutliers;

                    // within each condition, iterate through the trials. start at index 1 because
                    // the trial at index 0 is the special start-area trial, and should be ignored.
                    for (int j = 1; j <= cd.NumTrials; j++)
                    {
                        TrialData    td = cd[j];
                        MovementData md = td.Movement; // the movement path itself

                        // calculate the resampled submovement profiles
                        MovementData.Profiles profiles = md.CreateResampledProfiles();
                        int vidx = SeriesEx.Max(profiles.Velocity, 0, -1);     // max velocity
                        int aidx = SeriesEx.Max(profiles.Acceleration, 0, -1); // max acceleration
                        int jidx = SeriesEx.Max(profiles.Jerk, 0, -1);         // max jerk

                        // calculate the MacKenzie et al. (2001) path analysis measures
                        MovementData.PathAnalyses analyses = md.DoPathAnalyses(td.Start, td.TargetCenterFromStart);

                        // write the spreadsheet row here
                        writer.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21},{22},{23},{24},{25},{26},{27},{28},{29},{30},{31},{32},{33},{34},{35},{36},{37},{38},{39},{40},{41},{42},{43},{44},{45},{46},{47},{48},{49},{50},{51},{52},{53},{54},{55},{56},{57},{58},{59},{60},{61},{62},{63},{64},{65},{66},{67},{68},{69},{70},{71},{72},{73},{74},{75},{76},{77},{78},{79},{80},{81},{82},{83},{84},{85},{86}",
                                         _subject,                                                   // Subject,
                                         _circular ? 1 : 0,                                          // Circular?
                                         cd.Block,                                                   // Block,
                                         cd.Index,                                                   // Condition,
                                         td.Number,                                                  // Trial, (== j)
                                         td.IsPractice ? 1 : 0,                                      // Practice?,

                                         cd.UsedMetronome ? 1 : 0,                                   // Metronome?, (== td.UsedMetronome)
                                         cd.MTPct,                                                   // MT%,
                                         cd.MTPred,                                                  // MTPred,
                                         cd.MT,                                                      // MT, (== td.MT)
                                         _intercept,                                                 // a(given),
                                         _slope,                                                     // b(given),

                                         cd.A,                                                       // A, (== td.A)
                                         cd.W,                                                       // W, (== td.W)
                                         Math.Round(cd.ID, 4),                                       // ID, (== td.ID)
                                         Math.Round(GeotrigEx.Radians2Degrees(td.Axis), 4),          // axis,

                                         Math.Round(GeotrigEx.Radians2Degrees(td.Angle), 4),         // angle,
                                         Math.Round(td.GetAe(false), 4),                             // ae(1d),
                                         Math.Round(td.GetDx(false), 4),                             // dx(1d),

                                         Math.Round(td.GetAe(true), 4),                              // ae(2d),
                                         Math.Round(td.GetDx(true), 4),                              // dx(2d),

                                         cAe_1d,                                                     // Ae(1d),
                                         cSD_1d,                                                     // SD(1d),
                                         cWe_1d,                                                     // We(1d),
                                         cIDe_1d,                                                    // IDe(1d),
                                         cTP_1d,                                                     // TP(1d),

                                         cAe_2d,                                                     // Ae(2d),
                                         cSD_2d,                                                     // SD(2d),
                                         cWe_2d,                                                     // We(2d),
                                         cIDe_2d,                                                    // IDe(2d),
                                         cTP_2d,                                                     // TP(2d),

                                         td.MTe,                                                     // MTe,
                                         Math.Round(td.MTRatio, 4),                                  // MTRatio,
                                         meanMTe,                                                    // MeanMTe,
                                         meanMTe_sx,                                                 // MeanMTe(sx),
                                         meanMTe_tx,                                                 // MeanMTe(tx),

                                         td.TargetEntries,                                           // Entries,
                                         td.TargetOvershoots,                                        // Overshoots,
                                         td.IsError ? 1 : 0,                                         // Error?,
                                         errors,                                                     // Errors,
                                         errors_sx,                                                  // Errors(sx),
                                         errors_tx,                                                  // Errors(tx),
                                         errorPct,                                                   // Error%,
                                         errorPct_sx,                                                // Error%(sx),
                                         errorPct_tx,                                                // Error%(tx),

                                         td.IsSpatialOutlier ? 1 : 0,                                // SpatialOutlier?,
                                         td.IsTemporalOutlier ? 1 : 0,                               // TemporalOutlier?,
                                         nSpatialOutliers,                                           // SpatialOutliers,
                                         nTemporalOutliers,                                          // TemporalOutliers,

                                         td.Start.X,                                                 // StartX
                                         td.Start.Y,                                                 // StartY
                                         td.End.X,                                                   // EndX
                                         td.End.Y,                                                   // EndY
                                         td.TargetCenterFromStart.X,                                 // TargetX
                                         td.TargetCenterFromStart.Y,                                 // TargetY

                                         Math.Round(md.Travel, 4),                                   // Travel,
                                         md.Duration,                                                // Duration,
                                         md.GetNumSubmovements(),                                    // Submovements,

                                         Math.Round(profiles.Velocity[vidx].Y, 4),                   // MaxVelocity,
                                         Math.Round(profiles.Acceleration[aidx].Y, 4),               // MaxAcceleration,
                                         Math.Round(profiles.Jerk[jidx].Y, 4),                       // MaxJerk,
                                         Math.Round(profiles.Velocity[vidx].X / md.Duration, 4),     // tMaxVelocity,
                                         Math.Round(profiles.Acceleration[aidx].X / md.Duration, 4), // tMaxAcceleration,
                                         Math.Round(profiles.Jerk[jidx].X / md.Duration, 4),         // tMaxJerk,

                                         analyses.TaskAxisCrossings,                                 // TAC,
                                         analyses.MovementDirectionChanges,                          // MDC,
                                         analyses.OrthogonalDirectionChanges,                        // ODC,
                                         Math.Round(analyses.MovementVariability, 4),                // MV,
                                         Math.Round(analyses.MovementError, 4),                      // ME,
                                         Math.Round(analyses.MovementOffset, 4),                     // MO,

                                         fm.N,                                                       // N,
                                         fm.Fitts_TP_avg_1d,                                         // Fitts_TP_avg(1d),
                                         fm.Fitts_TP_inv_1d,                                         // Fitts_TP_inv(1d),
                                         fm.Fitts_a_1d,                                              // Fitts_a(1d),
                                         fm.Fitts_b_1d,                                              // Fitts_b(1d),
                                         fm.Fitts_r_1d,                                              // Fitts_r(1d),

                                         fm.Fitts_TP_avg_2d,                                         // Fitts_TP_avg(2d),
                                         fm.Fitts_TP_inv_2d,                                         // Fitts_TP_inv(2d),
                                         fm.Fitts_a_2d,                                              // Fitts_a(2d),
                                         fm.Fitts_b_2d,                                              // Fitts_b(2d),
                                         fm.Fitts_r_2d,                                              // Fitts_r(2d),

                                         fm.Error_m_1d,                                              // Error_m(1d),
                                         fm.Error_b_1d,                                              // Error_b(1d),
                                         fm.Error_r_1d,                                              // Error_r(1d),

                                         fm.Error_m_2d,                                              // Error_m(2d),
                                         fm.Error_b_2d,                                              // Error_b(2d),
                                         fm.Error_r_2d                                               // Error_r(2d)
                                         );
                    }
                }
            }
            catch (IOException ioex)
            {
                Console.WriteLine(ioex);
                success = false;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                success = false;
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }
            }
            return(success);
        }
Example #15
0
 private void PointsAddedHandler(SeriesEx series)
 {
     OnPointsAdded();
 }
        /// <summary>
        /// First, temporally resample the movement at 100 Hz. Second, compute the submovement profiles
        /// for velocity, acceleration, and jerk. Third, smooth these profiles using a 1D Gaussian convolution
        /// filter.
        /// </summary>
        /// <returns>This movement smoothed over time.</returns>
        /// <remarks>Smoothing velocity, acceleration, and jerk amounts to smoothing 1D time series. But
        /// position is a 2D time series, and although its x-coords and y-coords can be smoothed independently,
        /// bad artifacts occur at the beginnings and ends. These can be ameliorated by extending the first
        /// and last values position values in the series so that the kernel overlaps them during smoothing.
        /// </remarks>
        public Profiles CreateSmoothedProfiles()
        {
            //
            // Resample to get the submovement profiles with temporally-evenly spaced points. This
            // is a necessary step before applying the Gaussian convolution filter, since intervals
            // should be evenly spaced.
            //
            Profiles resampled = CreateResampledProfiles();

            if (resampled.IsEmpty)
            {
                return(Profiles.Empty);
            }

            //
            // Now smooth the resampled submovement profiles.
            //
            Profiles smoothed;
            int      halfLen = Kernel.Length / 2;

            //
            // To smooth position with 1D filter, we have to smooth the (x,y) coordinates independently.
            // This works fine except at either end of the profile, where it causes major departures. So
            // we must extend the profile at the head and tail to reduce this problem.
            //
            List <PointF> posx = new List <PointF>(resampled.Position.Count + Kernel.Length);
            List <PointF> posy = new List <PointF>(resampled.Position.Count + Kernel.Length);

            for (int i = 0; i < halfLen; i++) // extend first value
            {
                posx.Add(new PointF(0, resampled.Position[0].X));
                posy.Add(new PointF(0, resampled.Position[0].Y));
            }
            for (int i = 0; i < resampled.Position.Count; i++) // add actual values
            {
                posx.Add(new PointF(resampled.Position[i].Time, resampled.Position[i].X));
                posy.Add(new PointF(resampled.Position[i].Time, resampled.Position[i].Y));
            }
            for (int i = 0; i < halfLen; i++) // extend last value
            {
                posx.Add(new PointF(0, resampled.Position[resampled.Position.Count - 1].X));
                posy.Add(new PointF(0, resampled.Position[resampled.Position.Count - 1].Y));
            }

            posx = SeriesEx.Filter(posx, Kernel);                                // smooth x-values
            posy = SeriesEx.Filter(posy, Kernel);                                // smooth y-values

            smoothed.Position = new List <TimePointF>(resampled.Position.Count); // reassemble the (x,y) points
            for (int i = halfLen; i < resampled.Position.Count + halfLen; i++)
            {
                smoothed.Position.Add(new TimePointF(posx[i].Y, posy[i].Y, resampled.Position[i - halfLen].Time));
            }

            //
            // Smooth the derivative resampled time series to create the smoothed velocity, acceleration, and jerk profiles.
            //
            smoothed.Velocity     = SeriesEx.Filter(resampled.Velocity, Kernel);
            smoothed.Acceleration = SeriesEx.Filter(resampled.Acceleration, Kernel);
            smoothed.Jerk         = SeriesEx.Filter(resampled.Jerk, Kernel);

            return(smoothed);
        }
Example #17
0
        private void PointsAdded(SeriesEx series)
        {
            List <PointF> res = ApproximateSeries(series, detailedRange);

            series.WrappedSeries.Points.DataBindXY(res, "X", res, "Y");
        }
 /// <summary>
 /// Private static constructor for the entire class.
 /// </summary>
 static MovementData()
 {
     Kernel = SeriesEx.GaussianKernel(GaussianStdDev);
 }