PlotlyJS: subplots with subplot_titles + annotations

I need to create a figure with subplots using PlotlyJS. In particular, I need one with annotations and individual titles in the different subplots. I searched the internet and found an excellent example by @empet, which includes annotations, here.

@empte’s code and figure are below:

using PlotlyJS

fig= make_subplots(rows=1, cols=2,
	subplot_titles= ["First subplot"  "Second subplot"]	)

add_trace!(fig, scatter(
    x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
    y=[0, 1, 3, 2, 4, 3, 4, 6, 5]), 
    row=1, col=1)

add_trace!(fig, scatter(
    x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
    y=[0, 4, 5, 1, 2, 2, 3, 4, 2]), 
    row=1, col=2)

annotations =

    [attr(x=0.6,  #annot similar to ref "paper" when the fig contains only one subpl, 
                            #but here within plot area of the first trace
            y=0.75,
            xref="x domain",
            yref="y domain",
            text="refs domain<br>(0.6,0.75)",
            showarrow=false,
            align="center"), 
             
	attr(x=0.6,  #annot similar to ref "paper" when the fig contains only one subpl, 
                            #but here within plot area of the second trace
            y=0.75,
            xref="x2 domain",
            yref="y2 domain",
            text="refs domain<br>(0.6,0.75)",
            showarrow=false,
            align="center"),

    attr(x=0.5, #annot  with respect to "paper", below the fig plot area
            y=-0.15,
            xref="paper",
            yref="paper",
            text="refs paper<br>(0.5,-0.15)",
            showarrow=false,
            align="center"),

    attr(x=6, #annot with respect to xaxis 1, yaxis1
            y=1.5,
            xref="x1",
            yref="y1",
            text="refs x1, y1<br>(6,1.5)",
            showarrow=false,
            align="center"),

    attr(x=4, #annot with respect to xaxis2, yaxis2
            y=4.5,
            xref="x2",
            yref="y2",
            text="refs x2, y2<br>(4,4.5)",
            showarrow=false,
            align="center",
    )]
relayout!(fig, width=900, height=400, annotations=annotations)
fig

I can replicate @empet’s example. However, when I tried to add subplot_titles=["Subplot 1" "subplot 2"] it did not work. If I force having subplot_titles, I will not get the annotations, and vice versa. What am I doing wrong here?

Help will be very much appreciated.

Thanks

The subplot titles are added to layout as annotations.
This line:

relayout!(fig, width=900, height=400,
                     annotations=annotations)

does not update annotations, but overwrites the existing ones, i.e. the subplot titles.
In order to get the right plot, the first idea that comes to my mind is to proceed as follows:

relayout!(fig, width=900, height=400)
append!(fig.plot.layout.annotations, annotations)
display(fig)
1 Like

@empet, thank you very much. Your little trick did the job. The knowledge you have about this stuff seems never to end. In Pluto, your solution:

let
	fig= make_subplots(rows=1, cols=2,
		subplot_titles= ["First subplot"  "Second subplot"])
	
	add_trace!(fig, scatter(
    	x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
    	y=[0, 1, 3, 2, 4, 3, 4, 6, 5]), 
		row=1, col=1)
	add_trace!(fig, scatter(
    	x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
    	y=[0, 4, 5, 1, 2, 2, 3, 4, 2]), 
		row=1, col=2)

	annotations = [

    attr(x=0.6,  #annot similar to ref "paper" when the fig contains only one subpl, 
                            #but here within plot area of the first trace
            y=0.75,
            xref="x domain",
            yref="y domain",
            text="refs domain<br>(0.6,0.75)",
            showarrow=false,
            align="center"), 
             
	attr(x=0.6,  #annot similar to ref "paper" when the fig contains only one subpl, 
                            #but here within plot area of the second trace
            y=0.75,
            xref="x2 domain",
            yref="y2 domain",
            text="refs domain<br>(0.6,0.75)",
            showarrow=false,
            align="center"),

    attr(x=0.5, #annot  with respect to "paper", below the fig plot area
            y=-0.15,
            xref="paper",
            yref="paper",
            text="refs paper<br>(0.5,-0.15)",
            showarrow=false,
            align="center"),

    attr(x=6, #annot with respect to xaxis 1, yaxis1
            y=1.5,
            xref="x1",
            yref="y1",
            text="refs x1, y1<br>(6,1.5)",
            showarrow=false,
            align="center"),

    attr(x=4, #annot with respect to xaxis2, yaxis2
            y=4.5,
            xref="x2",
            yref="y2",
            text="refs x2, y2<br>(4,4.5)",
            showarrow=false,
            align="center" )
	]
	
	relayout!(fig, width=900, height=400)
	append!(fig.Plot.layout.annotations, annotations)
	fig

end

A small note. In VScode, the same code that does the job in Pluto does not lead to the same result (maybe the reactivity of Pluto has advantages here). It produces two sequential plots:

Anyway, the fact that it works in Pluto is what matters to me.

Thanks

@empet, contrary to what I mentioned in my previous post, using your code in a slightly different example works both in VScode and Pluto. In VScode:

using PlotlyJS

p = make_subplots(rows=2, cols=2, specs=[Spec(colspan=2) missing ; Spec() Spec()],
subplot_titles=["First subplot"  "Third subplot" ; "Second subplot" missing],
vertical_spacing = 0.1, horizontal_spacing = 0.09 )

add_trace!(p, scatter(x=1962:2022, y = randn(61), mode = "markers+lines", marker_color="navy", 
            marker_size = 7, marker_symbol = "circle", line_width = 0.5 , linewitdth=0.3, 
            name = "Birds"), 
            row=1, col=1)
	
add_trace!(p, scatter(x=1962:2022, y = randn(61), mode = "markers+lines", marker_color="blue",
            marker_size = 5.5, marker_symbol = "circle", line_width = 0.5 , linewitdth=0.3, 
            name = "Cats"), 
			row=2, col=1)
	
add_trace!(p, scatter(x=1962:2022, y = randn(61), mode = "markers+lines", marker_color="maroon",
            marker_size = 5.5, marker_symbol = "circle", line_width = 0.5 , linewitdth = 0.3, 
			name = "Dogs" ), 
			row=2, col=2)

	annotations=[
		attr(x=1999 , y=2.5, text="One cat", showarrow=false, arrowhead=1 ),
        attr(x=2008 , y=2.5, text="One dog", showarrow=false, arrowhead=1 ),
        attr(x=2019 , y=2.5, text="One frog", showarrow=false, yshift=0 )]

	
relayout!(p, showlegend=true, title_text = "Figure with subplots and annotations", 
            height = "700", xaxis_range = [1960, 2023], hovermode = "x", yaxis_range=[-3 , 3])	
	
append!(p.plot.layout.annotations, annotations)

add_shape!(p, line( x0=2001, y0=-3, x1=2001, y1=3,  line=attr(color="RoyalBlue", width=1.5, 
            dash="dashdot")), row=1, col=1)
	
add_shape!(p, line( x0=2008, y0=-3, x1=2008, y1=3,  line=attr(color="RoyalBlue", width=1.5, 
            dash="dashdot")), row=1, col=1)
	
add_shape!(p, line( x0=2019, y0=-3, x1=2019, y1=3,  line=attr(color="RoyalBlue", width=1.5, 
            dash="dashdot")), row=1, col=1)
p

with the plot:

1 Like