Subscribed unsubscribe Subscribe Subscribe

はてな記法からマークダウンへ

マークダウンに慣れたいと思ったので、はてブをマークダウン形式で書くことにしました。

とはいえそこまでマークダウンが書けるようになっているわけ

  • でも
  • ない
    • ので

調べながら

練習

していきたいと思います。

といいつつさらっと  {\LaTeX} なんかはかじったりもしてるので、数式書くのは

楽になる

かもです。

よみにくくて申し訳ないです。遊んでみました。 それではまたいずれ

ブログタイトル変えました

まんまですが、ブログタイトル変えました。

あんまりswiftやってないしな―とか、てかpythonしかやってなくない?とか思ってはいたので、一応変えてみました。

python以外のことを書く予定も特にはないのですが、他のことも色々書けるようなタイトルにしてみました。

ではまたいつか更新します。

scipyでピーク検出

タイトルの通りですが、新しい関数とその使い方について書きます。

やることはscipyでのピーク検出です。単純にピークと呼んでいますが、離散的なデータから極大極小を見つける関数のようです。
関数は以下のようにインポートします。

from scipy.signal import argrelmax
x = np.array([2, 1, 2, 3, 2, 0, 1, 0])
print(argrelmax(x))
>>> (array([3, 6]), )

基本的に必要な引数はデータだけなので、適当なnp.arrayを与えてやると、ピーク位置のインデックスを返してきます。
という使い方は以下にかいてありました。
参考:
org-technology.com

ここからは使ってみての考察なのですが、scipyのドキュメントを読むと、任意のパラメーターが幾つかあります。
scipy.signal.argrelmax — SciPy v0.17.0 Reference Guide
このうちorderのところを指定してやると、どの幅でピークを見つけるかということを指定できるのだと思います。
f:id:jinpei0908:20161126223220p:plain
このようなグラフ(先日取ったラマン分光のデータです)があったとき、デフォルト設定だとピークは
f:id:jinpei0908:20161126223139p:plain
以上のように検出されます。大量ですね。
しかし、求めているピーク自体は1460{\sf{cm^{-1}}}あたりのシャープなピークです。
これはorderがデフォルト設定(order = 1)だと、x軸の狭い幅の増減を検出してしまうためいろんなピークを検出しているのだと思います。
つまり

np.array([0, 1, 2, 1, 5, 1, 3, 2, 1])

という配列の場合order = 1 だとindex = 2, 4, 6が検出されますが、order = 3とするとindex = 4のみが検出されます。
先のグラフの例でいうと、order = 100とすると以下のようなグラフになりました。
f:id:jinpei0908:20161126224108p:plain
これで一応やりたいことがpythonでできるようになりました。

matplotlibで図を作成する際の細かいところ

matplotlibでグラフを実際に書くことが多くなってきたのですが、実際使うとなるとデフォルト設定ではなくもう少しいじりたいなと思うことが多々あります。一回グラフを作成してから、プレビューで画像編集をしてもいいのですが、出来る限りプロセスは簡単である方が作る方としては楽です。今回までで調べた細かい設定と、自分なりに関数を作ったものを載せます。

まず、図の保存時の余白について

これは

plt.savefig(filename = 'sample.png', dpi = 300, transparent = True, bbox_inches = 'tight', pad_inches = 0)

として保存してやると、グラフの余白が全くない状態で図が保存されます。

参考:
www40.atwiki.jp

次にyticklabelsの表示なのですが、y軸の値の桁数が多くなると{ x \times 10^{y}}と書きたくなります。
しかし、デフォルト設定だと(少なくとも自分の場合は)250000000とかふつうに表示されます。これでは有効数字もあったもんではないので、どうしたものかと調べていると、
villageofsound.hatenadiary.jp
こんな記事がありました。
しかし、各目盛りに{\times 10^{y}}がついていないのもなーと考えていたのですが、デフォルトでやり方がわからないなら関数化してしまえばいいじゃんと思い立ったので、実際にかいてみました。
以下その関数の定義です。

def exponent_mantissa(x):
	if(x >= 1000):
		log10_x = np.log10(x)
		exponent = int(log10_x)
		mantissa = 10**(log10_x % exponent)
		return r'$%.2f \times 10^{%d}$' % (mantissa, exponent)
	elif(x <= -1000):
		x = np.abs(x)
		log10_x = np.log10(x)
		exponent = int(log10_x)
		mantissa = 10**(log10_x % exponent)
		return r'$-%.2f \times 10^{%d}$' % (mantissa, exponent)
	else:
		return r'${}$'.format(x)

何をやっているかというと、引数xの値を判定して、4桁以上なら{ x \times 10^{y}}表記の文字列を返すという関数です。
{ x \times 10^{y}}の表記のx , yはそれぞれ仮数(mantissa)、指数(exponent)と呼ばれるそうです。
引数の常用対数をとると、その整数部分が指数となります。また、10の小数点以下の部分乗が仮数となります。
それぞれを文字列の値として埋め込んでやることで{ x \times 10^{y}}表記を可能にしています。
この関数をlist(map(exponent_mantissa, ytick))としてset_yticklabelsの引数として渡してやることで、y軸の目盛りのラベルと{ x \times 10^{y}}表記にできます。
参考画像を作るのが面倒なので載せていないサボり記事ですが、ご容赦ください。

matplotlibのカラーマップ

オリジナルのカラーマップを作成して、matplotlibのプロットに使いたいときの方法です。

参考
qiita.com

やりたいことはすべてこちらの方に書いてあるのですが、あくまで備忘録用に書かせていただきます。
参考のColormapのカスタマイズのところで定義されているgenerate_cmap関数さえ書いてしまえば、あとはプロットするだけです。

と、解説すべてを丸投げにしてもいいのですが、さすがにこれでは剽窃となるので、オリジナリティを追加するためにもこちらのgenerate_cmap関数の内部でやってることに対しての自分なりの解釈を書かせていただきたいと思います。

まず、引数にはカラーマップに使う色をリスト形式で与えています。

次に、使う色のリストの長さを求めて、それのリストを作ります。
参考先では3つの色のリストを与えているので、values = [0, 1, 2]として処理されているはずです。

そしてnormalizationをした値と色のリストをタプルとし、それを新たな色のリストとして与えています。


ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
ここでいうnormalizationは最大値と最小値で規格化することを指します。
標準正規分布に変換することはstandardizationというようです。
日本語だとどちらも標準化と言われたりするようですが、英語では割りと区別して呼ばれているのかもしれません。
こういった点は英語のほうが便利だと思いますね。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
閑話休題
さてどういうことかを具体的に説明していきたいと思います。
参考先のサンプルを見ながら読んでみてください。

まず、vmaxはvaluesの最大値です。最小値は0です。
ですので、for文内のv/vmaxは規格化された値を出しているのだと思われます。
つまり、
color_list = [(0, mediumblue), (0.5, limegreen), (1.0, orangered)]
となっているはずです。
あとはこのcolor_listを基にmatplotlib.colorsのLinearSegmentedColormapが自動的に0, 0.5, 1.0以外の数値の色を補完してくれるので自動でカラーマップが作成されています。

2016/11/29 追記

もっと単純な書き方を思いついたので記しておきます。

from matplotlib.colors import LinearSegmentedColormap

def create_cmap(color_list = None):
    n = len(color_list)-1
    return LinearSegmentedColormap.from_list(name = 'custom', colors = [(i/n, j) for i, j in enumerate(color_list)])

np.dot

numpyの行列積を表すときにだいたいdotメソッドを使うと思いますが、先日読んだ記事ではpython3.5以降では@マークで行列積を表すことができるそうです。

>>> import numpy as np
>>> a = np.arange(0, 6).reshape(3, 2)
>>> a
array([[0, 1],
       [2, 3],
       [4, 5]])
>>> b = np.arange(6, 10).reshape(2, 2)
>>> b
array([[6, 7],
       [8, 9]])
>>> a.dot(b)
array([[ 8,  9],
       [36, 41],
       [64, 73]])
>>> np.dot(a, b)
array([[ 8,  9],
       [36, 41],
       [64, 73]])
>>> a@b
array([[ 8,  9],
       [36, 41],
       [64, 73]])

上記の通り、すべて同じ結果になってますね。
dotメソッド自体は個人的には明示的に書かれていて、何をしているかわかりやすいと思うので、そんなに@を使うときがあるとは思えないですが、条件式の中に書く場合など、あまりごちゃごちゃさせたくないときは使いやすそうですね。

以下参考
neovisionconsulting.blogspot.jp

この記事は翻訳されたものですが、原文を書いている人はSebastian Raschkaという方でPython機械学習プログラミングという本を書かれている方です。アマゾンで検索していただけると割りと上の方に出てくる書籍だと思います。機械学習を学ぼうと思って、その本を読んでみましたが、完全に内容を理解できたわけではないですが、比較的わかりやすい本であったと思われます。ぜひ一度読んでみてください。

Remove all ads

limitlessledその2

limitlessledの使い方です。

まず、limitlessledのpythonAPIであるledcontrollerをpipでインストールします。

limitlessledのブリッジのIPアドレスを調べます。あとはledcontrollerをimportして普通にpythonコードを書くだけです。

サンプルは以下です。

#IPアドレスは各環境で調べて、その値を文字列として渡します。
IPaddress = "192.168.xx.xx"

import ledcontroller as con

LED = con.LedController(IPaddress)

#LEDのon/off
LED.on()
LED.off()

'''
LEDの色調整
上から赤、オレンジ、緑をつけます。
三行目みたく第2引数に数字を与えてやると、2番グループに登録されている電球色のみ変えることができます。
'''
LED.set_color('red')
LED.set_color('orange')
LED.set_color('green', 2)

#LEDを白色に変える
#引数に数字を与えてやると、指定したグループに登録されている電球を白色にします。

LED.white()
LED.white(2)

そんなに難しい使い方ではないと思います。自分もまだ詳しくわかっているわけではないので、まだ複雑な使い方ができるかもしれません。

また、書き忘れていましたが、自分の環境はlimitlessled RGBWのwarm whiteバージョンです。

on/offをタイマーで設定してやりたかったので、今はpythonのtimeモジュールをインポートして自動消灯を可能にしています。CLIで操作するのも面倒なので、pyqtの練習がてらguiアプリも作って見たので、気が向いたら更新します。

参考にさせていただいたのは以下です。
takashiski.hatenablog.com