最初,我希望我可以为 in 中的标记创建一种类matplotlib
,它是一个带有文本的正方形,显示 x 坐标和标签,所以我可以用类似(伪代码)的东西来实例化它:
plt.plot(..., marker=myMarkerClass(label="X:"), ... )
...但据我所知,你不能做那样的事情。
但是,标记的自定义似乎在旧版本中不可用matplotlib
;所以我想减少我的问题:如何在 old 中获取自定义(路径)标记matplotlib
,所以它们的大小是在屏幕坐标中定义的(所以标记在缩放时不会缩放)?为了澄清,这里有一些例子:
默认(未自定义)标记
下面是一个带有默认matplotlib
标记的示例,它适用于旧的matplotlib
. 请注意,我尝试直接使用而不是使用pyplot.plot()
,我尝试matplotlib.figure.Figure
直接使用(因为这是通常与不同后端一起使用的形式),需要使用“图形管理器”(另请参见matplotlib-devel - 后端对象结构):
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.figure
import numpy as np
t = np.arange(0.0,1.5,0.25)
s = np.sin(2*np.pi*t)
mfigure = matplotlib.figure.Figure(figsize=(5,4), dpi=100)
ax = mfigure.add_subplot(111)
ax.plot(t,s, marker='o', color='b', markerfacecolor='orange', markersize=10.0)
fig = plt.figure() # create something (fig num 1) for fig_manager
figman = matplotlib._pylab_helpers.Gcf.get_fig_manager(1)
figman.canvas.figure = mfigure # needed
mfigure.set_canvas(figman.canvas) # needed
plt.show()
如果我们在此处进行任意缩放矩形,则标记保持相同大小:
通过路径自定义标记
这记录在艺术家 (Line2D.set_marker) — Matplotlib 1.2.1 文档中;但是,它不适用于 old matplotlib
;这是一个例子:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.figure
import matplotlib.path
import numpy as np
print("matplotlib version {0}".format(matplotlib.__version__))
def getCustomSymbol1(inx, iny, sc, yasp):
verts = [
(-0.5, -0.5), # left, bottom
(-0.5, 0.5), # left, top
(0.5, 0.5), # right, top
(0.5, -0.5), # right, bottom
(-0.5, -0.5), # ignored
]
codes = [matplotlib.path.Path.MOVETO,
matplotlib.path.Path.LINETO,
matplotlib.path.Path.LINETO,
matplotlib.path.Path.LINETO,
matplotlib.path.Path.CLOSEPOLY,
]
pathCS1 = matplotlib.path.Path(verts, codes)
return pathCS1, verts
t = np.arange(0.0,1.5,0.25)
s = np.sin(2*np.pi*t)
mfigure = matplotlib.figure.Figure(figsize=(5,4), dpi=100)
ax = mfigure.add_subplot(111)
pthCS1, vrtCS1 = getCustomSymbol1(0,0, 1,1)
# here either marker=pthCS1 or marker=np.array(vrtCS1)
# have the same effect:
ax.plot(t,s, marker=pthCS1, markerfacecolor='orange', markersize=10.0)
#ax.plot(t,s, marker=np.array(vrtCS1), markerfacecolor='orange', markersize=10.0)
fig = plt.figure() # create something (fig num 1) for fig_manager
figman = matplotlib._pylab_helpers.Gcf.get_fig_manager(1)
figman.canvas.figure = mfigure # needed
mfigure.set_canvas(figman.canvas) # needed
plt.show()
这对我来说在新版本中运行良好matplotlib
,但在旧版本中失败:
$ python3.2 test.py
matplotlib version 1.2.0
$ python2.7 test.py # marker=pthCS1
matplotlib version 0.99.3
Traceback (most recent call last):
File "test.py", line 36, in <module>
ax.plot(t,s, marker=pthCS1, markerfacecolor='orange', markersize=10.0)
...
File "/usr/lib/pymodules/python2.7/matplotlib/lines.py", line 804, in set_marker
self._markerFunc = self._markers[marker]
KeyError: Path([[-0.5 -0.5]
[-0.5 0.5]
[ 0.5 0.5]
[ 0.5 -0.5]
[-0.5 -0.5]], [ 1 2 2 2 79])
$ python2.7 test.py # marker=np.array(vrtCS1)
matplotlib version 0.99.3
Traceback (most recent call last):
File "test.py", line 38, in <module>
ax.plot(t,s, marker=np.array(vrtCS1), markerfacecolor='orange', markersize=10.0)
...
File "/usr/lib/pymodules/python2.7/matplotlib/lines.py", line 798, in set_marker
if marker not in self._markers:
TypeError: unhashable type: 'numpy.ndarray'
但是,当它在 Python 3.2 中工作时,标记再次保持其大小在图表的缩放范围内,正如我所期望的:
...虽然请注意这个问题:关于这种类型的自定义标记,从顶点列表创建的自定义标记缩放错误·问题 #1980·matplotlib/matplotlib·GitHub。
通过 PatchCollection 中的路径
我从一些互联网帖子中获取了部分代码,但现在找不到链接。在任何情况下,我们都可以避免绘制标记,并且可以使用 PatchCollection 来绘制应该是标记的内容。这是在旧版本中运行的代码matplotlib
:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.figure
import matplotlib.path, matplotlib.patches, matplotlib.collections
import numpy as np
def getCustomSymbol1(inx, iny, sc, yasp):
verts = [
(inx-0.5*sc, iny-0.5*sc*yasp), # (0., 0.), # left, bottom
(inx-0.5*sc, iny+0.5*sc*yasp), # (0., 1.), # left, top
(inx+0.5*sc, iny+0.5*sc*yasp), # (1., 1.), # right, top
(inx+0.5*sc, iny-0.5*sc*yasp), # (1., 0.), # right, bottom
(inx-0.5*sc, iny-0.5*sc*yasp), # (0., 0.), # ignored
]
codes = [matplotlib.path.Path.MOVETO,
matplotlib.path.Path.LINETO,
matplotlib.path.Path.LINETO,
matplotlib.path.Path.LINETO,
matplotlib.path.Path.CLOSEPOLY,
]
pathCS1 = matplotlib.path.Path(verts, codes)
return pathCS1
def getXyIter(inarr):
# this supports older numpy, where nditer is not available
if np.__version__ >= "1.6.0":
return np.nditer(inarr.tolist())
else:
dimensions = inarr.shape
xlen = dimensions[1]
xinds = np.arange(0, xlen, 1)
return np.transpose(np.take(inarr, xinds, axis=1))
t = np.arange(0.0,1.5,0.25)
s = np.sin(2*np.pi*t)
mfigure = matplotlib.figure.Figure(figsize=(5,4), dpi=100)
ax = mfigure.add_subplot(111)
ax.plot(t,s)
customMarkers=[]
for x, y in getXyIter(np.array([t,s])): #np.nditer([t,s]):
#printse("%f:%f\n" % (x,y))
pathCS1 = getCustomSymbol1(x,y,0.05,1.5*500.0/400.0)
patchCS1 = matplotlib.patches.PathPatch(pathCS1, facecolor='orange', lw=1) # no
customMarkers.append(patchCS1)
pcolm = matplotlib.collections.PatchCollection(customMarkers)
pcolm.set_alpha(0.9)
ax.add_collection(pcolm)
fig = plt.figure() # create something (fig num 1) for fig_manager
figman = matplotlib._pylab_helpers.Gcf.get_fig_manager(1)
figman.canvas.figure = mfigure # needed
mfigure.set_canvas(figman.canvas) # needed
plt.show()
现在,在这里我尝试考虑初始纵横比,实际上,在第一次渲染时,“标记”在大小方面看起来是正确的 - 但是......:
...当我们尝试进行任意缩放时,很明显路径已在数据坐标中指定,因此它们的大小会根据缩放矩形而变化。(另一个令人讨厌的问题facecolor='orange'
是不遵守;但可以用 修复pcolm.set_facecolor('orange')
)
那么,有没有一种方法可以使用 PatchCollection 作为 old 的标记matplotlib
,因为渲染的路径将在屏幕坐标中定义,所以它们不会在任意缩放时改变它们的大小?