如何在不中断的情况下以物理单位绘制FancyBboxPatch?

时间:2019-06-20 00:35:23

标签: python matplotlib

我想将数据绘制为英寸的物理单位(也就是说,数据以“点”为单位,可以转换为英寸)。 (我看过matplotlib转换教程。)在下面的代码中,我希望能够自动计算所需的figsize。为此,我对三个变量WIDTH_SHIFT,HEIGHT_SHIFT和PORTION_OF_PLOT_INSIDE_THE_MARGINS进行了硬编码。这些值适用于本示例,但是,随着数字变大,我需要增加SHIFT变量,并且可能还需要更改PORTION变量。如果可能,我想自动计算这些值,或者找到其他方法。如果我将WIDTH_SHIFT和HEIGHT_SHIFT设置为零,则ABCDEFG和F节点框将无法正确绘制。它们落在轴外。 ABCDEFG框已部分绘制。

import matplotlib.pyplot as plt
from matplotlib.patches import BoxStyle, FancyBboxPatch


# Set-up the node data

node_width_ABCDEFG = 116/72  # inches
node_height_ABCDEFG = 28/72  # inches
node_center_x_ABCDEFG = 0 + 58/72  # inches
node_center_y_ABCDEFG = 3 + 14/72  # inches
lower_left_corner_ABCDEFG = [
    node_center_x_ABCDEFG - node_width_ABCDEFG/2,
    node_center_y_ABCDEFG - node_height_ABCDEFG/2]

node_width_F = 28/72  # inches
node_height_F = 28/72  # inches
node_center_x_F = 3 + 14/72  # inches
node_center_y_F = 0 + 14/72  # inches
lower_left_corner_F = [node_center_x_F - node_width_F/2,
                       node_center_y_F - node_height_F/2]

node_width_E = 28/72  # inches
node_height_E = 28/72  # inches
node_center_x_E = 5 + 14/72  # inches
node_center_y_E = 4 + 14/72  # inches
lower_left_corner_E = [node_center_x_E - node_width_E/2,
                       node_center_y_E - node_height_E/2]

node_width_C = 28/72  # inches
node_height_C = 28/72  # inches
node_center_x_C = 2.8 + 14/72  # inches  
node_center_y_C = 4.4 + 14/72  # inches
lower_left_corner_C = [node_center_x_C - node_width_C/2,
                       node_center_y_C - node_height_C/2]

# Compute size parameters needed to create the figure

# left edge of box ABCDEFG to right edge of box E
network_width_inches = (
    (node_center_x_E + node_width_E/2) - 
    (node_center_x_ABCDEFG - node_width_ABCDEFG/2))

# top edge of box C to bottom edge of box F
network_height_inches = (
    (node_center_y_C + node_height_C/2) - 
    (node_center_y_F - node_height_F/2))

print("network width inches: ", network_width_inches)
print("network height inches: ", network_height_inches)

WIDTH_SHIFT = .75  # width of left margin 
HEIGHT_SHIFT = 0.5  # height of bottom margin

# when these are zero, 
# the node boxes for ABCDEFG and F fall outside the axes
# WIDTH_SHIFT = 0  
# HEIGHT_SHIFT = 0

PORTION_OF_PLOT_INSIDE_THE_MARGINS = .7

fig_width_inches = 
    network_width_inches/PORTION_OF_PLOT_INSIDE_THE_MARGINS
fig_height_inches = 
    network_height_inches/PORTION_OF_PLOT_INSIDE_THE_MARGINS

# These enlargements are not big enough
# fig_width_inches = network_width_inches + 2*WIDTH_SHIFT
# fig_height_inches = network_height_inches + 2*HEIGHT_SHIFT

print("fig width inches: ", fig_width_inches)
print("fig height inches: ", fig_height_inches)

# Create the figure

fig = plt.figure(figsize=(fig_width_inches, fig_height_inches), dpi=72)

ax = plt.gca()

# Plotting in inches

# Create the node boxes

node_patch_ABCDEFG = FancyBboxPatch(
        [lower_left_corner_ABCDEFG[0] + WIDTH_SHIFT, 
         lower_left_corner_ABCDEFG[1] + HEIGHT_SHIFT],
        node_width_ABCDEFG,
        node_height_ABCDEFG,
        edgecolor="blue",
        facecolor="lightblue",
        linewidth=1,
        boxstyle=BoxStyle("round", 
                          pad=0,
                          rounding_size=.1),
        transform=fig.dpi_scale_trans
        )

node_patch_C = FancyBboxPatch(
        [lower_left_corner_C[0] + WIDTH_SHIFT, 
         lower_left_corner_C[1] + HEIGHT_SHIFT],
        node_width_C,
        node_height_C,
        edgecolor="blue",
        facecolor="lightblue",
        linewidth=1,
        boxstyle=BoxStyle("round", 
                          pad=0,
                          rounding_size=.1),
        transform=fig.dpi_scale_trans
        )

node_patch_E = FancyBboxPatch(
        [lower_left_corner_E[0] + WIDTH_SHIFT, 
         lower_left_corner_E[1] + HEIGHT_SHIFT],
        node_width_E,
        node_height_E,
        edgecolor="blue",
        facecolor="lightblue",
        linewidth=1,
        boxstyle=BoxStyle("round", 
                          pad=0,
                          rounding_size=.1),
        transform=fig.dpi_scale_trans
        )            

node_patch_F = FancyBboxPatch(
        [lower_left_corner_F[0] + WIDTH_SHIFT, 
         lower_left_corner_F[1] + HEIGHT_SHIFT],
        node_width_F,
        node_height_F,
        edgecolor="blue",
        facecolor="lightblue",
        linewidth=1,
        boxstyle=BoxStyle("round", 
                          pad=0,
                          rounding_size=.1),
        transform=fig.dpi_scale_trans
        )

ax.add_patch(node_patch_ABCDEFG)
ax.add_patch(node_patch_C)
ax.add_patch(node_patch_E)
ax.add_patch(node_patch_F)

# Add text labels for the nodes

plt.text(
    node_center_x_ABCDEFG + WIDTH_SHIFT,
    node_center_y_ABCDEFG + HEIGHT_SHIFT,
    "ABCDEFG",
    fontsize=12,
    color="black",
    fontname="Verdana",
    fontstyle="normal",
    horizontalalignment="center",
    verticalalignment="center",
    transform=fig.dpi_scale_trans
    )

plt.text(
    node_center_x_C + WIDTH_SHIFT,
    node_center_y_C + HEIGHT_SHIFT,
    "C",
    fontsize=12,
    color="black",
    fontname="Verdana",
    fontstyle="normal",
    horizontalalignment="center",
    verticalalignment="center",
    transform=fig.dpi_scale_trans
    )

plt.text(
    node_center_x_E + WIDTH_SHIFT,
    node_center_y_E + HEIGHT_SHIFT,
    "E",
    fontsize=12,
    color="black",
    fontname="Verdana",
    fontstyle="normal",
    horizontalalignment="center",
    verticalalignment="center",
    transform=fig.dpi_scale_trans
    )

plt.text(
    node_center_x_F + WIDTH_SHIFT,
    node_center_y_F + HEIGHT_SHIFT,
    "F",
    fontsize=12,
    color="black",
    fontname="Verdana",
    fontstyle="normal",
    horizontalalignment="center",
    verticalalignment="center",
    transform=fig.dpi_scale_trans
    )

plt.axis("equal")

#plt.axis("off")

plt.show()

fig.savefig("node_example.png", bbox_inches="tight")

node boxes drawn correctly

after subplots_adjust(0,0,1,1) and SHIFTS to 0 and PORTION to 1

removed bbox_inches="tight" from savefig

after subplots_adjust(0,0,1,1) in iPython console

1 个答案:

答案 0 :(得分:0)

感谢ImportingOfBeingErnest

解决方案是从图中删除边距,可以通过以下方式完成:

fig.subplots_adjust(0,0,1,1)

在这种情况下,无需设置任何值即可将节点图从边距移到轴中或使图大于图本身。

要在保存图形时起作用,

bbox_inches 

参数不应在

中使用
fig.savefig()

要使其与iPython控制台内联工作,请使用以下命令:

%config InlineBackend.print_figure_kwargs = {'bbox_inches':None}