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

Commit6119c12

Browse files
authored
DOC: manually placing images example (#28775)
1 parentac366ae commit6119c12

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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+
This example shows how to keep the images the same relative size, or
11+
how to make the images keep exactly the same pixels as the original data.
12+
13+
Preserving relative sizes
14+
=========================
15+
16+
By default the two images are made a similar size, despite one being 1.5 times the width
17+
of the other:
18+
"""
19+
20+
# sphinx_gallery_thumbnail_number = -1
21+
22+
importmatplotlib.pyplotasplt
23+
importnumpyasnp
24+
25+
importmatplotlib.patchesasmpatches
26+
27+
# make the data:
28+
N=450
29+
x=np.arange(N)/N
30+
y=np.arange(N)/N
31+
32+
X,Y=np.meshgrid(x,y)
33+
R=np.sqrt(X**2+Y**2)
34+
f0=5
35+
k=100
36+
a=np.sin(np.pi*2* (f0*R+k*R**2/2))
37+
A=a[:100, :300]
38+
B=A[:40, :200]
39+
40+
# default layout: both axes have the same size
41+
fig,axs=plt.subplots(1,2,facecolor='aliceblue')
42+
43+
axs[0].imshow(A,vmin=-1,vmax=1)
44+
axs[1].imshow(B,vmin=-1,vmax=1)
45+
46+
47+
defannotate_rect(ax):
48+
# add a rectangle that is the size of the B matrix
49+
rect=mpatches.Rectangle((0,0),200,40,linewidth=1,
50+
edgecolor='r',facecolor='none')
51+
ax.add_patch(rect)
52+
returnrect
53+
54+
annotate_rect(axs[0])
55+
56+
# %%
57+
# Note that both images have an aspect ratio of 1 (i.e. pixels are square), but
58+
# pixels sizes differ because the images are scaled to the same width.
59+
#
60+
# If the size of the images are amenable, we can preserve the relative sizes of two
61+
# images by using either the *width_ratio* or *height_ratio* of the subplots. Which
62+
# one you use depends on the shape of the image and the size of the figure.
63+
# We can control the relative sizes using the *width_ratios* argument *if* the images
64+
# are wider than they are tall and shown side by side, as is the case here.
65+
#
66+
# While we are making changes, let us also make the aspect ratio of the figure closer
67+
# to the aspect ratio of the axes using *figsize* so that the figure does not have so
68+
# much white space. Note that you could alternatively trim extra blank space when
69+
# saving a figure by passing ``bbox_inches="tight"`` to `~.Figure.savefig`.
70+
71+
fig,axs=plt.subplots(1,2,width_ratios=[300/200,1],
72+
figsize=(6.4,2),facecolor='aliceblue')
73+
74+
axs[0].imshow(A,vmin=-1,vmax=1)
75+
annotate_rect(axs[0])
76+
77+
axs[1].imshow(B,vmin=-1,vmax=1)
78+
# %%
79+
# Given that the data subsample is in the upper left of the larger image,
80+
# it might make sense if the top of the smaller Axes aligned with the top of the larger.
81+
# This can be done manually by using `~.Axes.set_anchor`, and using "NW" (for
82+
# northwest).
83+
84+
fig,axs=plt.subplots(1,2,width_ratios=[300/200,1],
85+
figsize=(6.4,2),facecolor='aliceblue')
86+
87+
axs[0].imshow(A,vmin=-1,vmax=1)
88+
annotate_rect(axs[0])
89+
90+
axs[0].set_anchor('NW')
91+
axs[1].imshow(B,vmin=-1,vmax=1)
92+
axs[1].set_anchor('NW')
93+
94+
# %%
95+
# Explicit placement
96+
# ==================
97+
# The above approach with adjusting ``figsize`` and ``width_ratios`` does
98+
# not generalize well, because it needs manual parameter tuning, and
99+
# possibly even code changes to using ``height_ratios`` instead of
100+
# ``width_ratios`` depending on the aspects and layout of the images.
101+
#
102+
# We can alternative calculate positions explicitly and place Axes at absolute
103+
# coordinates using `~.Figure.add_axes`. This takes the position in the form
104+
# ``[left bottom width height]`` and is in
105+
# :ref:`figure coordinates <transforms_tutorial>`. In the following, we
106+
# determine figure size and Axes positions so that one image data point
107+
# is rendered exactly to one figure pixel.
108+
109+
dpi=100# 100 pixels is one inch
110+
111+
# All variables from here are in pixels:
112+
buffer=0.35*dpi# pixels
113+
114+
# Get the position of A axes
115+
left=buffer
116+
bottom=buffer
117+
ny,nx=np.shape(A)
118+
posA= [left,bottom,nx,ny]
119+
# we know this is tallest, so we can already get the fig height (in pixels)
120+
fig_height=bottom+ny+buffer
121+
122+
# place the B axes to the right of the A axes
123+
left=left+nx+buffer
124+
125+
ny,nx=np.shape(B)
126+
# align the bottom so that the top lines up with the top of the A axes:
127+
bottom=fig_height-buffer-ny
128+
posB= [left,bottom,nx,ny]
129+
130+
# now we can get the fig width (in pixels)
131+
fig_width=left+nx+buffer
132+
133+
# figsize must be in inches:
134+
fig=plt.figure(figsize=(fig_width/dpi,fig_height/dpi),facecolor='aliceblue')
135+
136+
# the position posA must be normalized by the figure width and height:
137+
ax=fig.add_axes([posA[0]/fig_width,posA[1]/fig_height,
138+
posA[2]/fig_width,posA[3]/fig_height])
139+
ax.imshow(A,vmin=-1,vmax=1)
140+
annotate_rect(ax)
141+
142+
ax=fig.add_axes([posB[0]/fig_width,posB[1]/fig_height,
143+
posB[2]/fig_width,posB[3]/fig_height])
144+
ax.imshow(B,vmin=-1,vmax=1)
145+
plt.show()
146+
# %%
147+
# Inspection of the image will show that it is exactly 3* 35 + 300 + 200 = 605
148+
# pixels wide, and 2 * 35 + 100 = 170 pixels high (or twice that if the 2x
149+
# version is used by the browser instead). The images should be rendered with
150+
# exactly 1 pixel per data point (or four, if 2x).
151+
#
152+
# .. admonition:: References
153+
#
154+
# The use of the following functions, methods, classes and modules is shown
155+
# in this example:
156+
#
157+
# - `matplotlib.axes.Axes.imshow`
158+
# - `matplotlib.figure.Figure.add_axes`
159+
#
160+
# .. tags::
161+
#
162+
# component: figure
163+
# component: axes
164+
# styling: position
165+
# plot-type: image

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp