Advertisement
BenjaminLind

Sociogram--graph_plotly.jl

May 10th, 2014
913
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.40 KB | None | 0 0
  1. #####
  2. ### The code below is written by Benjamin Lind under CC: BY-NC-SA 3.0
  3. ### If you use or develop this code, please provide proper attribution.
  4. ### You may contact me at lind.benjamin//at//gmail//d0t//com
  5. ### You may also find me @benjaminlind on Twitter
  6. #####
  7.  
  8. # To use this code, uncomment the next line and enter it into Julia:
  9. # download("http://pastebin.com/raw.php?i=ymrmxPtU", "Sociogram--graph_plotly.jl"); include("Sociogram--graph_plotly.jl"); rm("Sociogram--graph_plotly.jl")
  10.  
  11. using Graphs, Color, Plotly
  12.  
  13. #####
  14. ### Sociogram plotting in Plotly using the Graphs library in the language of Julia.
  15. ### For more information on the library, see: graphsjl-docs.readthedocs.org/en/
  16. ### For more information on Plotly in Julia, see: https://plot.ly/julia/getting-started
  17. #####
  18.  
  19. # NOTEs:
  20. # Graph coordinates _MUST_ be saved as vertex attributes, "x" and "y".
  21. # The vertices _MUST_ therefore be of type ExVertex.
  22. # Undirected curved edges are not yet implemented
  23. # Directed graphs will take considerable time to load in Plotly due to the intensity tapering.
  24. # Lower the gradient and/or sample the network to increase the load time.
  25. # At this time, conventional "stick and arrow" approaches are not yet implemented
  26. # To speed up time and ignore directionality, set _directed_ equal to false.
  27.  
  28. function graph_plotly(g::GenericGraph, signin::String, apikey::String; directed::Bool = true, label::Bool = false, labelpos = "center", labelsize = 1, labelfamily = "sans serif", labelcol = "#000000", labelopac = 1, vertexsize = 1, vertexcolor = "#F297A0", vertexsymbol = "circle", vertexopacity = .9, vertexbordercolor = "#6F95A2", vertexborderwidth = 1, vertexborderopacity = .95, edgecolor = "#B6BFBE", edgeopacity = .95, edgewidth = 1, edgecolortip = "#FFFFFF", curved::Bool = true, curveintensity::Real = 1, gradient::Integer = 100)
  29.  
  30. Plotly.signin(signin, apikey)
  31.  
  32. #Some scaling constants
  33. vertexsize = vertexsize .* 32
  34. vertexborderwidth = vertexborderwidth .* 3
  35. edgewidth = edgewidth .* 6
  36. labelsize = labelsize .* 18
  37. curveintensity = curveintensity * 3
  38.  
  39. ecount = num_edges(g)
  40. vcount = num_vertices(g)
  41.  
  42. #Coordinates
  43. x = map((f)->f.attributes["x"], g.vertices)
  44. y = map((f)->f.attributes["y"], g.vertices)
  45. graphcenter = [mean(x), mean(y)]
  46. xel = Array(Real, ecount, 2)
  47. yel = Array(Real, ecount, 2)
  48. for i = 1:ecount
  49. sind = source(g.edges[i]).index
  50. tind = target(g.edges[i]).index
  51. xel[i,:] = [x[sind], x[tind]]
  52. yel[i,:] = [y[sind], y[tind]]
  53. end
  54.  
  55. # This function probably already exists in Julia, but I can only find it in the DataFrames library
  56. function my_rep(anyvalue::Any, times::Integer)
  57. anyvaluetype = typeof(anyvalue)
  58. anyvaluearray = Array(anyvaluetype, times)
  59. anyvaluearray[:] = anyvalue
  60. return anyvaluearray
  61. end
  62. if length([edgecolor]) != ecount
  63. edgecolor = my_rep([edgecolor][1], ecount)
  64. end
  65. if length(edgeopacity) != ecount
  66. edgeopacity = my_rep([edgeopacity][1], ecount)
  67. end
  68. if length(edgewidth) != ecount
  69. edgewidth = my_rep([edgewidth][1], ecount)
  70. end
  71. if length([edgecolortip]) != ecount
  72. edgecolortip = my_rep([edgecolortip][1], ecount)
  73. end
  74.  
  75. #Suppress axes
  76. axesstyle = [
  77. "autorange" => true,
  78. "autotick" => true,
  79. "showgrid" => false,
  80. "showline" => false,
  81. "showticklabels" => false,
  82. "zeroline" => false,
  83. "ticks" => ""
  84. ]
  85.  
  86. #Suppress legend and hover mode.
  87. #Hover mode might be interesting for the vertex attributes, but it's distracting for everything else.
  88. layout = [
  89. "xaxis" => axesstyle,
  90. "yaxis" => axesstyle,
  91. "showlegend" => false,
  92. "hovermode" => "none"
  93. ]
  94.  
  95. function bezier_edges(x1::Real, y1::Real, x2::Real, y2::Real, edgew::Real, edgeo::Real, edgec::String, edgect::String)
  96. # See: http://is-r.tumblr.com/post/38459242505/beautiful-network-diagrams-with-ggplot2
  97. # And: https://en.wikipedia.org/wiki/B%C3%A9zier_curve
  98.  
  99. # _x1_ and _y1_ are the source coordinates.
  100. # _x2_ and _y2_ are the target coordinates.
  101. # _edgew_ is the edge's weight/thickness. Goes from _edgew_ to 0.
  102. # Color:
  103. # Ranges from _edgec_ to _edgec_.
  104. # Color opacity ranges from _edgeo_ to 0.
  105.  
  106. # Curve midpoint
  107. if curved == false
  108. beziermid = ([x1, y1] .+ [x2. y2]) ./ 2
  109. else
  110. beziermid = [x1, y2]
  111. distance1 = sum([(graphcenter[1] - beziermid[1])^2, (graphcenter[2] - beziermid[2])^2])
  112. criticalbezier = sum(graphcenter .- [x2^2, y1^2])
  113. if distance1 < criticalbezier
  114. beziermid = [x2, y1]
  115. end
  116. beziermid = ([x1, y1] .+ [x2, y2] .+ beziermid) ./ curveintensity
  117. end
  118.  
  119. # Create continuous x and y coordinates
  120. function bezier_fun(p0, p1, p2, t)
  121. return ((1-t)^2) * p0 + 2 * (1-t) * t * p1 + (t^2) * p2
  122. end
  123. xbezier = Array(Real, gradient)
  124. ybezier = Array(Real, gradient)
  125. tvals = linspace(0, 1, gradient)
  126. for j = 1:gradient
  127. xbezier[j] = bezier_fun(x1, beziermid[1], x2, tvals[j])
  128. ybezier[j] = bezier_fun(y1, beziermid[2], y2, tvals[j])
  129. end
  130.  
  131. # Taper the edge width, opacity, and color
  132. twidth = linspace(edgew, 0, gradient) # Perhaps a variable could be used instead of 0 here.
  133. topacity = linspace(edgeo, 0, gradient) # Perhaps a variable could be used instead of 0 here.
  134. function rgb_2_string(rgbinput::RGB)
  135. colr = rgbinput.r
  136. colg = rgbinput.g
  137. colb = rgbinput.b
  138. stringoutput = "rgb($colr,$colg,$colb)"
  139. return stringoutput
  140. end
  141. tcolor = linspace(color(edgec), color(edgect), gradient)
  142. tcolor = map(rgb_2_string, tcolor) #Needs to be turned into a string for Plotly.
  143.  
  144. # Output many tiny lines
  145. outtrace = Array(Any, gradient - 1)
  146. for k = 1:(gradient-1)
  147. outtrace[k] = [
  148. "x" => xbezier[k:(k+1)],
  149. "y" => ybezier[k:(k+1)],
  150. "type" => "scatter",
  151. "mode" => "lines",
  152. "line" => [
  153. "color" => tcolor[k],
  154. "opacity" => topacity[k],
  155. "width" => twidth[k]
  156. ]
  157. ]
  158. end
  159. return outtrace
  160. end
  161.  
  162. #Add the edges to the plot
  163. if (is_directed(g) == false) | (directed == false)
  164. traceel = Array(Any, ecount)
  165. for i = 1:ecount
  166. traceel[i] = [
  167. "x" => [xel[i, 1], xel[i, 2]],
  168. "y" => [yel[i, 1], yel[i, 2]],
  169. "type" => "scatter",
  170. "mode" => "lines",
  171. "line" => [
  172. "color" => [edgecolor][i],
  173. "opacity" => edgeopacity[i],
  174. "width" => edgewidth[i]
  175. ]
  176. ]
  177. end
  178. else
  179. traceel = Any[]
  180. for i = 1:ecount
  181. smalledge = bezier_edges(
  182. xel[i, 1],
  183. yel[i, 1],
  184. xel[i, 2],
  185. yel[i, 2],
  186. edgewidth[i],
  187. edgeopacity[i],
  188. edgecolor[i],
  189. edgecolortip[i]
  190. )
  191. for l = 1:length(smalledge)
  192. push!(traceel, smalledge[l])
  193. end
  194. end
  195. end
  196.  
  197. #Add the vertices to the plot
  198. push!(traceel, [
  199. "x" => x,
  200. "y" => y,
  201. "type" => "scatter",
  202. "mode" => "markers",
  203. "marker" => [
  204. "symbol" => vertexsymbol,
  205. "size" => vertexsize,
  206. "color" => vertexcolor,
  207. "opacity" => vertexopacity,
  208. "line" => [
  209. "width" => vertexborderwidth,
  210. "color" => vertexbordercolor,
  211. "hovermode" => "none"
  212. ]
  213. ]
  214. ])
  215.  
  216. #Add the labels to the plot
  217. if label
  218. vertexnames = map((f)-> f.label, g.vertices)
  219. push!(traceel, [
  220. "x" => x,
  221. "y" => y,
  222. "name" => "Text",
  223. "text" => vertexnames,
  224. "type" => "scatter",
  225. "mode" => "text",
  226. "textposition" => labelpos,
  227. "textfont" => [
  228. "color" => labelcol,
  229. "opacity" => labelopac,
  230. "size" => labelsize,
  231. "fanily" => labelfamily
  232. ]
  233. ])
  234. end
  235.  
  236. response = Plotly.plot(traceel, ["layout" => layout])
  237. return response
  238. end
  239.  
  240. ###Sample code
  241.  
  242. # download("http://pastebin.com/raw.php?i=Z2t7XRd3", "GraphsPopularDataSets.jl")
  243. # include("GraphsPopularDataSets.jl")
  244. # rm("GraphsPopularDataSets.jl")
  245.  
  246. # yourplotlyname = "Not this string"
  247. # yourplotlyAPIkey = "Not this string, either"
  248.  
  249. # floplot = graph_plotly(flograph, yourplotlyname, yourplotlyAPIkey, vertexsize = 0.75, label = true)
  250. # floplot["url"] #Find the plot at this URL
  251. # colemanplot = graph_plotly(colemangraph, yourplotlyname, yourplotlyAPIkey, vertexsize = 0.33, vertexopacity = .95, vertexborderopacity = 1, gradient = 150)
  252. # colemanplot["url"] #Find the plot at this URL
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement