Matplotlib用户界面示例中断超过三个修补程序

时间:2017-03-17 01:28:14

标签: python svg matplotlib

我正在使用此Matplotlib User Interface example,当我运行基本示例时,它的工作方式与广告一致。当我开始适应我的需求时,事情开始横行了。

  • 当我添加第三个补丁时,它仍然可以像宣传的那样工作。
  • 当我添加第四个补丁时,它的鼠标悬停似乎被映射到子图X轴顶部而不是补丁。
  • 当我添加第五个补丁时,第四个仍然映射到子图X轴顶部,我找不到第五个补丁的鼠标悬停区域。

当修补程序>我无法弄清楚是什么让脚本生气了3.查看脚本,它似乎适用于任何数量的补丁。 SVG在Safari,Firefox和Chrome中显示相同的行为。

任何指针都会受到赞赏。

[Python 2.7.10,Matplotlib 1.3.1]

   <path clip-path="url(#p7ff5b81e1d)" d=" M161.28 352.08 L170.208 352.08 Q171.547 352.08 171.547 345.6 L171.547 302.4 Q171.547 295.92 170.208 295.92 L161.28 295.92 Q159.941 295.92 159.941 302.4 L159.941 345.6 Q159.941 352.08 161.28 352.08 z " style="fill:#0000ff;stroke:#000000;"/>


</g>

[ETA:输出路径]

探索输出路径,我得到了这个,这表明第四条路径显然有问题。

路径1:          

   <path clip-path="url(#p7ff5b81e1d)" d=" M250.56 308.88 L259.488 308.88 Q260.827 308.88 260.827 302.4 L260.827 259.2 Q260.827 252.72 259.488 252.72 L250.56 252.72 Q249.221 252.72 249.221 259.2 L249.221 302.4 Q249.221 308.88 250.56 308.88 z " style="fill:#0000ff;stroke:#000000;"/>


</g>

路径2:          

   <path clip-path="url(#p7ff5b81e1d)" d=" M339.84 265.68 L348.768 265.68 Q350.107 265.68 350.107 259.2 L350.107 216 Q350.107 209.52 348.768 209.52 L339.84 209.52 Q338.501 209.52 338.501 216 L338.501 259.2 Q338.501 265.68 339.84 265.68 z " style="fill:#0000ff;stroke:#000000;"/>


</g>

路径3:          

   <path d=" M72 43.2 L518.4 43.2" style="fill:none;stroke:#000000;"/>


</g>

路径4:          

{{1}}

High Quality Image of Behavior

1 个答案:

答案 0 :(得分:2)

我们必须得出结论,matplotlib页面中的svg_tooltip example是错误的。

问题来自行

for i, t in enumerate(ax.patches):
    t.set_gid('patch_%d' % i)

迭代轴上的补丁并向其添加一个名为patch_id的id。但是,轴可能比我们在代码中添加的更多补丁。例如。轴刺也是补丁。因此,当迭代所有补丁时,我们可能会将id "patch_4"设置为轴脊柱而不是我们想要设置的补丁。

为了克服这个问题,我们实际上需要将id设置为应该拥有它的补丁,例如:通过仅迭代添加的补丁。

此处存在第二个问题:保存时,画布中的其他元素也会使用标识patch_id。所以我们应该区别对待它,例如mypatch_id

接下来的问题是在设置可见性和回调时,我们也不应该迭代画布中的所有文本和补丁,而只是覆盖那些具有我们自己设置的id的文本和补丁。

请参阅下面的完整工作示例。

from io import BytesIO
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
import xml.etree.ElementTree as ET

ET.register_namespace("", "http://www.w3.org/2000/svg")

fig = plt.figure(figsize=(25,10))
fig, ax1 = plt.subplots()


years = [1980,1990, 2000, 2010]
labels = ["One", "Two", "Three", "Four"]

for i, year in enumerate(years):
    patch = mpatches.FancyBboxPatch((year, i+1), 1, 1, 
                        boxstyle=mpatches.BoxStyle("Round", pad=0.15))
    annotate = ax1.annotate(labels[i], xy=(year, i+1), xytext=(0, 0), 
                    textcoords='offset points', color='w', ha='center', 
                    fontsize=8, bbox=dict(boxstyle='round, pad=.5', fc=(.1, .1, .1, .92), 
                    ec=(1., 1., 1.), lw=1, zorder=1))

    ax1.add_patch(patch)
    patch.set_gid('mypatch_{:03d}'.format(i))
    annotate.set_gid('mytooltip_{:03d}'.format(i))


# Save the figure in a fake file object
ax1.set_xlim(1970, 2017)
ax1.set_ylim(0, 8)


f = BytesIO()
plt.savefig(f, format="svg")

# --- Add interactivity ---

# Create XML tree from the SVG file.
tree, xmlid = ET.XMLID(f.getvalue())
tree.set('onload', 'init(evt)')


for i, y in enumerate(years):
    # Hide the tooltips
    tooltip = xmlid['mytooltip_{:03d}'.format(i)]
    tooltip.set('visibility', 'hidden')
    # Assign onmouseover and onmouseout callbacks to patches.
    mypatch = xmlid['mypatch_{:03d}'.format(i)]
    mypatch.set('onmouseover', "ShowTooltip(this)")
    mypatch.set('onmouseout', "HideTooltip(this)")

# This is the script defining the ShowTooltip and HideTooltip functions.
script = """
    <script type="text/ecmascript">
    <![CDATA[

    function init(evt) {
        if ( window.svgDocument == null ) {
            svgDocument = evt.target.ownerDocument;
            }
        }

    function ShowTooltip(obj) {
        var cur = obj.id.split("_")[1];
        var tip = svgDocument.getElementById('mytooltip_' + cur);
        tip.setAttribute('visibility',"visible")
        }

    function HideTooltip(obj) {
        var cur = obj.id.split("_")[1];
        var tip = svgDocument.getElementById('mytooltip_' + cur);
        tip.setAttribute('visibility',"hidden")
        }

    ]]>
    </script>
    """

# Insert the script at the top of the file and save it.
tree.insert(0, ET.XML(script))
ET.ElementTree(tree).write('svg_tooltip_2.svg')