matplotlib:半球/楔形的自定义投影 [英] matplotlib: custom projection for hemisphere/wedge

查看:90
本文介绍了matplotlib:半球/楔形的自定义投影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在查看 自定义投影 matplotlib 库中的示例——我试图修改它以仅绘制南半球.我已将必要的 [-pi/2,pi/2] 限制调整为 [-pi/2,0].现在我一直在看:

I'm looking at the custom projection example in the matplotlib gallery -- I'm trying to modify it to plot only the southern hemisphere. I have adjusted the necessary [-pi/2,pi/2] limits to [-pi/2,0]. Now I've been looking at:

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)}

如您所见,我已将 Circle 补丁替换为 Wedge.这是投影图目前的样子:

As you can see, I've replaced the Circle patch with a Wedge. This is what the projection plot currently looks like:

脊椎仍然跟随圆/椭圆——如何指定脊椎跟随楔形边界?

The spine still follows the circle/ellipse -- how can I specify that I want the spine to follow the boundary of the wedge?

我不确定如何最好地修改脊椎,因此非常感谢您的帮助!

I am not sure how best to modify the spine, so any help would be very much appreciated!

谢谢,

亚历克斯

推荐答案

只是为了记录,如果您还是 Python 新手,您肯定会直接跳入池的深处.(感谢你直接进入!)

Just for the record, you're definitely jumping straight into the deep end of the pool if you're still new to python. (And kudos to you for going right in!)

您正在做的事情需要对 matplotlib 的内部工作原理有相当详细的了解,这是一个相当复杂的库.

What you're doing requires a reasonably detailed knowledge of the inner workings of matplotlib, which is a rather complex library.

话虽如此,这是快速学习的好方法!

That having been said, it's a good way to learn quickly!

对于这样的事情,您需要了解事物结构的内部架构,而不仅仅是公共"API.

For something like this, you need to understand the internal architecture of how things are structured instead of just the "public" api.

对于其中的大部分内容,您必须深入挖掘并使用源代码".对于任何项目,内部工作的文档就是代码本身.

For most of this, you have to dig in and "use the source". For any project, the documentation of the inner workings is the code itself.

话虽如此,对于一个简单的案例,它非常简单.

That having been said, for a simple case, it's pretty straight-forward.

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()

让我们深入研究一下 _get_axes_spines 方法:

Let's dig into the _get_axes_spines method a bit:

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 的结构时,您会注意到很多这些东西(尤其是轴补丁的中心)被有效地硬编码到变换中.(正如他们在评论中提到的,它是一个玩具"示例,假设你总是在处理整个地球,这使得转换中的数学更简单.)

However, when we take a look at how HammerAxes is structured, you'll notice that a lot these things (especially the centering of the axis patch) are effectively hard-coded into the transforms. (As they mention in the comments, it's meant to be a "toy" example, and making the assumption that you're always dealing with the full globe makes the math in the transformations much simpler.)

如果你想修复这些,你需要在HammerAxes._set_lim_and_transforms中调整几个不同的变换.

If you want to fix these, you'll need to tweak several of the various transforms in HammerAxes._set_lim_and_transforms.

但是,它按原样运行得相当好,所以我将把它留给读者作为练习.:)(请注意,这部分有点难,因为它需要详细了解 matplotlib 的转换.)

However, it works reasonably well as-is, so I'll leave that as an exercise to the reader. :) (Be warned, that part's a bit harder, as it requires a detailed knowledge of matplotlib's transformations.)

这篇关于matplotlib:半球/楔形的自定义投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆