computeStats method

TimeseriesStats computeStats()

Extracts useful statistics out of this timeseries.

See TimeseriesStats for more details.

Implementation

TimeseriesStats computeStats() {
  final int finalWarmUpFrameCount = warmUpFrameCount;

  assert(finalWarmUpFrameCount >= 0 && finalWarmUpFrameCount < count);

  // The first few values we simply discard and never look at. They're from the warm-up phase.
  final List<double> warmUpValues =
      _allValues.sublist(0, finalWarmUpFrameCount);

  // Values we analyze.
  final List<double> candidateValues =
      _allValues.sublist(finalWarmUpFrameCount);

  // The average that includes outliers.
  final double dirtyAverage = _computeAverage(name, candidateValues);

  // The standard deviation that includes outliers.
  final double dirtyStandardDeviation =
      _computeStandardDeviationForPopulation(name, candidateValues);

  // Any value that's higher than this is considered an outlier.
  final double outlierCutOff = dirtyAverage + dirtyStandardDeviation;

  // Candidates with outliers removed.
  final Iterable<double> cleanValues =
      candidateValues.where((double value) => value <= outlierCutOff);

  // Outlier candidates.
  final Iterable<double> outliers =
      candidateValues.where((double value) => value > outlierCutOff);

  // Final statistics.
  final double cleanAverage = _computeAverage(name, cleanValues);
  final double standardDeviation =
      _computeStandardDeviationForPopulation(name, cleanValues);
  final double noise =
      cleanAverage > 0.0 ? standardDeviation / cleanAverage : 0.0;

  // Compute outlier average. If there are no outliers the outlier average is
  // the same as clean value average. In other words, in a perfect benchmark
  // with no noise the difference between average and outlier average is zero,
  // which the best possible outcome. Noise produces a positive difference
  // between the two.
  final double outlierAverage =
      outliers.isNotEmpty ? _computeAverage(name, outliers) : cleanAverage;

  final List<AnnotatedSample> annotatedValues = <AnnotatedSample>[
    for (final double warmUpValue in warmUpValues)
      AnnotatedSample(
        magnitude: warmUpValue,
        isOutlier: warmUpValue > outlierCutOff,
        isWarmUpValue: true,
      ),
    for (final double candidate in candidateValues)
      AnnotatedSample(
        magnitude: candidate,
        isOutlier: candidate > outlierCutOff,
        isWarmUpValue: false,
      ),
  ];

  return TimeseriesStats(
    name: name,
    average: cleanAverage,
    outlierCutOff: outlierCutOff,
    outlierAverage: outlierAverage,
    standardDeviation: standardDeviation,
    noise: noise,
    cleanSampleCount: cleanValues.length,
    outlierSampleCount: outliers.length,
    samples: annotatedValues,
  );
}