0
0

More than 3 years have passed since last update.

matplotlibのscatter()/scatter3d()で陰面消去がうまくいかないときの対処メモ

Last updated at Posted at 2020-03-10

MPL(matplotlib)で 3D の散布図を作る際、scatter() に配色用の値listを渡すとき、陰面消去が狂ってしまう

先に結論: 散布データを list で渡すの諦めて、1個ずつ scatter() したら解決した。

2021/01/07 追記:
 この記事の症例は MPL3.2.* の頃のバグだったようです。
 
 MPLのVer.3.3.3 で試したところだいぶ挙動が変わってました。
  どうやらlist渡しでも正常になった(?)模様。
  また、一個ずつ渡す場合にdepthshade=Falseとしたときの処理が遅くなったかも。


散布図描画メソッド scatter() を使う際、
マーカーの位置と色分けの値は、普通はリストとかで渡したい。

リストxs,ys,zs,vsを渡す場合
ax.scatter(xs, ys, zs, c=vs, norm=norm, s=600, marker='o', alpha=1.0, zdir='z', depthshade=False )

ところが、なぜか c=vs で配色配列を渡した途端に陰面消去が狂ってしまい
「一番手前のマーカーが一番奥のマーカーに隠れて見えない」なんていうことが起きる。(バージョンに依存とかあるかも。)


対処:
思いつくことは一通り試しました結果、
「for 文でマーカー1個ずつ scatter()」 にしたら正常になりましたとさ。

1個毎にscatter()
ax = fig.add_subplot( 122, projection='3d')
for x,y,z,v in zip(xs,ys,zs,vs):
    ax.scatter(x, y, z, c=(v,),norm=norm, s=600, marker='o', alpha=1.0, zdir='z', depthshade=False )

以下は実例:

陰面消去比較
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize

def plot():
    def randrange(n, vmin, vmax):
        return (vmax - vmin)*np.random.rand(n) + vmin

    n = 20
    xs = randrange(n, 0, 100)
    ys = randrange(n, 0, 100)
    zs = randrange(n, 0, 100)
    vs = xs
    norm = Normalize(vmin=min(vs), vmax=max(vs) )

    fig = plt.figure()
    ax = fig.add_subplot(121, projection='3d')
    ax.scatter(xs, ys, zs, c=vs, norm=norm, s=600, marker='o', alpha=1.0, zdir='z', depthshade=False )
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')

    ax = fig.add_subplot( 122, projection='3d')
    for x,y,z,v in zip(xs,ys,zs,vs):
        ax.scatter(x, y, z, c=(v,),norm=norm, s=600, marker='o', alpha=1.0, zdir='z', depthshade=False )

    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')

    plt.show()

Pyton3.8 実行結果↓
3DPlotColoring_compare.png

↑ 左図がlistで渡した場合、右図が1個ごとに渡した場合。(区別のつきやすい方向を選んで描画したつもり)

右図は正常です。

注意点:
1.scatter() をマーカー毎に呼ぶ場合は、カラーリングのレンジを統一するために
norm=Normalizeでレンジ固定し scatter() に norm=norm で渡す。
2.scatter() のオプション「depthshade=True」 がとても遅くします。デフォルトTrueのようなので、かならず「depthshade=False」すべし。
2020/01/07:MPLのVer3.3.3ではdepthshadeによる差は小さい(無くなった?)ようです。


※ scatter()とscatter3d()の挙動はたぶん同じ。

※matoplotlib の公式ドキュメントは確認していません。そもそも前提の使い方が間違っているかもしれません。あしからず。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0