SHARE
TWEET

Sociogram--graph_plotly.jl

BenjaminLind May 10th, 2014 425 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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
RAW Paste Data
Top