matplotlib

富士山の世界文化遺産登録が無事に完了した。そして山開き。いいタイミングですなあ。 山に入るには1000円払うようだけど、これってミニ・ヒマラヤのまね? だんだん高騰 してって、50年後には、入山にはあらかじめ申請して、3日間の講習を受けてから、 お一人様10万円払ってください、ってなるんですかね?

昔海外出張が長引き、日本が恋しくなった。いよいよ帰国。空港へ行ったら鶴のマークの 飛行機が待ってた。やっと日本へ帰れる。そして機上の人。日本へ近づき、スチィワーデス の人が、朝日に映える富士山がくっきりご覧になれますってアナウンスしてくれた時、涙が 出てきましたよ。

日本の象徴。銭湯へ行っても、富士山が有ったなあ。日本人の心の象徴ですかね。あちこち に何とか富士ってのがあるからね。おいらが気にいったのは、鹿児島県にある開聞岳。 山の形が、なかなかのものです。

登録を期に一気に富士山ブームをという期待も大きく、 フジヤマNAVIなんてのを出してきて、世界に発信ですか。 儲かるのは、交通網をほぼ独占してる、富士急鉄道ですかね。株大好き人間が群がって ますなあ。

となあ、お祭りモードなんですが、あえてそれに冷水をぶっかけてみると、 富士山大噴火が懸念されています。1707年の宝永大噴火以来、300年も噴火が無いんですなあ。 地下にはマグマがたっぷり溜まっている事でしょう。いつそれが噴出してもおかしくないと 言う。

かの宝永噴火の時は、江戸に大被害をもたらしたにも関わらず、時の将軍は大奥というハーレムに 目が行ってて、庶民には何の援助もしなかったらしい。そんな政治はごめんだね。 現政府は、富士山の火山防災対策てので、 来るべきXdayに備えてる。

たった1mmの火山灰が降るだけで、飛行機は欠航、交通大混乱、停電、健康悪化と 大変な事になる。

火山灰は濡れると導電性を帯びる。乾くとセメントのように硬くなる。軽いんでちょっと した風で舞い上がる。いやな奴ですな。どうするんですかね?上の政府の取り組みも なんか不安。一応やってますからって、後から後ろ指さされないようにしてるだけ?

自前でPCBSD

前回は、VMWARE用のDiskをそのまま使っちゃたら、デフォで入っていたpkgが多すぎて、 Diskが肥大化しちゃった(pkgの数が軽く1000を超える)。前にやったvmware-toolbox-cmd disk shrink /usr を施して あげたら、13.4Gあった容量が10.9Gまで減量したけど、まだ太目。

これはもう、自分で手を動かしてインストールしろよと言うお告げに違いない。 ええ、やってみましたよ。GUIのインストーラなのね。

デフォのDeskTopが、KDEじゃなくてLXDEってのは、KDEが重すぎて文句たらたらだった からでしょう。それとも、初心者はプアなマシンを使ってるだろうから、そこへKDE なんかを突っ込んで、遅いって言われて逃げられちゃうのを恐れたからでしょうか。

入れるpkgをLXDEを指定する時にカスタマイズ。KDEやら懐かしいfvwm等も指定出来るけど 目当ては別の所にある。各種のdev用ツール類。それと、vmwareとかvbox用のtool。 こういうのを後から入れようとするとややこしくなる。インストールは一時間程で終了。

再起動すると、言語の指定やら使う場所の指定、アカウントの設定、画面サイズの設定を 経て、完了。何となくLinux風になってきたね。

javaもopenjdkになってpkgが用意されてたので、一応入れておいた。昔はFreeBSD用に 認定を受けたjavaが用意されてたけど、いつの間にか、open系になっちゃったね。 これもそれも、某おら さんの専横なんですかね。MySQLしかりですな。

浮かんだグラフ

オムロンの体重計を買った時、とあるサイトに誘われて行ってみた所、血圧グラフが 面白い表示をしてたので、まねてみる。面白いってのは、血圧差に相当する棒グラフが 浮かんでいるんだ。ちょいとこういう発想は無かったね。

グラフはpythonのモジュール、matplotlibを使って書いているんで、種は無いかと ギャラリーを 探してみた。積み重ねグラフの1段目を透明にすれば、何とかなりそう。

例のサンプルコードだけでは、意味を読み取れなかったので、 pyplot apiの該当部分を参照して みる。

Make a bar plot.

Call signature:

bar(left, height, width=0.8, bottom=0, **kwargs)

Make a bar plot with rectangles bounded by:

    left, left + width, bottom, bottom + height
        (left, right, bottom and top edges)

四角形を縦に2つ積む事が出来るんだな。3個以上積む時はどうするん? ってのはさておき、 今回の用途にはぴったり。早速コードを書いてみた。

import numpy as np
from pylab import *

def omron(v=''):
    expand(v)
    if len(hi) == 0:
        return
    figure()
    title('Blood transit')
    ind = np.arange(len(hi))
    sa = [h - l for h, l in zip(hi, low)]
    bar(ind, sa,  color='white', bottom=low)
    plot(pls, color='red')
    grid(True)  # transit grpha
    figure()
    title('Blood pressure')
    xlabel('Low pressure')
    ylabel('High pressure')
    scatter(low, hi)
    grid(True)  # low vs. hi
    show()

hiが高血圧データ、lowが低血圧データ。棒の下端をlowにし、それから上に向かって、血圧差分 だけの高さを持ったバーを表示。これで浮いた棒グラフになる。バーの色は、普通は青 とかにするんだろうけど、印刷するとベタになってインクの減りが早かろう。そんな 理由で、バーの色は白指定。枠だけ印刷。あれ? 白ってインクはどうなる? 透明って 指定は出来るのかな。

血圧差を取ってく時、どうやるかちょいと悩んだけど某所に答えが出てた。肝はzipなんだな。 一応、どう動くか確認。

In [1]: zip?
Type:       builtin_function_or_method
String Form:<built-in function zip>
Namespace:  Python builtin
Docstring:
zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]

Return a list of tuples, where each tuple contains the i-th element
from each of the argument sequences.  The returned list is truncated
in length to the length of the shortest argument sequence.

In [2]: a = [1,2,3,4,5]

In [3]: b = [10,20,30,40,50,60]

In [4]: zip(a,b)
Out[4]: [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50)]

ipython

PCBSDの記念にipython-py27 を入れてみた。なんかやたらにQt関係者がくっついて来るんだけど 何か良い事あるの? 深くは詮索しないでおこう。とは言うものの一応 ipython -hしとく。

  :
Examples
--------

    ipython --pylab            # start in pylab mode
    ipython --pylab=qt         # start in pylab mode with the qt4 backend
    ipython --log-level=DEBUG  # set logging to DEBUG
    ipython --profile=foo      # start with profile foo

    ipython qtconsole          # start the qtconsole GUI application
    ipython help qtconsole     # show the help for the qtconsole subcmd

    ipython console            # start the terminal-based console application
    ipython help console       # show the help for the console subcmd

    ipython notebook           # start the IPython notebook
    ipython help notebook      # show the help for the notebook subcmd

    ipython profile create foo # create profile foo w/ default config files
    ipython help profile       # show the help for the profile subcmd

    ipython locate             # print the path to the IPython directory
    ipython locate profile foo # print the path to the directory for profile `foo`

ipythonを入れると、とっても便利。たとえば

[sakae@pcbsd ~]$ ipython --pylab
Python 2.7.3 (default, Nov 19 2012, 20:06:57)
Type "copyright", "credits" or "license" for more information.

IPython 0.13.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

Welcome to pylab, a matplotlib-based Python environment [backend: GTKAgg].
For more information, type 'help(pylab)'.

こんな具合に、グラフ表示機も一緒に起動して、gnuplotの端末みたいに使える。 どんなプロットコマンドが使えるかは、help(pylab)で調べられる。

上でWebを参照して調べた barの使い方なんかも

In [1]: bar?
  :
Required arguments:

  ========   ===============================================
  Argument   Description
  ========   ===============================================
  *left*     the x coordinates of the left sides of the bars
  *height*   the heights of the bars
  ========   ===============================================

Optional keyword arguments:

  ===============   ==========================================
  Keyword           Description
  ===============   ==========================================
  *width*           the widths of the bars
  *bottom*          the y coordinates of the bottom edges of
                    the bars
  *color*           the colors of the bars
  *edgecolor*       the colors of the bar edges
  *linewidth*       width of bar edges; None means use default
                    linewidth; 0 means don't draw edges.
  *xerr*            if not None, will be used to generate
                    errorbars on the bar chart
  *yerr*            if not None, will be used to generate
                    errorbars on the bar chart
  *ecolor*          specifies the color of any errorbar
  *capsize*         (default 3) determines the length in
                    points of the error bar caps
  *error_kw*        dictionary of kwargs to be passed to
                    errorbar method. *ecolor* and *capsize*
                    may be specified here rather than as
                    independent kwargs.
  *align*           'edge' (default) | 'center'
  *orientation*     'vertical' | 'horizontal'
  *log*             [False|True] False (default) leaves the
                    orientation axis as-is; True sets it to
                    log scale
  ===============   ==========================================
    :

こんな具合に端末から調べられてとっても便利。

CUIでもmatplotlib

上で出てきた血圧グラフを書くやつ、端末から起動すると、

[sakae@pcbsd ~/py]$ python blood.py
/usr/local/lib/python2.7/site-packages/gtk-2.0/gtk/__init__.py:57: GtkWarning: could not open display
  warnings.warn(str(e), _gtk.Warning)
    :
RuntimeError: could not create GdkCursor object

こんな具合にエラーになる。まあ、確信犯なんですが。。。Xが起動したGUIの環境じゃ なきゃ、いやーん ってのは、うなずける事です、が、、、

そんじゃ、Webの上で動的にグラフを作成したーいって、要求はかなえられません。 不便ですなあ。gnuplotだと、出来てたよね、って事で調べてみました。そしたら、こんなのが ヒットしましたよ。

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
plt.ylabel('some numbers')
plt.savefig('somenum.png')

CUIな端末から実行すると、pngファイルがちゃんと作成されてました。これを手がかりに CUI用のやつを作ってみました。

import matplotlib
matplotlib.use('Agg')
from matplotlib.pyplot import *
# from pylab import *

def png(v='HOGE.png'):
        savefig(v)

グラフを表示するコマンドを発した後

[sakae@pcbsd ~/py]$ python blood.py
Loaded 720 datas!!
06> box 120.
06> png 120day-stat.png

こんな風に使います。ああ、.pngは決め打ちにしておいた方が親切だな。 但し、これは、1画面しかsaveできないので注意。

上で出てきた、use()って何や?

In [4]: matplotlib.use?
Set the matplotlib backend to one of the known backends.

The argument is case-insensitive.  For the Cairo backend,
the argument can have an extension to indicate the type of
output.  Example:

    use('cairo.pdf')

will specify a default of pdf output generated by Cairo.

.. note::

    This function must be called *before* importing pyplot for
    the first time; or, if you are not using pyplot, it must be called
    before importing matplotlib.backends.  If warn is True, a warning
    is issued if you try and call this after pylab or pyplot have been
    loaded.  In certain black magic use cases, e.g.
    :func:`pyplot.switch_backends`, we are doing the reloading necessary to
    make the backend switch work (in some cases, e.g. pure image
    backends) so one can set warn=False to supporess the warnings.

To find out which backend is currently set, see
:func:`matplotlib.get_backend`.

どんな裏方さんが利用出来るかと言うと

In [6]: matplotlib.get_backend()
Out[6]: 'GTKAgg'

他には、どんなのが使えるの? どうやって調べる? matplotlib.__dict__ したら、ぱーと 出てきたけど、いまいちスマートじゃないね。やっぱりソース嫁?

その前にipythonでも、pagerと言うかpretty printが出来るのね。便利だから使えー。

In [3]: page matplotlib.rcParams
          :
 'font.family': 'sans-serif',
 'font.fantasy': ['Comic Sans MS',
                  'Chicago',
                  'Charcoal',
                  'ImpactWestern',
                  'fantasy'],
           :

ソースは何処から読むのが順当だろう? 自分がpythonさんになった積もりで、__init__.py あたり からだな。さーっと素読むしてったら、

Manage user customizations through a rc file.

The default file location is given in the following order

  - environment variable MATPLOTLIBRC

  - HOME/.matplotlib/matplotlibrc if HOME is defined

  - PATH/matplotlibrc where PATH is the return value of
    get_data_path()

こんなのに出くわして、更に見て苦と、

def get_backend():
    "Returns the current backend."
    return rcParams['backend']

ほー、こんな所で定義してるんだ。後は、

In [4]: matplotlib.rcParams
Out[4]:
{'agg.path.chunksize': 0,
 'axes.axisbelow': False,
     :
 'backend': 'GTKAgg',
 'backend.qt4': 'PyQt4',
 'backend_fallback': True,
     :
 'ytick.minor.size': 2,
 'ytick.minor.width': 0.5}

こんな具合になってましたよ。

# Now allow command line to override

# Allow command line access to the backend with -d (MATLAB compatible flag)

for s in sys.argv[1:]:
    if s.startswith('-d') and len(s) > 2:  # look for a -d flag
        try:
            use(s[2:])
        except (KeyError, ValueError):
            pass
        # we don't want to assume all -d flags are backends, eg -debug

これ、隠しコマンド?

おまけ

ipadにもmatplotlibの説明書を入れた。巨大なPDF。1200ページもあるよ。アドビの リーダーで開いてみたんだけど、最初はスムーズに読める。そのうちに、画面のスクロールが 角々しはじめて、暫くするとリーダーが居なくなっちゃう。iOSが、お前メモリー使いすぎ だろ! 殺してやるーーーーってんで、殺されたんだな。gc入れろよ。>あどび。

matplotlib関係の資料を漁っていた時、GNURadioとかやってる 面白いサイトに行き着いた。スミスチャートを 書いたりしてて、実用になってるなあって思った次第。