ParticipationAndSummary Summarize(Participation participation) { ParticipationAndSummary result = new ParticipationAndSummary(); result.Participation = participation; ParticipationsSummary summary = new ParticipationsSummary(); Correlator correlator = new Correlator(); double x = this.GetWeight(participation.Duration); double weight = x / 2; correlator.Add(0, 0, weight); correlator.Add(x, x, weight); summary.Trend = correlator; Distribution logActiveTime = Distribution.MakeDistribution(Math.Log(participation.Duration.TotalSeconds), 0, 1); summary.LogActiveTime = logActiveTime; summary.Start = participation.StartDate; summary.End = participation.EndDate; summary.CumulativeIntensity = participation.Duration; result.Summary = summary; return(result); }
public ParticipationAndSummary Combine(ParticipationAndSummary a, ParticipationAndSummary b) { if (a == null || a.Summary.CumulativeIntensity.TotalSeconds <= 0) { return(b); } if (b == null || b.Summary.CumulativeIntensity.TotalSeconds <= 0) { return(a); } ParticipationsSummary earlier = a.Summary; ParticipationsSummary later = b.Summary; if (earlier.Start.CompareTo(later.Start) > 0) { ParticipationsSummary temp = earlier; earlier = later; later = temp; } ParticipationsSummary summary = new ParticipationsSummary(); summary.CumulativeIntensity = earlier.CumulativeIntensity.Add(later.CumulativeIntensity); summary.Start = earlier.Start; summary.End = later.End; summary.LogActiveTime = earlier.LogActiveTime.Plus(later.LogActiveTime); // time between prev end and next start TimeSpan idleDuration = later.Start.Subtract(earlier.End); double idleX1 = this.GetWeight(earlier.End.Subtract(earlier.Start)); double idleX2 = this.GetWeight(later.Start.Subtract(earlier.Start)); double earlierSum = this.GetWeight(earlier.CumulativeIntensity); Correlator laterShifted = later.Trend.CopyAndShiftRightAndUp(idleX2, earlierSum); Correlator correlator = earlier.Trend.Plus(laterShifted); if (idleDuration.TotalSeconds > 0) { double idleY = earlierSum; double weight = this.GetWeight(idleDuration); correlator.Add(idleX1, idleY, weight); correlator.Add(idleX2, idleY, weight); } summary.Trend = correlator; ParticipationAndSummary result = new ParticipationAndSummary(); result.Summary = summary; if (summary.Trend.Correlation < 0) { System.Diagnostics.Debug.WriteLine("illegal correlation found: " + summary.Trend.Correlation + " for Activity " + this.Owner.Name); } // not bothering to assign a Participation because nothing will need it return(result); }
public ProgressionValue GetValueViaCorrelation(DateTime when, bool strictlyEarlier) { double resultNumber = 0.5; DateTime startDate; // The UI for logging data improved at this date. Any earlier data isn't used for computing correlation DateTime changeDate = new DateTime(2015, 9, 20); if (when.CompareTo(changeDate) > 0) { startDate = changeDate; } else { startDate = DateTime.MinValue; } ParticipationAndSummary info = this.searchHelper.CombineBetweenKeys(startDate, true, when, !strictlyEarlier); if (info != null) { ParticipationsSummary summary = info.Summary; Correlator correlator = summary.Trend; double x = this.GetWeight(when.Subtract(summary.Start)); double predictedY = correlator.GetYForX(x); double actualY = this.GetWeight(summary.CumulativeIntensity); double deltaY = actualY - predictedY; // Ideally we'd just return deltaY, but we have to transform it into a predefined range so the interpolator can use it // Although it would be possible to divide by the total time elapsed, that would cause any deviation to decrease over time // So instead we just warp the space from (-infinity, infinity) into (0, 1) bool positive = true; if (deltaY < 0) { deltaY *= -1; positive = false; } // rescale such that a 32 hour deviation reaches halfway to the end of the space resultNumber = deltaY / this.GetWeight(TimeSpan.FromHours(32)); // rescale such that nothing escapes the end of the space resultNumber = 1.0 - 1.0 / (1.0 + Math.Log(1 + resultNumber)); if (positive) { resultNumber = (resultNumber + 1.0) / 2.0; } else { resultNumber = (1 - resultNumber) / 2.0; } } return(new ProgressionValue(when, Distribution.MakeDistribution(resultNumber, 0, 0))); }
public Correlator Plus(Correlator other) { return(new Correlator(this.count + other.count, this.sumXY + other.sumXY, this.xs.Plus(other.xs), this.ys.Plus(other.ys))); }
// updates the locations at which to draw the provided points private void UpdateDrawing(SKCanvas canvas, SkiaSharp.SKSizeI displaySize) { canvas.Clear(); if (this.plotRequests.Count < 1) { return; } DateTime start = DateTime.Now; double resolution = 1; // determine what domain and range we want to display double minimumX = this.MinX.GetValueOrDefault(this.minXPresent); double maximumX = this.MaxX.GetValueOrDefault(this.maxXPresent); double minimumY = this.MinY.GetValueOrDefault(this.minYPresent); double maximumY = this.MaxY.GetValueOrDefault(this.maxYPresent); int i; double scaleX = 0; double scaleY = 0; if (maximumX > minimumX) { scaleX = displaySize.Width / (maximumX - minimumX); } if (maximumY > minimumY) { scaleY = displaySize.Height / (maximumY - minimumY); } // plot all of the provided points double x, y, x2, y2; foreach (PlotRequest plotRequest in this.plotRequests) { List <Datapoint> pointList = plotRequest.Data; if (pointList.Count < 1) { continue; } x = (pointList[0].Input - minimumX) * scaleX; y = (maximumY - pointList[0].Output) * scaleY; SKPaint brush = makeBrush(plotRequest.DrawColor); for (i = 0; i < pointList.Count; i++) { x2 = (pointList[i].Input - minimumX) * scaleX; y2 = (maximumY - pointList[i].Output) * scaleY; if (Math.Abs(x2 - x) < resolution && Math.Abs(y2 - y) < resolution) { continue; // skip any lines that the user won't be able to see } if (plotRequest.DrawData) { canvas.DrawLine((float)x, (float)y, (float)x2, (float)y2, brush); } x = x2; y = y2; } if (plotRequest.Draw_RegressionLine) { Correlator correlator = plotRequest.Correlator; if (correlator.StdDevX != 0) { // if stdDevX == 0, we'll skip it if (correlator.StdDevX != 0) { SKPaint correlatorBrush = makeBrush(plotRequest.RegressionLine_Color); // compute the equation of the least-squares regression line double correlation = correlator.Correlation; // plot the least-squares regression line double slope = correlator.Slope; x = minimumX; y = (x - correlator.MeanX) * slope + correlator.MeanY; x2 = maximumX; y2 = (x2 - correlator.MeanX) * slope + correlator.MeanY; double renderX1 = (x - minimumX) * scaleX; double renderY1 = (maximumY - y) * scaleY; double renderX2 = (x2 - minimumX) * scaleX; double renderY2 = (maximumY - y2) * scaleY; double rescaleRatio; // cut off the right side of the line if it goes out of bounds rescaleRatio = 1; if (renderY2 > displaySize.Height) { rescaleRatio = (displaySize.Height - renderY1) / (renderY2 - renderY1); } else { if (renderY2 < 0) { rescaleRatio = (renderY1) / (renderY1 - renderY2); } } renderY2 = renderY1 + (renderY2 - renderY1) * rescaleRatio; renderX2 = renderX1 + (renderX2 - renderX1) * rescaleRatio; // cut off the left side of the line if it goes out of bounds rescaleRatio = 1; if (renderY1 > displaySize.Height) { rescaleRatio = (displaySize.Height - renderY2) / (renderY1 - renderY2); } else { if (renderY1 < 0) { rescaleRatio = (renderY2) / (renderY2 - renderY1); } } renderY1 = renderY2 - (renderY2 - renderY1) * rescaleRatio; renderX1 = renderX2 - (renderX2 - renderX1) * rescaleRatio; canvas.DrawLine((float)renderX1, (float)renderY1, (float)renderX2, (float)renderY2, correlatorBrush); } } } } // now draw some tick marks if (this.XAxisSubdivisions != null) { y = displaySize.Height - 1; y2 = displaySize.Height * 19 / 20; foreach (double tickX in this.XAxisSubdivisions) { canvas.DrawLine((float)((tickX - minimumX) * scaleX), (float)y, (float)((tickX - minimumX) * scaleX), (float)y2, cyanBrush); } } if (this.YAxisSubdivisions != null) { x = 0; x2 = displaySize.Width / 20; foreach (double tickY in this.YAxisSubdivisions) { canvas.DrawLine((float)x, (float)((maximumY - tickY) * scaleY), (float)x2, (float)((maximumY - tickY) * scaleY), cyanBrush); } } // draw some axes canvas.DrawLine(0, 0, 0, displaySize.Height, cyanBrush); canvas.DrawLine(0, displaySize.Height - 1, displaySize.Width, displaySize.Height - 1, cyanBrush); DateTime end = DateTime.Now; System.Diagnostics.Debug.WriteLine("spent " + end.Subtract(start) + " in PlotView.UpdatePoints"); }