private void configureXAxisSubdivisions(PlotView plotView) { AdaptiveInterpolation.FloatRange inputRange = this.xAxisProgression.EstimateOutputRange(); if (inputRange == null) { DateTime firstDate = this.queryStartDateDisplay.GetDate(); DateTime lastDate = this.queryEndDateDisplay.GetDate(); inputRange = new AdaptiveInterpolation.FloatRange(this.GetXCoordinate(firstDate), true, GetXCoordinate(lastDate), true); } plotView.XAxisSubdivisions = this.xAxisProgression.GetNaturalSubdivisions(inputRange.LowCoordinate, inputRange.HighCoordinate); plotView.MinX = inputRange.LowCoordinate; plotView.MaxX = inputRange.HighCoordinate; }
private void showErrors(PredictionErrors errors) { PlotView plotView = new PlotView(); List <Datapoint> correctValues = new List <Datapoint>(); List <Datapoint> predictedValues = new List <Datapoint>(); List <Datapoint> predictedPlusStdDev = new List <Datapoint>(); if (!double.IsInfinity(errors.MinAllowedValue)) { plotView.MinY = errors.MinAllowedValue; } if (!double.IsInfinity(errors.MaxAllowedValue)) { plotView.MaxY = errors.MaxAllowedValue; } DateTime referenceDate = new DateTime(2000, 1, 1); foreach (PredictionError error in errors.All) { double x = error.When.Subtract(referenceDate).TotalSeconds; correctValues.Add(new Datapoint(x, error.ActualMean, 1)); predictedValues.Add(new Datapoint(x, error.Predicted.Mean, 1)); predictedPlusStdDev.Add(new Datapoint(x, error.Predicted.Mean + error.Predicted.StdDev, 1)); } plotView.AddSeries(correctValues, false); plotView.AddSeries(predictedValues, false); plotView.AddSeries(predictedPlusStdDev, false); ImageLayout imageLayout = new ImageLayout(plotView, LayoutScore.Get_UsedSpace_LayoutScore(1)); TextblockLayout legend = new TextblockLayout("Prediction errors over time. Green: actual value. Blue: predicted value. White: prediction mean + stddev."); LayoutChoice_Set layout = new Vertical_GridLayout_Builder() .AddLayout(imageLayout) .AddLayout(legend) .BuildAnyLayout(); this.layoutStack.AddLayout(layout, "errors"); }
public void UpdateParticipationsPlot() { DateTime start = DateTime.Now; if (!this.queryStartDateDisplay.IsDateValid() || !this.queryEndDateDisplay.IsDateValid()) { return; } // draw the ParticipationProgression List <Participation> participations = this.yAxisActivity.Participations; DateTime firstDate = this.queryStartDateDisplay.GetDate(); DateTime lastDate = this.queryEndDateDisplay.GetDate(); //double firstCoordinate = this.GetXCoordinate(firstDate); //double lastCoordinate = this.GetXCoordinate(lastDate); List <Datapoint> cumulativeParticipationDurations = new List <Datapoint>(); List <Datapoint> cumulativeEffectivenesses = new List <Datapoint>(); List <Datapoint> cumulativeSuggestionCounts = new List <Datapoint>(); List <double> suggestionDates = new List <double>(); PlotView newPlot = new PlotView(); newPlot.MinX = 0; newPlot.MaxX = 1; double x1, x2, cumulativeParticipationSeconds, cumulativeEffectiveness, cumulativeSuggestionCount; x1 = 0; if (this.xAxisProgression != null) { this.configureXAxisSubdivisions(newPlot); } if (newPlot.MinX.HasValue) { x1 = newPlot.MinX.Value; } List <DateTime> startXs = new List <DateTime>(participations.Count); List <DateTime> endXs = new List <DateTime>(participations.Count); // figure out which dates we care about int numActiveIntervals = 0; int numIncludedParticipations = 0; foreach (Participation participation in participations) { // update some data about cumulative participation duration // make sure this participation is relevant if (participation.EndDate.CompareTo(firstDate) >= 0 && participation.StartDate.CompareTo(lastDate) <= 0) { startXs.Add(this.MaxDate(firstDate, participation.StartDate)); endXs.Add(this.MinDate(participation.EndDate, lastDate)); // update some data about cumulative num suggestions // this is slightly hacky - really there should be a method that just returns a list of every Suggestion for an Activity if (participation.Suggested) { // double-check that the participation was suggested more recently than the start DateTime if (participation.StartDate.CompareTo(participation.StartDate) >= 0) { suggestionDates.Add(this.GetXCoordinate(participation.StartDate)); } } } } startXs.Sort(); endXs.Sort(); cumulativeParticipationSeconds = 0; cumulativeEffectiveness = 0; DateTime prevDate = firstDate; while (endXs.Count > 0 || startXs.Count > 0) { DateTime participationStart; DateTime participationEnd; if (startXs.Count > 0) { if (endXs.Count > 0) { participationStart = startXs[0]; participationEnd = endXs[0]; } else { participationStart = startXs[0]; participationEnd = lastDate; // something larger that will be ignored } } else { participationEnd = endXs[0]; participationStart = lastDate; // something larger that will be ignored } if (participationStart.CompareTo(participationEnd) < 0) { x2 = this.GetXCoordinate(participationStart); double weight = x2 - x1; // add datapoints denoting the start of the idle interval cumulativeParticipationDurations.Add(new Datapoint(x1, cumulativeParticipationSeconds, weight)); cumulativeEffectivenesses.Add(new Datapoint(x1, cumulativeEffectiveness, weight)); // update cumulatives cumulativeParticipationSeconds += weight * numActiveIntervals; if (numActiveIntervals > 0) { Distribution efficiency = this.overallEfficiency_summarizer.GetValueDistributionForDates(prevDate, lastDate, true, false); if (efficiency.Weight > 0) { cumulativeEffectiveness += efficiency.Mean * weight * numActiveIntervals; } } numActiveIntervals++; numIncludedParticipations++; // add datapoints denoting the end of the idle interval cumulativeParticipationDurations.Add(new Datapoint(x2, cumulativeParticipationSeconds, weight)); cumulativeEffectivenesses.Add(new Datapoint(x2, cumulativeEffectiveness, weight)); startXs.RemoveAt(0); prevDate = participationStart; } else { x2 = this.GetXCoordinate(participationEnd); double weight = x2 - x1; // add datapoints denoting the start of the active interval cumulativeParticipationDurations.Add(new Datapoint(x1, cumulativeParticipationSeconds, weight)); cumulativeEffectivenesses.Add(new Datapoint(x1, cumulativeEffectiveness, weight)); cumulativeParticipationSeconds += weight * numActiveIntervals; Distribution efficiency = this.overallEfficiency_summarizer.GetValueDistributionForDates(prevDate, lastDate, true, false); if (efficiency.Weight > 0) { cumulativeEffectiveness += efficiency.Mean * weight * numActiveIntervals; } numActiveIntervals--; // add datapoints denoting the end of the active interval cumulativeParticipationDurations.Add(new Datapoint(x2, cumulativeParticipationSeconds, weight)); cumulativeEffectivenesses.Add(new Datapoint(x2, cumulativeEffectiveness, weight)); endXs.RemoveAt(0); prevDate = participationEnd; } x1 = x2; } double cumulativeParticipationHours = cumulativeParticipationSeconds / 3600; double hoursPerTick = this.computeTickInterval(cumulativeParticipationHours); double spacePerTick = hoursPerTick * 3600; // rescale cumulativeParticipationDurations to total 1 if (cumulativeParticipationSeconds != 0) { foreach (Datapoint item in cumulativeParticipationDurations) { item.Output = item.Output / cumulativeParticipationSeconds; } spacePerTick = spacePerTick / cumulativeParticipationSeconds; } // rescale cumulativeEffectivenesses to total 1 if (cumulativeEffectiveness != 0) { foreach (Datapoint item in cumulativeEffectivenesses) { item.Output = item.Output / cumulativeEffectiveness; } } // We also want to plot the number of times that the activity was suggested cumulativeSuggestionCount = 0; foreach (ListItemStats <DateTime, WillingnessSummary> item in this.yAxisActivity.ConsiderationProgression.AllItems) { // make sure the participation is within the requested window if (item.Key.CompareTo(firstDate) >= 0 && item.Key.CompareTo(lastDate) <= 0) { double x = this.GetXCoordinate(item.Key); if (item.Value.NumSkips > 0) { // found a skip suggestionDates.Add(x); } } } suggestionDates.Sort(); foreach (double x in suggestionDates) { cumulativeSuggestionCounts.Add(new Datapoint(x, cumulativeSuggestionCount, 1)); cumulativeSuggestionCount += 1; cumulativeSuggestionCounts.Add(new Datapoint(x, cumulativeSuggestionCount, 1)); } // rescale cumulativeSuggestionCounts to total 1 if (cumulativeSuggestionCount != 0) { foreach (Datapoint item in cumulativeSuggestionCounts) { item.Output /= cumulativeSuggestionCount; } } newPlot.AddSeries(cumulativeParticipationDurations, this.showTimeSpentTrend, this.showTimeSpent, 0); newPlot.AddSeries(cumulativeSuggestionCounts, false, this.showNumSuggestions, 2); newPlot.AddSeries(cumulativeEffectivenesses, false, this.showEffectiveness, 3); // assign y-axis tick marks if (spacePerTick > 0) { double y = 0; List <double> yTicks = new List <double>(); while (y < 1) { yTicks.Add(y); y += spacePerTick; } newPlot.YAxisSubdivisions = yTicks; } this.participationsContent = newPlot; this.participationsView.SetContent(new ImageLayout(newPlot, LayoutScore.Get_UsedSpace_LayoutScore(1))); DateTime end = DateTime.Now; System.Diagnostics.Debug.WriteLine("spent " + end.Subtract(start) + " to update partipations plot"); this.UpdateParticipationStatsView(cumulativeParticipationSeconds, numIncludedParticipations); // debugging //this.SetContent(this.participationsView.GetContent()); }
public void UpdateRatingsPlot() { DateTime start = DateTime.Now; if (!this.queryStartDateDisplay.IsDateValid() || !this.queryEndDateDisplay.IsDateValid()) { return; } // draw the RatingProgression RatingProgression ratingProgression = this.yAxisActivity.RatingProgression; List <AbsoluteRating> ratings = ratingProgression.GetRatingsInDiscoveryOrder(); DateTime startDate = this.queryStartDateDisplay.GetDate(); DateTime endDate = this.queryEndDateDisplay.GetDate(); List <Datapoint> points = new List <Datapoint>(); // make a plot PlotView newPlot = new PlotView(); newPlot.MinX = 0; newPlot.MaxX = endDate.Subtract(startDate).TotalDays; newPlot.MinY = 0; newPlot.MaxY = 1; if (this.xAxisProgression != null) { this.configureXAxisSubdivisions(newPlot); } newPlot.YAxisSubdivisions = new List <double> { 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 }; // compute the rating at each relevant date foreach (AbsoluteRating rating in ratings) { if (rating.Date != null) { double x = this.GetXCoordinate((DateTime)rating.Date); // calculate y double y = rating.Score; // make sure we want to include it in the plot (and therefore the regression line) if (x >= newPlot.MinX && x <= newPlot.MaxX) { points.Add(new Datapoint(x, y, 1)); } } } newPlot.AddSeries(points, this.showRatingsTrend, this.showRatings, 0); // compute a smoothed version of the ratings so we can show which activities are actually worth doing // (for example, sleeping might feel boring but might increase later happiness) TimeSpan totalDuration = endDate.Subtract(startDate); List <ScoreSummarizer> ratingSummarizers = new List <ScoreSummarizer>(); ratingSummarizers.Add(this.overallRating_summarizer); ratingSummarizers.Add(this.overallEfficiency_summarizer); foreach (ExponentialRatingSummarizer ratingSummarizer in ratingSummarizers) { double i; ScoreSummary ratingSummary = new ScoreSummary(endDate); List <Datapoint> smoothedRatings = new List <Datapoint>(); double maxY = 0; for (i = 1; i >= 0; i -= 0.001) { TimeSpan currentDuration = new TimeSpan((long)((double)totalDuration.Ticks * (double)i)); DateTime when = startDate.Add(currentDuration); if (when.CompareTo(ratingSummarizer.EarliestKnownDate) < 0) { break; } ratingSummary.Update(ratingSummarizer, when, endDate); if (ratingSummary.Item.Weight > 0) { double x = this.GetXCoordinate(when); double y = ratingSummary.Item.Mean; if (!double.IsNaN(y)) { if (ratingSummarizer == this.overallEfficiency_summarizer) { // rescale so that the typical value for this rating summarizer (1) is moved to match the typical value for the other plotted values (0.5) y /= 2; } if (y > maxY) { maxY = y; } smoothedRatings.Add(new Datapoint(x, y, 1)); } } } smoothedRatings.Reverse(); // if the plot overflowed, rescale it to fit if (maxY > 1) { foreach (Datapoint datapoint in smoothedRatings) { datapoint.Output = datapoint.Output / maxY; } } if (ratingSummarizer == this.overallRating_summarizer) { newPlot.AddSeries(smoothedRatings, false, this.showOverallHappiness, 2); } else { newPlot.AddSeries(smoothedRatings, this.showEfficiencyTrend, this.showEfficiency, 3); } } DateTime end = DateTime.Now; this.ratingsView.SetContent(new ImageLayout(newPlot, LayoutScore.Get_UsedSpace_LayoutScore(1))); System.Diagnostics.Debug.WriteLine("spent " + end.Subtract(start) + " to update ratings plot"); }