public double InterpolateIntensity(double timePoint)
 {
     if (time != null && time.Count > 4)
     {
         if (interpole == null)
         {
             try
             {
                 //interpole = new MathNet.Numerics.Interpolation.Algorithms.CubicSplineInterpolation(time, intensityCount);
                 interpole = new MathNet.Numerics.Interpolation.Algorithms.AkimaSplineInterpolation(time, intensityCount);
                 //interpole = MathNet.Numerics.Interpolation.Interpolate.LinearBetweenPoints(time, intensityCount);
             }catch (Exception ex)
             {
                 Console.WriteLine(ex.StackTrace);
             }
         }
         double intensity = interpole.Interpolate(timePoint);
         if (intensity < 0)
         {
             return(0);
         }
         else
         {
             return(intensity);
         }
     }
     return(0);
 }
Esempio n. 2
0
        /**
         * <summary>
         * <para>
         * Calculates knee points using the Kneedle algorithm. Returns the x value corresponding to the knee
         * point when successful, null otherwise.
         * </para>
         * <para>
         * Reference:
         *      Finding a ‘kneedle’in a haystack: Detecting knee points in system behavior.
         *      Satopaa, V and Albrecht, J and Irwin, D and Raghavan, B
         *      <see cref="https://raghavan.usc.edu/papers/kneedle-simplex11.pdf"/>
         * </para>
         *
         *  <list type="bullet">
         *  <param name="x">x: X axis values of the points. Points must be sorted in ascending order w.r.t. X axis.</param>
         *  <param name="y">y: Y axis values of the points.</param>
         *  <param name="direction">direction: If the curve is increasing or decreasing. Make sure to set this value according to the input curve.</param>
         *  <param name="concavity">concavity: Whether the curve has positive or negative curvature. In other words, concave or convex. Whether the tangent rotates clockwise or counterclockwise. Make sure to set this value according to the input curve.</param>
         *  <param name="sensitivity">sensitivity: Adjusts the knee detection threshold. Defaults to 1 as per the paper.</param>
         *  <param name="forceLinearInterpolation">forceLinearInterpolation: Interpolation is done using robust cubic splines. For some inputs, spline can overshoot. This param forces linear interpolation instead of cubic spline.</param>
         *  </list>
         *
         * Can return null when the algorithm fails to identify a knee/elbow for various reasons:
         *      - the number of data points is too small
         *      - there are no local maxima on the diffs, which means either the curve is a line, or the
         *        parameters provided are incompatible with the curve
         *
         *  <list type="bullet">
         *  2019-01-08: rename curvature enum to be easy to interpret and remember (Prashant Borole)
         *  2019-01-07: initial version (Prashant Borole)
         *  </list>
         *  </summary>
         */
        public static double?CalculateKneePoints(double[] x, double[] y, CurveDirection direction, Curvature concavity, double sensitivity = 1, bool forceLinearInterpolation = true)
        {
            if (x == null || y == null || x.Length != y.Length || x.Length < 2)
            {
                return(null);
            }

            var numPoints = x.Length;

            MathNet.Numerics.Interpolation.IInterpolation interpolator = null;
            if (numPoints > 5 && !forceLinearInterpolation)
            {
                interpolator = Interpolate.CubicSplineRobust(x, y);
            }
            else
            {
                interpolator = Interpolate.Linear(x, y);
            }
            var x_spaced = Generate.LinearSpaced(numPoints, x.Min(), x.Max());
            var y_spaced = Generate.Map(x_spaced, interpolator.Interpolate);

            var x_norm = MinMaxNormalize(x_spaced);
            var y_norm = MinMaxNormalize(y_spaced);

            var x_diff = x_norm;
            var y_diff = new double[numPoints];

            if (direction == CurveDirection.Decreasing)
            {
                for (int i = 0; i < numPoints; i++)
                {
                    y_diff[i] = x_norm[i] + y_norm[i];
                }
                if (concavity == Curvature.Counterclockwise)
                {
                    for (int i = 0; i < numPoints; i++)
                    {
                        y_diff[i] = 1 - y_diff[i];
                    }
                }
            }
            else
            {
                // increasing
                for (int i = 0; i < numPoints; i++)
                {
                    y_diff[i] = y_norm[i] - x_norm[i];
                }
                if (concavity == Curvature.Counterclockwise)
                {
                    for (int i = 0; i < numPoints; i++)
                    {
                        y_diff[i] = Math.Abs(y_diff[i]);
                    }
                }
            }


            // find local maxima
            var xmx_idxs = FindLocalExtrema(y_diff, true);

            if (xmx_idxs.Count == 0)
            {
                return(null);
            }
            var xmx = xmx_idxs.Select(idx => x_diff[idx]).ToArray();
            var ymx = xmx_idxs.Select(idx => y_diff[idx]).ToArray();

            // minima
            var xmn_idxs = FindLocalExtrema(y_diff, false);
            var xmn      = xmn_idxs.Select(idx => x_diff[idx]).ToArray();
            var ymn      = xmn_idxs.Select(idx => y_diff[idx]).ToArray();

            var tmx = Threshold(ymx, x_norm, sensitivity);

            // now find the knee point between each of the local maxima
            var    curMaximaIdx = 0;
            var    xmn_idxs_set = new HashSet <int>(xmn_idxs);
            double?knee         = null;

            for (int x_i = xmx_idxs[0] + 1; x_i < x.Length; x_i++)
            {
                if (curMaximaIdx < xmx_idxs.Count - 1 && x_i == xmx_idxs[curMaximaIdx + 1])
                {
                    curMaximaIdx++;
                    x_i++;
                    continue;
                }

                if (xmn_idxs_set.Contains(x_i))
                {
                    if (x_i < x.Length - 1 && y_diff[x_i + 1] > y_diff[x_i])
                    {
                        tmx[curMaximaIdx] = 0;
                    }
                }

                if (y_diff[x_i] < tmx[curMaximaIdx] || tmx[curMaximaIdx] < 0)
                {
                    knee = x[xmx_idxs[curMaximaIdx]];
                }
            }

            return(knee);
        }
Esempio n. 3
0
        private void HRNodeClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            SplitContainer chartsplit = (SplitContainer)splitContainer2.Panel2.Controls["chartsplit"];
            Chart          chart1     = (Chart)chartsplit.Panel1.Controls["chart1"];

            Chart chart2 = (Chart)chartsplit.Panel2.Controls["chart2"];

            chart1.ChartAreas.Clear();
            chart2.ChartAreas.Clear();

            ChartArea area = new ChartArea("0");

            area.AxisX.Minimum           = 0;
            area.AxisX.Interval          = 3;
            area.AxisX.IntervalType      = DateTimeIntervalType.Number;
            area.AxisX.LabelStyle.Format = "#.##";
            chart1.ChartAreas.Add("0");
            chart2.ChartAreas.Add("1");

            TreeView tv = (TreeView)splitContainer2.Panel1.Controls[0];

            if (ModifierKeys.HasFlag(Keys.Control))
            {
                TreeNode selected = tv.SelectedNode;
                selected.BackColor = Color.Aqua;
            }
            else
            {
                chart1.Series.Clear();
                chart2.Series.Clear();
                foreach (TreeNode tn in tv.Nodes)
                {
                    tn.BackColor = Color.White;
                }
            }
            TreeNode node = e.Node;

            Series s = new Series();

            s.ChartType   = SeriesChartType.Line;
            s.BorderWidth = 3;
            HRWorkout hr = (HRWorkout)node.Tag;

            List <double> xarr = new List <double>();
            List <double> yarr = new List <double>();

            foreach (var samp in hr.exercises[0].samples.heartRate)
            {
                double x = (samp.dateTime - hr.startTime).TotalSeconds / 60;
                int    y = samp.value;
                xarr.Add(x);
                yarr.Add(y);
            }

            for (int i = 0; i < xarr.Count; i++)
            {
                DataPoint dp = new DataPoint();
                dp.SetValueXY(xarr[i], yarr[i]);
                dp.ToolTip = xarr[i].ToString("#.##") + " mins" + "\n" + yarr[i].ToString() + " bpm" + "\n" + node.Text;
                s.Points.Add(dp);
            }

            RemoveZeros(yarr);

            #region old
            //double sampRate = (double)xarr.Count / (xarr[xarr.Count - 1] * 60);

            //MathNet.Filtering.Median.OnlineMedianFilter filter =
            //    new MathNet.Filtering.Median.OnlineMedianFilter(17);

            //double[] filtered = filter.ProcessSamples(yarr.ToArray());

            //Series filteredHR = new Series();
            //filteredHR.ChartType = SeriesChartType.Line;
            //filteredHR.BorderWidth = 3;
            //filteredHR.Color = Color.Orange;

            //for (int i = 0; i < xarr.Count; i++)
            //{
            //    DataPoint dp = new DataPoint(xarr[i], filtered[i]);
            //    filteredHR.Points.Add(dp);
            //}
            //chart1.Series.Add(filteredHR);
            //chart2.Series.Add(SeriesDerivative(filteredHR, 100));
            #endregion

            MathNet.Numerics.Interpolation.IInterpolation interp = MathNet.Numerics.Interpolate.CubicSplineRobust(xarr, yarr);
            Series splineHR = new Series();
            splineHR.ChartType   = SeriesChartType.Line;
            splineHR.BorderWidth = 3;

            for (int i = 0; i < xarr.Count; i++)
            {
                DataPoint dp = new DataPoint(xarr[i], interp.Interpolate(xarr[i]));
                splineHR.Points.Add(dp);
            }

            Series sdiff = new Series();
            sdiff.ChartType   = SeriesChartType.Line;
            sdiff.BorderWidth = 3;

            for (int i = 0; i < xarr.Count; i++)
            {
                DataPoint dp = new DataPoint(xarr[i], interp.Differentiate(xarr[i]));
                sdiff.Points.Add(dp);
            }

            chart1.Series.Add(splineHR);
            chart2.Series.Add(sdiff);
        }