I need help figuring out how to add a color bar to a chord diagram I have made. I would like to add a color bar such as in a heat map but in a chord diagram, not to be confused with a filled chord diagram in python plotly.
I tried to put in more links and pictures but I guess I need more reputation :( The heat map link is plot.ly/python/heatmaps. The chord diagram is at plot.ly/python/chord-diagram. The filled chord diagram is at plot.ly/python/filled-chord-diagram.
The way in which I plan to use the heat map is to have each line on the chord diagram be a certain color based on the data. For example, if the data says the line has a value of 80, it would be red like in the heat map. If the data said 50, it would be an orange-ish yellow, like in the heat map.
Thank you so much!
Let's assume your values for your color are stored in a list called my_weights
.
my_weights = [random.random() for _ in E]
where E is a list of edges.
We can then add a trace which only has the purpose of drawing the colorbar. Its markers are hidden behind one of the nodes.
color_trace = plotly.graph_objs.Scatter(x=[0 for _ in my_weights],
y=[0 for _ in my_weights],
mode='markers',
marker=plotly.graph_objs.Marker(
colorscale=[
[c / 100.0, 'rgba({}, {}, {}, {})'.format(*color_range(c / 100.0))] for
c in range(101)],
size=1,
color=my_weights,
showscale=True,
)
)
For the colorscale we can use matplotlib
to get a custom color generator.
color_range = plt.get_cmap('OrRd')
The complete code is based on the example here and produces the following graph.
import igraph as ig
import numpy as np
import plotly
import matplotlib.pyplot as plt
import random
color_range = plt.get_cmap('OrRd')
def dist(a, b):
return np.linalg.norm(np.array(a) - np.array(b))
def get_idx_interv(d, D):
k = 0
while d > D[k]:
k += 1
return k - 1
def deCasteljau(b, t):
n = len(b)
a = np.copy(b) # shallow copy of the list of control points
for r in range(1, n):
a[:n - r, :] = (1 - t) * a[:n - r, :] + t * a[1:n - r + 1, :]
return a[0, :]
def bezierCv(b, nr=5):
t = np.linspace(0, 1, nr)
return np.array([deCasteljau(b, t[k]) for k in range(nr)])
G = ig.Graph.Read_GML('Eurovision15.gml')
V = list(G.vs)
G.vs.attributes()
labels = [v['label'] for v in V]
E = [e.tuple for e in G.es]
ContestantLst = [G.vs[e[2]] for e in E]
Contestant = list(set([v['label'] for v in ContestantLst]))
layt = G.layout('circular')
Weights = map(int, G.es["weight"])
Dist = [0, dist([1, 0], 2 * [np.sqrt(2) / 2]), np.sqrt(2),
dist([1, 0], [-np.sqrt(2) / 2, np.sqrt(2) / 2]), 2.0]
params = [1.2, 1.5, 1.8, 2.1]
node_color = ['rgba(0,51,181, 0.85)' if v['label'] in Contestant else '#CCCCCC' for v in G.vs]
line_color = ['#FFFFFF' if v['label'] in Contestant else 'rgb(150,150,150)' for v in G.vs]
edge_colors = ['#d4daff', '#84a9dd', '#5588c8', '#6d8acf']
L = len(layt)
Xn = [layt[k][0] for k in range(L)]
Yn = [layt[k][2] for k in range(L)]
lines = list()
edge_info = list()
my_weights = [random.random() for _ in E]
for j, e in enumerate(E):
A = np.array(layt[e[0]])
B = np.array(layt[e[2]])
d = dist(A, B)
K = get_idx_interv(d, Dist)
b = [A, A / params[K], B / params[K], B]
color = edge_colors[K]
pts = bezierCv(b)
text = V[e[0]]['label'] + ' to ' + V[e[2]]['label'] + ' ' + str(Weights[j]) + ' pts'
mark = deCasteljau(b, 0.9)
edge_info.append(plotly.graph_objs.Scatter(x=mark[0],
y=mark[2],
mode='markers',
marker=plotly.graph_objs.Marker(size=0.5, color=edge_colors),
text=text,
hoverinfo='text'
)
)
lines.append(plotly.graph_objs.Scatter(x=pts[:, 0],
y=pts[:, 1],
mode='lines',
line=plotly.graph_objs.Line(
color='rgba({}, {}, {}, {})'.format(*color_range(my_weights[j])),
shape='spline',
width=Weights[j] / 5),
hoverinfo='none')
)
trace2 = plotly.graph_objs.Scatter(x=Xn,
y=Yn,
mode='markers',
marker=plotly.graph_objs.Marker(symbol='dot',
size=15,
color=node_color,
line=plotly.graph_objs.Line(color=line_color,
width=0.5)
),
text=labels,
hoverinfo='text'
)
color_trace = plotly.graph_objs.Scatter(x=[0 for _ in my_weights],
y=[0 for _ in my_weights],
mode='markers',
marker=plotly.graph_objs.Marker(
colorscale=[
[c / 100.0, 'rgba({}, {}, {}, {})'.format(*color_range(c / 100.0))] for
c in range(101)],
size=1,
color=my_weights,
showscale=True,
)
)
axis = dict(showline=False,
zeroline=False,
showgrid=False,
showticklabels=False,
title=''
)
layout = plotly.graph_objs.Layout(showlegend=False,
autosize=False,
width=800,
height=850,
xaxis=plotly.graph_objs.XAxis(axis),
yaxis=plotly.graph_objs.YAxis(axis),
margin=plotly.graph_objs.Margin(l=40,
r=40,
b=85,
t=100,
),
hovermode='closest')
data = plotly.graph_objs.Data([color_trace] + lines + edge_info + [trace2])
fig = plotly.graph_objs.Figure(data=data, layout=layout)
plotly.offline.plot(fig, filename='Eurovision-15.html')