| 
1
 | 
     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)
 |