2012-03-13 47 views
3

我正在看matplotlib庫中的custom projection示例 - 我試圖修改它只繪製南半球。我已將必要的[-pi/2,pi/2]限制調整爲[-pi/2,0]。現在我一直在看:matplotlib:半球/楔子的自定義投影

def _gen_axes_patch(self): 
    """ 
    Override this method to define the shape that is used for the 
    background of the plot. It should be a subclass of Patch. 

    In this case, it is a Circle (that may be warped by the axes 
    transform into an ellipse). Any data and gridlines will be 
    clipped to this shape. 
    """ 
    #return Circle((0.5, 0.5), 0.5) 
    return Wedge((0.5,0.5), 0.5, 180, 360) 

def _gen_axes_spines(self): 
    return {'custom_hammer':mspines.Spine.circular_spine(self, 
                (0.5, 0.5), 0.25)} 

正如你所看到的,我已經用Wedge替換了Circle補丁。這是投影圖目前的樣子: projection plot

脊柱仍然沿着圓/橢圓 - 我如何指定我希望脊椎跟着楔形邊界?

我不知道如何最好地修改脊柱,所以任何幫助將非常感激!

感謝,

亞歷

+0

哦,只是指出 - 我還是新的蟒蛇,所以任何方法的解釋是真的有用!謝謝! – aim 2012-03-13 18:07:02

回答

5

只是爲了記錄在案,你肯定直接跳進泳池的深水區,如果你還是新的蟒蛇。 (並且很榮幸地讓你進入!)

你在做什麼需要對matplotlib的內部工作有相當詳細的瞭解,這是一個相當複雜的庫。

這樣說了,這是一個快速學習的好方法!

對於這樣的事情,您需要了解內部體系結構,而不是僅僅是「公共」api。

對於大多數情況,您必須深入挖掘並「使用源代碼」。對於任何項目,內部工作的文檔都是代碼本身。

剛纔已經說過,對於一個簡單的情況,它非常簡單。

import numpy as np 
from matplotlib.projections.geo import HammerAxes 
import matplotlib.projections as mprojections 
from matplotlib.axes import Axes 
from matplotlib.patches import Wedge 
import matplotlib.spines as mspines 

class LowerHammerAxes(HammerAxes): 
    name = 'lower_hammer' 
    def cla(self): 
     HammerAxes.cla(self) 
     Axes.set_xlim(self, -np.pi, np.pi) 
     Axes.set_ylim(self, -np.pi/2.0, 0) 

    def _gen_axes_patch(self): 
     return Wedge((0.5, 0.5), 0.5, 180, 360) 

    def _gen_axes_spines(self): 
     path = Wedge((0, 0), 1.0, 180, 360).get_path() 
     spine = mspines.Spine(self, 'circle', path) 
     spine.set_patch_circle((0.5, 0.5), 0.5) 
     return {'wedge':spine} 

mprojections.register_projection(LowerHammerAxes) 

if __name__ == '__main__': 
    import matplotlib.pyplot as plt 
    fig = plt.figure() 
    ax = fig.add_subplot(111, projection='lower_hammer') 
    ax.grid(True) 
    plt.show() 

enter image description here

讓我們深入到_get_axes_spines方法的位:

def _gen_axes_spines(self): 
    """Return the spines for the axes.""" 
    # Make the path for the spines 
    # We need the path, rather than the patch, thus the "get_path()" 
    # The path is expected to be centered at 0,0, with radius of 1 
    # It will be transformed by `Spine` when we initialize it 
    path = Wedge((0, 0), 1.0, 180, 360).get_path() 

    # We can fake a "wedge" spine without subclassing `Spine` by initializing 
    # it as a circular spine with the wedge path. 
    spine = mspines.Spine(self, 'circle', path) 

    # This sets some attributes of the patch object. In this particular 
    # case, what it sets happens to be approriate for our "wedge spine" 
    spine.set_patch_circle((0.5, 0.5), 0.5) 

    # Spines in matplotlib are handled in a dict (normally, you'd have top, 
    # left, right, and bottom, instead of just wedge). The name is arbitrary 
    return {'wedge':spine} 

現在有幾個問題是:

  1. 事情不是你想象中的居中軸正確
  2. 軸補丁可以縮放比較大,以便正確佔據軸內的空間。
  3. 我們繪製了全球的網格線,然後剪切它們。只將它們繪製在我們的「較低」楔中會更有效率。

然而,當我們看看HammerAxes是如何構成的,你會發現很多這些東西(尤其是軸的補片的中心)的有效硬編碼到的變換。 (正如他們在評論中提到的那樣,它意在成爲一個「玩具」的例子,並且假設你總是處理整個地球,這使得變換中的數學變得更加簡單。)

如果要修復這些,你就需要調整幾個各種變換的HammerAxes._set_lim_and_transforms

但是,它的工作原理相當不錯的,是的,所以我會離開,作爲一個練習留給讀者。 :)(被警告,這部分是有點困難,因爲它需要matplotlib的轉換的詳細知識。)

+0

謝謝喬 - 這是一個非常有用的答案! (我承認到現在爲止我已經或多或少地堅持公開API了,直到我需要更多定製的東西)!感謝您分解get_axes_spines的解釋。那麼,通過使用「路徑」,我可以在理論上定義一個脊椎以遵循任意形狀? (雖然轉變會更復雜)。我要的matplotlib文件的必要頁面更詳細的讀,但我同意,關於玩的代碼可以啓發!再次感謝! – aim 2012-03-14 09:33:26

+0

您可以爲脊柱定義或多或少的任意路徑。對於真正的任意路徑,你需要繼承'Spine',但在這種情況下,它是足夠接近圓形(據中心等,行),我們可以把它當作一個圓形的脊柱。有沒有像有對繼承'Axes'繼承'Spine'詳盡的指引,所以你必須在挖掘和閒逛。祝好運,無論如何! – 2012-03-15 15:20:17