| Index: tracing/tracing/value/histogram.html
|
| diff --git a/tracing/tracing/value/histogram.html b/tracing/tracing/value/histogram.html
|
| index 3cdffc5ccb632728af97283e58b0cbaa6cf9c2fb..aec1731df8350a9df2a55826fe4d74ce128ee694 100644
|
| --- a/tracing/tracing/value/histogram.html
|
| +++ b/tracing/tracing/value/histogram.html
|
| @@ -23,24 +23,10 @@ tr.exportTo('tr.v', function() {
|
| const DEFAULT_BOUNDARIES_FOR_UNIT = new Map();
|
|
|
| const DELTA = String.fromCharCode(916);
|
| - const ABS_DELTA_AVG_NAME = 'abs' + DELTA + 'avg';
|
| - const PCT_DELTA_AVG_NAME = '%' + DELTA + 'avg';
|
| const Z_SCORE_NAME = 'z-score';
|
| - const ABS_DELTA_STD_NAME = 'abs' + DELTA + 'std';
|
| - const PCT_DELTA_STD_NAME = '%' + DELTA + 'std';
|
| const P_VALUE_NAME = 'p-value';
|
| const U_STATISTIC_NAME = 'U';
|
|
|
| - const DELTA_STATISTIC_NAMES = [
|
| - ABS_DELTA_AVG_NAME,
|
| - PCT_DELTA_AVG_NAME,
|
| - Z_SCORE_NAME,
|
| - ABS_DELTA_STD_NAME,
|
| - PCT_DELTA_STD_NAME,
|
| - P_VALUE_NAME,
|
| - U_STATISTIC_NAME,
|
| - ];
|
| -
|
| /**
|
| * Converts the given percent to a string in the format specified above.
|
| * @param {number} percent The percent must be between 0.0 and 1.0.
|
| @@ -498,7 +484,7 @@ tr.exportTo('tr.v', function() {
|
| for (let [stat, option] of other.summaryOptions) {
|
| if (stat === 'percentile') {
|
| for (let percent of option) {
|
| - let percentiles = this.summaryOptions.get('percentile');
|
| + let percentiles = this.summaryOptions.get(stat);
|
| if (percentiles.indexOf(percent) < 0) {
|
| percentiles.push(percent);
|
| }
|
| @@ -535,23 +521,10 @@ tr.exportTo('tr.v', function() {
|
| * @param {!tr.v.Histogram=} opt_referenceHistogram
|
| * @param {!HypothesisTestResult=} opt_mwu
|
| * @return {!tr.b.Scalar}
|
| + * @throws {Error} When statName is not recognized, such as delta statistics
|
| + * when !this.canCompare(opt_referenceHistograms).
|
| */
|
| getStatisticScalar(statName, opt_referenceHistogram, opt_mwu) {
|
| - if (!(opt_referenceHistogram instanceof Histogram) ||
|
| - (this.unit !== opt_referenceHistogram.unit) ||
|
| - (opt_referenceHistogram.numValues === 0)) {
|
| - if (statName === tr.v.ABS_DELTA_AVG_NAME ||
|
| - statName === tr.v.PCT_DELTA_AVG_NAME ||
|
| - statName === tr.v.Z_SCORE_NAME ||
|
| - statName === tr.v.P_VALUE_NAME ||
|
| - statName === tr.v.U_STATISTIC_NAME) {
|
| - statName = 'avg';
|
| - } else if (statName === tr.v.ABS_DELTA_STD_NAME ||
|
| - statName === tr.v.PCT_DELTA_STD_NAME) {
|
| - statName = 'std';
|
| - }
|
| - }
|
| -
|
| if (statName === 'avg') {
|
| if (this.running_ === undefined) return undefined;
|
| return new tr.b.Scalar(this.unit, this.average);
|
| @@ -583,49 +556,54 @@ tr.exportTo('tr.v', function() {
|
| return new tr.b.Scalar(this.unit, percentile);
|
| }
|
|
|
| - if (opt_referenceHistogram instanceof Histogram &&
|
| - this.unit === opt_referenceHistogram.unit &&
|
| - opt_referenceHistogram.numValues > 0) {
|
| - let absDeltaAvg = this.average - opt_referenceHistogram.average;
|
| - let suffix = tr.b.Unit.nameSuffixForImprovementDirection(
|
| - this.unit.improvementDirection);
|
| - if (statName === ABS_DELTA_AVG_NAME) {
|
| - return new tr.b.Scalar(this.unit.correspondingDeltaUnit, absDeltaAvg);
|
| - }
|
| - if (statName === PCT_DELTA_AVG_NAME) {
|
| + if (!this.canCompare(opt_referenceHistogram)) {
|
| + throw new Error(
|
| + 'Cannot compute ' + statName +
|
| + ' when histograms are not comparable');
|
| + }
|
| +
|
| + const suffix = tr.b.Unit.nameSuffixForImprovementDirection(
|
| + this.unit.improvementDirection);
|
| +
|
| + const deltaIndex = statName.indexOf(DELTA);
|
| + if (deltaIndex >= 0) {
|
| + const baseStatName = statName.substr(deltaIndex + 1);
|
| + const thisStat = this.getStatisticScalar(baseStatName);
|
| + const otherStat = opt_referenceHistogram.getStatisticScalar(
|
| + baseStatName);
|
| + const deltaValue = thisStat.value - otherStat.value;
|
| +
|
| + if (statName[0] === '%') {
|
| return new tr.b.Scalar(
|
| tr.b.Unit.byName['normalizedPercentageDelta' + suffix],
|
| - absDeltaAvg / opt_referenceHistogram.average);
|
| - }
|
| - let absDeltaStd = this.standardDeviation -
|
| - opt_referenceHistogram.standardDeviation;
|
| - if (statName === ABS_DELTA_STD_NAME) {
|
| - return new tr.b.Scalar(this.unit.correspondingDeltaUnit, absDeltaStd);
|
| - }
|
| - if (statName === PCT_DELTA_STD_NAME) {
|
| - let pctDeltaStd = absDeltaStd /
|
| - opt_referenceHistogram.standardDeviation;
|
| - return new tr.b.Scalar(this.unit.correspondingDeltaUnit, pctDeltaStd);
|
| - }
|
| - if (statName === Z_SCORE_NAME) {
|
| - return new tr.b.Scalar(
|
| - tr.b.Unit.byName['sigmaDelta' + suffix],
|
| - absDeltaAvg / opt_referenceHistogram.standardDeviation);
|
| + deltaValue / otherStat.value);
|
| }
|
| + return new tr.b.Scalar(
|
| + thisStat.unit.correspondingDeltaUnit, deltaValue);
|
| + }
|
|
|
| - let mwu = opt_mwu || tr.b.Statistics.mwu(
|
| - this.sampleValues, opt_referenceHistogram.sampleValues);
|
| - if (statName === P_VALUE_NAME) {
|
| - return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.p);
|
| - }
|
| - if (statName === U_STATISTIC_NAME) {
|
| - return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.U);
|
| - }
|
| + if (statName === Z_SCORE_NAME) {
|
| + return new tr.b.Scalar(
|
| + tr.b.Unit.byName['sigmaDelta' + suffix],
|
| + (this.average - opt_referenceHistogram.average) /
|
| + opt_referenceHistogram.standardDeviation);
|
| + }
|
| +
|
| + let mwu = opt_mwu || tr.b.Statistics.mwu(
|
| + this.sampleValues, opt_referenceHistogram.sampleValues);
|
| + if (statName === P_VALUE_NAME) {
|
| + return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.p);
|
| + }
|
| + if (statName === U_STATISTIC_NAME) {
|
| + return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.U);
|
| }
|
|
|
| - throw new Error('Unrecognized statistic name');
|
| + throw new Error('Unrecognized statistic name: ' + statName);
|
| }
|
|
|
| + /**
|
| + * @return {!Array.<string>} names of enabled summary statistics
|
| + */
|
| get statisticsNames() {
|
| let statisticsNames = new Set();
|
| for (let [statName, option] of this.summaryOptions) {
|
| @@ -641,6 +619,57 @@ tr.exportTo('tr.v', function() {
|
| }
|
|
|
| /**
|
| + * Returns true if delta statistics can be computed between |this| and
|
| + * |other|.
|
| + *
|
| + * @param {!tr.v.Histogram=} other
|
| + * @return {boolean}
|
| + */
|
| + canCompare(other) {
|
| + return other instanceof Histogram &&
|
| + this.unit === other.unit &&
|
| + this.numValues > 0 &&
|
| + other.numValues > 0;
|
| + }
|
| +
|
| + /**
|
| + * Returns |statName| if it can be computed, or the related non-delta
|
| + * statistic if |statName| is a delta statistic and
|
| + * !this.canCompare(opt_referenceHist).
|
| + *
|
| + * @param {string} statName
|
| + * @param {!tr.v.Histogram=} opt_referenceHist
|
| + * @return {string}
|
| + */
|
| + getAvailableStatisticName(statName, opt_referenceHist) {
|
| + if (this.canCompare(opt_referenceHist)) return statName;
|
| + if (statName === Z_SCORE_NAME ||
|
| + statName === P_VALUE_NAME ||
|
| + statName === U_STATISTIC_NAME) {
|
| + return 'avg';
|
| + }
|
| + const deltaIndex = statName.indexOf(DELTA);
|
| + if (deltaIndex < 0) return statName;
|
| + return statName.substr(deltaIndex + 1);
|
| + }
|
| +
|
| + /**
|
| + * Returns names of delta statistics versions of given non-delta statistics
|
| + * names.
|
| + *
|
| + * @param {!Array.<string>} statNames
|
| + * @return {!Array.<string>}
|
| + */
|
| + static getDeltaStatisticsNames(statNames) {
|
| + const deltaNames = [];
|
| + for (const statName of statNames) {
|
| + deltaNames.push(`${DELTA}${statName}`);
|
| + deltaNames.push(`%${DELTA}${statName}`);
|
| + }
|
| + return deltaNames.concat([Z_SCORE_NAME, P_VALUE_NAME, U_STATISTIC_NAME]);
|
| + }
|
| +
|
| + /**
|
| * Returns a Map {statisticName: Scalar}.
|
| *
|
| * Each enabled summary option produces the corresponding value:
|
| @@ -676,8 +705,10 @@ tr.exportTo('tr.v', function() {
|
| this.binBoundariesDict_);
|
| let hist = new Histogram(this.name, this.unit, binBoundaries);
|
| for (let [stat, option] of this.summaryOptions) {
|
| - // Copy the array of percentiles.
|
| - if (stat === 'percentile') option = Array.from(option);
|
| + // Copy arrays.
|
| + if (stat === 'percentile') {
|
| + option = Array.from(option);
|
| + }
|
| hist.summaryOptions.set(stat, option);
|
| }
|
| hist.addHistogram(this);
|
| @@ -1180,18 +1211,14 @@ tr.exportTo('tr.v', function() {
|
| HistogramBinBoundaries.createLinear(-5, 5, 50));
|
|
|
| return {
|
| + DELTA,
|
| Histogram,
|
| HistogramBinBoundaries,
|
| - percentToString,
|
| - percentFromString,
|
| - ABS_DELTA_AVG_NAME,
|
| - PCT_DELTA_AVG_NAME,
|
| - ABS_DELTA_STD_NAME,
|
| - PCT_DELTA_STD_NAME,
|
| P_VALUE_NAME,
|
| U_STATISTIC_NAME,
|
| Z_SCORE_NAME,
|
| - DELTA_STATISTIC_NAMES,
|
| + percentFromString,
|
| + percentToString,
|
| };
|
| });
|
| </script>
|
|
|