Commit 1f55758f authored by Anze Vavpetic's avatar Anze Vavpetic

initial hierarchical clustering widget.

parent 2d31935f
from django.shortcuts import render
import json
def cforange_filter_integers(request,input_dict,output_dict,widget):
return render(request, 'interactions/cforange_filter_integers.html',{'widget':widget,'intList':input_dict['intList']})
\ No newline at end of file
return render(request, 'interactions/cforange_filter_integers.html',{'widget':widget,'intList':input_dict['intList']})
def cforange_hierarchical_clustering(request,input_dict,output_dict,widget):
import orange
matrix = input_dict['dm']
root = orange.HierarchicalClustering(matrix, linkage=orange.HierarchicalClustering.Average)
def build_hierarchy(node, root=False):
return {
'name' : 'root' if root else '',
'height' : node.height if node.branches else 0,
'children' : [build_hierarchy(node.left), build_hierarchy(node.right)] if node.branches else []
}
hierarchy = json.dumps(build_hierarchy(root, root=True))
return render(request, 'interactions/cforange_hierarchical_clustering.html', {'widget' : widget, 'hierarchy' : hierarchy})
\ No newline at end of file
......@@ -380,4 +380,10 @@ def cforange_attribute_distance(input_dict):
matrix[a1, a2] = (1.0 - statc.spearmanr(f1, filleds[a2])[0]) / 2.0
output_dict = {}
output_dict['dm']=matrix
return output_dict
\ No newline at end of file
return output_dict
def cforange_hierarchical_clustering(input_dict):
return {'centroids' : None, 'selected_examples' : None, 'unselected_examples' : None}
def cforange_hierarchical_clustering_finished(input_dict):
return {'centroids' : None, 'selected_examples' : None, 'unselected_examples' : None}
<div id="widgetinteract-{{widget.pk}}" rel="{{widget.pk}}" class="widgetinteractdialog" title="{{widget.name}} interaction" width="1280" height="800">
<div>
<div id="clustering_canvas{{widget.pk}}"></div>
<form>
<input type="hidden" name="widget_id" value="{{widget.pk}}"/>
</form>
</div>
</div>
<style type="text/css">
path.arc {
cursor: move;
fill: #fff;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node {
font-size: 10px;
pointer-events: none;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
</style>
<script type="text/javascript">
var hierarchy = {{hierarchy|safe}};
draw(1280, 800, hierarchy, "#clustering_canvas{{widget.pk}}");
function draw(w, h, hierarchy, target) {
var rx = w/2,
ry = h/2,
m0,
rotate = 0,
delta = 30;
var root = [rx, ry];
var width = ry - delta;
var cluster = d3.layout.cluster()
.size([360, ry - delta])
.sort(null);
var diagonal = d3.svg.diagonal.radial()
.projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
var svg = d3.select(target).append("div")
.style("width", w + "px")
.style("height", w + "px")
.on("click", select_clusters);
var vis = svg.append("svg:svg")
.attr("width", w)
.attr("height", w)
.append("svg:g")
.attr("transform", "translate(" + rx + "," + ry + ")");
vis.append("svg:path")
.attr("class", "arc")
.attr("d", d3.svg.arc().innerRadius(ry - delta).outerRadius(ry).startAngle(0).endAngle(2 * Math.PI))
.on("mousedown", mousedown);
var nodes = cluster.nodes(hierarchy);
var max_height = 0;
for (node in nodes) {
if (nodes[node].height>max_height) {
max_height=nodes[node].height;
}
}
for (node in nodes) {
nodes[node].y = width-(nodes[node].height/max_height) * width;
}
var link = vis.selectAll("path.link")
.data(cluster.links(nodes))
.enter().append("svg:path")
.attr("class", "link")
.attr("d", diagonal);
var node = vis.selectAll("g.node")
.data(nodes)
.enter().append("svg:g")
.attr("class", "node")
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; });
node.append("svg:circle")
.attr("r", 3);
node.append("svg:text")
.attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
.attr("dy", ".31em")
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
.attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
.text(function(d) { return d.name; });
d3.select(window)
.on("mousemove", mousemove)
.on("mouseup", mouseup);
var threshold_arc = null;
var root_node = nodes[0];
function select_clusters() {
var click_pos = d3.mouse(this);
var r = Math.min(distance(click_pos, root), ry-delta);
if (threshold_arc) {
threshold_arc.remove();
}
threshold_arc = vis.append("svg:path")
.attr("class", "arc")
.attr("d", d3.svg.arc().innerRadius(r).outerRadius(r+1).startAngle(0).endAngle(2 * Math.PI));
node.selectAll("circle")
.style('fill', function(d) {
if (distance([d.x, d.y], [root_node.x, root_node.y]) > r) {
return 'blue';
} else {
return 'white';
}
});
}
function mouse(e) {
return [e.pageX - rx, e.pageY - ry];
}
function mousedown() {
m0 = mouse(d3.event);
d3.event.preventDefault();
}
function mousemove() {
if (m0) {
var m1 = mouse(d3.event),
dm = Math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / Math.PI,
tx = "translate3d(0," + (ry - rx) + "px,0)rotate3d(0,0,0," + dm + "deg)translate3d(0," + (rx - ry) + "px,0)";
svg
.style("-moz-transform", tx)
.style("-ms-transform", tx)
.style("-webkit-transform", tx);
}
}
function mouseup() {
if (m0) {
var m1 = mouse(d3.event),
dm = Math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / Math.PI,
tx = "rotate3d(0,0,0,0deg)";
rotate += dm;
if (rotate > 360) rotate -= 360;
else if (rotate < 0) rotate += 360;
m0 = null;
svg
.style("-moz-transform", tx)
.style("-ms-transform", tx)
.style("-webkit-transform", tx);
vis
.attr("transform", "translate(" + rx + "," + ry + ")rotate(" + rotate + ")")
.selectAll("g.node text")
.attr("dx", function(d) { return (d.x + rotate) % 360 < 180 ? 8 : -8; })
.attr("text-anchor", function(d) { return (d.x + rotate) % 360 < 180 ? "start" : "end"; })
.attr("transform", function(d) { return (d.x + rotate) % 360 < 180 ? null : "rotate(180)"; });
}
}
function cross(a, b) {
return a[0] * b[1] - a[1] * b[0];
}
function dot(a, b) {
return a[0] * b[0] + a[1] * b[1];
}
function distance(a, b) {
return Math.sqrt((a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]));
}
}
</script>
\ No newline at end of file
......@@ -37,6 +37,9 @@
<script type="text/javascript" src="{{ STATIC_URL }}js/new-script.js"></script>
<script src="{{STATIC_URL}}js/highcharts-2.2.5-tooltip-id.js"></script>
<script src="{{STATIC_URL}}js/highcharts-exporting.js"></script>
<script src="{{STATIC_URL}}js/d3/d3.v3.min.js"></script>
<!-- <script src="{{STATIC_URL}}js/d3/d3.js"></script>
<script src="{{STATIC_URL}}js/d3/d3.layout.js"></script> -->
<script type="text/javascript">
{% load url from future %}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment