2012年6月30日土曜日

matplotlib その3(プロットした点をクリック、ハイライトする)


matplotlibでマウスのイベントを取得して、クリックした点のデータをとってくる。
参考URLを勉強がてら少しシンプルにしてみる。
描画データをPointBrowserに関連付けておいて、データをクリックするたびに、その上に黄色い薄い丸を描画するようにしている。


メモ:
plotのpicker=5でクリックしたときの許容範囲を決定。
複数のデータがクリック範囲に入ったときも、そのうち1番最初の1つのみを使う。(ind[0])
mpl_connectを使えば、マウス以外にもイベントを取得できる。ハンドラーというのだろう。(http://matplotlib.sourceforge.net/api/backend_bases_api.html#matplotlib.backend_bases.FigureCanvasBase.mpl_connect)


参考URL:http://matplotlib.sourceforge.net/examples/event_handling/data_browser.html

from numpy.random import rand
from pylab import figure, show


class PointBrowser:
    """
    pass a subplot to __init__
    overwrite the yellow circle on the clicked data
    """
    def __init__(self, fig, ax):
        self.fig = fig
        self.text = ax.text(0.05, 0.95, 'selected: none',
                            transform=ax.transAxes, va='top')


        self.selected,  = ax.plot([], [], 'o', ms=12, alpha=0.4,
                                  color='yellow', visible=False)

    def onpick(self, event):
        """
        it picks up the index of clicked data

        """
        if not len(event.ind):
            return True

        ind = event.ind[0]
        x = event.artist.get_xdata()[ind]
        y = event.artist.get_ydata()[ind]
        clicked = (x, y)

        self.selected.set_visible(True)
        self.selected.set_data(clicked)
        self.text.set_text(' x: %f\n y: %f'%(clicked))
        self.fig.canvas.draw()

if __name__ == "__main__":
    xs = rand(100)
    ys = rand(100)

    fig = figure()
    ax = fig.add_subplot(111)
    ax.set_title('picking demo')
    ax.plot(xs, ys, 'o', picker=5)  # 5 points tolerance

    browser = PointBrowser(fig, ax)
    fig.canvas.mpl_connect('pick_event', browser.onpick)

    show()




matplotlib 軸の目盛り設定

軸の目盛りは自動で最大値をつけてくれるけど、
手動で付けたい時はset_yticks(list)を使う。

def main():
    fig = figure()
    ax1 = fig.add_subplot(111)
    ax1.plot(rand(10))
    ax1.set_yticks(np.arange(0, 1.1, 0.1))

    show()

if __name__ == "__main__":
    main()







matplotlib その2 (複数のプロット)

matplotlib で複数のグラフを表示する。

1つのウィンドウに2つのグラフを表示する場合
from matplotlib.pyplot import figure, show
import numpy as np
from numpy.random import rand

def main():
    fig = figure()
    ax1 = fig.add_subplot(211)
    ax1.plot(rand(10))
    ax1.set_yticks(np.arange(0, 1.1, 0.1))

    ax2 = fig.add_subplot(212)
    ax2.plot(rand(10), 'o')
    show()

if __name__ == "__main__":
    main()


2つのウィンドウにそれぞれプロットするときは
    fig = figure()

    ax1 = fig.add_subplot(111)
    ax1.plot(rand(10))
    ax1.set_yticks(np.arange(0, 1.1, 0.1))

    fig = figure()
    ax2 = fig.add_subplot(111)
    ax2.plot(rand(10), 'o')
    show()





fig2としなくても描画はできるようだ。
試しにfig=figure()を2回読んだときのfigの中身を調べてみたら
numberとかいうのがあって、それが2になっていた。
以下参考までに
>>> fig = figure()
>>> fig = figure()
>>> fig.__dict__
{'_agg_filter': None,
 '_alpha': None,
 '_animated': False,
 '_axobservers': [],
 '_axstack': ,
 '_cachedRenderer': None,
 '_clipon': True,
 '_clippath': None,
 '_contains': None,
 '_dpi': 80,
 '_gid': None,
 '_hold': True,
 '_label': '',
 '_lod': False,
 '_oid': 0,
 '_picker': None,
 '_propobservers': {},
 '_rasterized': None,
 '_remove_method': None,
 '_snap': None,
 '_transform': None,
 '_transformSet': False,
 '_url': None,
 '_visible': True,
 'artists': [],
 'bbox': TransformedBbox(Bbox(array([[ 0.,  0.],
       [ 8.,  6.]])), Affine2D(array([[ 80.,   0.,   0.],
       [  0.,  80.,   0.],
       [  0.,   0.,   1.]]))),
 'bbox_inches': Bbox(array([[ 0.,  0.],
       [ 8.,  6.]])),
 'callbacks': ,
 'canvas': ,
 'clipbox': None,
 'dpi_scale_trans': Affine2D(array([[ 80.,   0.,   0.],
       [  0.,  80.,   0.],
       [  0.,   0.,   1.]])),
 'eventson': False,
 'figure': None,
 'figurePatch': ,
 'frameon': True,
 'images': [],
 'legends': [],
 'lines': [],
 'number': 2,
 'patch': ,
 'patches': [],
 'show':  at 0x03A35730>,
 'subplotpars': ,
 'suppressComposite': None,
 'texts': [],
 'transFigure': BboxTransformTo(TransformedBbox(Bbox(array([[ 0.,  0.],
       [ 8.,  6.]])), Affine2D(array([[ 80.,   0.,   0.],
       [  0.,  80.,   0.],
       [  0.,   0.,   1.]])))),
 'x_isdata': True,
 'y_isdata': True}


matplotlib その1 (グラフ表示)

これからmatplotlibの使い方をメモしていく。
最終的にはインタラクティブなグラフを作りたい。
例えばデータ点をドラッグしてデータを動かしたり、クリックで編集したり。

まずはグラフの表示。
def main():
    ax = figure().add_subplot(111)
    ax.set_title('test')
    ax.set_ylabel('ylabel')
    ax.plot(rand(10))
    ax.plot(rand(10), 'o')
    show()

if __name__ == "__main__":
    main()

調べたことの覚書:

  1. figure(http://matplotlib.sourceforge.net/api/figure_api.html)
    • すべてのプロット要素を含んだ属性(Artist,Figure)を持つらしい。
  2. add_subplot(111)





2012年6月24日日曜日

Pythonでpwdとかcdとかlsとか


Pythonでpwdとかcdとかlsとか使うには
osモジュールを使うらしい。
具体的には、
>>> import os
>>> os.getcwd()
'C:\\Program Files (x86)'
>>> os.getcwd()
'C:\\Program Files (x86)\\PyScripter'
>>> os.listdir('.')
['Lib',
 'locale',
 'PyProject.ico',
 'PyScripter.chm',
 'PyScripter.exe',
 'unins000.dat',
 'unins000.exe']


2012年6月19日火曜日

Python クラスメソッドのselfにはインスタンスが渡されるらしい。

クラスメソッドの第一引数にはselfが出てくる。
例えば、簡単な例をつくると、
class Person:
    def __init__(self, name):
        self.name = name
    def changeName(self, name):
        self.name = name

if __name__ == "__main__":
    taro = Person("taro")
    jiro = Person("jiro")
    print taro.name, jiro.name

    taro.changeName("tatsuro")
    jiro.changeName("eijiro")
    print taro.name, jiro.name
changeNameを呼び出したとき、引数には名前(文字列)しか与えていないが、
どうやら、自動的にselfにはtaroのインスタンス、またはjiroのインスタンスが渡されているようだ。



Python 簡単なクラスの作成法

Pythonでインタラクティブにクラスを生成する方法。
>>> class person: pass
... 
>>> person.name = "taro"
>>> person.age = 26
>>> print person.name
taro
属性(attribute)を後付けで定義している。
クラスのオブジェクトを定義しただけで、まだインスタンスは作っていない。
インスタンスを生成する。
>>> x = person()
>>> print x.name
taro



クラスにある属性を調べる
なぜかインスタンスのほうは定義したものしか現れない。
呼ばれるまで作らないということなのか??
>>> x.name = "jiro"
>>> person.__dict__.keys()
['age', '__module__', '__doc__', 'name']
>>> x.__dict__.keys()
['name']


どのクラスに関連付けされているかを調べるには
>>> x.__class__


あと付けで関数を定義して、それをクラスメソッドにする。
>>> def firstLetter(self):
...     return self.name[0]
... 
>>> firstLetter(x)
'j'
>>> person.method = firstLetter
>>> x.method()
'j'






2012年6月14日木曜日

モジュールについて

外部ファイルに記述された関数や変数(モジュール)に対して

モジュールを使う利点は3つ挙げられる。

  1. コードの再利用
  2. 名前の衝突を防ぐ
  3. データや関数の共有


Pythonでモジュールを使うには、importやfromを使うが、


import  モジュール全体を取り込む
from    あるモジュールの特定の名前を取り込む

import文が実行されると、次の3ステップが行われる。

  1. 該当するファイルを見つける。
  2. コンパイルする(.pycができる)。
  3. 上から下まで実行される。
たとえばimport bと書いた時、bに拡張子は付けない。
つまりb.pycが呼ばれるときもある。優先順位は539ページにあるのでチェックすべし。


初めてのPython 20章その4 デフォルト引数使用時の注意

デフォルト引数はdef文が実行されるときに定義される。
関数が呼ばれるときは何もしない。
>>> def saver(x=[]):
...     x.append('aho')
...     print x
...     
>>> saver([4])
[4, 'aho']
>>> saver()
['aho']
>>> saver()
['aho', 'aho']
>>> saver([1])
[1, 'aho']
>>> saver()
['aho', 'aho', 'aho']
>>> 

デフォルト引数はグローバル変数のように生き残るが、
名前が衝突するようなことはない




python. and とか or とか notとか

and, or, notの動作についての確認メモ

>>> 1 or 3    #左がtrueでなければ右のを返す
1
>>> 0 or 3
3
>>> [] or 3
3
>>> [0] or 3
[0]

>>> 1 and 2, 0 and 3 #左がTrueなら右のを返す。
(2, 0)
>>> [] and 4
[]
>>> 





2012年6月13日水曜日

初めてのPython 20章 その3 (timer module)



関数の実行時間を計測するタイマー。
使えそうなのでメモしておく。


>>> import time
>>> reps = 1000
>>> repslist = range(reps)
>>> 
>>> def timer(func, *pargs, **kargs):
...     start = time.clock()
...     for i in repslist:
...         ret = func(*pargs, **kargs)
...     elapsed = time.clock() - start
...     return (elapsed, ret)
... 


初めてのPython20章 その2

とりあえず20章のつづき。

まずはzip関数とシーケンスを分解してタプルで返す
>>> zip([-2, -1, 0])
[(-2,), (-1,), (0,)]
>>>
>>> zip([-2, -1, 0], [3, 2, 1, 0])
[(-2, 3), (-1, 2), (0, 1)]



関数に複数の引数を与え、それをzip関数で解凍する
>>> def mymap(func, *seqs):
...     return [func(*args) for args in zip(*seqs)]
zip関数を自作すると以下のようになる。
while all(seqs)に注目
>>> def myzip(*seqs):
...     seqs = [list(S) for S in seqs]                #各引数をリストに直したものをseqsに入れる
...     res = []
...     while all(seqs):                              #各引数について先頭のものを消去しながらループ
...         res.append(tuple(S.pop(0) for S in seqs))
...     return res
... 
>>> myzip([1,2,3])
[(1,), (2,), (3,)]

ここでallはリスト内の各要素が反復可能か調べるみたい
anyとかいうのもある。
>>> all([1,2,3])
True
>>> all([1,2,0])
False
>>> all([[1,2], [0]])
True
>>> all([[1,2], []])
False
>>> all([])
True

dictionaryの反復はkeyでアクセスする。
>>> d = {'jap': 35, 'ame': 2, 'eng': 0}
>>> for key in d:
...     print key, d[key]
...     
ame 2
jap 35
eng 0
>>> 

リストをfor文で作れるがセットでは違ってくる(重複するのを避ける)
>>> [x + y for x in [1,2,3] for y in [4, 5, 6]]
[5, 6, 7, 6, 7, 8, 7, 8, 9]
>>> {x + y for x in [1,2,3] for y in [4,5,6]}
set([5, 6, 7, 8, 9])


2012年6月8日金曜日

初めてのPython20章

この章リストやforループの応用について書かれてあるようだ。14章の続きみたいなものらしい。

例えば19章のmap関数を使わなくてもリストの表現で次のように掛ける。
>>> [x+10 for x in [0, 1, 2, 3]]
[10, 11, 12, 13]
更にif文を加えるとfilter関数のようになる。
>>> [x for x in range(-5, 5) if x > 0]
[1, 2, 3, 4]
このfor文は何個も続けて(nest)させることができる。
下の2つは別表現で同じことをやっている。
>>> [x * y for x in [0, 1, 2] for y in [3, 4, 5]]
[0, 0, 0, 3, 4, 5, 6, 8, 10]

>>> l = []
>>> for x in [0, 1, 2]:
...     for y in [3, 4, 5]:
...         l.append(x*y)
... 
>>> l
[0, 0, 0, 3, 4, 5, 6, 8, 10]
ちなみに本文によると、これらのリスト表現はmapなどより若干早いとのこと。


続いてはgeneratorと言うものについて。
関数ではreturnで戻り値を返すわけだが、yieldで返すこともできる。
yieldで値を返したときには、関数がその状態を保持してくれているみたいだ。
次の状態に遷移させるにはnext()を使う。具体的には以下のようになる。
>>> def gen(N):
...     for i in range(N):
...         yield i*2
...         
>>> x = gen(3)
>>> x.next()
0
>>> x.next()
2
>>> x.next()
4
>>> x.next()
Traceback (most recent call last):
  File "", line 1, in 
StopIteration
その都度値を生成するので、大きなリストを作るときに役立つのだろう。


yieldは式なので、=の右辺に持ってきたりもできる。
するともう少し高度な使い方が出来るとのこと。
そこで登場するのがsend()メソッド。
generatorとのコミュニケーションを行うことができるのだ。
なんとか理解できたけど、どんな使い方があるのだろうか...
例を示すとこうなる。
>>> def gen():
...     for i in range(5):
...         x = yield i*2
...         print "yes", x
... 
>>> g = gen()
>>> g.next() #yieldまでgeneratorを進める。ここで一度yieldを呼ばずsend()をするとエラーになる。
0
>>> g.next() #next()やsend()をすると止まっていたgeneratorが動くき次のyeildまで進む。
yes None
2
>>> g.send(100) #send()でxに値を与えることができる。
yes 100
4
>>> g.next()
yes None
6
>>> 

上のgeneratorはgenerator関数。 generator式(expression)というのもある。
これらgeneratorは1つのオブジェクトであり、
何個も作って途中で止めておいたり、なんてできない。
>>> g = (c*2 for c in "apple") #generator expression
>>> i = iter(g)                #イタレータを登録
>>> i is g
True
>>> i.next()
'aa'
>>> g.next()
'pp'
>>> i.next()
'pp'
>>> i.next()
'll'
>>> g is i                     #同じオブジェクト
True
>>> 

続く…

2012年6月5日火曜日

初めてのPython 19章

19章はもう少し関数について


関数を再帰的に呼び出す
isinstanceで型を調べるようだ。
>>> def sumtree(L):
...     tot = 0
...     for x in L:
...         if not isinstance(x, list):
...             tot += x
...         else:
...             tot += sumtree(x)
...     return tot
... 
>>> L = [1, [2, [3,4], 5], 6, [7, 8]]
>>> sumtree(L)
36

関数はオブジェクトなので引数に渡すこともできる。
関数と引数をリストにしてfor文で実行してみる。
>>> def sayhello(func, arg): 
...     func(arg)
...     
>>> sayhello(func, 'morning') #funcという関数を渡す
morning
>>> schedule = [(func, 'hello'), (func, 'morning')]
>>> for (f, arg) in schedule:
...     f(arg)
...     
hello
morning
>>> 


続いてlambdaについて勉強する
lambdaはdefとは違い式である→defが書けないところにも書けたりする。
シンプルな記述が可能になるとこのこと。
まずは基本。
>>> f = (lambda x = 3, y = 4: x**2 + y**2)
>>> f()
25

リストにlambdaを定義してこんなこともできるのら。
>>> l = [lambda x: x**2,
...      lambda x: x**4,
...      lambda x: x**8]
>>> 
>>> for f in l:
...     print f(2)
...     
4
16
256
>>> 

>>> d = {"plus": (lambda x, y: x + y),
...      "mult": (lambda x, y: x * y),
...      "pow": (lambda x, y: x**y)}
>>> d["plus"](2,3)
5

シーケンス(リストなど)を扱う関数にmapやfilter, reduceというものがある。
これらの関数は自作でいちいちその関数を定義するよりも速く動く。
まず、マップについて。使い方はこうなる。
>>> nums = [0, 1, 2, 3]
>>> func = lambda x: x + 10
>>> map(func, nums)
[10, 11, 12, 13]
関数が2つの引数を取るなら、リストを2つ渡してもよい。
>>> map(pow, nums, [0, 1, 2, 3])
[1, 1, 4, 27]

続いてfilter。
filterはその名の通り、条件をつけてシーケンスにフィルターを掛けることができる。
>>> func = lambda x: x > 0
>>> filter(func, range(-3, 3))
[1, 2]

reduceはリストを1つにまとめるからそういう名前になったのだろうか。
使い方はこうだ。
>>> func = lambda x,y: x + y
>>> reduce(func, [0, 1, 2, 3])
6

と言う感じで次の章へ~


初めてのPython 18章

18章は引数について

Immutable(integer, string)などは値が渡さえる。
Mutable(list, dictionary)などは参照(pointer)が渡される。
>>> def changer(a, b):
...     a = 2
...     b[0] = "spam"
...     
>>> x = 1
>>> l = [1,2]
>>> changer(x, l)
>>> x
1
>>> l
['spam', 2]


リストなどの内容を変更したくないときはコピーを渡すか、関数ないでコピーを作る
>>> changer(x, l[:])
>>> def changer(a, b):
...     b = b[:]


複数のオブジェクトをタプルとしてreturnできる。
>>> def multiple(x, y):
...     x = 2
...     y = [3, 4]
...     return x, y
... 
つづく…

2012年6月3日日曜日

ミシュラン フランス料理の行けそうなものをピックアップしてみる。

まずはリスト。
http://blog.livedoor.jp/luliecross/archives/52235096.html


モナリザ☆ リーズナブルらしい。。。
http://www.monnalisa.co.jp/top.html

なりさわさん☆☆
http://www.narisawa-yoshihiro.com/jp/menu.html

小田原にある☆ 雰囲気よし。
http://herlequin.com/herlequinbis/menu/03.html
http://rirutomo527.blog79.fc2.com/blog-entry-330.html


横浜栄区☆
http://cheznaka.easy-magic.com/files/cheznaka/dinner01.htm?PHPSESSID=d194ea843c2eb259cfb65b3887035785

ty お店3件とも星(1~2個)を獲得している。
http://www.tateruyoshino.com/index.html

あのピエールの店☆☆
http://www.anaintercontinental-tokyo.jp/pierre_gagnaire/index.html

あのKoujimuraのお店☆☆
http://www.koji-shimomura.jp/index.html

カーエム☆☆ 当日予約はダメ
http://www.km-french.jp/index.html

代官山にある☆
http://www.augoutdujour-group.com/la/info.html


ふぅ~

初めてのPython 17章

lambdaを関数にネストする
>>> def func():
        x = 4
        action = (lambda n: x**n)
        return action
>>> x = func()
>>> x(4)
256
ループ内でlambdaを定義した場合は最後の変数が使われるので注意
>>> def makeActions():
...     acts = []
...     for i in range(5):
...         acts.append(lambda x: i**x)
...     return acts
...
>>> acts = makeActions()
>>> acts[0](2) #4**2になる
16
>>> acts[0](0) #4**0
1
>>> acts[2](2) #4**2
16

こうならないためにはデフォルト引数で指定しておく。
lambdaが作られるときの値がつかわれる。
>>> def makeActions():
...     acts = []
...     for i in range(5):
...         acts.append(lambda x, i=i: i**x)
...     return acts
...
>>> acts = makeActions()
>>> acts[0](2)
0
>>> acts[2](2)
4

nonlocalは飛ばして次へ~

はじめに

このブログは「初めてのPython」で学習した表現を忘れないためにメモしておくことが目的。
初めてのPythonに目に通しながらPythonの表現を勉強していく。
C++とJavaはやったことあるけど、それにはないPythonならではのスタイルを味わいたい。


ちなみにその他読んでいる本(読んでいきたい本)は
パターン認識と機械学習と
Physically Based Rendering, Second Editionと
はじめてのCUDAプログラミング

この辺と光学関連の勉強も適時載せていきたい。