【问题标题】:Using matplotlib, how can I print something "actual size"?使用 matplotlib,如何打印“实际尺寸”?
【发布时间】:2015-04-01 20:27:43
【问题描述】:

我有许多图,其中 x 轴和 y 轴以厘米为单位,并且我已经在使用 axis('equal') 来确保正确的纵横比。我想打印出这些图,以便在我测量轴内的距离时,这些距离对应于现实世界的厘米。

也就是说,图中 3 个单位 (cm) 长的线应打印为 3 cm 长。 (一个更复杂的例子是在 Matplotlib 中绘制尺子,然后将其打印出来以使用 /as/ 尺子。)我在 matlab 和 mathematica 中找到了解决方案,但不适用于 Matplotlib。有没有一个神奇的公式来实现这一点?我相信它需要一个特殊的组合/排序:figure(figsize=??), axis('equal')、fig.canvas.draw()、fig.savefig('filename',format="??"),可能是一些带有fig.bbox 参数的数学,可能还有一个或多个 dpi 设置。我尝试了很多组合,但没有找到正确的组合。也许有一种更简单的方法......

【问题讨论】:

  • 我认为缺少的步骤是强制 Axes 对象成为测量图形大小的已知比例,然后设置轴限制,以便数据单位与实际单位匹配。跨度>

标签: python printing matplotlib plot scaling


【解决方案1】:

考虑这个例子。我以厘米为单位精确指定轴的尺寸。 matplotlib 以英寸为单位,所以我转换为英寸。然后我还使用特定的 dpi (128) 保存它,以便它与我的显示器中的设计尺寸相匹配。这当然因每个显示器而异。我通过反复试验发现,即使可能有其他方法。那么这里的代码:

left_margin = 1.   # cm
right_margin = 1.  # cm
figure_width = 10. # cm
figure_height = 7. # cm
top_margin = 1.    # cm
bottom_margin = 1. # cm

box_width = left_margin + figure_width + right_margin   # cm
box_height = top_margin + figure_height + bottom_margin # cm

cm2inch = 1/2.54 # inch per cm

# specifying the width and the height of the box in inches
fig = figure(figsize=(box_width*cm2inch,box_height*cm2inch))
ax = fig.add_subplot(111)
ax.plot([1,2,3])

fig.subplots_adjust(left   = left_margin / box_width,
                    bottom = bottom_margin / box_height,
                    right  = 1. - right_margin / box_width,
                    top    = 1. - top_margin   / box_height,
                    )
fig.savefig('ten_x_seven_cm.png', dpi=128)
# dpi = 128 is what works in my display for matching the designed dimensions.

【讨论】:

  • 这是在显示器中——它可以与打印机一起使用吗? (原问题)
  • 如果您打开保存的图形并以 100% 的比例打印,它应该与指定的尺寸相匹配。对于打印机来说,dpi 只对图像的分辨率很重要。
  • 我刚试过,但没有;比规模大得多。甚至不是等距的——纸上的 y 单位是 3cm,x 单位是 5cm。这是 100% 比例打印的,没有自动任何东西,在查看器中查看实际大小,我能想到的一切。 (我相信打印机在这方面大多不可靠;准确的是绘图仪。)
  • 您使用什么查看/打印?我使用了 mac OS X 预览版。然后在打印机菜单中,比例为 100%,它完成了这项工作。另存为 pdf 也反映了所选的大小。
  • OS X Preview,标准桌面打印机。将尝试 GIMP。
【解决方案2】:

将此添加到@pablo reyes 的答案中,检查打印机是否处于 100%,并且非常接近;

ax.set_ylim(0,7)
ax.set_xlim(0,10)

ax.plot([0.5, 1.5],[0.25, 0.25],label='One cm?')
ax.plot([6,6],[1,2], label='One cm?')
ax.legend()

我们强制轴为我们知道的大小,我们使它的数据转换与现实世界相匹配,我们可以“打印一把尺子”。

【讨论】:

  • 现在我明白了困惑。我更关心轴的实际尺寸。
  • 是否可以编写一个 transReal 变换,使其尽可能接近计算机可以“打印尺子”? t 我认为 Axes 必须从 Figure 中获取该 Figure 通常不会传递的信息,所以,也许不会,而且肯定会很痛苦。
  • 谢谢大家!在将 dpi 修改为 72 后,Pablo 的解决方案大部分都有效。在添加 cphlewis 的片段时,我遇到了一些错误(奇怪?):我的 axis([xmin, xmax, ymin, ymax]) 命令被忽略了...... set_xlim 也有同样的问题() 和 set_ylim() ...也许是与轴('equal')的奇怪交互?解决方法是绘制所有内容,让 matplotlib 选择 x/y 限制,尝试强制它们(不成功),使用 ax.get_xlim() 和 ax.get_ylim() 来确定实际限制是什么(不是我设置的),从中计算 figure_width 和 figure_height,然后继续 Pablo 的解决方案。再次感谢!
  • 我认为axis([xo, x1, y0, y1]) 是关于数字的比例,而不是数据转换。你试过ax.set_xlim等,而不是原来定义轴大小?
  • 另外,如果您在打印时将它们定义为相等,则不需要 axis('equal') - 所以我将其取出,以跳过解决方法。
【解决方案3】:

使用fig.add_axes 的另一种方法非常准确。我也包括了 1 厘米的网格。

import matplotlib.pyplot as plt
import matplotlib as mpl

# This example fits a4 paper with 5mm margin printers

# figure settings
figure_width = 28.7 # cm
figure_height = 20 # cm
left_right_margin = 1 # cm
top_bottom_margin = 1 # cm

# Don't change
left   = left_right_margin / figure_width # Percentage from height
bottom = top_bottom_margin / figure_height # Percentage from height
width  = 1 - left*2
height = 1 - bottom*2
cm2inch = 1/2.54 # inch per cm

# specifying the width and the height of the box in inches
fig = plt.figure(figsize=(figure_width*cm2inch,figure_height*cm2inch))
ax = fig.add_axes((left, bottom, width, height))

# limits settings (important)
plt.xlim(0, figure_width * width)
plt.ylim(0, figure_height * height)

# Ticks settings
ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(5))
ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(1))
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(5))
ax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(1))

# Grid settings
ax.grid(color="gray", which="both", linestyle=':', linewidth=0.5)

# your Plot (consider above limits)
ax.plot([1,2,3,5,6,7,8,9,10,12,13,14,15,17])

# save figure ( printing png file had better resolution, pdf was lighter and better on screen)
plt.show()
fig.savefig('A4_grid_cm.png', dpi=1000)
fig.savefig('tA4_grid_cm.pdf')

结果:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-09
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多