summaryrefslogtreecommitdiff
path: root/code/weightviswrapper.js
blob: 74ae622932509b65e8de50e556be179010181204 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
var WeightVisWrapper = (function() {
    var attributeNames = 
        ["CRIM", "ZN", "INDUS", "CHAS", "NOX", "RM", "AGE", "DIS", "RAD", "TAX", "PTRATIO", "B", "LSTAT"];

    function WeightVisWrapper() {
        this.container = d3.select("body").append("div").remove();
        this.svgContainer = this.container.append("div");
        this.controlContainer = this.container.append("div");
        this.svg = this.svgContainer.append("svg");
        this.netVisualizer = new NetVisualizer(this.svg);
        this.resizeHooks = [];
        this.ready = false;

        this.svgContainer
            .style("margin-top", "1.5em")
            .style("margin-bottom", "1em")
            .style("height", "100%")
            .style("width", "100%");

        this.spinner = this.container.append("div")
            .attr("class", "mdl-spinner mdl-js-spinner mdl-spinner--single-color is-active visContainer")
            .style("position", "absolute")
            .style("left", "50%")
            .style("top", "50%");
        componentHandler.upgradeElement(this.spinner.node());

        this.controlContainer
            .style("margin-left", "auto")
            .style("margin-right", "auto")
            .style("width", "50%");
        this.button = this.controlContainer.append("button")
            .attr("class", "mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored")
            .attr("data-pressed", "false")
            .style("float", "left");
        this.button.append("i")
            .attr("class", "material-icons play")
            .text("play_arrow");
        this.button.append("i")
            .attr("class", "material-icons pause")
            .style("display", "none")
            .text("pause");
        componentHandler.upgradeElement(this.button.node());
        var sliderContainer = this.controlContainer.append("p")
            .style("margin-top", "1.4em");
        this.slider = sliderContainer.append("input")
            .attr("class", "mdl-slider mdl-js-slider visSlider")
            .attr("type", "range")
            .attr("min", "0")
            .attr("max", "1")
            .attr("value", "0")
            .attr("tabindex", "0");
        componentHandler.upgradeElement(this.slider.node());
    }

    WeightVisWrapper.prototype.load = function(url, callback) {
        var self = this;
        this.netVisualizer.load(url, function(){
            var inputNodes = self.svg.selectAll(".layer-1")[0];
            for (node=0; node<inputNodes.length; node++) {
                self.svg
                    .append("text")
                    .attr("class", "attribute")
                    .attr("text-anchor", "middle")
                    .attr("font-weight", "bold")
                    .attr("font-size", attrFontSize + "px")
                    .attr("pointer-events", "none") // disable hovering
                    .attr("cursor", "default")
                    .text(attributeNames[node]);
            }
            self.resizeHooks.push(function() { self.netVisualizer.reposition(); });
            self.resizeHooks.push(function() { self.placeAttributes(); });
            self.netVisualizer.hookStepper(function(step) { self.slider.node().MaterialSlider.change(step); });
            self.netVisualizer.hookStop(function() {
                self.button.attr("data-pressed", "false");
                self.button.select(".play").style("display", "");
                self.button.select(".pause").style("display", "none");
                if (self.slider.node().value >= self.slider.node().max * 0.95) {
                    self.slider.node().MaterialSlider.change(0); // wrap at right end
                }
            });
            self.slider.attr("max", self.netVisualizer.getSteps() - 1);
            self.slider.node().addEventListener("input", function() { self.netVisualizer.showStep(this.value); });
            self.button.node().addEventListener("click", function toggle() {
                if (self.button.attr("data-pressed") != "true") {
                    var step = self.slider.node().value;
                    self.netVisualizer.animate(15, 10, step);
                    self.button.attr("data-pressed", "true");
                    self.button.select(".play").style("display", "none");
                    self.button.select(".pause").style("display", "");
                } else {
                    self.netVisualizer.stopAnimation();
                    self.button.attr("data-pressed", "false");
                    self.button.select(".play").style("display", "");
                    self.button.select(".pause").style("display", "none");
                }
            });
            self.ready = true;
            callback();
            console.log("ready"); // DEBUG
        });
    };

    var attrFontSize = 20;
    WeightVisWrapper.prototype.placeAttributes = function() {
        var inputNodes = this.svg.selectAll(".layer-1")[0];
        var attrs = this.svg.selectAll(".attribute")[0];
        for (node=0; node<inputNodes.length; node++) {
            var iNode = d3.select(inputNodes[node]);
            d3.select(attrs[node])
                .attr("x", iNode.attr("cx"))
                .attr("y", Math.floor(parseInt(iNode.attr("cy")) + attrFontSize / 2));
        }
    };

    WeightVisWrapper.prototype.addPlaceholder = function(el) {
        el.node().parentNode.appendChild(this.spinner.node().cloneNode(true));
        el.remove();
    };

    WeightVisWrapper.prototype.openIn = function(el) {
        el.node().parentNode.appendChild(this.svgContainer.node());
        el.node().parentNode.appendChild(this.controlContainer.node());
        el.remove();
        this.reposition();
    };

    WeightVisWrapper.prototype.remove = function(el) {
        this.svgContainer.node().parentNode.removeChild(this.controlContainer.node());
        this.svgContainer.node().parentNode.appendChild(this.spinner.node().cloneNode(true));
        this.svgContainer.node().parentNode.removeChild(this.svgContainer.node());
        this.container.node().appendChild(this.controlContainer.node());
        this.container.node().appendChild(this.svgContainer.node());
        this.netVisualizer.stopAnimation();
        this.slider.node().MaterialSlider.change(0);
    };

    WeightVisWrapper.prototype.reposition = function() {
        this.svg
            .style("width", this.svgContainer.style("width"))
            .style("height", this.svgContainer.style("height"));
        this.resizeHooks.forEach(function (hook) { hook(); });
        this.netVisualizer.reposition();
    };

    WeightVisWrapper.prototype.animate = function(secs, steps) {
        this.netVisualizer.animate(secs, steps);
        this.button.attr("data-pressed", "true");
        this.button.select(".play").style("display", "none");
        this.button.select(".pause").style("display", "");
    };

    return WeightVisWrapper;
})();