Mercurial > repos > bornea > plot_force
changeset 0:4324d3f925fe draft
Uploaded
author | bornea |
---|---|
date | Wed, 18 Oct 2017 15:34:12 -0400 |
parents | |
children | 70c42d02d54e |
files | plotForce.py |
diffstat | 1 files changed, 409 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plotForce.py Wed Oct 18 15:34:12 2017 -0400 @@ -0,0 +1,409 @@ +import sys +def readTab(infile): # read in txt file + with open(infile, 'r') as input_file: + # read in tab-delim text + output = [] + for input_line in input_file: + input_line = input_line.strip() + temp = input_line.split('\t') + output.append(temp) + return output +def network2JSON(nodes_att_file, edge_file): + nodes = readTab(nodes_att_file) + edges = readTab(edge_file) + + start = """{"nodes": [""" + node_numbers = {} + cnt=0 + for i in nodes[1:]: + node_numbers[i[0]] = cnt + cnt+=1 + start = start + '{"id":'+'"'+i[0]+'", "size":'+str(float(i[2])*1)+', "score":'+i[1]+',"type":"circle"},' + start = start[:-1] + start = start+"""], "links": [""" + for i in edges: + start = start + """{"source":"""+str(node_numbers[i[0]])+""","target":"""+str(node_numbers[i[1]])+"""},""" + start = start[:-1] + start = start + """]}""" + return start + + +output = """<!DOCTYPE html> +<meta charset="utf-8"> +<style> +body { + overflow:hidden; + margin:0; +} + +text { + font-family: sans-serif; + pointer-events: none; +} + +</style> +<body> +<script src="http://d3js.org/d3.v3.min.js"></script> +<script> +jsondata='""" + +output = output + network2JSON(sys.argv[1],sys.argv[2]) + "'\n" + +output = output + """var w = window.innerWidth; +var h = window.innerHeight; + +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 + +var focus_node = null, highlight_node = null; + +var text_center = false; +var outline = false; + +var min_score = 0; +var max_score = 1; + +var color = d3.scale.category20() + .range(["green", "orange", "red","black","steelblue","purple","gray","blue","yellow","lime"]); + +var highlight_color = "red"; +var highlight_trans = 0.1; + +var size = d3.scale.pow().exponent(1) + .domain([1,100]) + .range([8,24]); + +var force = d3.layout.force() + .linkDistance(60) + .charge(-500) + .size([w,h]); + +var default_node_color = "#000"; +//var default_node_color = "rgb(3,190,100)"; +var default_link_color = "#888"; +var nominal_base_node_size = 8; +var nominal_text_size = 10; +var max_text_size = 24; +var nominal_stroke = 1.5; +var max_stroke = 4.5; +var max_base_node_size = 36; +var min_zoom = 0.1; +var max_zoom = 7; +var svg = d3.select("body").append("svg"); +var zoom = d3.behavior.zoom().scaleExtent([min_zoom,max_zoom]) +var g = svg.append("g"); +svg.style("cursor","move"); + +var data = JSON.parse(jsondata); +function plot_graph(graph) { + +var linkedByIndex = {}; + graph.links.forEach(function(d) { + linkedByIndex[d.source + "," + d.target] = true; + }); + + function isConnected(a, b) { + return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index] || a.index == b.index; + } + + function hasConnections(a) { + for (var property in linkedByIndex) { + s = property.split(","); + if ((s[0] == a.index || s[1] == a.index) && linkedByIndex[property]) return true; + } + return false; + } + + force + .nodes(graph.nodes) + .links(graph.links) + .start(); + + var link = g.selectAll(".link") + .data(graph.links) + .enter().append("line") + .attr("class", "link") + .style("stroke-width",nominal_stroke) + .style("stroke", function(d) { + if (isNumber(d.score) && d.score>=0) return color(d.score); + else return default_link_color; }) + + + var node = g.selectAll(".node") + .data(graph.nodes) + .enter().append("g") + .attr("class", "node") + + .call(force.drag) + + + node.on("dblclick.zoom", function(d) { d3.event.stopPropagation(); + var dcx = (window.innerWidth/2-d.x*zoom.scale()); + var dcy = (window.innerHeight/2-d.y*zoom.scale()); + zoom.translate([dcx,dcy]); + g.attr("transform", "translate("+ dcx + "," + dcy + ")scale(" + zoom.scale() + ")"); + + + }); + + + + + var tocolor = "fill"; + var towhite = "stroke"; + if (outline) { + tocolor = "stroke" + towhite = "fill" + } + + + + var circle = node.append("path") + + + .attr("d", d3.svg.symbol() + .size(function(d) { return Math.PI*Math.pow(size(d.size)||nominal_base_node_size,2); }) + .type(function(d) { return d.type; })) + + .style(tocolor, function(d) { + if (isNumber(d.score) && d.score>=0) return color(d.score); + else return default_node_color; }) + //.attr("r", function(d) { return size(d.size)||nominal_base_node_size; }) + .style("stroke-width", nominal_stroke) + .style(towhite, "white"); + + + var text = g.selectAll(".text") + .data(graph.nodes) + .enter().append("text") + .attr("dy", ".35em") + .style("font-size", nominal_text_size + "px") + + if (text_center) + text.text(function(d) { return d.id; }) + .style("text-anchor", "middle"); + else + text.attr("dx", function(d) {return (size(d.size)||nominal_base_node_size);}) + .text(function(d) { return '\u2002'+d.id; }); + + node.on("mouseover", function(d) { + set_highlight(d); + }) + .on("mousedown", function(d) { d3.event.stopPropagation(); + focus_node = d; + set_focus(d) + if (highlight_node === null) set_highlight(d) + +} ).on("mouseout", function(d) { + exit_highlight(); + +} ); + + d3.select(window).on("mouseup", + function() { + if (focus_node!==null) + { + focus_node = null; + if (highlight_trans<1) + { + + circle.style("opacity", 1); + text.style("opacity", 1); + link.style("opacity", 1); + } + } + + if (highlight_node === null) exit_highlight(); + }); + +function exit_highlight() +{ + highlight_node = null; + if (focus_node===null) + { + svg.style("cursor","move"); + if (highlight_color!="white") + { + circle.style(towhite, "white"); + text.style("font-weight", "normal"); + link.style("stroke", function(o) {return (isNumber(o.score) && o.score>=0)?color(o.score):default_link_color}); + } + + } +} + +function set_focus(d) +{ +if (highlight_trans<1) { + circle.style("opacity", function(o) { + return isConnected(d, o) ? 1 : highlight_trans; + }); + + text.style("opacity", function(o) { + return isConnected(d, o) ? 1 : highlight_trans; + }); + + link.style("opacity", function(o) { + return o.source.index == d.index || o.target.index == d.index ? 1 : highlight_trans; + }); + } +} + + +function set_highlight(d) +{ + svg.style("cursor","pointer"); + if (focus_node!==null) d = focus_node; + highlight_node = d; + + if (highlight_color!="white") + { + circle.style(towhite, function(o) { + return isConnected(d, o) ? highlight_color : "white";}); + text.style("font-weight", function(o) { + return isConnected(d, o) ? "bold" : "normal";}); + link.style("stroke", function(o) { + 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); + + }); + } +} + + + zoom.on("zoom", function() { + + var stroke = nominal_stroke; + if (nominal_stroke*zoom.scale()>max_stroke) stroke = max_stroke/zoom.scale(); + link.style("stroke-width",stroke); + circle.style("stroke-width",stroke); + + var base_radius = nominal_base_node_size; + if (nominal_base_node_size*zoom.scale()>max_base_node_size) base_radius = max_base_node_size/zoom.scale(); + circle.attr("d", d3.svg.symbol() + .size(function(d) { return Math.PI*Math.pow(size(d.size)*base_radius/nominal_base_node_size||base_radius,2); }) + .type(function(d) { return d.type; })) + + //circle.attr("r", function(d) { return (size(d.size)*base_radius/nominal_base_node_size||base_radius); }) + if (!text_center) text.attr("dx", function(d) { return (size(d.size)*base_radius/nominal_base_node_size||base_radius); }); + + var text_size = nominal_text_size; + if (nominal_text_size*zoom.scale()>max_text_size) text_size = max_text_size/zoom.scale(); + text.style("font-size",text_size + "px"); + + g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); + }); + + svg.call(zoom); + + resize(); + //window.focus(); + d3.select(window).on("resize", resize).on("keydown", keydown); + + force.on("tick", function() { + + node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); + text.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); + + link.attr("x1", function(d) { return d.source.x; }) + .attr("y1", function(d) { return d.source.y; }) + .attr("x2", function(d) { return d.target.x; }) + .attr("y2", function(d) { return d.target.y; }); + + node.attr("cx", function(d) { return d.x; }) + .attr("cy", function(d) { return d.y; }); + }); + + function resize() { + var width = window.innerWidth, height = window.innerHeight; + svg.attr("width", width).attr("height", height); + + force.size([force.size()[0]+(width-w)/zoom.scale(),force.size()[1]+(height-h)/zoom.scale()]).resume(); + w = width; + h = height; + } + + function keydown() { + if (d3.event.keyCode==32) { force.stop();} + else if (d3.event.keyCode>=48 && d3.event.keyCode<=90 && !d3.event.ctrlKey && !d3.event.altKey && !d3.event.metaKey) + { + switch (String.fromCharCode(d3.event.keyCode)) { + case "C": keyc = !keyc; break; + case "S": keys = !keys; break; + case "T": keyt = !keyt; break; + case "R": keyr = !keyr; break; + case "X": keyx = !keyx; break; + case "D": keyd = !keyd; break; + case "L": keyl = !keyl; break; + case "M": keym = !keym; break; + case "H": keyh = !keyh; break; + case "1": key1 = !key1; break; + case "2": key2 = !key2; break; + case "3": key3 = !key3; break; + case "0": key0 = !key0; break; + } + + link.style("display", function(d) { + 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); + linkedByIndex[d.source.index + "," + d.target.index] = flag; + return flag?"inline":"none";}); + node.style("display", function(d) { + return (key0||hasConnections(d))&&vis_by_type(d.type)&&vis_by_node_score(d.score)?"inline":"none";}); + text.style("display", function(d) { + return (key0||hasConnections(d))&&vis_by_type(d.type)&&vis_by_node_score(d.score)?"inline":"none";}); + + if (highlight_node !== null) + { + if ((key0||hasConnections(highlight_node))&&vis_by_type(highlight_node.type)&&vis_by_node_score(highlight_node.score)) { + if (focus_node!==null) set_focus(focus_node); + set_highlight(highlight_node); + } + else {exit_highlight();} + } + +} +} + +}; + +function vis_by_type(type) +{ + switch (type) { + case "circle": return keyc; + case "circle": return keys; + case "triangle-up": return keyt; + case "diamond": return keyr; + case "cross": return keyx; + case "triangle-down": return keyd; + default: return true; +} +} +function vis_by_node_score(score) +{ + if (isNumber(score)) + { + if (score>=0.666) return keyh; + else if (score>=0.333) return keym; + else if (score>=0) return keyl; + } + return true; +} + +function vis_by_link_score(score) +{ + if (isNumber(score)) + { + if (score>=0.666) return key3; + else if (score>=0.333) return key2; + else if (score>=0) return key1; +} + return true; +} + +function isNumber(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} +plot_graph(data) + +</script>""" + +with open(sys.argv[3],"w") as x: + x.write(output)