I am trying to plot a function defined on a simplex. Apparently, you can do it very nicely using the Matlab API.
But I cannot figure out how to do this using the Python API. The reference has a section named Ternary Contour Plots in Python but it does not plot a numeric function, but a function mapping the simplex to a given discrete set.
I tried to emulate the Matlab code:
import plotly as py
A = [0, .2, .2, .2, 0, .6, .75, .9, 0, 1, .8, .3]
B = [1, .2, .4, .1, 0, .4, .05, 0, .8, 0, .05, .3]
C = [0, .6, .4, .7, 1, 0, .2, .1, .2, 0, .15, .4]
Z = [.1, .5, .1, .2, 1, .8, .4, 0, .1, .6, 1, .7]
trace = {
"type": 'scatterternary',
"carpet": 'scattercontour',
"a": A,
"b": B,
"c": C,
"z": Z
}
layout = {
'title': 'Simple Ternary Contour Plot with Python'
}
figure = dict(data=[trace], layout=layout)
py.offline.plot(figure, validate=False)
But I get this plot instead:
2 Answers 2
If someone is still interested, here is a Jupyter Notebook to see how to generate a Plotly ternary contour plot.
One workaround is possible if you can generate the data whose contours you want to plot for arbitrary proportions. In this case, you can generate the (x, y) data on a mesh, map them to barycentric coordinates, and compute the value z. Then you can use the non-ternary plots like contour or surface.
Here is an example that plots the density function of the Dirichlet distribution:
import plotly as py
import plotly.graph_objs as go
import numpy as np
def compute_in_barycentric_coordinates(a, b, c):
epsilon = 1e-6
if 0.0 < a < 1.0 and 0.0 < b < 1.0 and 0.0 < c < 1.0 and abs(a + b + c - 1.0) < epsilon:
return pow(a, 2) * pow(b, 1.5) * pow(c, 1.8)
return None
x_data = np.linspace(0, 1, 101)
y_data = np.linspace(0, 1, 101)
z_data = []
f = 1.0 / pow(3.0, 0.5)
for y in y_data:
next_slice = []
for x in x_data:
a = 1 - x - f*y
b = x - f*y
c = 2*f*y
z = compute_in_barycentric_coordinates(a, b, c)
next_slice.append(z)
z_data.append(next_slice)
data = [
go.Contour(
x=x_data,
y=y_data,
z=z_data,
)
]
py.offline.plot(data)
However, it is still a workaround, so if you have a better idea, I will be very happy to hear from you.