2012-03-13 70 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