1

もともと、私はマーカーの一種のクラスを で作成できることを望んでいましたmatplotlib。これは、たとえば x 座標とラベルを示すテキストを含む正方形であり、(疑似コード) のようなものでインスタンス化できます。

plt.plot(..., marker=myMarkerClass(label="X:"), ... )

...しかし、私が見る限り、そのようなことはできません。

ただし、マーカーのカスタマイズは古いものでは利用できないようですmatplotlib。だから私は私の質問を次のように減らしたいと思います:古い でカスタム(パス)マーカーを取得する方法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()

ここで任意のズーム矩形を実行すると、マーカーは同じサイズのままです。

マーカー-ex01

パスによるカスタマイズされたマーカー

これはアーティスト (Line2D.set_marker) — Matplotlib 1.2.1 ドキュメントに記載されています。ただし、古いものでは機能しません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()

これは newermatplotlibでは問題なく動作しますが、古いものでは失敗します:

$ 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 で動作する場合、予想どおり、グラフのズーム全体でマーカーのサイズが再び維持されます。

マーカー ex02

... ただし、この問題に注意してください:頂点リストから作成されたカスタム マーカーのスケールが間違っています · Issue #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()

さて、ここで図の初期アスペクト比を考慮しようとしましたが、実際、最初のレンダリングでは、「マーカー」はサイズに関して正しく見えますが...:

マーカー ex03

...任意のズームを実行しようとすると、パスがデータ座標で指定されていることは明らかであり、そのサイズはズーム四角形に応じて変化します。(もう 1 つの問題は、facecolor='orange'従わないことですが、これは で修正できますpcolm.set_facecolor('orange'))

 

matplotlibそれで、レンダリングされたパスが画面座標で定義され、任意のズーム時にサイズが変更されないという意味で、PatchCollection を古い のマーカーとして使用できる方法はありますか?

4

1 に答える 1