Search code examples
pythonplotplotlydiagram

How to add data labels in ternary plotly diagram?


I am following the example from the plotly documentation. I obtained nice contour plot with datapoints:

enter image description here

Now I would like to make it more readable by either adding labels to the datapoints or to isolines. Currently, I can know datapoint's coordinates and values by hovering my mouse over it, but I would prefer those numbers to be permanently annotated, so I can for example print it in a scientific article.


Solution

  • I would highlight points of interest with fig.add_trace(go.Scatterternary() and tweak the text and marker attributes to make it look good. Here's an example where I've highlighted a point in the lower left corner:

    Plot 2

    enter image description here

    Why not fig.add_annotatoins() or something else?

    The perfect would arguably be to be able just set the hoverinfo for any given marker to show all the time. But to my knowledge that's just not possible at the moment. You could also use fig.add_annotations(), but as far as I know you would have to rely on x, y coordinates only both xref and yref set to paper.

    An upside of the fig.add_trace(go.Scatterternary() though is that you can include those data in the legend as well with:

    fig.update_layout(showlegend = True)
    fig.for_each_trace(lambda t: t.update(showlegend = False))
    fig.data[-1].showlegend = True
    

    Plot 2

    enter image description here

    Complete code:

    import plotly.figure_factory as ff
    import numpy as np
    import plotly.graph_objects as go
    
    
    Al, Cu = np.mgrid[0:1:7j, 0:1:7j]
    Al, Cu = Al.ravel(), Cu.ravel()
    mask = Al + Cu <= 1
    Al, Cu = Al[mask], Cu[mask]
    Y = 1 - Al - Cu
    
    enthalpy = (Al - 0.5) * (Cu - 0.5) * (Y - 1)**2
    fig = ff.create_ternary_contour(np.array([Al, Y, Cu]), enthalpy,
                                    pole_labels=['Al', 'Y', 'Cu'],
                                    ncontours=20,
                                    coloring='lines',
                                    showmarkers=True)
    
    fig.add_trace(go.Scatterternary(
        a = [2],
        b = [8],
        c = [2],
        mode = "markers+text",
        text = ["A"],
        texttemplate = "%{text}<br>(%{a:.2f}, %{b:.2f}, %{c:.2f})",
        textposition = "bottom center",
        marker_symbol = 'circle-open',
        marker_color = 'green',
        marker_line_width = 3,
        marker_size = 12,
        textfont = {'family': "Times", 'size': [14, 14, 14],
    #                 'color': ["IndianRed", "MediumPurple", "DarkOrange"]
                   }
    ))
    
    fig.update_layout(showlegend = True)
    fig.for_each_trace(lambda t: t.update(showlegend = False))
    fig.data[-1].showlegend = True
    
    fig.show()