Trying to get, e.g., two annotations to lay one next to/above/below the other on a figure using xref=‘paper’, but (0,0) and (1,1) in the paper domain correspond to the plottable area, not the entire figure. Since layout.height and layout.width set the pixel size of the figure, I need to figure out how to back out the actual pixel dimensions of the paper coordinates. I tried subtracting out the margins, but that’s still not quite right (see code and image below).
Anyone know how I can get the exact pixel dimensions of the “paper” domain?
ann_width=80
ann_height=20
left_px = 50
right_px = 50
top_px = 50
bottom_px = 50
W_px = 800
H_px = 600
ann_1 = go.layout.Annotation(
text='TEXT_A',
xref='paper',
yref='paper',
bordercolor='black',
borderwidth=1,
height=ann_height,
width=ann_width,
showarrow=False
ann_2 = go.layout.Annotation(
text='TEXT_B',
x=ann_width/(W_px-left_px-right_px),
xref='paper',
yref='paper',
bordercolor='black',
borderwidth=1,
height=ann_height,
width=ann_width,
showarrow=False
fig_layout = go.Layout(
width=W_px,
height=H_px,
margin=dict(
l=left_px,
r=right_px,
t=top_px,
b=bottom_px,
annotations=[ann_1,ann_2]
fig = go.Figure(layout=fig_layout)
fig.show()
HI @gwurman welcome to the forums.
You are pretty close, but I think you have to include the border width of the annotations. Not sure if this is 100% correct though.
import plotly.graph_objects as go
ann_width=80
ann_height=20
left_px = 50
right_px = 50
top_px = 50
bottom_px = 50
W_px = 1800
H_px = 800
total = W_px-left_px-right_px
border_ann_1 = 1
border_ann_2 = 1
ann_1 = go.layout.Annotation(
text='TEXT_A',
xref='paper',
yref='paper',
bordercolor='black',
borderwidth=border_ann_1,
height=ann_height,
width=ann_width,
showarrow=False
ann_2 = go.layout.Annotation(
text='TEXT_B',
x=(ann_width+2*(border_ann_1+border_ann_2))/total,
xref='paper',
yref='paper',
bordercolor='black',
borderwidth=border_ann_2,
height=ann_height,
width=ann_width,
showarrow=False
fig_layout = go.Layout(
width=W_px,
height=H_px,
margin=dict(
l=left_px,
r=right_px,
t=top_px,
b=bottom_px,
annotations=[ann_1,ann_2]
fig = go.Figure(layout=fig_layout)
fig.show()
Thanks, that was exactly what I was missing. However, this is almost right. With a little playing around, I was able to figure out that the augmented annotation width should be:
aug_ann_width = ann_width + 2 * (border_width + 1)
This is assuming the annotations all have the same border width, which mine do. For a 1-pixel border the solutions are the same.
Hah! Be careful what you ask for! MRE is below. In the process of testing it I found a bug (try ncols>=4 or nrows>=8), which I will post as a new thread after I explore it a bit more.
import plotly.graph_objects as go
ann_width = 80
ann_height = 20
border_px = 2
aug_ann_height = ann_height + 2 * (border_px + 1)
aug_ann_width = ann_width + 2 * (border_px + 1)
left_px = 50
right_px = 50
top_px = 50
bottom_px = 50
W_px = 800
H_px = 600
reduced_W = W_px - left_px - right_px
reduced_H = H_px - top_px - bottom_px
nrows = 2
ncols = 2
annot_list = []
for row in range(nrows):
for col in range(ncols):
annot = go.layout.Annotation(
text = f'ANN_{len(annot_list)}',
x = col * (aug_ann_width / reduced_W),
y = row * (aug_ann_height / reduced_H),
xref = 'paper',
yref = 'paper',
bordercolor = 'black',
borderwidth = border_px,
height = ann_height,
width = ann_width,
showarrow=False
annot_list.append(annot)
fig_layout = go.Layout(
width = W_px,
height = H_px,
margin = dict(
l = left_px,
r = right_px,
t = top_px,
b = bottom_px,
annotations = annot_list
fig = go.Figure(layout=fig_layout)
fig.show()
Upon further investigation, it is not a bug, but rather an artifact of how annotations are aligned in paper coordinates.
Annotations with x on [0,1/3) will be aligned on the left edge of the annotation. With x on (2/3,1] they will be aligned on the right edge, and on [1/3,2/3] they will be aligned on center. Similar behavior in the y coordinate.
Caveat coder 