2015-01-02 47 views
2

有沒有一種方法來設置剪輯範圍爲matplotlib.text.Annotation剪輯註釋

import matplotlib.pyplot as plt 
from matplotlib.transforms import Bbox 

fig, ax = plt.subplots() 
vals = [ 
     (10,20,"Lorem ipsum dolor sit amet, consectetur adipiscing elit"), 
     (30,20, "Pellentesque scelerisque congue fermentum."), 
     (50,10, "Aliquam erat volutpat") 
] 
ax.set_ylim(0,1) 
ax.broken_barh(map(lambda v: v[:2],vals), (0, 1), facecolors=('yellow','red','green')) 
for v in vals: 
    ax.annotate(
     v[2], 
     xy=(v[0],0.4), 
     clip_on=True, 
     clip_box=Bbox([[v[0],0],[v[0]+v[1],1]]) 
    ) 

plt.show() 

我試圖設置clip_box & clip_pathax.annotate調用,但這是行不通的。 enter image description here

+2

你在哪裏使用'broken_bar_h'有什麼用呢? (與手頭的問題無關,正在爲mpl進行用戶研究;)) – tacaswell

+1

我發現它是電視指南可視化的完美工具([示例](http://cl.ly/image/0T3g2A301b3r))。前段時間我在ggplot中做過類似的事情,我依靠'aes(xmin =,xmax =,ymin =,ymax =)' – trnl

+0

有趣。這是一個非常酷的數字! – tacaswell

回答

4

首先,好問題!你正在潛心鑽研細節,因此你需要知道的相當數量的半無證細節。

您當前的法會,除了兩件事情的工作:

  1. clip_box預計將在顯示座標,所以你需要改變它。
  2. 這是不夠用「純」 Bbox這一點。每次顯示更改時,要重新轉換爲數據座標,您需要使用TransformedBbox

爲了證明多一點這是怎麼回事,讓我們來解決第一個問題,但不是第二:

import matplotlib.pyplot as plt 
from matplotlib.transforms import Bbox 

fig, ax = plt.subplots() 
vals = [ 
     (10,20,"Lorem ipsum dolor sit amet, consectetur adipiscing elit"), 
     (30,20, "Pellentesque scelerisque congue fermentum."), 
     (50,10, "Aliquam erat volutpat") 
] 
ax.set_ylim(0,1) 
ax.broken_barh(map(lambda v: v[:2],vals), (0, 1), 
       facecolors=('yellow','red','green')) 
for v in vals: 
    box = Bbox([[v[0],0],[v[0]+v[1],1]]).transformed(ax.transData) 
    anno = ax.annotate(v[2], xy=(v[0],0.4), clip_box=box) 

plt.show() 

enter image description here

它看起來不錯,在第一,但有另外一個問題:因爲clip_box是靜態的,在顯示座標,它會很快在不正確的位置,你以任何方式更改的情節(例如縮放,平移,自動定標,改變圖形窗口的大小,改變圖形DPI)。

例如,如果我點擊「保存」按鈕(或調用savefig),剪輯框將不正確,因爲在保存之前圖的DPI將被更改(從80到100)!

enter image description here

出於這個原因,你需要使用此一TransformedBbox。這只是一個版本的Bbox是保存到一個轉型的參考和重新改造底層Bbox如果轉換變化。在matplotlib中沿着這些行有幾個類:Transformed*TransformedPath等。它們不是您總是需要知道的細節水平,但它們可能非常有用。

作爲最後一個例子,這將正常工作,無論情節如何縮放/平移/改變:

import matplotlib.pyplot as plt 
from matplotlib.transforms import TransformedBbox, Bbox 

fig, ax = plt.subplots() 
vals = [ 
     (10,20,"Lorem ipsum dolor sit amet, consectetur adipiscing elit"), 
     (30,20, "Pellentesque scelerisque congue fermentum."), 
     (50,10, "Aliquam erat volutpat") 
] 
ax.set_ylim(0,1) 
ax.broken_barh(map(lambda v: v[:2],vals), (0, 1), 
       facecolors=('yellow','red','green')) 
for v in vals: 
    box = TransformedBbox(Bbox([[v[0],0],[v[0]+v[1],1]]), ax.transData) 
    anno = ax.annotate(v[2], xy=(v[0],0.4), clip_box=box) 

plt.show() 

enter image description here

+1

哇,謝謝,這是非常全面的答案! 另外我發現 - 如果將clip_box設置爲特定的broken_barh的邊界,那麼'clip_on = True'的值將被丟棄,因此要解決此問題,您需要注意'ax.get_xlim()'創建'TransformedBbox'。 – trnl

+0

http://matplotlib.org/users/transforms_tutorial.html對此答案有幫助。 – trnl