- * Extracts one series from the raw data (a 2D array) into an array of (date,
- * value) tuples.
- *
- * This is where undesirable points (i.e. negative values on log scales and
- * missing values through which we wish to connect lines) are dropped.
- * TODO(danvk): the "missing values" bit above doesn't seem right.
- *
- * @private
- */
-Dygraph.prototype.extractSeries_ = function(rawData, i, logScale) {
- // TODO(danvk): pre-allocate series here.
- var series = [];
- for (var j = 0; j < rawData.length; j++) {
- var x = rawData[j][0];
- var point = rawData[j][i];
- if (logScale) {
- // On the log scale, points less than zero do not exist.
- // This will create a gap in the chart.
- if (point <= 0) {
- point = null;
- }
- }
- series.push([x, point]);
- }
- return series;
-};
-
-/**
- * @private
- * Calculates the rolling average of a data set.
- * If originalData is [label, val], rolls the average of those.
- * If originalData is [label, [, it's interpreted as [value, stddev]
- * and the roll is returned in the same form, with appropriately reduced
- * stddev for each value.
- * Note that this is where fractional input (i.e. '5/10') is converted into
- * decimal values.
- * @param {Array} originalData The data in the appropriate format (see above)
- * @param {Number} rollPeriod The number of points over which to average the
- * data
- */
-Dygraph.prototype.rollingAverage = function(originalData, rollPeriod) {
- rollPeriod = Math.min(rollPeriod, originalData.length);
- var rollingData = [];
- var sigma = this.attr_("sigma");
-
- var low, high, i, j, y, sum, num_ok, stddev;
- if (this.fractions_) {
- var num = 0;
- var den = 0; // numerator/denominator
- var mult = 100.0;
- for (i = 0; i < originalData.length; i++) {
- num += originalData[i][1][0];
- den += originalData[i][1][1];
- if (i - rollPeriod >= 0) {
- num -= originalData[i - rollPeriod][1][0];
- den -= originalData[i - rollPeriod][1][1];
- }
-
- var date = originalData[i][0];
- var value = den ? num / den : 0.0;
- if (this.attr_("errorBars")) {
- if (this.attr_("wilsonInterval")) {
- // For more details on this confidence interval, see:
- // http://en.wikipedia.org/wiki/Binomial_confidence_interval
- if (den) {
- var p = value < 0 ? 0 : value, n = den;
- var pm = sigma * Math.sqrt(p*(1-p)/n + sigma*sigma/(4*n*n));
- var denom = 1 + sigma * sigma / den;
- low = (p + sigma * sigma / (2 * den) - pm) / denom;
- high = (p + sigma * sigma / (2 * den) + pm) / denom;
- rollingData[i] = [date,
- [p * mult, (p - low) * mult, (high - p) * mult]];
- } else {
- rollingData[i] = [date, [0, 0, 0]];
- }
- } else {
- stddev = den ? sigma * Math.sqrt(value * (1 - value) / den) : 1.0;
- rollingData[i] = [date, [mult * value, mult * stddev, mult * stddev]];
- }
- } else {
- rollingData[i] = [date, mult * value];
- }
- }
- } else if (this.attr_("customBars")) {
- low = 0;
- var mid = 0;
- high = 0;
- var count = 0;
- for (i = 0; i < originalData.length; i++) {
- var data = originalData[i][1];
- y = data[1];
- rollingData[i] = [originalData[i][0], [y, y - data[0], data[2] - y]];
-
- if (y !== null && !isNaN(y)) {
- low += data[0];
- mid += y;
- high += data[2];
- count += 1;
- }
- if (i - rollPeriod >= 0) {
- var prev = originalData[i - rollPeriod];
- if (prev[1][1] !== null && !isNaN(prev[1][1])) {
- low -= prev[1][0];
- mid -= prev[1][1];
- high -= prev[1][2];
- count -= 1;
- }
- }
- if (count) {
- rollingData[i] = [originalData[i][0], [ 1.0 * mid / count,
- 1.0 * (mid - low) / count,
- 1.0 * (high - mid) / count ]];
- } else {
- rollingData[i] = [originalData[i][0], [null, null, null]];
- }
- }
- } else {
- // Calculate the rolling average for the first rollPeriod - 1 points where
- // there is not enough data to roll over the full number of points
- if (!this.attr_("errorBars")){
- if (rollPeriod == 1) {
- return originalData;
- }
-
- for (i = 0; i < originalData.length; i++) {
- sum = 0;
- num_ok = 0;
- for (j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) {
- y = originalData[j][1];
- if (y === null || isNaN(y)) continue;
- num_ok++;
- sum += originalData[j][1];
- }
- if (num_ok) {
- rollingData[i] = [originalData[i][0], sum / num_ok];
- } else {
- rollingData[i] = [originalData[i][0], null];
- }
- }
-
- } else {
- for (i = 0; i < originalData.length; i++) {
- sum = 0;
- var variance = 0;
- num_ok = 0;
- for (j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) {
- y = originalData[j][1][0];
- if (y === null || isNaN(y)) continue;
- num_ok++;
- sum += originalData[j][1][0];
- variance += Math.pow(originalData[j][1][1], 2);
- }
- if (num_ok) {
- stddev = Math.sqrt(variance) / num_ok;
- rollingData[i] = [originalData[i][0],
- [sum / num_ok, sigma * stddev, sigma * stddev]];
- } else {
- rollingData[i] = [originalData[i][0], [null, null, null]];
- }
- }
- }
- }
-
- return rollingData;
-};
-
-/**