Skip to content

Commit

Permalink
Merge pull request #18 from Pastafarians/parseTreeVisualization
Browse files Browse the repository at this point in the history
Parse tree visualization
  • Loading branch information
Justin Peterson committed Mar 5, 2016
2 parents 7366079 + 296aacd commit 3f72541
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 5 deletions.
204 changes: 203 additions & 1 deletion assets/js/analysis/show.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,213 @@
}
};

$scope.visualize = function () {
$scope.visualizeParseTree = function(sentiment) {

//Move this to a listener when supporting multiple sentences
//#TODO: Make this not a single sentence

var dataToConvert = sentiment? $scope.results[0].sentiment_json :
$scope.results[0].deps_json;
data = convertData(dataToConvert);
renderTree();

//Converts results from flat to heirarchical
function convertData(words) {

var rootNode = { 'id': 0, 'value': 'root', 'pos': 'root' };
words.push(rootNode);

var dataMap = words.reduce(function(map, node) {
map[node.id] = node;
return map;
}, {});

var treeData = [];
words.forEach(function(node) {

var head = dataMap[node.head];

if (head)
(head.children || (head.children = [])).push(node);
else
treeData.push(node);
});

return treeData;
}

//Builds canvas and creates root
function renderTree() {
var tree = d3.layout.tree().nodeSize([100, 50]);

tree.separation(function (a, b) {
var w1 = a.value.length;
var w2 = b.value.length;

var scale = 0.13;

return Math.ceil((w1 * scale) + (w2 * scale) / 2);
});

var svg = d3.select("#graph").append('svg')
.attr('class', 'svg-container')
.style('width', 1500)
.style('height', 1500)
.style('overflow', 'auto');

var canvas = svg.append('g')
.attr('class', 'canvas');

canvas.append('g')
.attr('transform', 'translate(500 , 10) scale(.75)');

var root = data[0];

update(root, tree, svg);

return this;
}

//Draws the tree from the root
function update(source, tree, svg) {

var diagonal = d3.svg.diagonal()
.projection(function (d) {
return [d.x, d.y];
});

var nodes = tree(source).reverse(),
links = tree.links(nodes);

nodes.forEach(function (d) {
d.y = d.depth * 100;
});

var node = svg.select('.canvas g')
.selectAll('g.node')
.data(nodes, function (d, i) {
return d.id || (d.id = ++i);
});

var nodeEnter = node.enter()
.append('g')
.attr('class', 'node')
.attr('transform', function (d) {
return 'translate(' + source.x + ', ' + source.y + ')';
});

nodeEnter.append('circle')
.attr('r', 10)
.style('stroke', '#000')
.style('stroke-width', '3px')
.style('fill', '#FFF');

nodeEnter.append('text')
.attr('y', function (d, i) {
return (d.pos == 'root') ? -30 : 15;
})
.attr('dy', '14px')
.attr('text-anchor', 'middle')
.text(function (d) {
return d.value;
})
.style('fill', function (d, i) {
return (d.pos == 'root') ? '#CCC' : '#333';
})
.style('font-size', '18px')
.style('fill-opacity', 1);
if(sentiment){
nodeEnter.append('text')
.attr('y', function (d, i) {
return (d.pos == 'root') ? 0 : -30;
})
.attr('dy', '12px')
.attr('text-anchor', 'middle')
.attr('class', 'label')
.style('font-size', '12px')
.style('font-weight', 500)
.style('fill', '#666')
.text(function (d) {
return d.tag;
});
}else{
nodeEnter.append('text')
.attr('y', function (d, i) {
return (d.pos == 'root') ? 0 : -30;
})
.attr('dy', '12px')
.attr('text-anchor', 'middle')
.attr('class', 'label')
.style('font-size', '12px')
.style('font-weight', 500)
.style('fill', '#666')
.text(function (d) {
switch(d.tag){
case 0:
return "--";
case 1:
return "-";
case 3:
return "+";
case 4:
return "++";
default:
return "";
};
});
}

var nodeUpdate = node.transition()
.duration(500)
.attr('transform', function (d) {
return 'translate(' + d.x + ', ' + d.y + ')';
});

var link = svg.select('.canvas g')
.selectAll('path.link')
.data(links, function (d) {
return d.target.id;
});

link.enter()
.insert('path', 'g')
.attr('class', 'link')
.style('stroke', '#CCC')
.style('stroke-width', '2px')
.style('fill', 'none')
.attr('d', function (d) {
var o = {
x: source.x,
y: source.y
};

return diagonal({
source: o,
target: o
});
});

link.transition()
.duration(500)
.attr('d', diagonal);

nodes.forEach(function (d, i) {
d.x0 = d.x;
d.y0 = d.y;
});
}
};


$scope.visualize = function(){
if ($scope.analysis.analysis === "tfidf" ) {
$scope.visualizeTfidf();
} else if ($scope.analysis.analysis == "wordcloudop") {
$scope.visualizeWordcloud();
} else if ($scope.analysis.analysis == "nlp-pos"){
$scope.visualizeParseTree(false);
} else if ($scope.analysis.analysis == "nlp-sentiment"){
$scope.visualizeParseTree(true);
}
}

Expand Down
3 changes: 2 additions & 1 deletion assets/js/index.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
frequency: 10
}]

var fill = d3.scale.ordinal().range(["#ff7f0e","aec7e8","#ffbb78","#2ca02c","#ff9896","#9467bd","#17becf","#d62728","#d62728"]);
var fill = d3.scale.ordinal().range(["#ff7f0e","aec7e8","#ffbb78",
"#2ca02c","#ff9896","#9467bd","#17becf","#d62728","#d62728"]);

d3.layout.cloud().size([400, 400])
.words(words)
Expand Down
1 change: 1 addition & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module.exports = function(config) {
'public/bower_components/ng-file-upload/angular-file-upload-html5-shim.min.js',
'public/bower_components/angular/angular.min.js',
'public/bower_components/angular-mocks/angular-mocks.js',
'public/bower_components/d3-cloud/d3.layout.cloud.js',
'public/bower_components/d3/d3.min.js',
'public/bower_components/d3-cloud/build/d3.layout.cloud.js',
'public/bower_components/lodash/dist/lodash.min.js',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "index.js",
"scripts": {
"test": "gulp test",
"start": "./bin/www",
"start": "node ./bin/www",
"ldap": "./fix_ldap.sh"
},
"repository": {
Expand Down
1 change: 0 additions & 1 deletion views/index.jade
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ head
link(rel='stylesheet' href='css/app.css')
link(rel='stylesheet' href='bower_components/font-awesome/css/font-awesome.css')
link(href='bower_components/jsoneditor/dist/jsoneditor.min.css' rel='stylesheet' type='text/css')

script(src='bower_components/angular/angular.min.js')
script(src="bower_components/jsoneditor/dist/jsoneditor.min.js")
script(src='bower_components/d3/d3.min.js')
Expand Down
2 changes: 1 addition & 1 deletion views/templates/analysis/show.jade
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
tabset(justified='true')
tab(heading='Visualization')
#graph
div(ng-if="analysis.analysis !== 'wordcloudop' && analysis.analysis !== 'nlp-sentiment' && analysis.analysis !== 'nlp-pos'")

div(ng-if="analysis.analysis !== 'wordcloudop'")
h3 Hold tight. Visualizations for this analysis will be coming later this year!
img(src="img/soon.png")

Expand Down

0 comments on commit 3f72541

Please sign in to comment.