Plot Inside a Plot

Embedding small plots inside subplots in matplotlib

I wrote a function very similar to plt.axes. You could use it for plotting yours sub-subplots. There is an example...

import matplotlib.pyplot as plt
import numpy as np

#def add_subplot_axes(ax,rect,facecolor='w'): # matplotlib 2.0+
def add_subplot_axes(ax,rect,axisbg='w'):
fig = plt.gcf()
box = ax.get_position()
width = box.width
height = box.height
inax_position = ax.transAxes.transform(rect[0:2])
transFigure = fig.transFigure.inverted()
infig_position = transFigure.transform(inax_position)
x = infig_position[0]
y = infig_position[1]
width *= rect[2]
height *= rect[3] # <= Typo was here
#subax = fig.add_axes([x,y,width,height],facecolor=facecolor) # matplotlib 2.0+
subax = fig.add_axes([x,y,width,height],axisbg=axisbg)
x_labelsize = subax.get_xticklabels()[0].get_size()
y_labelsize = subax.get_yticklabels()[0].get_size()
x_labelsize *= rect[2]**0.5
y_labelsize *= rect[3]**0.5
subax.xaxis.set_tick_params(labelsize=x_labelsize)
subax.yaxis.set_tick_params(labelsize=y_labelsize)
return subax

def example1():
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111)
rect = [0.2,0.2,0.7,0.7]
ax1 = add_subplot_axes(ax,rect)
ax2 = add_subplot_axes(ax1,rect)
ax3 = add_subplot_axes(ax2,rect)
plt.show()

def example2():
fig = plt.figure(figsize=(10,10))
axes = []
subpos = [0.2,0.6,0.3,0.3]
x = np.linspace(-np.pi,np.pi)
for i in range(4):
axes.append(fig.add_subplot(2,2,i))
for axis in axes:
axis.set_xlim(-np.pi,np.pi)
axis.set_ylim(-1,3)
axis.plot(x,np.sin(x))
subax1 = add_subplot_axes(axis,subpos)
subax2 = add_subplot_axes(subax1,subpos)
subax1.plot(x,np.sin(x))
subax2.plot(x,np.sin(x))
if __name__ == '__main__':
example2()
plt.show()

Sample Image

Plot inside a plot

OK, here's an example, which I plotted to a 10 by 10 inch pdf. (Part of what's frustrating about using par(fig = ) et al. is that their effects are very much dependent on the size of the plotting device.)


Edited to add some explanation:

The base graphic plotting parameter par("fig") describes/sets the location of a figure region as a proportion of the "drawing region" (which is usually the entire device, for single figure plots). It takes a length-4 vector of the form c(xmin, xmax, ymin, ymax) consisting of numbers (proportions) between 0 and 1.

Here I use grconvertX() and grconvertY() to convert x-y locations expressed in terms of the larger plot's own (a.k.a. "user") coordinate system into the "ndc" (normalized device coordinates) coordinate system. The "user" coordinate system is more human-user-friendly, while the "ndc" is (with the caveats expressed above) the coordinate system used by par("fig"). The grconvert*() calls are just there to perform the translation between them.

## pdf("fig-in-fig.pdf", width=10, height=10)
curve(exp(x), from=1, to=5, lwd=5)
curve(150-exp(x), from=1, to=5, lwd=5, col="darkblue",add=T)

## Here's the bit I added.
par(fig = c(grconvertX(c(1, 3), from="user", to="ndc"),
grconvertY(c(50, 125), from="user", to="ndc")),
mar = c(4,6,1,1),
new = TRUE)

curve(exp(x), from=1, to=5, lwd=7, xlab="chi", ylab="exp(x)", cex.lab=4,axes=F)
axis(1, labels=NA,at=c(0,5))
axis(2, labels=NA,at=c(0,150))
text(1,120,"Alpha",adj=c(0,0),cex=3)
text(3.5,10,"Beta",adj=c(0,0),cex=3)
## dev.off()

Sample Image

Gnuplot: multiplot and insets

This is how I understand your question. I guess you simply need to set the origin and sizes yourself. You can use variables to calculate the necessary values.

Code:

### multiplot with "insets"
reset session

set key top left
set multiplot

# settings for main plots
set ytics auto

# first plot
s1x = 0.5
s1y = 1.0
set size s1x, s1y
o1x = 0.0
o1y = 0.0
set origin o1x, o1y
plot exp(-x)

# second plot
s2x = 0.5
s2y = 1.0
set size s2x, s2y
o2x = 0.5
o2y = 0.0
set origin o2x, o2y
set ytics auto
plot exp(-2*x)

# settings for insets
set ytics 0.5

# first inset
set size s1x*0.6, s1y*0.5
set origin o1x+s1x*0.4, o1y+s1y*0.5
plot cos(x)

# second inset
set size s2x*0.6, s2y*0.5
set origin o2x+s2x*0.4, o2y+s2y*0.5
plot sin(x)

unset multiplot
### end of code

Result:

Sample Image

How to add different graphs (as an inset) in another python graph

There's more than one way do to this, depending on the relationship that you want the inset to have.

If you just want to inset a graph that has no set relationship with the bigger graph, just do something like:

import matplotlib.pyplot as plt

fig, ax1 = plt.subplots()

# These are in unitless percentages of the figure size. (0,0 is bottom left)
left, bottom, width, height = [0.25, 0.6, 0.2, 0.2]
ax2 = fig.add_axes([left, bottom, width, height])

ax1.plot(range(10), color='red')
ax2.plot(range(6)[::-1], color='green')

plt.show()

Sample Image

If you want to have some sort of relationship between the two, have a look at some of the examples here: http://matplotlib.org/1.3.1/mpl_toolkits/axes_grid/users/overview.html#insetlocator

This is useful if you want the inset to be a "zoomed in" version, (say, at exactly twice the scale of the original) that will automatically update as you pan/zoom interactively.

For simple insets, though, just create a new axes as I showed in the example above.

How to place a matplotlib plot inside a tkinter window in the simplest way possible?

Try this:

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk

# All of your code

root = tk.Tk() # Create the tkinter window

canvas = FigureCanvasTkAgg(fig, master=root) # Convert the Figure to a tkinter widget
canvas.get_tk_widget().pack() # Show the widget on the screen
canvas.draw() # Draw the graph on the canvas?

root.mainloop() # Start tkinter's mainloop

That will show your Figure on the screen. Please note that it uses the fig that you defined when you used fig, ax = plt.subplots()



Related Topics



Leave a reply



Submit