{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Plotly ternary contour plot"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"2d point position can be given in a cartesian, polar or barycentric system of coordinates.\n",
"Ternary plots work in barycentric coordinates.\n",
"\n",
"Given a triangle of vertices $V_k$, $k=0, 1, 2$, indexed such that the sequence $V_0, V_1, V_2$ is run in counter-clockwise\n",
"direction, like in the figure below, then each 2D point, $P$, can be expressed as a barycentric combination of the vertices:\n",
"$$P=aV_0+bV_1+cV_2,$$ with $a+b+c=1$. The scalars $a, b, c$ are called barycentric coordinates of the point P\n",
"with respect to the given triangle."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from IPython.display import SVG\n",
"SVG(filename='Data/triangle.svg')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"All points within the triangular region, bounded by the reference triangle, have positive barycentric coordinates, i.e.\n",
"$a, b, c\\geq 0$, $a+b+c=1$.\n",
"\n",
"A ternary plot is a scatter plot of n points in a triangular region, represented by their barycentric coordinates with respect to that triangle.\n",
"\n",
"\n",
"Ternary plot is used to represent triplets of values of\n",
" three dependent positive variables $A, B, C$, whose sum is a constant, $k$. Scaling each variable we get $\\displaystyle\\frac{1}{k}A+\\displaystyle\\frac{1}{k}B+\\displaystyle\\frac{1}{k}C=1$.\n",
"Hence n normalized triplets interpreted as values of a variable $Y=\\left(\\displaystyle\\frac{1}{k}A, \\displaystyle\\frac{1}{k}B, \\displaystyle\\frac{1}{k}C\\right)$ can be interpreted as barycentric coordinates with respect to a triangle, and can be represented by points in a triangular region, i.e. as a scatter ternary plot. In most cases the constant $k$ is 100, and a, b, c represent the percent of parts in a composition of three elements.\n",
"\n",
"The reference triangle in a ternary plot is, by convention, an equilateral triangle. \n",
"\n",
"\n",
"If the triangle vertices, $V_k$, have the cartesian coordinates $(x_k, y_k)$, $k=0, 1, 2$, and a point $P$ has the barycentric coordinates $(a, b, c)$, then its cartesian coordinates, $P(x,y)$, are derived from this relation:\n",
" $$\\left[\\begin{array}{c} x\\\\y\\\\1\\end{array}\\right ]= \\left(\\begin{array}{ccc}x_0&x_1&x_2\\\\y_0&y_1&y_2\\\\1&1&1\\end{array}\\right)\\left[\\begin{array}{c} a\\\\b\\\\c\\end{array}\\right ]$$\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A ternary contour plot is the contour plot of a function $z=f(a, b, c)$, $a, b, c \\geq 0$, $a+b+c=1$, \n",
"i.e. a function of positive barycentric coordinates."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Plotly provides a `scatterternary` trace, but a ternary contour trace that maps z-values to a continuous colorscale is not introduced yet."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Task:\n",
"\n",
"*Given n points of barycentric coordinates, (a, b, c), with respect to an equilateral triangle of vertices $V_k(x_k, y_k)$, $k=0, 1, 2$, and n values\n",
"in a list or array, z, extract data for a Plotly ternary contour plot or heatmap*. \n",
"\n",
"Since these Plotly traces work only in cartesian coordinates\n",
"we proceed as follows:\n",
"\n",
"- compute the cartesian coordinates, (x, y), of the given points from their barycentric coordinates, via the above tranformation;\n",
"\n",
"- define a meshgrid on the rectangle $[min(x), max(x)] \\times [min(y), max(y)]$;\n",
"\n",
"- interpolate data (x, y; z) and evaluate the interpolatory function at the meshgrid points to get an array, `grid_z`;\n",
"\n",
"- compute the barycentric coordinates of the meshgrid points, and associate a `nan` value to `grid_z` where at least one of these barycentric coordinates is negative (i.e. insert `nan` in the position of points that are outside the reference triangle).\n",
"\n",
"- define a contour type trace from `grid_z`"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Python version: 3.6.4\n",
"Plotly version: 3.4.0\n"
]
}
],
"source": [
"import platform\n",
"import plotly\n",
"print(f'Python version: {platform.python_version()}')\n",
"print(f'Plotly version: {plotly.__version__}')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import plotly.graph_objs as go\n",
"import numpy as np\n",
"from scipy.interpolate import griddata"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define data for a ternary contour plot:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = np.array([0, .3 ,.25, .34 ,0, .4 ,.65, 0.05, 0, 1, .47, .2, .7]) #pos 10 1, 0, 0\n",
"B = np.array([1, .1, .45, .56, 0, .5, .3, 0.75, .85, 0, .33, .3, .13])\n",
"C = np.array([0, .6 ,.3, .1, 1, .1, .05, .2, .15, 0, .2, .5, .17])\n",
"\n",
"z=np.array([1.27036107, 1.27893858, 0.52255697, 1.50035059, 0.84853798,\n",
" 1.27722501, 1.20920733, 0.88965008, 0.59293362, 0.9223051 ,\n",
" 1.57173859, 1.33606612, 1.08977333])\n",
"A+B+C"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Note** that to get a full triangle contour plot the initial data must contain the vertex points and values z at these points.\n",
"Otherwise the contour plot will be generated in a subregion of the triangular one!!!!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get acquainted with Plotly ternary axes we first plot the points $(a_j, b_j, c_j)$, with $a_j \\in A, b_j\\in B, c_j\\in C$, $j\\in\\{0, 1, \\ldots, 12\\}$:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f15d7a595e1446fd84ca860d7390d39f",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"FigureWidget({\n",
" 'data': [{'a': array([0. , 0.3 , 0.25, 0.34, 0. , 0.4 , 0.65, 0.05, 0. , 1. , 0.47, 0.2…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pl_ternary=dict(type='scatterternary',\n",
" a=A,\n",
" b=B, \n",
" c=C,\n",
" mode='markers',\n",
" marker=dict(size=10, color='red'))\n",
"\n",
"layout=dict(width=500, height=400,\n",
" ternary= {'sum':1,\n",
" 'aaxis':{'title': 'a', 'min': 0.001, 'linewidth':0.5, 'ticks':'outside' },\n",
" 'baxis':{'title': 'b', 'min': 0.001, 'linewidth':0.5, 'ticks':'outside' },\n",
" 'caxis':{'title': 'c', 'min': 0.001, 'linewidth':0.5, 'ticks':'outside' }},\n",
" showlegend= False,\n",
" paper_bgcolor='#EBF0F8')\n",
"\n",
"fw=go.FigureWidget(data=[pl_ternary], layout=layout)\n",
"fw #this plot is visible only when the notebook is run"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The triangle sides opposite to the vertices marked by a, b, respectively c, are the lines of 0 barycentric coordinate: a=0, b=0, respectively c=0.\n",
"Each parallel to such a side has a constant a, b, respectively c coordinate. Notice that the ticks are drawn correspondingly. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Functions that define elements for plotting a ternary contour plot"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def tr_b2c2b():\n",
" # returns the transformation matrix from barycentric to cartesian coordinates and conversely\n",
" tri_verts = np.array([[0.5, np.sqrt(3)/2], [0, 0], [1, 0]])# reference triangle\n",
" M = np.array([tri_verts[:,0], tri_verts[:, 1], np.ones(3)]) \n",
" return M, np.linalg.inv(M) "
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def contour_trace(x, y, z, tooltip, \n",
" colorscale='Viridis', reversescale=False,\n",
" linewidth=0.5, linecolor='rgb(150,150,150)'):\n",
" \n",
" return dict(type='contour',\n",
" x=x,\n",
" y=y, \n",
" z=z,\n",
" text=tooltip,\n",
" hoverinfo='text', \n",
" colorscale=colorscale,\n",
" reversescale=reversescale,\n",
" line=dict(width=linewidth, color=linecolor),\n",
" colorbar=dict(thickness=20, ticklen=4))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As outlined above, our ternary contour is plotted in cartesian coordinates, hence we cannot use the Plotly ternary \n",
"layout defined for `scatterternary` trace.\n",
"We have to define the tick positions and directions in a cartesian system.\n",
"\n",
"The next two functions return the barycentric coordinates of tick starting points, respectively the lists of x, and y-coordinates of points that defines the ticks, as well as the position of ticklabels:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def barycentric_ticks(side):\n",
" # side 0, 1 or 2; side j has 0 in the j^th position of barycentric coords of tick origin\n",
" # returns the list of tick origin barycentric coords\n",
" p = 10\n",
" if side == 0: #where a=0\n",
" return np.array([(0, j/p, 1-j/p) for j in range(p-2, 0, -2)])\n",
" elif side == 1: # b=0\n",
" return np.array([(i/p, 0, 1-i/p) for i in range( 2, p, 2) ])\n",
" elif side == 2: #c=0\n",
" return np.array([(i/p, j/p, 0) for i in range(p-2, 0, -2) for j in range(p-i, -1, -1) if i+j==p])\n",
" else:\n",
" raise ValueError('The side can be only 0, 1, 2')\n",
"\n",
"\n",
"\n",
"def cart_coord_ticks(side, t=0.01):\n",
" # side 0, 1 or 2\n",
" # each tick segment is parameterized as (x(s), y(s)), s in [0, t]\n",
" global M, xt, yt, posx, posy\n",
" # M is the transformation matrix from barycentric to cartesian coords\n",
" # xt, yt are the lists of x, resp y-coords of tick segments\n",
" # posx, posy are the lists of ticklabel positions for side 0, 1, 2 (concatenated)\n",
" \n",
" baryc = barycentric_ticks(side)\n",
" xy1 = np.dot(M, baryc.T)\n",
" xs, ys = xy1[:2] \n",
" \n",
" if side == 0:\n",
" for i in range(4):\n",
" xt.extend([xs[i], xs[i]+t, None])\n",
" yt.extend([ys[i], ys[i]-np.sqrt(3)*t, None])\n",
" posx.extend([xs[i]+t for i in range(4)])\n",
" posy.extend([ys[i]-np.sqrt(3)*t for i in range(4)])\n",
" \n",
" elif side == 1:\n",
" for i in range(4):\n",
" xt.extend([xs[i], xs[i]+t, None])\n",
" yt.extend([ys[i], ys[i]+np.sqrt(3)*t, None])\n",
" posx.extend([xs[i]+t for i in range(4)]) \n",
" posy.extend([ys[i]+np.sqrt(3)*t for i in range(4)])\n",
" \n",
" elif side == 2:\n",
" for i in range(4):\n",
" xt.extend([xs[i], xs[i]-2*t, None])\n",
" yt.extend([ys[i], ys[i], None])\n",
" posx.extend([xs[i]-2*t for i in range(4)])\n",
" posy.extend([ys[i] for i in range(4)]) \n",
" else:\n",
" raise ValueError('side can be only 0,1,2')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Layout definition:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def ternary_layout(title='Ternary contour plot', width=550, height=525, \n",
" fontfamily= 'Balto, sans-serif' , lfontsize=14,\n",
" plot_bgcolor='rgb(240,240,240)',\n",
" vertex_text=['a', 'b', 'c'], v_fontsize=14):\n",
"\n",
" return dict(title=title,\n",
" font=dict(family=fontfamily, size=lfontsize),\n",
" width=width, height=height,\n",
" xaxis=dict(visible=False),\n",
" yaxis=dict(visible=False),\n",
" plot_bgcolor=plot_bgcolor,\n",
" showlegend=False,\n",
" #annotations for strings placed at the triangle vertices\n",
" annotations=[dict(showarrow=False,\n",
" text=vertex_text[0],\n",
" x=0.5,\n",
" y=np.sqrt(3)/2,\n",
" align='center',\n",
" xanchor='center',\n",
" yanchor='bottom',\n",
" font=dict(size=v_fontsize)),\n",
" dict(showarrow=False,\n",
" text=vertex_text[1],\n",
" x=0,\n",
" y=0,\n",
" align='left',\n",
" xanchor='right',\n",
" yanchor='top',\n",
" font=dict(size=v_fontsize)),\n",
" dict(showarrow=False,\n",
" text=vertex_text[2],\n",
" x=1,\n",
" y=0,\n",
" align='right',\n",
" xanchor='left',\n",
" yanchor='top',\n",
" font=dict(size=v_fontsize))\n",
" ])\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"def set_ticklabels(annotations, posx, posy, proportion=True):\n",
" #annotations: list of annotations previously defined in layout definition as a dict,\n",
" # not as an instance of go.Layout\n",
" #posx, posy: lists containing ticklabel position coordinates\n",
" #proportion - boolean; True when ticklabels are 0.2, 0.4, ... False when they are 20%, 40%...\n",
" \n",
" if not isinstance(annotations, list):\n",
" raise ValueError('annotations should be a list')\n",
" \n",
" ticklabel = [0.8, 0.6, 0.4, 0.2] if proportion else ['80%', '60%', '40%', '20%'] \n",
" \n",
" annotations.extend([dict(showarrow=False, # annotations for ticklabels on side 0\n",
" text=f'{ticklabel[j]}',\n",
" x=posx[j],\n",
" y=posy[j],\n",
" align='center',\n",
" xanchor='center', \n",
" yanchor='top',\n",
" font=dict(size=12)) for j in range(4)])\n",
" \n",
" annotations.extend([dict(showarrow=False, # annotations for ticklabels on side 1\n",
" text=f'{ticklabel[j]}',\n",
" x=posx[j+4],\n",
" y=posy[j+4],\n",
" align='center',\n",
" xanchor='left', \n",
" yanchor='middle',\n",
" font=dict(size=12)) for j in range(4)])\n",
"\n",
" annotations.extend([dict(showarrow=False, # annotations for ticklabels on side 2\n",
" text=f'{ticklabel[j]}',\n",
" x=posx[j+8],\n",
" y=posy[j+8],\n",
" align='center',\n",
" xanchor='right', \n",
" yanchor='middle',\n",
" font=dict(size=12)) for j in range(4)])\n",
" return annotations"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"def styling_traces():\n",
" global xt, yt\n",
" side_trace = dict(type='scatter',\n",
" x=[0.5, 0, 1, 0.5],\n",
" y=[np.sqrt(3)/2, 0, 0, np.sqrt(3)/2],\n",
" mode='lines',\n",
" line=dict(width=2, color='#444444'),\n",
" hoverinfo='none')\n",
" \n",
" tick_trace = dict(type='scatter',\n",
" x=xt,\n",
" y=yt,\n",
" mode='lines',\n",
" line=dict(width=1, color='#444444'),\n",
" hoverinfo='none')\n",
" \n",
" return side_trace, tick_trace"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Extract and process data for a ternary contour plot"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"M, invM = tr_b2c2b()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Convert the barycentric coordinates of data points, (a, b, c), to cartesian coordinates:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"cartes_coord_points = np.einsum('ik, kj -> ij', M, np.stack((A, B, C)))\n",
"xx, yy = cartes_coord_points[:2]"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"a, b = xx.min(), xx.max()\n",
"c, d = yy.min(), yy.max()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define a meshgrid on the rectangle [a,b] x [c,d]:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"N=150\n",
"gr_x = np.linspace(a,b, N)\n",
"gr_y = np.linspace(c,d, N)\n",
"grid_x, grid_y = np.meshgrid(gr_x, gr_y)\n",
"\n",
"#interpolate data (cartes_coords[:2].T; z) and evaluate the interpolatory function at the meshgrid points to get grid_z\n",
"grid_z = griddata(cartes_coord_points[:2].T, z, (grid_x, grid_y), method='cubic')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Compute the barycentric coordinates of meshgrid points:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"bar_coords = np.einsum('ik, kmn -> imn', invM, np.stack((grid_x, grid_y, np.ones(grid_x.shape))))\n",
"bar_coords[np.where(bar_coords<0)] = None # invalidate the points outside of the reference triangle\n",
"xy1 = np.einsum('ik, kmn -> imn', M, bar_coords) # recompute back the cartesian coordinates of bar_coords with invalid positions\n",
" # and extract indices where x are nan\n",
"\n",
"I = np.where(np.isnan(xy1[0]))\n",
"grid_z[I] = None"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define the hover text for proportions and percents, i.e. when a hovered point displays a, b, c in [0,1], respectively in [0,100]:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"# tooltips for proportions, i.e. a+b+c=1\n",
"\n",
"t_proportions = [[f'a: {round(bar_coords[0][i,j], 2)}
b: {round(bar_coords[1][i,j], 2)}'+\\\n",
" f'
c: {round(1-round(bar_coords[0][i,j], 2)-round(bar_coords[1][i,j], 2), 2)}'+\\\n",
" f'
z: {round(grid_z[i,j],2)}' if ~np.isnan(xy1[0][i,j]) else '' for j in range(N)]\n",
" for i in range(N)] \n",
"\n",
"# tooltips for percents, i.e. a+b+c=100\n",
"t_percents=[[f'a: {int(100*bar_coords[0][i,j]+0.5)}
b: {int(100*bar_coords[1][i,j]+0.5)}'+\\\n",
" f'
c: {100-int(100*bar_coords[0][i,j]+0.5)-int(100*bar_coords[1][i,j]+0.5)}'+\\\n",
" f'
z: {round(grid_z[i,j],2)}' if ~np.isnan(xy1[0][i,j]) else '' for j in range(N)] \n",
" for i in range(N)] "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Colorscale for contour:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"pl_deep = [[0.0, 'rgb(253, 253, 204)'],\n",
" [0.1, 'rgb(201, 235, 177)'],\n",
" [0.2, 'rgb(145, 216, 163)'],\n",
" [0.3, 'rgb(102, 194, 163)'],\n",
" [0.4, 'rgb(81, 168, 162)'],\n",
" [0.5, 'rgb(72, 141, 157)'],\n",
" [0.6, 'rgb(64, 117, 152)'],\n",
" [0.7, 'rgb(61, 90, 146)'],\n",
" [0.8, 'rgb(65, 64, 123)'],\n",
" [0.9, 'rgb(55, 44, 80)'],\n",
" [1.0, 'rgb(39, 26, 44)']]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Ternary contour plot that displays proportions"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"xt = []\n",
"yt = []\n",
"posx = []\n",
"posy = []\n",
"for side in [0, 1, 2]:\n",
" cart_coord_ticks(side, t=0.01)\n",
"\n",
"\n",
"tooltip = t_proportions\n",
"layout = ternary_layout()\n",
"annotations = set_ticklabels(layout['annotations'], posx, posy, proportion=True)\n",
"\n",
"c_trace = contour_trace(gr_x, gr_y, grid_z, tooltip, colorscale=pl_deep, reversescale=True)\n",
"side_trace, tick_trace =styling_traces()\n",
"fw1 = go.FigureWidget(data=[c_trace, tick_trace, side_trace], layout=layout)\n",
"fw1.layout.annotations=annotations\n",
" \n",
"#fw1"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import plotly.plotly as py\n",
"py.sign_in('empet', 'api_key')\n",
"py.iplot(fw1, filename='ternary1_cont')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Ternary contour plot that displays percents"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Note**: When we associate the ternary contour plot to variables, A, B, C, with A+B+C=100, we have to scale each one by \n",
" $1./100$, because the code works with barycentric coordinates. In this case however we can pass the tooltips corresponding to percents and plot the percents as ticklabels:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"xt = []\n",
"yt = []\n",
"posx = []\n",
"posy = []\n",
"for side in [0, 1, 2]:\n",
" cart_coord_ticks(side, t=0.01)# set xt, yt posx, posy for this side\n",
"\n",
"\n",
"tooltip = t_percents\n",
"layout = ternary_layout(title='Ternary contour plot that displays percents')\n",
"annotations = set_ticklabels(layout['annotations'], posx, posy, proportion=False)\n",
"\n",
"c_trace = contour_trace(gr_x, gr_y, grid_z, tooltip, colorscale=pl_deep, reversescale=True)\n",
"side_trace, tick_trace = styling_traces()\n",
"fw2 = go.FigureWidget(data=[c_trace, tick_trace, side_trace], layout=layout)\n",
"fw2.layout.annotations=annotations\n",
"#fw2 "
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import plotly.plotly as py\n",
"py.iplot(fw2, filename='ternary2_cont')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}