Mercurial > repos > bornea > plot_force_ev
comparison plotForce_EV.py @ 1:bfe4b93b611e draft default tip
Uploaded
| author | bornea |
|---|---|
| date | Wed, 18 Oct 2017 15:35:41 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:98078b04e474 | 1:bfe4b93b611e |
|---|---|
| 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(nodes_att_file, edge_file): | |
| 12 nodes = readTab(nodes_att_file) | |
| 13 edges = readTab(edge_file) | |
| 14 | |
| 15 start = """{"nodes": [""" | |
| 16 node_numbers = {} | |
| 17 cnt=0 | |
| 18 scalar = 100 | |
| 19 if nodes[0][2] == "page": | |
| 20 scalar = 5000 | |
| 21 if nodes[0][2] == "betweenness": | |
| 22 scalar = 0.1 | |
| 23 if nodes[0][2] == "closeness": | |
| 24 scalar = 100 | |
| 25 for i in nodes[1:]: | |
| 26 node_numbers[i[0]] = cnt | |
| 27 cnt+=1 | |
| 28 start = start + '{"id":'+'"'+i[0]+'", "size":'+str(float(i[2])*scalar)+', "score":'+i[1]+',"type":"circle"},' | |
| 29 start = start[:-1] | |
| 30 start = start+"""], "links": [""" | |
| 31 for i in edges: | |
| 32 start = start + """{"source":"""+str(node_numbers[i[0]])+""","target":"""+str(node_numbers[i[1]])+"""},""" | |
| 33 start = start[:-1] | |
| 34 start = start + """]}""" | |
| 35 return start | |
| 36 | |
| 37 | |
| 38 output = """<!DOCTYPE html> | |
| 39 <meta charset="utf-8"> | |
| 40 <style> | |
| 41 body { | |
| 42 overflow:hidden; | |
| 43 margin:0; | |
| 44 } | |
| 45 | |
| 46 text { | |
| 47 font-family: sans-serif; | |
| 48 pointer-events: none; | |
| 49 } | |
| 50 | |
| 51 </style> | |
| 52 <body> | |
| 53 <script src="http://d3js.org/d3.v3.min.js"></script> | |
| 54 <script> | |
| 55 jsondata='""" | |
| 56 | |
| 57 output = output + network2JSON(sys.argv[1],sys.argv[2]) + "'\n" | |
| 58 | |
| 59 output = output + """var w = window.innerWidth; | |
| 60 var h = window.innerHeight; | |
| 61 | |
| 62 var keyc = true, keys = true, keyt = true, keyr = true, keyx = true, keyd = true, keyl = true, keym = true, keyh = true, key1 = true, key2 = true, key3 = true, key0 = true | |
| 63 | |
| 64 var focus_node = null, highlight_node = null; | |
| 65 | |
| 66 var text_center = false; | |
| 67 var outline = false; | |
| 68 | |
| 69 var min_score = 0; | |
| 70 var max_score = 1; | |
| 71 | |
| 72 var color = d3.scale.category20() | |
| 73 .range(["green", "orange", "red","black","steelblue","purple","gray","blue","yellow","lime"]); | |
| 74 | |
| 75 var highlight_color = "red"; | |
| 76 var highlight_trans = 0.1; | |
| 77 | |
| 78 var size = d3.scale.pow().exponent(1) | |
| 79 .domain([1,100]) | |
| 80 .range([8,24]); | |
| 81 | |
| 82 var force = d3.layout.force() | |
| 83 .linkDistance(60) | |
| 84 .charge(-700) | |
| 85 .size([w,h]); | |
| 86 | |
| 87 var default_node_color = "#000"; | |
| 88 //var default_node_color = "rgb(3,190,100)"; | |
| 89 var default_link_color = "#888"; | |
| 90 var nominal_base_node_size = 8; | |
| 91 var nominal_text_size = 10; | |
| 92 var max_text_size = 24; | |
| 93 var nominal_stroke = 1.5; | |
| 94 var max_stroke = 4.5; | |
| 95 var max_base_node_size = 36; | |
| 96 var min_zoom = 0.1; | |
| 97 var max_zoom = 7; | |
| 98 var svg = d3.select("body").append("svg"); | |
| 99 var zoom = d3.behavior.zoom().scaleExtent([min_zoom,max_zoom]) | |
| 100 var g = svg.append("g"); | |
| 101 svg.style("cursor","move"); | |
| 102 | |
| 103 var data = JSON.parse(jsondata); | |
| 104 function plot_graph(graph) { | |
| 105 | |
| 106 var linkedByIndex = {}; | |
| 107 graph.links.forEach(function(d) { | |
| 108 linkedByIndex[d.source + "," + d.target] = true; | |
| 109 }); | |
| 110 | |
| 111 function isConnected(a, b) { | |
| 112 return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index] || a.index == b.index; | |
| 113 } | |
| 114 | |
| 115 function hasConnections(a) { | |
| 116 for (var property in linkedByIndex) { | |
| 117 s = property.split(","); | |
| 118 if ((s[0] == a.index || s[1] == a.index) && linkedByIndex[property]) return true; | |
| 119 } | |
| 120 return false; | |
| 121 } | |
| 122 | |
| 123 force | |
| 124 .nodes(graph.nodes) | |
| 125 .links(graph.links) | |
| 126 .start(); | |
| 127 | |
| 128 var link = g.selectAll(".link") | |
| 129 .data(graph.links) | |
| 130 .enter().append("line") | |
| 131 .attr("class", "link") | |
| 132 .style("stroke-width",nominal_stroke) | |
| 133 .style("stroke", function(d) { | |
| 134 if (isNumber(d.score) && d.score>=0) return color(d.score); | |
| 135 else return default_link_color; }) | |
| 136 | |
| 137 | |
| 138 var node = g.selectAll(".node") | |
| 139 .data(graph.nodes) | |
| 140 .enter().append("g") | |
| 141 .attr("class", "node") | |
| 142 | |
| 143 .call(force.drag) | |
| 144 | |
| 145 | |
| 146 node.on("dblclick.zoom", function(d) { d3.event.stopPropagation(); | |
| 147 var dcx = (window.innerWidth/2-d.x*zoom.scale()); | |
| 148 var dcy = (window.innerHeight/2-d.y*zoom.scale()); | |
| 149 zoom.translate([dcx,dcy]); | |
| 150 g.attr("transform", "translate("+ dcx + "," + dcy + ")scale(" + zoom.scale() + ")"); | |
| 151 | |
| 152 | |
| 153 }); | |
| 154 | |
| 155 | |
| 156 | |
| 157 | |
| 158 var tocolor = "fill"; | |
| 159 var towhite = "stroke"; | |
| 160 if (outline) { | |
| 161 tocolor = "stroke" | |
| 162 towhite = "fill" | |
| 163 } | |
| 164 | |
| 165 | |
| 166 | |
| 167 var circle = node.append("path") | |
| 168 | |
| 169 | |
| 170 .attr("d", d3.svg.symbol() | |
| 171 .size(function(d) { return Math.PI*Math.pow(size(d.size)||nominal_base_node_size,2); }) | |
| 172 .type(function(d) { return d.type; })) | |
| 173 | |
| 174 .style(tocolor, function(d) { | |
| 175 if (isNumber(d.score) && d.score>=0) return color(d.score); | |
| 176 else return default_node_color; }) | |
| 177 //.attr("r", function(d) { return size(d.size)||nominal_base_node_size; }) | |
| 178 .style("stroke-width", nominal_stroke) | |
| 179 .style(towhite, "white"); | |
| 180 | |
| 181 | |
| 182 var text = g.selectAll(".text") | |
| 183 .data(graph.nodes) | |
| 184 .enter().append("text") | |
| 185 .attr("dy", ".35em") | |
| 186 .style("font-size", nominal_text_size + "px") | |
| 187 | |
| 188 if (text_center) | |
| 189 text.text(function(d) { return d.id; }) | |
| 190 .style("text-anchor", "middle"); | |
| 191 else | |
| 192 text.attr("dx", function(d) {return (size(d.size)||nominal_base_node_size);}) | |
| 193 .text(function(d) { return '\u2002'+d.id; }); | |
| 194 | |
| 195 node.on("mouseover", function(d) { | |
| 196 set_highlight(d); | |
| 197 }) | |
| 198 .on("mousedown", function(d) { d3.event.stopPropagation(); | |
| 199 focus_node = d; | |
| 200 set_focus(d) | |
| 201 if (highlight_node === null) set_highlight(d) | |
| 202 | |
| 203 } ).on("mouseout", function(d) { | |
| 204 exit_highlight(); | |
| 205 | |
| 206 } ); | |
| 207 | |
| 208 d3.select(window).on("mouseup", | |
| 209 function() { | |
| 210 if (focus_node!==null) | |
| 211 { | |
| 212 focus_node = null; | |
| 213 if (highlight_trans<1) | |
| 214 { | |
| 215 | |
| 216 circle.style("opacity", 1); | |
| 217 text.style("opacity", 1); | |
| 218 link.style("opacity", 1); | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 if (highlight_node === null) exit_highlight(); | |
| 223 }); | |
| 224 | |
| 225 function exit_highlight() | |
| 226 { | |
| 227 highlight_node = null; | |
| 228 if (focus_node===null) | |
| 229 { | |
| 230 svg.style("cursor","move"); | |
| 231 if (highlight_color!="white") | |
| 232 { | |
| 233 circle.style(towhite, "white"); | |
| 234 text.style("font-weight", "normal"); | |
| 235 link.style("stroke", function(o) {return (isNumber(o.score) && o.score>=0)?color(o.score):default_link_color}); | |
| 236 } | |
| 237 | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 function set_focus(d) | |
| 242 { | |
| 243 if (highlight_trans<1) { | |
| 244 circle.style("opacity", function(o) { | |
| 245 return isConnected(d, o) ? 1 : highlight_trans; | |
| 246 }); | |
| 247 | |
| 248 text.style("opacity", function(o) { | |
| 249 return isConnected(d, o) ? 1 : highlight_trans; | |
| 250 }); | |
| 251 | |
| 252 link.style("opacity", function(o) { | |
| 253 return o.source.index == d.index || o.target.index == d.index ? 1 : highlight_trans; | |
| 254 }); | |
| 255 } | |
| 256 } | |
| 257 | |
| 258 | |
| 259 function set_highlight(d) | |
| 260 { | |
| 261 svg.style("cursor","pointer"); | |
| 262 if (focus_node!==null) d = focus_node; | |
| 263 highlight_node = d; | |
| 264 | |
| 265 if (highlight_color!="white") | |
| 266 { | |
| 267 circle.style(towhite, function(o) { | |
| 268 return isConnected(d, o) ? highlight_color : "white";}); | |
| 269 text.style("font-weight", function(o) { | |
| 270 return isConnected(d, o) ? "bold" : "normal";}); | |
| 271 link.style("stroke", function(o) { | |
| 272 return o.source.index == d.index || o.target.index == d.index ? highlight_color : ((isNumber(o.score) && o.score>=0)?color(o.score):default_link_color); | |
| 273 | |
| 274 }); | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 | |
| 279 zoom.on("zoom", function() { | |
| 280 | |
| 281 var stroke = nominal_stroke; | |
| 282 if (nominal_stroke*zoom.scale()>max_stroke) stroke = max_stroke/zoom.scale(); | |
| 283 link.style("stroke-width",stroke); | |
| 284 circle.style("stroke-width",stroke); | |
| 285 | |
| 286 var base_radius = nominal_base_node_size; | |
| 287 if (nominal_base_node_size*zoom.scale()>max_base_node_size) base_radius = max_base_node_size/zoom.scale(); | |
| 288 circle.attr("d", d3.svg.symbol() | |
| 289 .size(function(d) { return Math.PI*Math.pow(size(d.size)*base_radius/nominal_base_node_size||base_radius,2); }) | |
| 290 .type(function(d) { return d.type; })) | |
| 291 | |
| 292 //circle.attr("r", function(d) { return (size(d.size)*base_radius/nominal_base_node_size||base_radius); }) | |
| 293 if (!text_center) text.attr("dx", function(d) { return (size(d.size)*base_radius/nominal_base_node_size||base_radius); }); | |
| 294 | |
| 295 var text_size = nominal_text_size; | |
| 296 if (nominal_text_size*zoom.scale()>max_text_size) text_size = max_text_size/zoom.scale(); | |
| 297 text.style("font-size",text_size + "px"); | |
| 298 | |
| 299 g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); | |
| 300 }); | |
| 301 | |
| 302 svg.call(zoom); | |
| 303 | |
| 304 resize(); | |
| 305 //window.focus(); | |
| 306 d3.select(window).on("resize", resize).on("keydown", keydown); | |
| 307 | |
| 308 force.on("tick", function() { | |
| 309 | |
| 310 node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); | |
| 311 text.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); | |
| 312 | |
| 313 link.attr("x1", function(d) { return d.source.x; }) | |
| 314 .attr("y1", function(d) { return d.source.y; }) | |
| 315 .attr("x2", function(d) { return d.target.x; }) | |
| 316 .attr("y2", function(d) { return d.target.y; }); | |
| 317 | |
| 318 node.attr("cx", function(d) { return d.x; }) | |
| 319 .attr("cy", function(d) { return d.y; }); | |
| 320 }); | |
| 321 | |
| 322 function resize() { | |
| 323 var width = window.innerWidth, height = window.innerHeight; | |
| 324 svg.attr("width", width).attr("height", height); | |
| 325 | |
| 326 force.size([force.size()[0]+(width-w)/zoom.scale(),force.size()[1]+(height-h)/zoom.scale()]).resume(); | |
| 327 w = width; | |
| 328 h = height; | |
| 329 } | |
| 330 | |
| 331 function keydown() { | |
| 332 if (d3.event.keyCode==32) { force.stop();} | |
| 333 else if (d3.event.keyCode>=48 && d3.event.keyCode<=90 && !d3.event.ctrlKey && !d3.event.altKey && !d3.event.metaKey) | |
| 334 { | |
| 335 switch (String.fromCharCode(d3.event.keyCode)) { | |
| 336 case "C": keyc = !keyc; break; | |
| 337 case "S": keys = !keys; break; | |
| 338 case "T": keyt = !keyt; break; | |
| 339 case "R": keyr = !keyr; break; | |
| 340 case "X": keyx = !keyx; break; | |
| 341 case "D": keyd = !keyd; break; | |
| 342 case "L": keyl = !keyl; break; | |
| 343 case "M": keym = !keym; break; | |
| 344 case "H": keyh = !keyh; break; | |
| 345 case "1": key1 = !key1; break; | |
| 346 case "2": key2 = !key2; break; | |
| 347 case "3": key3 = !key3; break; | |
| 348 case "0": key0 = !key0; break; | |
| 349 } | |
| 350 | |
| 351 link.style("display", function(d) { | |
| 352 var flag = vis_by_type(d.source.type)&&vis_by_type(d.target.type)&&vis_by_node_score(d.source.score)&&vis_by_node_score(d.target.score)&&vis_by_link_score(d.score); | |
| 353 linkedByIndex[d.source.index + "," + d.target.index] = flag; | |
| 354 return flag?"inline":"none";}); | |
| 355 node.style("display", function(d) { | |
| 356 return (key0||hasConnections(d))&&vis_by_type(d.type)&&vis_by_node_score(d.score)?"inline":"none";}); | |
| 357 text.style("display", function(d) { | |
| 358 return (key0||hasConnections(d))&&vis_by_type(d.type)&&vis_by_node_score(d.score)?"inline":"none";}); | |
| 359 | |
| 360 if (highlight_node !== null) | |
| 361 { | |
| 362 if ((key0||hasConnections(highlight_node))&&vis_by_type(highlight_node.type)&&vis_by_node_score(highlight_node.score)) { | |
| 363 if (focus_node!==null) set_focus(focus_node); | |
| 364 set_highlight(highlight_node); | |
| 365 } | |
| 366 else {exit_highlight();} | |
| 367 } | |
| 368 | |
| 369 } | |
| 370 } | |
| 371 | |
| 372 }; | |
| 373 | |
| 374 function vis_by_type(type) | |
| 375 { | |
| 376 switch (type) { | |
| 377 case "circle": return keyc; | |
| 378 case "circle": return keys; | |
| 379 case "triangle-up": return keyt; | |
| 380 case "diamond": return keyr; | |
| 381 case "cross": return keyx; | |
| 382 case "triangle-down": return keyd; | |
| 383 default: return true; | |
| 384 } | |
| 385 } | |
| 386 function vis_by_node_score(score) | |
| 387 { | |
| 388 if (isNumber(score)) | |
| 389 { | |
| 390 if (score>=0.666) return keyh; | |
| 391 else if (score>=0.333) return keym; | |
| 392 else if (score>=0) return keyl; | |
| 393 } | |
| 394 return true; | |
| 395 } | |
| 396 | |
| 397 function vis_by_link_score(score) | |
| 398 { | |
| 399 if (isNumber(score)) | |
| 400 { | |
| 401 if (score>=0.666) return key3; | |
| 402 else if (score>=0.333) return key2; | |
| 403 else if (score>=0) return key1; | |
| 404 } | |
| 405 return true; | |
| 406 } | |
| 407 | |
| 408 function isNumber(n) { | |
| 409 return !isNaN(parseFloat(n)) && isFinite(n); | |
| 410 } | |
| 411 plot_graph(data) | |
| 412 | |
| 413 </script>""" | |
| 414 | |
| 415 with open(sys.argv[3],"w") as x: | |
| 416 x.write(output) |
