情報通信システム(5) http://www10.plala.or.jp/katofmly/chiba-u/ 2016年5月24日 火曜日 午後4時10分~5時40分 NTT-IT Corp. 加藤 洋一 千葉大学 5- 2 プログラム言語について • 講師のプログラミング遍歴 – 千葉大学2年の頃:8ビットマイクロコンピューターApple IIのクローンを自作し、 Basic、機械語、アセンブラなどを覚えた。原始的なシューティングゲームなど を書いて遊んでいた。 – 大学3年:計算機センター(?)でLISPを受講。 – 大学4年:卒研のため、FORTRANを先輩から教わる(劣化画像の復元) – 大学4年の頃:バイトでプログラムを書いていた。MBASIC使用。小学校の成 績管理ソフトや、自動車修理工場の作業管理ソフトなど。 – 大学4年の頃:PASCALを独習。PL/1をちょっとだけ。 – NTT研究所にて:FORTRANでビデオ符号化の研究(1990年くらいまで) – NTT研究所でLANやメールを立ち上げた。UNIXを使用。シェルスクリプトを 覚えた。 – NTT画像通信事業本部(1991):Cを始めて使用した。ポインタの理解にてこ ずる。最初から商用のプログラムを書いた。 – 1993年ごろ:C++を使い始める。最初は何でもオブジェクト(クラス)化したが、 今では必要のあるものだけクラスを使う。 – 1996年頃から:業務でLISPを使用。3D仮想空間通信のプログラム – 1997年頃から:Pythonを使い始める。部下のひとりが、「どうしてもこれを使 いたい」と主張し、受け入れた。 – 2000年頃から:JavaScriptを使い始める。 – 現在:C、C++、Python、JavaScript、HTML、Flashなどを主に使用している。 千葉大学 5- 3 プログラム言語についての私見 • Cは、コンピューターの動きに近い形でプログラミン グできる。どちらかというとプリミティブ(高級言語と はいえない)。 – コンピューターがどのように動作しているか理解していな いと良いプログラムは書けない。 • FORTRANは数値演算が得意 – – – – 配列演算が高速。コンパイル時の最適化がしやすい 数値演算用パッケージが豊富 文字列処理などには向かない 業務用システムで使われているのを見たことがない 千葉大学 5- 4 プログラム言語についての私見 • Java – – – – インタープリーター 講師は経験がほとんどない いろいろなプラットフォームで動作するというのが売り Cとスクリプト言語の中間くらいの「高級度」 • スクリプト言語(Perl、Python、Ruby、など) – インタープリーター、高級プログラミング言語 – ライブラリーが豊富で、短いコードで様々なプログラムが できる – 学習も楽 – どちらかというと実行速度は遅い • JavaScriptとHTML – Web+データベースシステムでは、GUIで利用されている。 千葉大学 5- 5 プログラム言語についての私見 • プログラムのパラダイムシフト – プラットフォームが提供する機能が増えた – プログラム言語は、プラットフォームが提供する機能を組み合わせ、 コントロールするために使われる。 – プラットフォームへの理解が必要 • Windowsなら、Win32アーキテクチャ。 • UNIXなら、X-windowなど。 • インターネットなら、HTML、HTTP、HTTPサーバー、DBサーバー、SQL、 CGIなど 大 小 個別アプリケーション プログラムが 提供する部分 プラットフォームが 提供する部分 昔 個別アプリケーション プログラムが 提供する部分 小 プラットフォームが 提供する部分 大 今 千葉大学 5- 6 Pythonについて • あるプログラムをいろいろな言語で多くの人に作成してもらっ た。完成までの時間を比較した(生産性)。 http://page.mi.fu-berlin.de/~prechelt/Biblio/jccpprt_computer2000.pdf 千葉大学 5- 7 Pythonについて • プログラムの長さ(行数)を比較した http://page.mi.fu-berlin.de/~prechelt/Biblio/jccpprt_computer2000.pdf 千葉大学 5- 8 Pythonについて • 実行時間を比較した http://page.mi.fu-berlin.de/~prechelt/Biblio/jccpprt_computer2000.pdf 千葉大学 5- 9 プログラミング言語Pythonの紹介 • ダウンロード – URL: http://www.python.org/download/ – “Python 2.7.6 Windows installer” をダウンロー ド • File Name: python-2.7.6.msi – UNIX系のOSを使っている人は、ソースコードを 自分でコンパイルしても良い。 • インストール – Windows版の場合、python-2.7.6.msi というファ イルをダブルクリックするだけ。 千葉大学 5- 10 Pythonは良いのか? • Pythonが実ビジネスで使われている例です。 – NASA – ILM(ルーカスフィルム) – Google,Yahooも使っています。当初GooleAppsで使える唯一のスク リプト言語(今はJavaも使えるらしい) • Pythonプログラミング人口は、世界で数万人と考えられてい ます。Cなどに比べるとずっと少ないです。 • 本講義では、なぜPython? – 学習が容易で、フリーで、豊富なライブラリーとともに、使えるからで す。 – 国内では、Rubyも良く使われています。どちらが良いかは最後は「好 み」かもしれません。 千葉大学 5- 11 チュートリアル文書 • 日本語のマニュアルやチュートリアルは以下 からダウンロードできます – http://www.python.jp/Zope/ • 書籍も10種類以上出ています • 原典は、下記の公式サイト – http://www.python.org/ 千葉大学 5- 12 まずは、インタープリーターを使う(1) • Python (command line)を起動する。 • 「スタート」->「全てのプログラム」 -> 「Python2.7」 -> Python (command line) • いろいろな計算を試してみる。 – 整数、フローティングポイント、複素数 • 複素数の虚数単位は、”j“です。例えば、 a=1+3jなど。 – 四則演算、べき乗、剰余 • べき乗は**です。 • 剰余は%です。 – 論理値は、TrueとFalseです。 • 論理演算には、not and or があります。 – ‘何もない’という状態を表すために、Noneがあります。 • 変数を使う – 変数の型は、それがはじめて使われたときに決まる。あら かじめ宣言する必要はない。 • インタープリーターだからですね。 千葉大学 5- 13 電卓代わり Python 2.4.1 (#65, Mar 30 2005, 09:13:57) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> 1+1 2 >>> 2*5 10 >>> 10/4 2 >>> 10.0/4.0 2.5 >>> 100**10 100000000000000000000 L >>> 1.2*5.2 6.2400000000000002 >>> 1.2**5.2 2.5807294598021677 >>> 10 % 3 1 >>> 1==1 True >>> 1==0 False >>> True or False True >>> True and False False >>> not True False >>> not False True 千葉大学 5- 14 変数を使う >>> a = 10 >>> b = 3 >>> c = 10.5 >>> a*b/c 2.8571428571428572 >>> d=0+100j >>> a+b/d+c (20.5-0.029999999999999999j) >>> e = 'abcdef' >>> d = 'ghijklm' >>> e+d 'abcdefghijklm' >>> e+c Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: cannot concatenate 'str' and 'float' objects >>> d/0 Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: unsupported operand type(s) for /: 'str' and 'int' 千葉大学 5- 15 複素数 >>> a=1+7j >>> abs(a) 7.0710678118654755 >>> a.imag 7.0 >>> a.real 1.0 >>> b=a**2 >>> b (-48+14j) >>> b/a (1+6.9999999999999991j) >>> c=10+50j >>> a*c (-340+120j) >>> a.real * c.real - a.imag * c.imag -340.0 >>> a.real * c.imag + a.imag * c.real 120.0 >>> 千葉大学 5- 16 文字列 >>> a='abcdef' >>> b='ABCDEF' >>> c=a*2+b >>> c 'abcdefabcdefABCDEF' >>> c[2:4] 'cd' >>> c[2;0] File "<stdin>", line 1 c[2;0] ^ SyntaxError: invalid syntax >>> c[5] 'f' >>> c[:5] 'abcde' >>> c[5:] 'fabcdefABCDEF' >>> len(c) 18 >>> d=" %d " % (5) >>> " %d " % (5) '5' >>> " %d %f %r" % (5, 10.0, 4+7j) ' 5 10.000000 (4+7j)' >>> (" %d %f %r" % (5, 10.0, 4+7j)) + "AAAA" ' 5 10.000000 (4+7j)AAAA' >>> (" %d %f %r" % (5, 10.0, 4+7j)) * 2 ' 5 10.000000 (4+7j) 5 10.000000 (4+7j)' >>> c[len(c)-5:] 'BCDEF' C の printf と同じフォーマットが使える % の後ろに、変数リストをおく 文字列の切り出しは:を使う 千葉大学 5- 17 演算子 • 演算子は、Cと同じです。 – 四則演算 + - / * • + や * は、数字だけでなく、文字列やリストなどにも使える場合が あります。 – べき乗 ** • 3**4 は 81 – 剰余 実数や複素数もOK % • A % Bは、AをBで割った余り。実数でも複素数でも使える – 割り算(答えは整数) // • A // Bは、AをBで割ったときの整数部 – ビットシフト << • 1 << 4 は16 >> 256 >>2は64 – ビット演算 & | ^ ~ • 整数の各ビットごとに and(&), or(|), exclusive or(^), ビット反転 (~)、をそれぞれ行う。~は単項演算子 – 関係演算 < > <= >= == != 千葉大学 5- 18 豊富にあるライブラリを使って‘楽’をする • ライブラリの使い方 – import ‘ライブラリ名’ – ライブラリの関数は、 ‘ライブラリ名’.’関数名’で呼ぶ • >>> import math • >>> math.sin( 1 ) – ほかのやり方もあります。 • >>> import * from math あるいは from math import sin • sin(1) • ただし、このやり方は、関数名のオーバーラップなどある場合に 問題があるので、あまりお勧めしません。 – math ライブラリを使って、三角関数などを試す • import math 複素数の math ライブラリは cmath 千葉大学 5- 19 Math ライブラリ >>> import math >>> math.sin(1.1) 0.89120736006143542 >>> math.pi 3.1415926535897931 >>> math.e 2.7182818284590451 >>> math.log(128,2) 7.0 >>> math.log(128,math.e) 4.8520302639196169 >>> math.atan(0.5) 0.46364760900080609 >>> math.asin(0.5) 0.52359877559829893 >>> math.asin(0.707) 0.78524716339515299 >>> math.asin(0.707) / math.pi 0.24995193520645564 >>> math.asin(0.7071) / math.pi 0.24999694740819128 >>> from cmath import * >>> e 2.7182818284590451 >>> pi 3.1415926535897931 >>> e**pi 23.140692632779263 >>> e**(pi)*1j 23.140692632779263j >>> e**(pi*1j) (-1+1.2246063538223773e-016j) >>> e**(pi/2 * 1j) (6.1230317691118863e-017+1j) >>> e**0.0 1.0 >>> sin(1+1j) (1.2984575814159773+0.6349639147847 3613j) >>> from cmath import * の形式はあまりお勧めしない 千葉大学 5- 20 String の扱い >>> a=" It is beautiful day today " >>> a.strip() 'It is beautiful day today' >>> a.find('day') 19 >>> a.replace('day', 'night') ' It is beautiful night tonight ' >>> a.upper() ' IT IS BEAUTIFUL DAY TODAY ' >>> a.lower() ' it is beautiful day today ' >>> a.capitalize() ' it is beautiful day today ' >>> string.atoi( "1002302") 1002302 >>> string.atof( "100.2302") 100.2302 int(), float(), str() >>> a=1 >>> str(a) '1' >>> float(a) 1.0 >>> b='1111' >>> int(b) 1111 >>> b='11234.221' >>> int(b) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: invalid literal for int() with base 10: '11234.221' >>> float(b) 11234.221 >>> c='asdfg' >>> int(c) Traceback (most recent call last): 千葉大学 5- 21 まずは、インタープリーターを使う(2) • リストを試してみる(「配列」を高機能化したもの)。 – L=[ ]とすると、Lはリストになる。 – リストに要素を追加する。ソートする。リストから要素を取 り出す、など • append(), sort(), count(), reverse(), index(), … • リストの中にリストも作れます。 • 文字列もリストの一種です。 • 辞書型(ディクショナリ)を試してみる。 – D={ }とすると、Dはディクショナリ形となる。 – ディクショナリの要素には順序はありません。 – ディクショナリとリストを使って、相当複雑なデータ構造が 実現できます。 千葉大学 5- 22 リスト >>> l=[] >>> l.append(1) >>> l.append(4) >>> l [1, 4] >>> l*5 [1, 4, 1, 4, 1, 4, 1, 4, 1, 4] >>> l.append(-2) >>> l.sort() >>> l [-2, 1, 4] >>> l.append('dfgg') >>> l.sort() >>> l [-2, 1, 4, 'dfgg'] >>> l.append(100) >>> l [-2, 1, 4, 'dfgg', 100] >>> l.sort() >>> l [-2, 1, 4, 100, 'dfgg'] >>> l[3] >>> l.append([0,5,9]) 100 >>> l >>> l[3] = 200 [-2, 1, 4, 'dfgg', [0, 5, 9]] >>> l >>> [-2, 1, 4, 200, 'dfgg'] >>> del l[3] >>> l [-2, 1, 4, 'dfgg'] >>> l[2:2] [] >>> l[2:4] [4, 'dfgg'] >>> min(l) -2 リストの要素へのアクセスは、[]を >>> max(l) 使う 'dfgg' リストから部分リストを取り出すに >>> 4 in l は:を使う True >>> 5 in l False 千葉大学 5- 23 辞書型 >>> dic={} >>> dic[12] = 'fzdfzff' >>> dic['421423']=5 >>> dic.keys() ['421423', 12] >>> dic.sort() Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: 'dict' object has no attribute 'sort' >>> len (dic) 2 >>> dic[4124123123]=[34,66,764,4] >>> dic {'421423': 5, 4124123123L: [34, 66, 764, 4], 12: 'fzdfzff'} 例えば、URLのパラメータリストは辞書型としてあらわされる http://maps.google.co.jp/maps?hl=ja&tab=wl {‘hl’:’ja’, ‘tab’:’wl’} 千葉大学 5- 24 ファイル型 >>> f = open('../test.txt', 'w') >>> f.write('this is a test file \n') >>> f.write('%d %d %f' % (5, 5, 1.0)) >>> f.close() >>> test.txt の中身 this is a test file 5 5 1.000000 >>> f = open('../test.txt', 'r') >>> a = f.readline() >>> print a this is a test file >>> b = f.readline() >>> print b 5 5 1.000000 >>> f.seek(0) >>> c = f.readlines() >>> print c ['this is a test file \n', '5 5 1.000000 \n'] >>> 一ラインを要素とするリストになっている 千葉大学 5- 25 オブジェクト • A=1+3j とすれば、Aには複素数が格納される。 • すると、Aは複素数オブジェクトとなり、例えば、A.imag とするこ とにより、虚数部分が取り出せるようになる。 • B=[]とすると、Bはリストオブジェクトとなり、B.sort() などで、演 算も可能となる。 • A.imagのように、オブジェクトの何らかの値を示すものを attribute (属性)といいます。 • B.sort()のように、操作を行うものは、method(メソッド)といい ます。 • 複素数オブジェクトでは、A.imagはAの虚数部分というattribute、 A.conjugate()は、Aの複素共役を返すmethodです。 • 特に、文字列、リスト、辞書型には、便利なmethodがあります。 • オブジェクトやオブジェクトで使えるメソッドや属性を調べるには、 dir()を使うことができます。 オブジェクト 複素数の場合 >>> a=1+1j >>> dir(a) ['__abs__', '__add__', '__class__', '__coerce__', '__delattr__', '__div__', '__d : __rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__str__', '__sub__', '__t ruediv__', 'conjugate', 'imag', 'real'] >>> ファイルの場合 >>> f=open('C:\Chiba-u\html\Python\InformationTheory\hp5.txt','r') >>> dir(f) ['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__getattribute : , 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 're adline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writeli nes', 'xreadlines'] >>> f.close() >>> 千葉大学 5- 26 オブジェクト 千葉大学 5- 27 文字列の場合 >>> s='This is a string' >>> dir(s) ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__ : __rmul__', '__setattr__', '__str__', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdi git', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lst rip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit' , 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', ' translate', 'upper', 'zfill'] >>> ライブラリの場合 (math ライブラリ) >>> import math >>> dir(math) ['__doc__', '__name__', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log' , 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'] >>> 千葉大学 5- 28 「関数」を作ろう • 関数を定義する – def function1(a, b, c, d): – 関数もブロック。関数の内部は、インデントを増加する • ファイル名は、*.py • 最初に、#!’pythonへのパス’を書く – Windowsなら、#!C:\Python26\python • Windowsの場合、省略してもOKのようです – Unixなら、#!/usr/local/bin/python – Linuxなら#!/usr/bin/python • 関数の計算結果(出力)は“return”で呼び元に戻す – 複数の値を同時に戻せる • 編集と実行ができる簡単な環境もある • 「スタート」->「全てのプログラム」 -> 「Python2.7」 -> IDLE (Python GUI) 千葉大学 5- 29 分岐やループ • 分岐の書き方、ループの書き方 – if elif – for in – while else • インデントでプログラムブロックの境界を規定する。 これはPythonの最大の特徴 – プログラムブロックを示すのに()も{}もBEGIN…ENDも ありません。 – ブロックの始まりの行には: (コロン)をつける • if a > 0: – ブロックの内部の行は、インデントを増加する – インデントを元に戻すことは、ブロックの終わりを意味する。 千葉大学 5- 30 関数定義、ループ # loop1.py def factorial(n): f = 1 for i in range(2, n + 1): # change indent for this loop (more spaces) f = f * i print i, f # end of this section # indent changed return f ft4 = factorial(4) print 'factorial 4 is ',ft4 >>> 2 2 3 6 4 24 factorial 4 is >>> 24 forループ ブロック 関数 factorial のブロッ ク インデントとは、テキストの左端をあけること。イ ンデントにはスペースを用いること。「ブロック」と は: がある行と、それに続く同じ数のインデントを 持つ複数のライン。インデントが元に戻る直前で、 そのブロックは終了する。ブロックの範囲を括弧 ではなく、インデントで行うので、プログラムの書 き方が統一されやすい。 for ‘変数’ in リスト: で、リストの要素がひとつずつ順に‘変数’に代入される。 range range(’初期値’,’最終値’,’ステップ’) は、初期値から、最終値-1までのステッ プごとの整数のリストを返す。 引数が1つなら、初期値は0、ステップ は1が用いられる 引数が2つなら、ステップは1が用いら れる。 >>> range(2,5) [2, 3, 4] >>> range(4, 12, 1) [4, 5, 6, 7, 8, 9, 10, 11] >>> range(4, 12, 2) [4, 6, 8, 10] >>> range(4, 12) [4, 5, 6, 7, 8, 9, 10, 11] >>> range(12) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] for xxx in yyy: で、リストyyyの要素が ひとつずつxxxに代入される。 more ‘for’ 千葉大学 5- 31 # loop2.py a = [1, 2, [3,4,5], 'abc', 1.0, 2+2j] for x in a: print x print x, ' is ', type(x) 1 1 is <type 'int'> 2 2 is <type 'int'> [3, 4, 5] [3, 4, 5] is <type 'list'> abc abc is <type 'str'> 1.0 1.0 is <type 'float'> (2+2j) (2+2j) is <type 'complex'> >>> 千葉大学 5- 32 if ~ elif ~ else if ~ elif ~ else はごく一般的な動作です # if1.py # def func1(n): if n < 0: print n, elif n < 5: print n, elif n < 10: print n, else: print n, ' is less than 0' ' is equal to or larger than 0 and less than 5' ' is equal to or larger than 5 and less than 10' ' is equal to or larger than 10' func1(-1) func1(100) func1(7) >>> -1 is less than 0 100 is equal to or larger than 10 7 is equal to or larger than 5 and less than 10 >>> 千葉大学 5- 33 while While は条件が成立している 間、ブロックを実行します # if1.py # def func1(n): n = 100 s = 0 while n > 0: s = s + n n = n -1 print s ループからの脱出、は ループの最初に戻る、は break continue # if1.py # def func1(n): n = 100 s = 0 while n > 0: s = s + n n = n -1 if n < 10: continue print s n が10未満のときは、sをプリントしない ライブラリの調べ方 • 標準添付のライブラリ – http://www.python.jp/doc/release/lib/ • 本家HPを調べる – http://www.python.org/ の右下の欄 • インターネットを検索する 千葉大学 5- 34 やってみよう(1) 千葉大学 5- 35 • 課題: – DFTとFFTのプログラムを作る – 数式やアルゴリズムからプログラムを作る練習 1 Fk N N 1 N 1 f e n n N ( DFTの計算式 ) n 0 fn Fk e n 0 jk 2 n jk 2 N ( IDFT の計算式 ) 離散フーリエ変換の変換核 千葉大学 5- 36 ( N個のサンプルからなる 信号fnの DFTの計算式 ) 1 Fk N W e n N 1 f e jk 2 n n N , 0 k N 1 n 0 j 2 ところで、 n N と定義すると、 WN e j 2 N N 1 Fk N fn W kn , 0 k N 1 n 0 e j 2 1 なので、 kn mN r (0 r N 1) と書けるとき、 W kn W mN r W mNW r W r となる。 そこで、まず、 N 1 W r を計算する。 r は kn を N で割ったときの余り。 やってみよう(2) • ライブラリの使い方の練習 千葉大学 5- 37 • 課題 – WaveSpectraのように、FFTを順次行いそれを表示 する • 方針 – Waveファイルからデータを読み込む(ライブラリ使用) – 数値演算ライブラリを使う – 結果はgnuplotで表示する 千葉大学 5- 38 N=8の場合(並び替えを最後にまとめて行う) f0 A0 G0 F0 000 000 0 f1 C0 H0 -1 F4 001 100 4 f2 B0 G2 F2 010 010 2 F6 011 110 6 F1 100 001 1 101 101 5 F3 110 011 3 F7 111 111 7 -1 W82 D0 f3 f4 -1 f5 f6 H2 -1 A1 G1 C1 -1 f7 -1 W81 -j -1 H1 -j B1 D1 W 2 8 j j W 1 8 G3 F5 W83 H3 ( W20 1, W40 1, W41 j , W80 1 ) W 3 8 計算結果をビット逆順で並べ替える 千葉大学 5- 39 FFT f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 W 0 2 W40 W 0 2 W 0 4 W 0 2 W 0 4 W 0 2 W 0 4 W 0 2 N=16の場合 0 8 W W80 W 0 8 W 0 8 2 8 W 0 4 W W 0 2 W 0 4 W82 W 0 2 W 0 4 W 0 2 W 0 4 W 0 2 W20 W 2 8 W 2 8 1 8 W 1 4 W W 1 4 W81 W 1 4 W81 1 4 W W 0 2 W f12 0 2 W W W f13 0 2 W20 W41 W83 W20 W41 W83 W20 W41 W f11 f14 f15 1 4 1 8 3 8 W 3 8 F0 0000 0000 0 F8 0001 1000 8 F4 0010 F12 0011 0100 4 1100 12 F2 0100 F10 0101 0010 F6 0110 F14 0111 0110 2 1010 10 6 1110 14 F1 1000 F9 1001 0001 1 1001 9 F5 1010 F13 1011 0101 5 1101 13 F3 1100 F11 1101 0011 F7 1110 F15 1111 0111 3 1011 11 7 1111 15 タスク 1 wavファイルを読み込む • wave ライブラリの使い方を調べる 千葉大学 5- 40 – 日本語のページなら、下記参照 • http://www.python.jp/doc/release/lib/modulewave.html – ファイル名とモード(読むのか、書くのか)を指定 してopenを呼び、Wave読み込みオブジェクトを 得る • wave_in = wave.open(‘c:\....’, ‘r’) – チャネル数、標本化周波数、サンプル当たりのバ イト数、などを読み込む • n_ch = wave_in. getnchannels(), etc. – データを読み込む • data = wave_in.getframes(N) タスク 1 wavファイルを読み込む 千葉大学 5- 41 • メソッド getframesで読み込んだデータは、「 文字列形」となっています • 高速な配列の計算のため、numpyライブラリ を使用します – 離散フーリエ変換は計算量が多いため(本来は 高速計算アルゴリズムFFTを使うべきところです) • Numpy ライブラリの fromstring 関数で、 wave ライブラリで読み込んだデータを numpy の配列に変換します タスク 1 wavファイルを読み込む 千葉大学 5- 42 • ステレオなので、ひとつのチャネルのみ取り 出します。 • 念のため、取り出したチャネルをモノラルの wavファイルとして保存し、確認します。 文字列=1バイトの並び 元のデータの並び 左 右 左 右 16ビットをひとつの数値としてnumpy配列に読み込む [左、右、左、右、左、右、左、右、…..] numpy配列の形を変え、左右のサンプルを分離する 2バイト=16ビットで一サンプル [左、右] [左、右] [左、右] [左、右] : 左のみ取 り出す タスク 2 FFT、絶対値、dB変換 千葉大学 5- 43 • FFTは数値演算ライブラリNumpyのFFTモジ ュールを使う。 – http://docs.scipy.org/doc/numpy/reference/ – http://docs.scipy.org/doc/numpy/reference/routi nes.fft.html • WaveSpectraの横軸は周波数 – 標本化周波数を f0 とし、FFTの次数をNとすると、 FFTの周波数間隔は、f0/Nとなる。 タスク 2 FFT、絶対値、dB変換 千葉大学 5- 44 • WaveSpectraの縦軸は、最大値(=32768)を 0dBとした表示と思われる。 – 電圧のデシベル値=20*log10 電圧値 – FFTの結果を32768で正規化し、さらに、log10を とり20倍する。 – 絶対値は、sqrt(F(k)F*(k))を計算すればよい。 タスク 3 gnuplotで表示 千葉大学 5- 45 • 周波数成分をテキストファイルへ書き出す。 – 数字から文字列への変換 • 整数のときは%d、実数のときは%fを使う。 • Gnuplotを使う – 解説はWebに豊富に見つかる。例えば、 – http://adlib.rsch.tuis.ac.jp/~akira/zemi/gnuplot/ wgnupl.htm 千葉大学 5- 46 Pythonでプログラムを作るコツ • どう動くか、インタープリーターで確認しながら進める。 – いちいちコンパイルする必要もないし、main()関数のようなものを用 意する必要もない。思いついたように実際に動くかどうかは、コマンド ラインから簡単に直接確認できます。 • ライブラリーが豊富。スクラッチから作るのも良いが、ライブ ラリーを調べて使うのも効率的。 – CGIプログラミング、DBとの連携、などはライブラリが豊富。 – 辞書型というデータタイプは便利 – クロスプラットフォームのGUIプログラムなら、wxPython • 講師はまだ使ったことがありません。一度試してみようと思ってます。 • サンプルプログラムを探して参考にする。 – Webを検索すれば、Pythonを使った様々なプログラムを見つけるこ とができます。これらから、オブジェクトやクラスの使い方を見よう見 まねで知ることができます。 千葉大学 5- 47 西暦、月、日を与えて、曜日を計算するプログラム 方針:本日(2009年5月19日)は火曜日。本日から指定された日までの日数を数え、そ の7の剰余(7で割ったあまり)を計算する。 def future_or_past(year, month, day):与えられた日にちが本日より過去か未来か? # past or future from 2009/5/27? return -1 for past, 0 for future if year < 2008: # check year return -1 # past year elif year > 2008: return 0 # future year if month < 5: # check month return -1 # past month elif month > 5: return 0 # future month if day < 27: # check day return -1 # past day return 0 # future or the day 与えられた年はうるう年かどうか? # leap year: (year % 4 == 0 and year % 100 != 100) or year % 400 == 0 def is_leap_year(year): if (year % 4 == 0 and year % 100 != 100) or year % 400 == 0: return True return False 千葉大学 5- 48 西暦、月、日を与えて、曜日を計算するプログラム ある月の日数 def ndays_in_month(year, month): # Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ndays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if is_leap_year(year): # this is leap year ndays[1] = 29 return ndays [ month - 1 ] def ndays_in_year(year): if is_leap_year(year): # leap year return 366 return 365 ある年の日数 千葉大学 5- 49 日数の計算 def count_days(ys, ms, ds, ye, me, de): y = ys m = ms d = ds ndays = 0 if y == ye: if m == me: return de - ds ndays = ndays_in_month(y, m) - ds m = m + 1 while m < me: ndays = ndays + ndays_in_month(y, m) m = m + 1 return ndays + de ndays = ndays_in_month(y, m) - ds m = m + 1 while m <= 12: ndays = ndays + ndays_in_month(y, m) m = m + 1 y = y + 1 while y < ye: ndays = ndays + ndays_in_year(y) y = y + 1 m = 1 while m < me: ndays = ndays + ndays_in_month(y, m) m = m + 1 return ndays + de ys年ms月ds日からye年me 月de日までの日数を計算す る。前提としてys/ms/dsの方 がye/me/deより以前である。 年が同じ(月が同じ)場合の 計算 ys の日数。つまり ys/ms/dsからys/12/31ま で。 ys+1からye-1 の日数。 ye の日数。つまりye/1/1 からye/me/deまで。 千葉大学 5- 50 曜日の計算と計算結果 def day_in_a_week(year, month, day): days = ['Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'Monday'] fp = future_or_past(year, month, day) if fp == 0: # day in future ndays = count_days(2008, 5, 27, year, month, day) else: # day in past ndays = -count_days(year, month, day, 2008, 5, 27) print "%4d %2d %2d %10d %s" % ( year, month, day, ndays, days[ ndays % 7 ] ) 計算結果 2007 2007 2007 2007 2007 2007 2007 2008 2008 2008 2008 2006 5 5 5 5 12 12 12 1 1 1 1 12 1 28 29 30 29 30 31 1 2 3 4 31 -28 -1 0 1 214 215 216 217 218 219 220 -149 Tuesday Monday Tuesday Wednesday Saturday Sunday Monday Tuesday Wednesday Thursday Friday Sunday 千葉大学 5- 51 通信システムの学習・研究に便利なライブラリ • • • 数学関連 – 行列計算、FFTなど(numpy) – – – 大量の数字の列(配列や行列)を効率よく扱える 基本的な行列演算やFFTなどが備わっている ダウンロード、インストールが必要 • • • • http://sourceforge.net/project/showfiles.php?group_id=1369&release_id=223264 Download numpy-1.3.1.win32-py2.5.exe 日本語の解説はまだ少ない模様 次回以降の講義では、このモジュールを使います。 WindowsのWAVEファイルを取り扱う(wave) – – – • math, cmath, randomなど waveファイルの読み書き 機能は多くない • WAVEフォーマットのファイルの読み書きのみです。 標準で組み込み済み • 今回の講義で使います。 Windowsの静止画像ファイルを扱う(PIL) – – – 画像の読み込み 画像処理 ダウンロード、インストールが必要 • • • • http://www.pythonware.com/products/pil/index.htm#pil116 Python Imaging Library 1.1.6 for Python 2.5 次回以降の講義では、このモジュールを使います。 日本語マニュアルは見つかりませんでした。 • 画像処理(OpenCV) – 一般的な画像処理 千葉大学 5- 52 いろいろな波形の音声データを作ってみる • waveファイルのパラメータ – チャンネルの数 • ステレオなら2、モノラルなら1 – サンプリング周波数 • PCのサウンドデバイスが対応しているのは、通常、8 KHz、11.025KHz、22.05KHz、44.1KHz – 1サンプルあたりのバイト数 • 1バイト( 256段階)あるいは2バイト(65536段階) – 圧縮方式 • waveライブラリでは、無圧縮しか使えない – サンプルデータは、文字列に格納される。 千葉大学 5- 53 いろいろな波形の音声データを作ってみる WAVEファイルを生成するためのサブルーチンとサイン波の生成 import wave, math, array SAMPF = 44100 LENGTH = 3 def wave_init(fname, sampf, length): f = wave.open(fname, 'w') # f.setnchannels(1) # f.setsampwidth(2) # f.setframerate(sampf) # f.setcomptype('NONE', 'not compressed')# return f def prepare_array(n): data = array.array('h') data.extend([0]*n); return data open wave file for write monoral 2bytes / sample set sampling frequency no compression # make array object # make n samples data area def wave_write(f, data): f.writeframesraw(data.tostring()) # convert array to string f.close() # then write to the file def sin_wave(fname, freq): f = wave_init(fname, SAMPF, LENGTH) data = prepare_array(SAMPF * LENGTH) a = math.pi * 2.0 * float(freq) / float(SAMPF) for i in range(SAMPF * LENGTH): ft = int(math.sin(a * float(i)) * 30000.0) data[i] = ft wave_write(f, data) 千葉大学 5- 54 いろいろな波形の音声データを作ってみる def two_sin(fname, freq1, freq2, phase): f = wave_init(fname, SAMPF, LENGTH) data = prepare_array(SAMPF * LENGTH) a1 = math.pi * 2.0 * float(freq1) / float(SAMPF) a2 = math.pi * 2.0 * float(freq2) / float(SAMPF) サイン波2つの和 for i in range(SAMPF * LENGTH): ft1 = int(math.sin(a1 * float(i)) * 15000.0) ft2 = int(math.sin(a2 * float(i) + phase) * 15000.0) data[i] = ft1 + ft2 wave_write(f, data) def saw(fname, freq, flag): f = wave_init(fname, SAMPF, LENGTH) data = prepare_array(SAMPF * LENGTH) ns2 = SAMPF / freq / 2 ns = ns2 * 2 - 1 a = float( 30000 / ns2 ) for i in range(SAMPF * LENGTH): ft = int (float(flag * ((i % ns) - ns2)) * a) data[i] = ft wave_write(f, data) sin_wave('../wave/sin_440.wav', 440) two_sin('../wave/sin_440_560.wav', 440, 560, 0.0) two_sin('../wave/sin_440_460.wav', 440, 460, 0.0) two_sin('../wave/sin_440_560.wav', 440, 560, 0.0) two_sin('../wave/sin_440_880_0.wav', 440, 880, 0.0) two_sin('../wave/sin_440_880_1.wav', 440, 880, math.pi/2.0) saw('../wave/saw1.wav', 440, 1) saw('../wave/saw2.wav', 440, -1) のこぎり波 千葉大学 5- 55 Apacheと組み合わせCGIスクリプトとして使う Httpd.confの編集 (ハンドラーの追加) AddHandler cgi-script .py 基本的な処理の流れ http://a.b.c/a.py?min=0&max=100 print """Content-Type: text/html; a.py ---------------------------------#!/usr/bin/python <html> <head> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf8"> <title>Table</TITLE> </head> <body> “”” print ‘min = %d max = %d’ % (min.max)’ Print “”” Hello world! </body> </html> """ import cgi # Query form = cgi.FieldStorage() if form.has_key('min'): price_min = form['min'].value if form.has_key('max'): price_max = form['max'].value 千葉大学 5- 56 CGI作成で用いる便利なライブラリ:email # Import smtplib for the actual sending function import smtplib # Import the email modules we'll need from email.mime.text import MIMEText # Open a plain text file for reading. For this example, assume that # the text file contains only ASCII characters. fp = open(textfile, 'rb') # Create a text/plain message msg = MIMEText(fp.read()) fp.close() # me == the sender's email address # you == the recipient's email address msg['Subject'] = 'The contents of %s' % textfile msg['From'] = me msg['To'] = you # Send the message via our own SMTP server, but don't include the # envelope header. s = smtplib.SMTP() s.connect() s.sendmail(me, [you], msg.as_string()) s.close() 千葉大学 5- 57 CGI作成で用いる便利なライブラリ:urllib CGI中から他のURLをアクセスし、中身を利用することはよくある。 Here is an example session that uses the "GET" method to retrieve a URL containing parameters: 辞書型のデータをURLエンコード して、URLのパラメータにできる >>> import urllib >>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0}) >>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params) >>> print f.read() >>> f.close() 辞書型のデータをその The following example uses the "POST" method instead: ままurlopenに渡せば、 HTTPのコンテント領域 にデータをマルチパー トで入れてくれる。 >>> import urllib >>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0}) >>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query", params) >>> print f.read() >>> f.close() より高度に制御できるurllib2もあります 千葉大学 5- 58 PostgreSQLと組み合わせる 準備 PostgreSQLのインストール PostgreSQLをpythonから使うためのライブラリをインストール ここでは、PyGreSQLを使います。 千葉大学 5- 59 MVCフレームワーク「Django」を使う • PostgreSQLとApacheを使って、簡単にWeb アプリケーションを作成する。 • MVCとは「Model、View、Control」 – DBへのアクセスが簡単に行える。 • Models.pyというプログラム中に、データベース定義の ための情報を記述するだけ – DBから取得したデータやプログラム的に生成し たデータを簡単にHTML内に配置できる • 「テンプレート」という概念で、動的なWebページを簡 単に構築できる。 千葉大学 5- 60 リンク ご本尊 http://www.python.org/ 日本Pythonユーザー会 http://www.python.jp/Zope/ Django http://ymasuda.jp/python/django/index.html
© Copyright 2024 ExpyDoc