Suppose one has multiple sets of annotations, which are merged into 1 large List
of annotations in the fig.update_layout
of the go.Figure
object in plotly/Dash. Since the annotations are created at different places, it may be somewhat tedious to keep track of the indices based on list index
. So I thought, if I add an identifier to the annotation, I am sure I am updating the right annotation each time. Especially as the annotations may contain duplicate properties or possibly be complete duplicates (without identifier).
A trivial MWE is included:
import plotly.graph_objects as go
import numpy as np
t = np.linspace(0, 4*np.pi, 50)
t2 = np.pi * np.arange(5)
fig = go.Figure(go.Scatter(x=t, y=np.sin(t), mode='lines'))
fig.add_trace(go.Scatter(x=t2, y=np.sin(t2), mode='markers'))
first_annotations=[
go.layout.Annotation(
x=point,
y=np.sin(point),
xref="x",
yref="y",
text="dict Text",
align='center',
showarrow=False,
yanchor='bottom',
textangle=90) for point in t2]
second_annotations=[
go.layout.Annotation(
x=point,
y=np.cos(point),
xref="x",
yref="y",
text="Other dict Text",
align='center',
showarrow=False,
yanchor='bottom',
textangle=90) for point in t2]
first_annotations.extend(second_annotations)
fig.update_layout(annotations=first_annotations
)
fig.show()
Example with 2 sets of annotations:
How can one add an identifier to an Annotation object in plotly dash?
I looked through the documentation of plotly.graph_objs.layout.Annotation:
however, I did not find an "identifier" (like) property.
You can create a super class called NamedAnnotation
with the desired name
property (as well as a getName
convenience function if you like):
from plotly.graph_objs.layout import Annotation
class NamedAnnotation(Annotation):
def __init__(self, name, **kwargs):
super().__init__(self, **kwargs)
self.name = name
def getName(self):
return self.name
Then you can use NamedAnnotations
instead of go.Layout.Annotation
and pass the new parameter name
:
first_names = [f"first_name_{i}" for i in range(len(t2))]
second_names = [f"second_name_{i}" for i in range(len(t2))]
first_annotations=[
NamedAnnotation(
name=name, # ⭠ new parameter
x=point,
y=np.sin(point),
xref="x",
yref="y",
text="dict Text",
align='center',
showarrow=False,
yanchor='bottom',
textangle=90) for name,point in zip(first_names,t2)]
second_annotations=[
NamedAnnotation(
name=name,
x=point,
y=np.cos(point),
xref="x",
yref="y",
text="Other dict Text",
align='center',
showarrow=False,
yanchor='bottom',
textangle=90) for name,point in zip(second_names,t2)]
first_annotations.extend(second_annotations)
If you need to get the name of any of your annotations at a later point in the program, you can do something like:
first_annotations[0].getName()
And this will return 'first_name_0'
.