Skip to content

Commit c891bdf

Browse files
author
Brett Graham
committed
working, simple and inflexible serving so far
0 parents  commit c891bdf

File tree

9 files changed

+495
-0
lines changed

9 files changed

+495
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.pyc
2+
build/*
3+
dist/*
4+
*.swp

collustro/__init__.py

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env python
2+
3+
import converters
4+
import server
5+
import templates
6+
7+
__all__ = ['converters', 'server', 'templates']
8+
9+
10+
structure_map = {
11+
'tree': converters.heirarchy.convert,
12+
'treemap': converters.heirarchy.convert,
13+
'pack': converters.heirarchy.convert,
14+
'partition': converters.heirarchy.convert,
15+
'cluster': converters.heirarchy.convert,
16+
'heirarchy': converters.heirarchy.convert,
17+
}
18+
19+
20+
def raise_structure_map_error(layout):
21+
raise Exception("Unknown layout: %s" % layout)
22+
23+
24+
def explore(obj, layout, *args, **kwargs):
25+
"""
26+
layout lookup
27+
"""
28+
# load template (from layout)
29+
template_filename = templates.find_template(layout)
30+
31+
# convert object to correct structure (from layout)
32+
data = structure_map.get(layout, raise_structure_map_error)(obj)
33+
34+
# serve it all up
35+
app = server.render_data(template_filename, data)
36+
37+
app.run(*args, **kwargs)

collustro/converters/__init__.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env python
2+
3+
import heirarchy
4+
5+
__all__ = ['heirarchy']

collustro/converters/heirarchy.py

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/usr/bin/env python
2+
3+
# for d3 layouts:
4+
# 1) Tree
5+
# 2) Treemap
6+
# 3) Pack
7+
# 4) Partition
8+
# 5) Cluster
9+
# 6) Heirarchy
10+
11+
import json
12+
13+
import utils
14+
15+
16+
def raise_convert_error(obj):
17+
raise utils.ConvertException(obj, 'heirarchy')
18+
19+
20+
def convert(obj):
21+
"""
22+
Try to convert an object to a json heirarchy object like (from d3):
23+
{
24+
"name": "flare",
25+
"children": [
26+
{
27+
"name": "analytics",
28+
"children": [
29+
{"name": "AgglomerativeCluster", "size": 3938},
30+
{"name": "CommunityStructure", "size": 3812},
31+
{"name": "MergeEdge", "size": 743}
32+
]
33+
},
34+
{
35+
"name": "graph",
36+
"children": [
37+
{"name": "BetweennessCentrality", "size": 3534},
38+
{"name": "LinkDistance", "size": 5731}
39+
]
40+
}
41+
]
42+
}
43+
"""
44+
return {
45+
dict: from_dict,
46+
list: from_list,
47+
}.get(type(obj), raise_convert_error)(obj)
48+
49+
50+
def from_dict(d):
51+
"""
52+
format:
53+
{'main name': {children....}}
54+
55+
where children are of type:
56+
{'name': <value or children>}
57+
"""
58+
children = from_dict_to_children(d)
59+
if len(children) == 1:
60+
return json.dumps(children[0])
61+
else:
62+
# TODO make this a more informative error
63+
raise Exception("Invalid conversion")
64+
65+
66+
def from_dict_to_children(d):
67+
children = []
68+
for k, v in d.iteritems():
69+
if type(v) == dict:
70+
children.append({'name': k, \
71+
'children': from_dict_to_children(v)})
72+
else:
73+
children.append({'name': k, 'size': v})
74+
return children
75+
76+
77+
def from_list(l):
78+
"""
79+
format:
80+
[ [1, [2,3,4], 5] ]
81+
82+
should be a list of lists with the dimension 0 len 1
83+
so that the main_name can be set correctly
84+
"""
85+
if len(l) != 1:
86+
return from_dict(list_to_dict([l]))
87+
else:
88+
return from_dict(list_to_dict(l))
89+
90+
91+
def list_to_dict(l, level=''):
92+
"""
93+
Use a numbered heirarchy
94+
1, 1.1, 1.2, 1.2.1
95+
"""
96+
d = {}
97+
for (i, v) in enumerate(l):
98+
nl = '%s%i' % (level, i)
99+
if type(v) == list:
100+
d[nl] = list_to_dict(v, nl + '.')
101+
else:
102+
d[nl] = v
103+
return d

collustro/converters/utils.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env python
2+
3+
4+
class ConvertException(Exception):
5+
def __init__(self, obj, target):
6+
message = 'Cannot convert %s to %s' % \
7+
(str(obj), str(target))
8+
Exception.__init__(self, message)

collustro/templates/__init__.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env python
2+
3+
import os
4+
5+
6+
def find_template(layout):
7+
template_dir = os.path.join(os.path.dirname(__file__), 'defaults')
8+
template_filename = os.path.join(template_dir, layout + '.html')
9+
if not os.path.exists(template_filename):
10+
raise OSError("Template %s not found in %s" % \
11+
(layout, template_dir))
12+
return template_filename
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="content-type" content="text/html;charset=utf-8">
5+
<title>Tree Layout</title>
6+
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
7+
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.js?2.8.1"></script>
8+
<style type="text/css">
9+
.node circle {
10+
fill: #fff;
11+
stroke: steelblue;
12+
stroke-width: 1.5px;
13+
}
14+
15+
.node {
16+
font: 10px sans-serif;
17+
}
18+
19+
.link {
20+
fill: none;
21+
stroke: #ccc;
22+
stroke-width: 1.5px;
23+
}
24+
</style>
25+
<script type="text/javascript">
26+
</script>
27+
</head>
28+
<body>
29+
<script type="text/javascript">
30+
var data = null;
31+
$.ajaxSetup ({ cache: false });
32+
$(document).ready(function () {
33+
$.getJSON('data', {}, function (received) {
34+
data = received;
35+
render('#graph', data);
36+
});
37+
});
38+
function render(graphid, data) {
39+
var r = 960 / 2;
40+
var tree = d3.layout.tree()
41+
.size([360, r - 120])
42+
.separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
43+
44+
var diagonal = d3.svg.diagonal.radial()
45+
.projection(function(d) { return[d.y, d.x / 180 * Math.PI]; });
46+
47+
var vis = d3.select(graphid).append("svg")
48+
.attr("width", r * 2)
49+
.attr("height", r * 2 - 150)
50+
.append("g")
51+
.attr("transform", "translate(" + r + "," + r + ")");
52+
53+
var nodes = tree.nodes(data);
54+
55+
var link = vis.selectAll("path.link")
56+
.data(tree.links(nodes))
57+
.enter().append("path")
58+
.attr("class", "link")
59+
.attr("d", diagonal);
60+
61+
var node = vis.selectAll("g.node")
62+
.data(nodes)
63+
.enter().append("g")
64+
.attr("class", "node")
65+
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; });
66+
67+
node.append("circle")
68+
.attr("r", 4.5);
69+
70+
node.append("text")
71+
.attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
72+
.attr("dy", ".31em")
73+
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
74+
.attr("transform", function(d) { return d.x < 180 ? null : "rotate(180"; })
75+
.text(function(d) { return d.name; });
76+
};
77+
</script>
78+
<div class='tree' id='graph'>
79+
</div>
80+
</body>
81+
</html>

notes

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Show me data!
2+
3+
in python:
4+
data, stuff, things
5+
6+
take those things, and show them to me in pretty ways
7+
8+
pipeline
9+
10+
mongo <-> python(stuff) <-> flask (to web) <-> javascript <-> d3 <-> d3 layouts
11+
12+
Not all of thes parts are necessary (like mongo)
13+
14+
First usecase
15+
16+
#!/usr/bin/env python
17+
data_dict = {'a': {'b': 10, 'c': 10}, 'd': {'e' : 70, 'f': 5}, 'g': 5}
18+
explore(data_dict, tree)
19+
20+
this will take the data_dictionary, push it to javascript,
21+
convert it to json that fits a heirarchy layout
22+
show it as a tree layout
23+
24+
To do this:
25+
1) convert data dictionary to json object (of a certain structure)
26+
2) serve up a template that requests for the data (ajax)
27+
3) display template and data

0 commit comments

Comments
 (0)