Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6faa8e0

Browse files
committed
DOC: manually placing images example
1 parentd8ff960 commit6faa8e0

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
"""
2+
=========================================
3+
Placing images, preserving relative sizes
4+
=========================================
5+
6+
By default Matplotlib resamples images created with `~.Axes.imshow` to
7+
fit inside the parent `~.axes.Axes`. This can mean that images that have very
8+
different original sizes can end up appearing similar in size.
9+
10+
Sometimes, however, it is desirable to keep the images the same relative size, or
11+
even to make the images keep exactly the same pixels as the original data.
12+
Matplotlib does not automatically make either of these things happen,
13+
but it is possible with some manual manipulation.
14+
15+
Preserving relative sizes
16+
=========================
17+
18+
By default the two images are made a similar size, despite one being 1.5 times the width
19+
of the other:
20+
"""
21+
22+
# sphinx_gallery_thumbnail_number = -1
23+
24+
importmatplotlib.pyplotasplt
25+
importnumpyasnp
26+
27+
importmatplotlib.patchesasmpatches
28+
29+
# make the data:
30+
N=450
31+
x=np.arange(N)/N
32+
y=np.arange(N)/N
33+
34+
X,Y=np.meshgrid(x,y)
35+
R=np.sqrt(X**2+Y**2)
36+
f0=5
37+
k=100
38+
a=np.sin(np.pi*2* (f0*R+k*R**2/2))
39+
A=a[:100, :300]
40+
B=A[:40, :200]
41+
42+
# plot with default axes handling:
43+
fig,axs=plt.subplots(1,2,facecolor='aliceblue')
44+
45+
axs[0].imshow(A,vmin=-1,vmax=1)
46+
axs[1].imshow(B,vmin=-1,vmax=1)
47+
48+
49+
defannotate_rect(ax):
50+
# add a rectangle that is the size of the B matrix
51+
rect=mpatches.Rectangle((0,0),200,40,linewidth=1,
52+
edgecolor='r',facecolor='none')
53+
ax.add_patch(rect)
54+
returnrect
55+
56+
annotate_rect(axs[0])
57+
58+
# %%
59+
# Note that both images are rendered at a 1:1 ratio, but are made to look almost the
60+
# same width, despite image B being smaller than image A.
61+
#
62+
# If the size of the images are amenable, we can preserve the relative sizes of two
63+
# images by using either the *width_ratio* or *height_ratio* of the subplots. Which
64+
# one you use depends on the shape of the image and the size of the figure.
65+
# We can control the relative sizes using the *width_ratios* argument *if* the images
66+
# are wider than they are tall and shown side by side, as is the case here.
67+
68+
fig,axs=plt.subplots(1,2,width_ratios=[300/200,1],facecolor='aliceblue')
69+
70+
axs[0].imshow(A,vmin=-1,vmax=1)
71+
annotate_rect(axs[0])
72+
73+
axs[1].imshow(B,vmin=-1,vmax=1)
74+
75+
# %%
76+
# Given that the data subsample is in the upper left of the larger image,
77+
# it might make sense if the top of the smaller Axes aligned with the top of the larger.
78+
# This can be done manually by using `~.Axes.set_anchor`, and using "NW" (for
79+
# northwest).
80+
81+
fig,axs=plt.subplots(1,2,width_ratios=[300/200,1],facecolor='aliceblue')
82+
83+
axs[0].imshow(A,vmin=-1,vmax=1)
84+
annotate_rect(axs[0])
85+
86+
axs[0].set_anchor('NW')
87+
axs[1].imshow(B,vmin=-1,vmax=1)
88+
axs[1].set_anchor('NW')
89+
90+
# %%
91+
# Note that this procedure still leaves large white spaces (that can be trimmed
92+
# in a final product by ``bbox_inches="tight"`` in `~.Figure.savefig`), and is
93+
# not very general. For instance, if the axes had been arranged vertically
94+
# instead of horizontally, setting the height aspect ratio would not have
95+
# helped because the axes are wider than they are tall. For more complicated
96+
# situations it is necessary to place the axes manually.
97+
#
98+
# Manual placement
99+
# ================
100+
#
101+
# We can manually place axes when they are created by passing a position to
102+
# `~.Figure.add_axes`. This position takes the form ``[left bottom width height]`` and
103+
# is in units that are a fraction of the figure width and height. Here we decide how
104+
# large to make the axes based on the size of the images, and add a small buffer of
105+
# 0.35 inches. We do all this at 100 dpi.
106+
107+
dpi=100# 100 pixels is one inch
108+
109+
# All variables from here are in pixels:
110+
buffer=0.35*dpi# pixels
111+
112+
# Get the position of A axes
113+
left=buffer
114+
bottom=buffer
115+
ny,nx=np.shape(A)
116+
posA= [left,bottom,nx,ny]
117+
# we know this is tallest, so we can already get the fig height (in pixels)
118+
fig_height=bottom+ny+buffer
119+
120+
# place the B axes to the right of the A axes
121+
left=left+nx+buffer
122+
123+
ny,nx=np.shape(B)
124+
# align the bottom so that the top lines up with the top of the A axes:
125+
bottom=fig_height-buffer-ny
126+
posB= [left,bottom,nx,ny]
127+
128+
# now we can get the fig width (in pixels)
129+
fig_width=left+nx+buffer
130+
131+
# figsize must be in inches:
132+
fig=plt.figure(figsize=(fig_width/dpi,fig_height/dpi),facecolor='aliceblue')
133+
134+
# the position posA must be normalized by the figure width and height:
135+
ax=fig.add_axes([posA[0]/fig_width,posA[1]/fig_height,
136+
posA[2]/fig_width,posA[3]/fig_height])
137+
ax.imshow(A,vmin=-1,vmax=1)
138+
annotate_rect(ax)
139+
140+
ax=fig.add_axes([posB[0]/fig_width,posB[1]/fig_height,
141+
posB[2]/fig_width,posB[3]/fig_height])
142+
ax.imshow(B,vmin=-1,vmax=1)
143+
144+
# %%
145+
# Inspection of the image will show that it is exactly 3* 35 + 300 + 200 = 605
146+
# pixels wide, and 2 * 35 + 100 = 170 pixels high (or twice that if the 2x
147+
# version is used by the browser instead). The images should be rendered with
148+
# exactly 1 pixel per data point (or four, if 2x).

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp