情報通信システム(1) 2005年4月19日 火曜日 午後4時10分~5時40分

情報通信システム(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