Mercurial > repos > bornea > plot_edge_bundling
comparison plot_edge_bundling.py @ 1:7dc4b20f5974 draft default tip
Uploaded
author | bornea |
---|---|
date | Wed, 18 Oct 2017 15:32:49 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:9b42fbe3faba | 1:7dc4b20f5974 |
---|---|
1 import sys | |
2 def readTab(infile): # read in txt file | |
3 with open(infile, 'r') as input_file: | |
4 # read in tab-delim text | |
5 output = [] | |
6 for input_line in input_file: | |
7 input_line = input_line.strip() | |
8 temp = input_line.split('\t') | |
9 output.append(temp) | |
10 return output | |
11 def network2JSON(node_attr_file,edge_file): | |
12 nodes = readTab(node_attr_file) | |
13 edges = readTab(edge_file) | |
14 | |
15 connections = {} | |
16 communities = {} | |
17 for i in nodes[1:]: | |
18 communities[i[0]] = i[1] | |
19 for i in nodes[1:]: | |
20 temp = [] | |
21 for j in edges: | |
22 if i[0] in j: | |
23 if i[0] != j[0]: | |
24 temp.append(str(communities[j[0]]) + "." + str(j[0])) | |
25 if i[0] != j[1]: | |
26 temp.append(str(communities[j[1]])+"."+str(j[1])) | |
27 connections[i[0]] = temp | |
28 json = "[" | |
29 for i in nodes[1:]: | |
30 json = json + '{"name":"' + i[1] + '.' + str(i[0]) + '" ,"imports":'+str(connections[i[0]])+'},' | |
31 json = json[:-1] | |
32 json = json + "]" | |
33 json = json.replace("'",'"') | |
34 return json | |
35 ############################################ | |
36 top = """<!DOCTYPE html> | |
37 <meta charset="utf-8"> | |
38 <style> | |
39 | |
40 .node { | |
41 font: 300 11px "Arial", Arial, Arial, Arial; | |
42 fill: #bbb; | |
43 } | |
44 | |
45 .node:hover { | |
46 fill: #d62728; | |
47 } | |
48 | |
49 .link { | |
50 stroke: steelblue; | |
51 stroke-opacity: .4; | |
52 fill: none; | |
53 pointer-events: none; | |
54 } | |
55 | |
56 .node:hover, | |
57 .node--source, | |
58 .node--target { | |
59 font-weight: 700; | |
60 } | |
61 | |
62 .node--source { | |
63 fill: black; | |
64 } | |
65 | |
66 .node--target { | |
67 fill: black; | |
68 } | |
69 | |
70 .link--source, | |
71 .link--target { | |
72 stroke-opacity: 1; | |
73 stroke-width: 2px; | |
74 } | |
75 | |
76 .link--source { | |
77 stroke: #d62728; | |
78 } | |
79 | |
80 .link--target { | |
81 stroke: #d62728; | |
82 } | |
83 | |
84 </style> | |
85 <body> | |
86 <script src="http://d3js.org/d3.v3.min.js"></script> | |
87 <script> | |
88 | |
89 var diameter = 960, | |
90 radius = diameter / 2, | |
91 innerRadius = radius - 120; | |
92 | |
93 var cluster = d3.layout.cluster() | |
94 .size([360, innerRadius]) | |
95 .sort(null) | |
96 .value(function(d) { return d.size; }); | |
97 | |
98 var bundle = d3.layout.bundle(); | |
99 | |
100 var line = d3.svg.line.radial() | |
101 .interpolate("bundle") | |
102 .tension(.85) | |
103 .radius(function(d) { return d.y; }) | |
104 .angle(function(d) { return d.x / 180 * Math.PI; }); | |
105 | |
106 var svg = d3.select("body").append("svg") | |
107 .attr("width", diameter) | |
108 .attr("height", diameter) | |
109 .append("g") | |
110 .attr("transform", "translate(" + radius + "," + radius + ")"); | |
111 | |
112 var link = svg.append("g").selectAll(".link"), | |
113 node = svg.append("g").selectAll(".node");""" | |
114 ############################################ | |
115 | |
116 middle = "\njsondata = '" + network2JSON(sys.argv[1],sys.argv[2]) + "'\n" | |
117 | |
118 ############################################ | |
119 bottom = """var data = JSON.parse(jsondata); | |
120 function bundle_edges(classes){ | |
121 | |
122 var nodes = cluster.nodes(packageHierarchy(classes)), | |
123 links = packageImports(nodes); | |
124 | |
125 link = link | |
126 .data(bundle(links)) | |
127 .enter().append("path") | |
128 .each(function(d) { d.source = d[0], d.target = d[d.length - 1]; }) | |
129 .attr("class", "link") | |
130 .attr("d", line); | |
131 | |
132 node = node | |
133 .data(nodes.filter(function(n) { return !n.children; })) | |
134 .enter().append("text") | |
135 .attr("class", "node") | |
136 .attr("dy", ".31em") | |
137 .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); }) | |
138 .style("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; }) | |
139 .text(function(d) { return d.key; }) | |
140 .on("mouseover", mouseovered) | |
141 .on("mouseout", mouseouted); | |
142 }; | |
143 | |
144 function mouseovered(d) { | |
145 node | |
146 .each(function(n) { n.target = n.source = false; }); | |
147 | |
148 link | |
149 .classed("link--target", function(l) { if (l.target === d) return l.source.source = true; }) | |
150 .classed("link--source", function(l) { if (l.source === d) return l.target.target = true; }) | |
151 .filter(function(l) { return l.target === d || l.source === d; }) | |
152 .each(function() { this.parentNode.appendChild(this); }); | |
153 | |
154 node | |
155 .classed("node--target", function(n) { return n.target; }) | |
156 .classed("node--source", function(n) { return n.source; }); | |
157 } | |
158 | |
159 function mouseouted(d) { | |
160 link | |
161 .classed("link--target", false) | |
162 .classed("link--source", false); | |
163 | |
164 node | |
165 .classed("node--target", false) | |
166 .classed("node--source", false); | |
167 } | |
168 | |
169 d3.select(self.frameElement).style("height", diameter + "px"); | |
170 | |
171 // Lazily construct the package hierarchy from class names. | |
172 function packageHierarchy(classes) { | |
173 var map = {}; | |
174 | |
175 function find(name, data) { | |
176 var node = map[name], i; | |
177 if (!node) { | |
178 node = map[name] = data || {name: name, children: []}; | |
179 if (name.length) { | |
180 node.parent = find(name.substring(0, i = name.lastIndexOf("."))); | |
181 node.parent.children.push(node); | |
182 node.key = name.substring(i + 1); | |
183 } | |
184 } | |
185 return node; | |
186 } | |
187 | |
188 classes.forEach(function(d) { | |
189 find(d.name, d); | |
190 }); | |
191 | |
192 return map[""]; | |
193 } | |
194 | |
195 // Return a list of imports for the given array of nodes. | |
196 function packageImports(nodes) { | |
197 var map = {}, | |
198 imports = []; | |
199 | |
200 // Compute a map from name to node. | |
201 nodes.forEach(function(d) { | |
202 map[d.name] = d; | |
203 }); | |
204 | |
205 // For each import, construct a link from the source to target node. | |
206 nodes.forEach(function(d) { | |
207 if (d.imports) d.imports.forEach(function(i) { | |
208 imports.push({source: map[d.name], target: map[i]}); | |
209 }); | |
210 }); | |
211 | |
212 return imports; | |
213 } | |
214 bundle_edges(data); | |
215 </script>""" | |
216 ############################################ | |
217 with open(sys.argv[3],"w") as x: | |
218 x.write(top + middle + bottom) |