# Plots.jl with inset

I’m trying to use Plots.jl with an inset. For simplicity, consider the plot

``````x=range(0,3pi/2,length=100)
plot(x,[sin.(x),sinc.(x)], label=["sin" "sinc"])
``````

Suppose I want to insert an `inset` in the lower left corner of the plot with details of the same plot around the first crossing of the curves, i.e., ca. (x,y) ca = (0.6,0.5). So I want to replicate the same plot, say, with xlim changed to ca. xlim=(0.5,0.7) and ylim=(0.4,0.6) for the inset, and put it in the lower left corner.

How can I do that?

`inset_subplots` here: Layouts · Plots

Thanks, I figured it out…

It could have been simpler, but it works.

Nice! Feel free to post any suggestions, recent frustration is a valuable resource

2 Likes

Sorry for (week-end) delay. Here is more or less what I did (I don’t include all the code, just the essential parts).

### Here is what I did

Note: at the outset, I have already defined 3 functions: `uₒ`, `uₒ_c`, and `uₒ_` which depend on temperature in a temperature span `T_span`.

• I plot the “main plot”:
``````plot(T_span.-273.15,uₒ.(T_span),...)
plot!(T_span.-273.15,uₒ_c.(T_span),...
plot!(T_span.-273.15,uₒ_.(T_span),...)
``````
• Next, I plot the inset:
``````plot!(
T_span.-273.15, [uₒ.(T_span), uₒ_c.(T_span),uₒ_.(T_span)], ...
xlim=(0,100),ylim=(1.165,1.192),
frame=:box,
yticks=false,
inset=bbox(0.143,0.47,0.35,0.35),
subplot=2
)
``````

### Some “recent frustrations” and (unrealistic?) suggestions…

#### Things in documentation that confused me

1. At first, I didn’t know where to find the information in the documentation for Plots.jl.

If I search `Plots.jl` and open the

page, attempt to find the `inset` information by:

• typing in `inset` in the search box – now luck

• do `Ctrl+f` in the browser, and searched for `inset`. Again, now luck, because the browser search function only search in the active window, i.e., in the `Tutorial` up until (but not including) `Series Types`.

• your suggstion of `inset_subplots` helped somewhat, but what really helped is the link to `Layouts . Plots`.

Still, `inset_subplots` does not occur in the `plot` command… it is possible that `inset_subplots` really means "the range of commands from `inset` to `subplot`?? That is, however, not obvious to me.

NOTE: this problem I have with search is not unique for `Plots.jl`.

1. Somewhat confusing argument list?
``````# The call is `bbox(x, y, width, height, origin...)`, where numbers are treated as
# "percent of parent"
``````

This is somewhat confusing… the numbers (`x`, `y`, `width`, `height`) are not “percent of parent” (a number from 0-100), but fraction of parent (range: 0-1).

So my understanding of these numbers are:

• `x`, `y` gives the coordinates of the inset relative to the upper left corner of the parent figure, which is position (0,0), with coordinate axes going downwards (`x`) and to the right ( `y`), and where the lower right corner of the parent plot is in position (1,1).

• `width`, `height` specify the width and height of the inset in fraction of the parent plot window.

• Is it somewhat confusing the the first coordinate of `x`, `y` relates to the vertical position, while the first of `width`, `height` relates to horizontal size? More logical with `x`, `y`, `height`, `width`? Perhaps.

• the `origin` argument is not really explained. But from examples, I assume that it is possible with two arguments, and that the purpose is to define how the inset is positioned relative to the inset origin specified by `x`, `y`. Where the default is that the inset origin is the upper left corner of the inset, so possible `origin` commands are `:bottom`, `:right`, and similar.

1. What does the `subplot` command do? Do I have to set the `subplot = 2` if I have a single parent plot, i.e., without subplots?

#### Could the inset work in a simpler way?

Perhaps. The `plot` command may get somewhat convoluted for complex plots with insets.

Would it be possible to do my plot above in the following way?

``````plot(T_span.-273.15,uₒ.(T_span),...)
plot!(T_span.-273.15,uₒ_c.(T_span),...
fig_parent = plot!(T_span.-273.15,uₒ_.(T_span),...)
``````

followed by:

``````fig_sub = plot(T_span.-273.15, [uₒ.(T_span), uₒ_c.(T_span),uₒ_.(T_span)], ...
xlim=(0,100),ylim=(1.165,1.192),
frame=:box,
yticks=false)
``````

followed by:

``````plot!(fig_parent,
fig_sub,
inset=bbox(0.143,0.47,0.35,0.35),
subplot=2
``````

That way, the plot command holding the `inset` command itself becomes relatively simple, while it is still possible to created complex plots for the parent plot and the inset.

OK – I have no idea whether this is possible from the architecture of `Plots`

Yes, this is unfortunate. It’s really difficult to make everything that’s possible also easily searchable, but this could definitely be improved in this case. We should consider having a header for “Inset plots”, because it’s not obvious that the fifth (or whatever) item in that list, “Layouts” is the correct one.

Yes, that’s a mistake. I think your understanding of the arguments to `bbox` are nearly correct, but `x` goes from left to right and `y` goes from top to bottom, so they are in the same order as the `width`/`height` arguments. `origin` is poorly explained, I think a good solution would be to expand the docstring of `bbox` (which right now is pretty usesless).

Kind of, yes. This makes it so none of your keyword arguments affect the parent subplot. Consider

``````plot([sin, cos])
plot!([sin, cos]; xlim=(-0.5,0.5), inset=bbox(0.2,0.2,0.3,0.3,:right))
``````

and

``````plot([sin, cos])
plot!([sin, cos];xlim=(-0.5,0.5), inset=bbox(0.2,0.2,0.3,0.3,:right), subplot=2)
``````

These two will be very similar, but in the former, the `xlim` kwarg also updates the xlims of the parent subplot, so both of them go from -0.5 to 0.5, while the latter has the parent going from -4.5 to 4.5 and the inset going from -0.5 to 0.5. This is not at all transparent, but possibly necessary for this to be a consistent interface (What if I want to create an insert and update the xlims in a single call, this is how I would expect to do so). Perhaps the solution here is to create an `inset!(parent, ...)` alias, where the parent is not affected by any of the kwargs. Worth considering.

I agree with your suggestion, to be able to place a Plot object in an inset. In fact, when searching to see if anyone else had a similar suggestion in the Plots github repo, I found that I had raised just such an issue a year ago. I thought this sounded familiar. It should not be impossible to make one of these work.

Thank you for your comments! I hope the status quo is acceptable for now, I’ll try to make some time to make a PR at least fixing the documentation.

1 Like

Status quo is fine for now :-).

but `x` goes from left to right and `y` goes from top to bottom

Argh. Of course.

Could you please share the code for making this plot? I have two plots defined as p1 and p2. I am trying to have a similar plot to the one shown here.

Assuming two plots, `p1` and `p2` – for illustration

``````x = range(0,2pi,length=100)
p1 = plot(x,sin)
p2 = plot(x,cos)
``````

What I would have liked is the following to work (but it doesn’t):

``````plot(p1)
plot!(p2,
inset=bbox(0.15,0.45,0.35, 0.4),
subplot=2
)
``````

… the result is:

It seems like it is necessary to create `p2` inside of the `plot` statement which has the `inset` statement:

``````plot(p1)
plot!(x, cos,
inset=bbox(0.15,0.45,0.35, 0.4),
subplot=2
)
``````

which gives the desired result:

This lack of support for writing `plot!(p2, inset...)` is not a problem for a simple inset, but rather limiting for more complex insets.

@rafael.guerra – did you delete your response?

Anyways, I got an e-mail copy of your suggestions, and it works! Nice! Here is how it can be done:

``````x = range(0,2pi,length=100)
p1 = plot(x,sin)
``````

produces:

Then do:

``````plot!(p1,
inset=bbox(0.15,0.45,0.35, 0.4),
subplot=2)
``````

``````plot!(p1[2],x,cos)