Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #####
- ### The code below is written by Benjamin Lind under CC: BY-NC-SA 3.0
- ### If you use or develop this code, please provide proper attribution.
- ### You may contact me at lind.benjamin//at//gmail//d0t//com
- ### You may also find me @benjaminlind on Twitter
- #####
- # To use this code, uncomment the next line and enter it into Julia:
- # download("http://pastebin.com/raw.php?i=ymrmxPtU", "Sociogram--graph_plotly.jl"); include("Sociogram--graph_plotly.jl"); rm("Sociogram--graph_plotly.jl")
- using Graphs, Color, Plotly
- #####
- ### Sociogram plotting in Plotly using the Graphs library in the language of Julia.
- ### For more information on the library, see: graphsjl-docs.readthedocs.org/en/
- ### For more information on Plotly in Julia, see: https://plot.ly/julia/getting-started
- #####
- # NOTEs:
- # Graph coordinates _MUST_ be saved as vertex attributes, "x" and "y".
- # The vertices _MUST_ therefore be of type ExVertex.
- # Undirected curved edges are not yet implemented
- # Directed graphs will take considerable time to load in Plotly due to the intensity tapering.
- # Lower the gradient and/or sample the network to increase the load time.
- # At this time, conventional "stick and arrow" approaches are not yet implemented
- # To speed up time and ignore directionality, set _directed_ equal to false.
- 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)
- Plotly.signin(signin, apikey)
- #Some scaling constants
- vertexsize = vertexsize .* 32
- vertexborderwidth = vertexborderwidth .* 3
- edgewidth = edgewidth .* 6
- labelsize = labelsize .* 18
- curveintensity = curveintensity * 3
- ecount = num_edges(g)
- vcount = num_vertices(g)
- #Coordinates
- x = map((f)->f.attributes["x"], g.vertices)
- y = map((f)->f.attributes["y"], g.vertices)
- graphcenter = [mean(x), mean(y)]
- xel = Array(Real, ecount, 2)
- yel = Array(Real, ecount, 2)
- for i = 1:ecount
- sind = source(g.edges[i]).index
- tind = target(g.edges[i]).index
- xel[i,:] = [x[sind], x[tind]]
- yel[i,:] = [y[sind], y[tind]]
- end
- # This function probably already exists in Julia, but I can only find it in the DataFrames library
- function my_rep(anyvalue::Any, times::Integer)
- anyvaluetype = typeof(anyvalue)
- anyvaluearray = Array(anyvaluetype, times)
- anyvaluearray[:] = anyvalue
- return anyvaluearray
- end
- if length([edgecolor]) != ecount
- edgecolor = my_rep([edgecolor][1], ecount)
- end
- if length(edgeopacity) != ecount
- edgeopacity = my_rep([edgeopacity][1], ecount)
- end
- if length(edgewidth) != ecount
- edgewidth = my_rep([edgewidth][1], ecount)
- end
- if length([edgecolortip]) != ecount
- edgecolortip = my_rep([edgecolortip][1], ecount)
- end
- #Suppress axes
- axesstyle = [
- "autorange" => true,
- "autotick" => true,
- "showgrid" => false,
- "showline" => false,
- "showticklabels" => false,
- "zeroline" => false,
- "ticks" => ""
- ]
- #Suppress legend and hover mode.
- #Hover mode might be interesting for the vertex attributes, but it's distracting for everything else.
- layout = [
- "xaxis" => axesstyle,
- "yaxis" => axesstyle,
- "showlegend" => false,
- "hovermode" => "none"
- ]
- function bezier_edges(x1::Real, y1::Real, x2::Real, y2::Real, edgew::Real, edgeo::Real, edgec::String, edgect::String)
- # See: http://is-r.tumblr.com/post/38459242505/beautiful-network-diagrams-with-ggplot2
- # And: https://en.wikipedia.org/wiki/B%C3%A9zier_curve
- # _x1_ and _y1_ are the source coordinates.
- # _x2_ and _y2_ are the target coordinates.
- # _edgew_ is the edge's weight/thickness. Goes from _edgew_ to 0.
- # Color:
- # Ranges from _edgec_ to _edgec_.
- # Color opacity ranges from _edgeo_ to 0.
- # Curve midpoint
- if curved == false
- beziermid = ([x1, y1] .+ [x2. y2]) ./ 2
- else
- beziermid = [x1, y2]
- distance1 = sum([(graphcenter[1] - beziermid[1])^2, (graphcenter[2] - beziermid[2])^2])
- criticalbezier = sum(graphcenter .- [x2^2, y1^2])
- if distance1 < criticalbezier
- beziermid = [x2, y1]
- end
- beziermid = ([x1, y1] .+ [x2, y2] .+ beziermid) ./ curveintensity
- end
- # Create continuous x and y coordinates
- function bezier_fun(p0, p1, p2, t)
- return ((1-t)^2) * p0 + 2 * (1-t) * t * p1 + (t^2) * p2
- end
- xbezier = Array(Real, gradient)
- ybezier = Array(Real, gradient)
- tvals = linspace(0, 1, gradient)
- for j = 1:gradient
- xbezier[j] = bezier_fun(x1, beziermid[1], x2, tvals[j])
- ybezier[j] = bezier_fun(y1, beziermid[2], y2, tvals[j])
- end
- # Taper the edge width, opacity, and color
- twidth = linspace(edgew, 0, gradient) # Perhaps a variable could be used instead of 0 here.
- topacity = linspace(edgeo, 0, gradient) # Perhaps a variable could be used instead of 0 here.
- function rgb_2_string(rgbinput::RGB)
- colr = rgbinput.r
- colg = rgbinput.g
- colb = rgbinput.b
- stringoutput = "rgb($colr,$colg,$colb)"
- return stringoutput
- end
- tcolor = linspace(color(edgec), color(edgect), gradient)
- tcolor = map(rgb_2_string, tcolor) #Needs to be turned into a string for Plotly.
- # Output many tiny lines
- outtrace = Array(Any, gradient - 1)
- for k = 1:(gradient-1)
- outtrace[k] = [
- "x" => xbezier[k:(k+1)],
- "y" => ybezier[k:(k+1)],
- "type" => "scatter",
- "mode" => "lines",
- "line" => [
- "color" => tcolor[k],
- "opacity" => topacity[k],
- "width" => twidth[k]
- ]
- ]
- end
- return outtrace
- end
- #Add the edges to the plot
- if (is_directed(g) == false) | (directed == false)
- traceel = Array(Any, ecount)
- for i = 1:ecount
- traceel[i] = [
- "x" => [xel[i, 1], xel[i, 2]],
- "y" => [yel[i, 1], yel[i, 2]],
- "type" => "scatter",
- "mode" => "lines",
- "line" => [
- "color" => [edgecolor][i],
- "opacity" => edgeopacity[i],
- "width" => edgewidth[i]
- ]
- ]
- end
- else
- traceel = Any[]
- for i = 1:ecount
- smalledge = bezier_edges(
- xel[i, 1],
- yel[i, 1],
- xel[i, 2],
- yel[i, 2],
- edgewidth[i],
- edgeopacity[i],
- edgecolor[i],
- edgecolortip[i]
- )
- for l = 1:length(smalledge)
- push!(traceel, smalledge[l])
- end
- end
- end
- #Add the vertices to the plot
- push!(traceel, [
- "x" => x,
- "y" => y,
- "type" => "scatter",
- "mode" => "markers",
- "marker" => [
- "symbol" => vertexsymbol,
- "size" => vertexsize,
- "color" => vertexcolor,
- "opacity" => vertexopacity,
- "line" => [
- "width" => vertexborderwidth,
- "color" => vertexbordercolor,
- "hovermode" => "none"
- ]
- ]
- ])
- #Add the labels to the plot
- if label
- vertexnames = map((f)-> f.label, g.vertices)
- push!(traceel, [
- "x" => x,
- "y" => y,
- "name" => "Text",
- "text" => vertexnames,
- "type" => "scatter",
- "mode" => "text",
- "textposition" => labelpos,
- "textfont" => [
- "color" => labelcol,
- "opacity" => labelopac,
- "size" => labelsize,
- "fanily" => labelfamily
- ]
- ])
- end
- response = Plotly.plot(traceel, ["layout" => layout])
- return response
- end
- ###Sample code
- # download("http://pastebin.com/raw.php?i=Z2t7XRd3", "GraphsPopularDataSets.jl")
- # include("GraphsPopularDataSets.jl")
- # rm("GraphsPopularDataSets.jl")
- # yourplotlyname = "Not this string"
- # yourplotlyAPIkey = "Not this string, either"
- # floplot = graph_plotly(flograph, yourplotlyname, yourplotlyAPIkey, vertexsize = 0.75, label = true)
- # floplot["url"] #Find the plot at this URL
- # colemanplot = graph_plotly(colemangraph, yourplotlyname, yourplotlyAPIkey, vertexsize = 0.33, vertexopacity = .95, vertexborderopacity = 1, gradient = 150)
- # colemanplot["url"] #Find the plot at this URL
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement