4

I am trying to plot a function defined on a simplex. Apparently, you can do it very nicely using the Matlab API.

enter image description here

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:

enter image description here

asked Jun 29, 2018 at 15:01

2 Answers 2

2

If someone is still interested, here is a Jupyter Notebook to see how to generate a Plotly ternary contour plot.

answered Nov 7, 2018 at 17:34
0

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)

enter image description here

However, it is still a workaround, so if you have a better idea, I will be very happy to hear from you.

answered Jul 2, 2018 at 15:26

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.