two different versions; tweak color logic
authorDan Vanderkam <danvdk@gmail.com>
Thu, 16 Sep 2010 01:19:04 +0000 (21:19 -0400)
committerDan Vanderkam <danvdk@gmail.com>
Thu, 16 Sep 2010 01:19:04 +0000 (21:19 -0400)
tests/linear-regression-addseries.html [new file with mode: 0644]
tests/linear-regression.html

diff --git a/tests/linear-regression-addseries.html b/tests/linear-regression-addseries.html
new file mode 100644 (file)
index 0000000..3aa0632
--- /dev/null
@@ -0,0 +1,165 @@
+<html>
+  <head>
+    <title>Linear Regression</title>
+    <!--[if IE]>
+    <script type="text/javascript" src="excanvas.js"></script>
+    <![endif]-->
+    <script type="text/javascript" src="../strftime/strftime-min.js"></script>
+    <script type="text/javascript" src="../rgbcolor/rgbcolor.js"></script>
+    <script type="text/javascript" src="../dygraph-canvas.js"></script>
+    <script type="text/javascript" src="../dygraph.js"></script>
+    <style type="text/css">
+    body { max-width: 640 px; }
+    </style>
+  </head>
+  <body>
+    <h2>Linear Regression Demo</h2>
+    <p>Click the buttons to generate linear regressions over either data
+    series. If you zoom in and click the regression button, the regression will
+    only be run over visible points. Zoom back out to see what the local
+    regression looks like over the full data.</p>
+
+    <div id="demodiv" style="width: 480px; height: 320px;"></div>
+
+    <script type="text/javascript">
+      var data = [];
+      for (var i = 0; i < 120; i++) {
+        data.push([i,
+                   i / 5.0 + 10.0 * Math.sin(i / 3.0),
+                   30.0 - i / 5.0 - 10.0 * Math.sin(i / 3.0 + 1.0)]);
+      }
+      var labels = ['X', 'Y1', 'Y2'];
+      var orig_colors = [];
+
+      g = new Dygraph(
+              document.getElementById("demodiv"),
+              data,
+              {
+                labels: labels,
+                drawPoints: true,
+                drawCallback: function(g, is_initial) {
+                  if (!is_initial) return;
+                  var c = g.getColors();
+                  for (var i = 0; i < c.length; i++) orig_colors.push(c[i]);
+                }
+              }
+          );
+
+      // coefficients of regression for each series.
+      // if coeffs = [ null, [1, 2], null ] then we draw a regression for series 1
+      // only. The regression line is y = 1 + 2 * x.
+      var coeffs = [ null, null, null ];
+      function regression(series) {
+        // Only run the regression over visible points.
+        var range = g.xAxisRange();
+
+        var sum_xy = 0.0, sum_x = 0.0, sum_y = 0.0, sum_x2 = 0.0, num = 0;
+        for (var i = 0; i < data.length; i++) {
+          var x = data[i][0];
+          if (x < range[0] || x > range[1]) continue;
+
+          var y = data[i][series];
+          if (y == null) continue;
+
+          num++;
+          sum_x += x;
+          sum_y += y;
+          sum_xy += x * y;
+          sum_x2 += x * x;
+        }
+
+        var a = (sum_xy - sum_x * sum_y / num) / (sum_x2 - sum_x * sum_x / num);
+        var b = (sum_y - a * sum_x) / num;
+
+        coeffs[series] = [b, a];
+        if (console) {
+          console.log("coeffs(" + series + "): [" + b + ", " + a + "]");
+        }
+
+        updateChart();
+      }
+
+      function updateChart() {
+        // Generate a new data set with the regression lines.
+        var new_labels = [];
+        var new_colors = [];
+        for (var i = 0; i < labels.length; i++) {
+          new_labels.push(labels[i]);
+          if (i) new_colors.push(orig_colors[i - 1]);
+          if (coeffs[i]) {
+            // Darken the series by 50% to generate its regression.
+            new_labels.push(labels[i] + " Regression");
+            var c = new RGBColor(orig_colors[i - 1]);
+            c.r = Math.floor(255 - 0.5 * (255 - c.r));
+            c.g = Math.floor(255 - 0.5 * (255 - c.g));
+            c.b = Math.floor(255 - 0.5 * (255 - c.b));
+            new_colors.push(c.toHex());
+          }
+        }
+
+        var new_data = [];
+        for (var i = 0; i < data.length; i++) {
+          new_data.push([]);
+          for (var j = 0; j < data[i].length; j++) {
+            new_data[i].push(data[i][j]);
+            if (coeffs[j]) {
+              new_data[i].push(coeffs[j][0] + coeffs[j][1] * data[i][0]);
+            }
+          }
+        }
+
+        // TODO(danvk): set colors intelligently.
+
+        g.updateOptions({
+          file: new_data,
+          labels: new_labels,
+          colors: new_colors
+        });
+      }
+
+      function clearLines() {
+        for (var i = 0; i < coeffs.length; i++) coeffs[i] = null;
+        updateChart();
+      }
+
+      // function drawLines(ctx, area, layout) {
+      //   if (typeof(g) == 'undefined') return;  // won't be set on the initial draw.
+
+      //   var range = g.xAxisRange();
+      //   for (var i = 0; i < coeffs.length; i++) {
+      //     if (!coeffs[i]) continue;
+      //     var a = coeffs[i][1];
+      //     var b = coeffs[i][0];
+
+      //     var x1 = range[0];
+      //     var y1 = a * x1 + b;
+      //     var x2 = range[1];
+      //     var y2 = a * x2 + b;
+
+      //     var p1 = g.toDomCoords(x1, y1);
+      //     var p2 = g.toDomCoords(x2, y2);
+
+      //     var color = g.getColors()[i - 1];
+      //     ctx.save();
+      //     ctx.strokeStyle = color;
+      //     ctx.lineWidth = 1.0;
+      //     ctx.beginPath();
+      //     ctx.moveTo(p1[0], p1[1]);
+      //     ctx.lineTo(p2[0], p2[1]);
+      //     ctx.closePath();
+      //     ctx.stroke();
+      //     ctx.restore();
+      //   }
+      // }
+      
+    </script>
+    
+    <div style="position: absolute; left: 500px; top: 150px;">
+    <input type=button style="color: green;" value="Regression (Y1)" onClick="regression(1)" />
+    <br/><br/>
+    <input type=button style="color: blue;" value="Regression (Y2)" onClick="regression(2)" />
+    <br/><br/>
+    <input type=button value="Clear Lines" onClick="clearLines()" />
+    </div>
+</body>
+</html>
index e3636c1..bed74e0 100644 (file)
           var p1 = g.toDomCoords(x1, y1);
           var p2 = g.toDomCoords(x2, y2);
 
-          var color = g.getColors()[i - 1];
+          var c = new RGBColor(g.getColors()[i - 1]);
+          c.r = Math.floor(255 - 0.5 * (255 - c.r));
+          c.g = Math.floor(255 - 0.5 * (255 - c.g));
+          c.b = Math.floor(255 - 0.5 * (255 - c.b));
+          var color = c.toHex();
           ctx.save();
           ctx.strokeStyle = color;
           ctx.lineWidth = 1.0;