15 May 2014

概要

matplotlib の contour について調べたので、それを報告する。jekyll markup のテストも兼ねる

countor(..) 関数の self domument

最初に行うのは info(contour) です。

PythonSf ワンライナー
import matplotlib.pyplot as plt; info(plt.contour)
 contour(*args, **kwargs)

:func:`~matplotlib.pyplot.contour` and
:func:`~matplotlib.pyplot.contourf` draw contour lines and
filled contours, respectively.  Except as noted, function
signatures and return values are the same for both versions.

:func:`~matplotlib.pyplot.contourf` differs from the MATLAB
version in that it does not draw the polygon edges.
To draw edges, add line contours with
calls to :func:`~matplotlib.pyplot.contour`.


call signatures::

  contour(Z)

make a contour plot of an 2D array *Z*. The level values are chosen
automatically.
::

  contour(X,Y,Z)

*X*, *Y* specify the (*x*, *y*) coordinates of the surface

::

  contour(Z,N)
  contour(X,Y,Z,N)

contour *N* automatically-chosen N point levels that could not be shown partly.

::

  contour(Z,V)
  contour(X,Y,Z,V)

draw contour lines at the values specified in sequence *V*

この info(contour) 結果は 180 行と多すぎるので、以下に隠しておきます。

しかし分かりにくい説明文章です。いかにも技術屋が書く文章です。私も反面教師にすべき文章です。少しは分かりやすくなるように、”2D” と “N point”.. の太字部分を追加しておきました。

“contour *N* automatically-chosen levels” の英語は何が主語か述語かも分かりません。並べられた単語から意味を類推するしかないでしょう。contour contourf 二つの関数を同時に説明するのも無理があります。別の節で「contorf(..) 関数 は線ではなく帯で等高線を表示する。引数の与え方は contour(..) 関数と殆どおなじだ。」とすべきでしょう。Matlab との比較は別の節で行うべきでしょう。

以下、私流の contour(..) 関数の説明を書いてみます。なるべく PythonSf オープン版のコードも書いていきます。こちらならば、PythonSf を知らない方でも scipy, matplotlib を知っていれば理解できると思います。

私流の countour(..) 関数についての説明

関数 f(x,y) の 等高線を手っ取り早く表示させたければ、二次元座標の平面格子点上の f(x,y) の値を要素とする行列をcontour(..) 関数に与えるだけです。格子点以外での値は contour(..) 関数が自動的に補完してくれます。

PythonSf ワンライナー
mt=~[(`X^2+2`Y^2)(x,y) for x,y in mitr(*[klsp(-3,3)]*2)].reshape(50,50); import matplotlib.pyplot as plt; plt.contour(mt); plt.show()
x^2+2y^2 の等高線

二次元 np.array を二重リストで代用できます。(下のコードならば PythonSf オープン版でも動きます)

PythonSf ワンライナー
kl=np.linspace(-3,3); mt=[[(`X^2+2*`Y^2)(x,y) for y in kl] for x in kl]; import matplotlib.pyplot as plt; plt.contour(mt); plt.show()

等高線の数の指定

等高線の数を指定することもできます。contour(2D_array, N) と、整数 N で等高線の数を渡してやります。ピッタリ指定の数になるとは限りません。数本少なく表記されるようです。

PythonSf ワンライナー
# 等高線 50 本弱を表示させる
mt=~[(`X^2+2`Y^2)(x,y) for x,y in mitr(*[klsp(-3,3)]*2)].reshape(50,50); import matplotlib.pyplot as plt; plt.contour(mt, 50); plt.show()

# PythonSf Open で等高線 50 本弱を表示させる
kl=np.linspace(-3,3); mt=[[(`X^2+2*`Y^2)(x,y) for y in kl] for x in kl]; import matplotlib.pyplot as plt; plt.contour(mt, 50); plt.show()


等高線の値の指定

三次元図形の変化が緩やかなときは contour(..) 関数まかせで良いのですが、1/r^2 のように急峻に変化する図形では無理が出てきます。

PythonSf ワンライナー
# 1/(x^2+y^2) で等高線 50 本弱を自動的に表示させる
mt=~[(1/(`X^2+2`Y^2))(x,y) for x,y in mitr(*[klsp(-3,3)]*2)].reshape(50,50); import matplotlib.pyplot as plt; plt.contour(mt, 50); plt.show()

# PythonSf Open で等高線 50 本弱を表示させる
kl=np.linspace(-3,3); mt=[[(1/(`X^2+2*`Y^2))(x,y) for y in kl] for x in kl]; import matplotlib.pyplot as plt; plt.contour(mt, 50); plt.show()

そこで等高線の値のシーケンス:V を contour(mt, V) と与えてやることで、等高線の位置を制御します。

PythonSf ワンライナー
# 1/(x^2+y^2) で等高線表示値シーケンスを指定する
mt=~[(1/(`X^2+2`Y^2))(x,y) for x,y in mitr(*[klsp(-3,3)]*2)].reshape(50,50); import matplotlib.pyplot as plt; plt.contour(mt, [10,5,2,1, .5, .1, .01]); plt.show()

# PythonSf Open で等高線表示値シーケンスを指定する
kl=np.linspace(-3,3); mt=[[(1/(`X^2+2*`Y^2))(x,y) for y in kl] for x in kl]; import matplotlib.pyplot as plt; plt.contour(mt, [10,5,2,1, .5, .1, .01]); plt.show()

Matlab 流の mesh grid を使った等高線表示

Matlab 流儀に mesh grid 引数を使って等高線を表示させることも可能です。

PythonSf ワンライナー
# mesh grid を使って等高線表示値シーケンスを指定する
mt=~[(1/(`X^2+2`Y^2))(x,y) for x,y in mitr(*[klsp(-3,3)]*2)].reshape(50,50); import matplotlib.pyplot as plt; plt.contour(klsp(-3,3)^([1]*50),([1]*50)^klsp(-3,3), mt.t, [10,5,2,1, .5, .1, .01]); plt.show()

# PythonSf Open で mesh grid を使って等高線表示値シーケンスを指定する
kl=np.linspace(-3,3); MX,MY=np.meshgrid(kl,kl); mt=[[(1/(`X^2+2*`Y^2))(x,y) for y in kl] for x in kl]; import matplotlib.pyplot as plt; plt.contour(MX, MY, mt, [10,5,2,1, .5, .1, .01]); plt.show()

SciPy では Matlab の影響が強く、頻繁に mesh grid が使われます。SciPy 三次元表示関数の多くで mesh grid 引数が必須だったりします。Web ページでも mesh grid を使った contour(..) 関数の説明が大部分です。でも多くの場合 mesh grid の使用は冗長に感じます。大部分の場合は一様格子だけで考えているので、 contour(..) 関数で mesh grid 引数を渡すのは無駄です。グラフの X,Y 軸の値が正しく表示されるメリットがあります。でも、自分自身だけがみる等高線表示を描くときには、正しい X,Y 軸の値なんて殆ど意味ありません。コードを書いた自分は X,Y 軸の範囲なんて十分に承知しているのですから。そのことを十分に分かっている contour(..) 関数の作者は contor(Z) でも働くようにプログラムを作ってくれました。

Mesh grid を使わずに等高線を表示させる機能を実装してくれた contour(..) 関数の開発者に感謝します。

参考資料

pylab_examples example code: contour_demo.py ;;http://matplotlib.org/examples/pylab_examples/contour_demo.html



blog comments powered by Disqus