我正在看matplotlib画廊中的custom projection示例 - 我正在尝试修改它以仅绘制南半球。我已将必要的[-pi / 2,pi / 2]限制调整为[-pi / 2,0]。现在我一直在看:
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补丁。这就是投影图目前的样子:
脊椎仍然遵循圆/椭圆 - 我如何指定我希望脊椎遵循楔形的边界?
我不确定如何最好地修改脊柱,所以非常感谢任何帮助!
谢谢,
亚历
答案 0 :(得分:5)
只是为了记录,如果你还是Python的新手,你肯定会直接进入游泳池的深处。 (感谢你向前走!)
您正在做的事情需要对matplotlib的内部工作原理有相当详细的了解,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()
让我们深入研究_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}
现在有一些问题:
但是,当我们看一下HammerAxes
的结构时,你会注意到很多这些东西(尤其是轴补丁的居中)被有效地硬编码到变换中。 (正如他们在评论中提到的那样,它意味着是一个“玩具”的例子,并且假设你总是在处理整个地球,这使得转换中的数学变得更加简单。)
如果你想解决这些问题,你需要调整HammerAxes._set_lim_and_transforms
中的几种变换。
然而,它的工作原理相当不错,所以我将把它作为练习留给读者。 :)(请注意,该部分有点难,因为它需要详细了解matplotlib的转换。)