diff options
| -rw-r--r-- | .gitmodules | 6 | ||||
| -rw-r--r-- | code/weightvis.js (renamed from index.js) | 188 | ||||
| m--------- | d3 | 0 | ||||
| -rw-r--r-- | dep/d3.js (renamed from d3.js) | 0 | ||||
| -rw-r--r-- | index.html | 23 |
5 files changed, 112 insertions, 105 deletions
diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index bc54fcc..0000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "brain"] - path = brain - url = https://github.com/harthur/brain -[submodule "d3"] - path = d3 - url = https://github.com/mbostock/d3 diff --git a/index.js b/code/weightvis.js index e58ddd7..7b4b5ef 100644 --- a/index.js +++ b/code/weightvis.js @@ -1,55 +1,28 @@ -/* custom d3 widgets */ +// material colors +var + // 50 100 200 300 400 500 + pDeepPurple = ['#ede7f6', '#d1c4e9', '#b39ddb', '#9575cd', '#7e57c2', '#673ab7', + // 600 700 800 900 + '#5e35b1', '#512da8', '#4527a0', '#311b92', + // A100 A200 A400 A700 + '#b388ff', '#7c4dff', '#651fff', '#6200ea'], + // A100 A200 A400 A700 + pGreen = ['#b9f6ca', '#69f0ae', '#00e676', '#00c853'], + pDark = ['#000000', '#212121', '#303030', '#424242'], + pLight = ['#E0E0E0', '#F5F5F5', '#FAFAFA', '#FFFFFF'], -// slider -function makeSlider(labelName, x, y, scale, cb) { - var brush = d3.svg.brush() - .x(scale) - .extent([0, 0]) - .on("brush", brushed); + primaryColor = [pDeepPurple[1], pDeepPurple[5], pDeepPurple[7]], + secondaryColor = pGreen[3], + themeColor = pLight, - var label = svg.append("text") - .attr("x", x-5) - .attr("y", y) - .text(labelName); + accentColor = secondaryColor, + bgColor = themeColor[3], - var brushg = svg.append("g") - .attr("transform", "translate(" + x + "," + (y+10) + ")"); - - brushg.append("g") - .attr("class", "x axis") - .call(d3.svg.axis() - .scale(scale) - .ticks(5) - .tickSize(1) - .tickFormat(function(d) { return Math.floor(d*100) + "%"; }) - .tickPadding(10) - .orient("bottom")); - - var slider = brushg.append("g") - .attr("class", "slider") - .call(brush); - - var handle = slider.append("circle") - .attr("r", 5) - .attr("cx", 0) - .attr("cy", 0) - .attr("stroke", "#000") - .attr("fill", "#DDD"); - - slider.call(brush); - - function brushed() { - var value = brush.extent()[0]; - - if (d3.event.sourceEvent) { // not a programmatic event - value = scale.invert(d3.mouse(this)[0]); - brush.extent([value, value]); - } - - handle.attr("cx", scale(value)); - cb(value); - } -} + linkColor = primaryColor[0], + linkHighlightColor = primaryColor[1], + nodeColor = primaryColor[1], + nodeHighlightColor = accentColor +; /* network construction */ @@ -224,21 +197,21 @@ var Loader = (function() { } } } - console.log(layout); // DEBUG - if (this._finished) this._finished(layout, json); }; return Loader; })(); + +/* animation stepping */ + var Animator = (function() { function Animator(layout, time, step) { this.layout = layout; this.step = step; this.batch = this.epoch = 0; this.frameDuration = time / (this.layout.data.batches * this.layout.data.epochs / this.step); - console.log("frame duration:" + this.frameDuration); // DEBUG } Animator.prototype.start = function(callback) { @@ -265,51 +238,71 @@ var Animator = (function() { return Animator; })(); + +/* main */ + var Visualizer = (function() { + var _weightScaler = 10; // size of thickest line + function Visualizer(svg) { this.loader = new Loader(); this.svg = svg; } - Visualizer.prototype.start = function(url, animationTime, resolution) { - // animationTime in seconds per frame - // resolution in epochs per frame + Visualizer.prototype.getSteps = function() { + return this.layout.data.batches * this.layout.data.epochs; + }; + + Visualizer.prototype.load = function(url, callback) { var self = this; - this.animationTime = animationTime; - this.resolution = resolution; function wrapper(layout, data) { self.layout = layout; self.data = data; self._setup(); + callback(); } this.loader.load("data/log.json", wrapper); }; + Visualizer.prototype.animate = function(animationTime, resolution) { + // animationTime in seconds per frame + // resolution in epochs per frame + var self = this; + this.domLink = this.svg.selectAll(".link"); + + this.animator = new Animator(this.layout, animationTime * 1000, resolution); + this.animator.start(function(batch, epoch){self.show(batch, epoch);}); + }; + + Visualizer.prototype.showStep = function(step) { + var epoch = step % this.layout.data.epochs, + batch = Math.floor(step / this.layout.data.epochs); + this.show(batch, epoch); + }; + + Visualizer.prototype.show = function(batch, epoch, transitionDuration) { + this.network.updateWeights(this.data[batch][epoch], this.layout.layers[batch][epoch]); + if (transitionDuration) { + // 10% extra time per frame for the code execution + this.domLink + .transition() + .duration(transitionDuration / 1.1); + } + this.domLink.style("stroke-width", function(d) { return d.weight * _weightScaler; }); + }; + Visualizer.prototype._setup = function() { - console.log("setup"); // DEBUG var self = this; // create empty elements and determine the visualisation's size - this.svg - .attr("width", "100%") - .attr("height", "100%"); var width = parseInt(this.svg.style("width")) || 800, height = parseInt(this.svg.style("height")) || 600; - /*var slideScaler = d3.scale.linear() - .domain([0, 180]) - .range([0, 200]) - .clamp(true); - function slid(val) { - console.log(val); - } - makeSlider("Test", 10, 20, slideScaler, slid);*/ - this.network = new Network(this.layout); this.network.init(); this.network.resize({"width": width, "height": height}); this.network.updateWeights(this.data[0][0], this.layout.layers[0][0]); - function resized() { + function reposition() { width = parseInt(self.svg.style("width")) || 800; height = parseInt(self.svg.style("height")) || 600; @@ -325,42 +318,43 @@ var Visualizer = (function() { .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); } - window.addEventListener("resize", resized, true); + window.addEventListener("resize", reposition, true); var link = this.svg.selectAll(".link") .data(this.network.links) .enter().append("line") - .attr("class", "link") - .style("stroke", "grey") - .style("stroke-width", function(d) { return d.weight * 10; }) - .attr("x1", function(d) { return d.source.x; }) - .attr("y1", function(d) { return d.source.y; }) - .attr("x2", function(d) { return d.target.x; }) - .attr("y2", function(d) { return d.target.y; }); + .attr("class", function(d) { return "link source-" + d.source.id + " target-" + d.target.id; }) + .style("stroke", linkColor) + .style("stroke-width", function(d) { return d.weight * _weightScaler; }) + .on("mouseover", function(d) { + d3.select("#node-" + d.source.id).style("fill", nodeHighlightColor); + d3.select("#node-" + d.target.id).style("fill", nodeHighlightColor); + d3.select(this).style("stroke", linkHighlightColor); + }) + .on("mouseout", function(d) { + d3.select("#node-" + d.source.id).style("fill", nodeColor); + d3.select("#node-" + d.target.id).style("fill", nodeColor); + d3.select(this).style("stroke", linkColor); + }); var node = this.svg.selectAll(".node") .data(this.network.nodes) .enter().append("circle") .attr("class", "node") - .attr("cx", function(d) { return d.x; }) - .attr("cy", function(d) { return d.y; }) - .attr("r", function(d) { return d.r; }); - - this.animator = new Animator(this.layout, this.animationTime * 1000, this.resolution); - this.animator.start(function(batch, epoch, duration) { - self.network.updateWeights(self.data[batch][epoch], self.layout.layers[batch][epoch]); + .attr("id", function(d) { return "node-" + d.id; }) + .style("fill", nodeColor) + .on("mouseover", function(d) { + d3.selectAll(".source-" + d.id).style("stroke", linkHighlightColor); + d3.selectAll(".target-" + d.id).style("stroke", linkHighlightColor); + d3.select(this).style("fill", nodeHighlightColor); + }) + .on("mouseout", function(d) { + d3.selectAll(".source-" + d.id).style("stroke", linkColor); + d3.selectAll(".target-" + d.id).style("stroke", linkColor); + d3.select(this).style("fill", nodeColor); + }); - // 10% extra time per frame for the code execution - duration = duration / 1.1; - link - .transition() - .duration(duration) - .style("stroke-width", function(d) { return d.weight * 10; }); - }); + reposition(); }; return Visualizer; })(); - -var svg = d3.select("#visContainer").append("svg"); -var visualizer = new Visualizer(svg); -visualizer.start("data/log.json", 30, 10); diff --git a/d3 b/d3 deleted file mode 160000 -Subproject c36befc7361cd61538294048c387a8a407b65dd @@ -4,10 +4,29 @@ <meta charset="UTF-8"> <title></title> <link rel="stylesheet" href="index.css"> + <link rel="stylesheet" href="dep/material-icons.css"> + <link rel="stylesheet" href="dep/material.deep_purple-blue.min.css"> </head> <body> + <script src="dep/d3.js" type="text/javascript"></script> + <script src="dep/material.min.js"></script> + + <script src="code/weightvis.js" type="text/javascript"></script> + <div id="visContainer" /> - <script src="d3.js" type="text/javascript"></script> - <script src="index.js" type="text/javascript"></script> + <script type="text/javascript"> + var svg = d3.select("#visContainer").append("svg"); + svg + .attr("width", "100%") + .attr("height", "100%"); + svg.append("rect") + .attr("width", "100%") + .attr("height", "100%") + .attr("fill", bgColor); + var visualizer = new Visualizer(svg); + visualizer.load("data/log.json", function(){ + visualizer.animate(10, 20); + }); + </script> </body> </html> |
