Check that setRow is not negative, fixes #644. (#773)
[dygraphs.git] / src / datahandler / bars-error.js
1 /**
2 * @license
3 * Copyright 2013 David Eberlein (david.eberlein@ch.sauter-bc.com)
4 * MIT-licensed (http://opensource.org/licenses/MIT)
5 */
6
7 /**
8 * @fileoverview DataHandler implementation for the error bars option.
9 * @author David Eberlein (david.eberlein@ch.sauter-bc.com)
10 */
11
12 /*global Dygraph:false */
13 "use strict";
14
15 import BarsHandler from './bars';
16
17 /**
18 * @constructor
19 * @extends BarsHandler
20 */
21 var ErrorBarsHandler = function() {
22 };
23
24 ErrorBarsHandler.prototype = new BarsHandler();
25
26 /** @inheritDoc */
27 ErrorBarsHandler.prototype.extractSeries = function(rawData, i, options) {
28 // TODO(danvk): pre-allocate series here.
29 var series = [];
30 var x, y, variance, point;
31 var sigma = options.get("sigma");
32 var logScale = options.get('logscale');
33 for ( var j = 0; j < rawData.length; j++) {
34 x = rawData[j][0];
35 point = rawData[j][i];
36 if (logScale && point !== null) {
37 // On the log scale, points less than zero do not exist.
38 // This will create a gap in the chart.
39 if (point[0] <= 0 || point[0] - sigma * point[1] <= 0) {
40 point = null;
41 }
42 }
43 // Extract to the unified data format.
44 if (point !== null) {
45 y = point[0];
46 if (y !== null && !isNaN(y)) {
47 variance = sigma * point[1];
48 // preserve original error value in extras for further
49 // filtering
50 series.push([ x, y, [ y - variance, y + variance, point[1] ] ]);
51 } else {
52 series.push([ x, y, [ y, y, y ] ]);
53 }
54 } else {
55 series.push([ x, null, [ null, null, null ] ]);
56 }
57 }
58 return series;
59 };
60
61 /** @inheritDoc */
62 ErrorBarsHandler.prototype.rollingAverage =
63 function(originalData, rollPeriod, options) {
64 rollPeriod = Math.min(rollPeriod, originalData.length);
65 var rollingData = [];
66 var sigma = options.get("sigma");
67
68 var i, j, y, v, sum, num_ok, stddev, variance, value;
69
70 // Calculate the rolling average for the first rollPeriod - 1 points
71 // where there is not enough data to roll over the full number of points
72 for (i = 0; i < originalData.length; i++) {
73 sum = 0;
74 variance = 0;
75 num_ok = 0;
76 for (j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) {
77 y = originalData[j][1];
78 if (y === null || isNaN(y))
79 continue;
80 num_ok++;
81 sum += y;
82 variance += Math.pow(originalData[j][2][2], 2);
83 }
84 if (num_ok) {
85 stddev = Math.sqrt(variance) / num_ok;
86 value = sum / num_ok;
87 rollingData[i] = [ originalData[i][0], value,
88 [value - sigma * stddev, value + sigma * stddev] ];
89 } else {
90 // This explicitly preserves NaNs to aid with "independent
91 // series".
92 // See testRollingAveragePreservesNaNs.
93 v = (rollPeriod == 1) ? originalData[i][1] : null;
94 rollingData[i] = [ originalData[i][0], v, [ v, v ] ];
95 }
96 }
97
98 return rollingData;
99 };
100
101 export default ErrorBarsHandler;