Plot in plot at grdipoint using Plots.jl

I am trying to make a plot, in which I want to position another shrunk plot at certain coordinates of my first plot (MWE below).

Following the example at the end of the Layouts manual, I can, given a base plot p, use
Plots.scatter!(p, randn(100), inset = (1, bbox(x_norm,y_norm, 0.1, 0.1, :bottom))
to add a basic scatter plot to at the point with normalized coordinates `x_norm, y_norm``.

However, when I try to add a more sophisticated plot, call it s, which I can not declare in one go, I cannot use

Plots.plot!(p, s, inset = (1, bbox(x_norm,y_norm, 0.1, 0.1, :bottom))

which throws the error:

Error showing value of type Plots.Plot{Plots.GRBackend}:
ERROR: MethodError: no method matching get(::Int64, ::Symbol, ::Int64)

MWE:

using Plots

xs = -5:.1:5 
f = 0.5 * xs.^2 

## First Plot 

p = Plots.plot()

plot!(p,xs,f, 
    label = :none, 
    fc = :blues, 
    fillrange = zero(xs), 
    lc = :blues 
)

plot!(p,xs,f, 
	fillrange = fill(20,length(xs)),
    fillalpha = 0.35,
    fc = :red,  
    label = :none, 
    linewidth = 0.0, 
    grid=false,
    widen = false
)

p

## Second plot 

step = [-10,10,0] 
mult = [25,25,51]
vals = randn.(mult) .+ [fill(val,mult) for (val,mult) in zip(step,mult)]

seq_ends = cumsum(vcat(0,mult))
seqs = [(1+seq_ends[i-1]):seq_ends[i] for i in 2:length(seq_ends)]

(x,y) = (0,10)
scatter!(p, [x], [y], color = :gray, label = :none, fillstyle = :none, markersize = 1 ) 

## Normalize the unnormalized coordinates
xlim = Plots.xlims(p) 
ylim = Plots.ylims(p) 

offset_abs =  .01

x_norm = (x  - xlim[1]) / (xlim[2] - xlim[1]) * 1.025
y_norm = (y  - ylim[1]) / (ylim[2] - ylim[1]) * 1.025

s = Plots.plot() 
for i in eachindex(seqs)
    Plots.plot!(s,seqs[i],fill(step[i],length(seqs[i])), 
        linecolor = :purple, 
        linewidth = 2, 
        label = :none 
    )  
end 

Plots.scatter!(s,vcat(vals...), 
    color = :gray,
    label = :none 
)

s

## This works: 

Plots.scatter!(p,
    vcat(vals...),
    color = :gray,
    label = :none, 
    markersize = 1, 
    inset = (1, bbox(x_norm, y_norm, 0.1, 0.1, :bottom)),
    subplot = 2, 
    ticks = nothing,
    bg_inside = nothing
)

p2

## This does not 

Plots.plot!(
    p,
    s,
    inset = (1, bbox(x_norm, y_norm, 0.1, 0.1, :bottom)),
    subplot = 2, 
    ticks = nothing,
    bg_inside = nothing,
    label =:none 
)
Error showing value of type Plots.Plot{Plots.GRBackend}:
ERROR: MethodError: no method matching get(::Int64, ::Symbol, ::Int64)
Closest candidates are:
  get(::Union{Tables.AbstractColumns, Tables.AbstractRow}, ::Union{Integer, Symbol}, ::Any) at ~/.julia/packages/Tables/AcRIE/src/Tables.jl:193
  get(::DataStructures.RobinDict{K, V}, ::Any, ::Any) where {K, V} at ~/.julia/packages/DataStructures/59MD0/src/robin_dict.jl:384
  get(::DataStructures.PriorityQueue, ::Any, ::Any) at ~/.julia/packages/DataStructures/59MD0/src/priorityqueue.jl:176
  ...
Stacktrace:
  [1] get_thickness_scaling(kw::Int64)
    @ Plots ~/.julia/packages/Plots/p3KMq/src/utils.jl:603
  [2] get_thickness_scaling(series::Plots.Series)
    @ Plots ~/.julia/packages/Plots/p3KMq/src/utils.jl:606
  [3] gr_set_line(lw::Int64, style::Symbol, c::PlotUtils.ContinuousColorGradient, s::Plots.Series)
    @ Plots ~/.julia/packages/Plots/p3KMq/src/backends/gr.jl:410
  [4] gr_draw_segments(series::Plots.Series, x::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, y::Vector{Float64}, z::Nothing, fillrange::Vector{Float64}, clims::Tuple{Float64, Float64})
    @ Plots ~/.julia/packages/Plots/p3KMq/src/backends/gr.jl:1815
  [5] gr_add_series(sp::Plots.Subplot{Plots.GRBackend}, series::Plots.Series)
    @ Plots ~/.julia/packages/Plots/p3KMq/src/backends/gr.jl:1742
  [6] gr_display(sp::Plots.Subplot{Plots.GRBackend}, w::Measures.AbsoluteLength, h::Measures.AbsoluteLength, vp_canvas::Plots.GRViewport{Float64})
    @ Plots ~/.julia/packages/Plots/p3KMq/src/backends/gr.jl:964
  [7] (::Plots.var"#532#533"{Int64, Int64, Plots.GRViewport{Float64}})(sp::Plots.Subplot{Plots.GRBackend})
    @ Plots ~/.julia/packages/Plots/p3KMq/src/backends/gr.jl:688
  [8] foreach(f::Plots.var"#532#533"{Int64, Int64, Plots.GRViewport{Float64}}, itr::Vector{Plots.Subplot})
    @ Base ./abstractarray.jl:2774
  [9] gr_display(plt::Plots.Plot{Plots.GRBackend}, dpi_factor::Int64)
    @ Plots ~/.julia/packages/Plots/p3KMq/src/backends/gr.jl:688
 [10] #575
    @ ~/.julia/packages/Plots/p3KMq/src/backends/gr.jl:2052 [inlined]
 [11] withenv(::Plots.var"#575#576"{Plots.Plot{Plots.GRBackend}, Int64}, ::Pair{String, String}, ::Vararg{Pair{String, String}})
    @ Base ./env.jl:172
 [12] _show(io::IOBuffer, #unused#::MIME{Symbol("image/svg+xml")}, plt::Plots.Plot{Plots.GRBackend})
    @ Plots ~/.julia/packages/Plots/p3KMq/src/backends/gr.jl:2047
 [13] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [14] invokelatest
    @ ./essentials.jl:726 [inlined]
 [15] show
    @ ~/.julia/packages/Plots/p3KMq/src/output.jl:232 [inlined]
 [16] __binrepr(m::MIME{Symbol("image/svg+xml")}, x::Plots.Plot{Plots.GRBackend}, context::Nothing)
    @ Base.Multimedia ./multimedia.jl:159
 [17] display(d::VSCodeServer.InlineDisplay, m::MIME{Symbol("image/svg+xml")}, x::Plots.Plot{Plots.GRBackend})
    @ VSCodeServer ./strings/string.jl:0
 [18] display(d::VSCodeServer.InlineDisplay, mime::String, x::Any)
    @ Base.Multimedia ./multimedia.jl:216
 [19] display(d::VSCodeServer.InlineDisplay, x::Plots.Plot{Plots.GRBackend})
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.38.2/scripts/packages/VSCodeServer/src/display.jl:165
 [20] display(x::Any)
    @ Base.Multimedia ./multimedia.jl:328
 [21] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [22] invokelatest
    @ ./essentials.jl:726 [inlined]
 [23] print_response(errio::IO, response::Any, show_value::Bool, have_color::Bool, specialdisplay::Union{Nothing, AbstractDisplay})
    @ REPL /Applications/Julia-1.8.5.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:296
 [24] (::REPL.var"#45#46"{REPL.LineEditREPL, Pair{Any, Bool}, Bool, Bool})(io::Any)
    @ REPL /Applications/Julia-1.8.5.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:278
 [25] with_repl_linfo(f::Any, repl::REPL.LineEditREPL)
    @ REPL /Applications/Julia-1.8.5.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:521
 [26] print_response(repl::REPL.AbstractREPL, response::Any, show_value::Bool, have_color::Bool)
    @ REPL /Applications/Julia-1.8.5.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:276
 [27] (::REPL.var"#do_respond#66"{Bool, Bool, REPL.var"#77#87"{REPL.LineEditREPL, REPL.REPLHistoryProvider}, REPL.LineEditREPL, REPL.LineEdit.Prompt})(s::REPL.LineEdit.MIState, buf::Any, ok::Bool)
    @ REPL /Applications/Julia-1.8.5.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:857
 [28] (::VSCodeServer.var"#98#101"{REPL.var"#do_respond#66"{Bool, Bool, REPL.var"#77#87"{REPL.LineEditREPL, REPL.REPLHistoryProvider}, REPL.LineEditREPL, REPL.LineEdit.Prompt}})(mi::REPL.LineEdit.MIState, buf::IOBuffer, ok::Bool)
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.38.2/scripts/packages/VSCodeServer/src/repl.jl:122
 [29] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [30] invokelatest
    @ ./essentials.jl:726 [inlined]
 [31] run_interface(terminal::REPL.Terminals.TextTerminal, m::REPL.LineEdit.ModalInterface, s::REPL.LineEdit.MIState)
    @ REPL.LineEdit /Applications/Julia-1.8.5.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/LineEdit.jl:2510
 [32] run_frontend(repl::REPL.LineEditREPL, backend::REPL.REPLBackendRef)
    @ REPL /Applications/Julia-1.8.5.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:1248
 [33] (::REPL.var"#49#54"{REPL.LineEditREPL, REPL.REPLBackendRef})()
    @ REPL ./task.jl:484

Perhaps it is necessary to plot to the same inset incrementaly, as shown here (in old Julia, the new syntax has changed a bit).

Indeed, thanks for the pointer! This works:

for i in eachindex(seqs)
           Plots.plot!(p[2],seqs[i],fill(step[i],length(seqs[i])), 
               linecolor = :purple, 
               linewidth = 2, 
               label = :none 
           )  
end 

with the desired result
p3

1 Like