いつもながら適当なことをつらつらと
新年明けたのに何も書かないのもなあと思ったので書いてみます。
プログラミングの継承について
去年の暮れにあるプログラムを3つほどPythonで書いてたんですが、3つとも初っ端の書き出しの部分が同じ処理をしているんですよね。まあ、コピペすればいいだけの話なんですが、見栄えがよろしくないというのと保守性が悪い(だれかにソースコードを見てもらう必要がないので、これに関しては気にしてはないのですが)ということからどうにかならんかなと思ってました。そこで継承したらいいんじゃね?と思いつきまして、実際書いてみたら、まープログラムの見通しがよくなりましたね。今まで、継承って何のためにあんのかな―とか、GUIプログラミングしないなら使わんかとか思ってましたが、使ってみるといいもんですね。必要性を感じていなければ理解できない、と昔から自分は思っているんですが、まさにその通りだなと思いました。これからも継承使っていきたいですね。そこまで同じ処理をさせるプログラムを組むことがあるかどうかは疑問ですが。
C/C++のコンパイルについて
今までCの文法とかはそこそこ学んできていたんですが、コンパイルとかは最低限のことしかしてきませんでした。まあ、コンパイルできればいいかみたいなことですね。ただ、Cのソースコードを実行するにもいくつか方法があるようです。
以下に書くのはあくまで自分の理解です。はっきり言ってあまり調べこんだ内容ではないので正確ではないと思います。
ただのコンパイル
一番主流というか、簡単というか、これがそのままコンパイルって感じですかね。ソースコードをオブジェクトファイルにします、的な。ファイルが分割されているとそれぞれコンパイルされた後、ファイル同士を結合するリンクという作業が行われるようです。ビルド
IDEを使ってコンパイルすること。IDEの中ではプロジェクトという単位でプログラムを管理しているようで、プロジェクトの中に幾つもの分割されたファイルがあるというイメージですね。ビルドはそのすべてのファイルのコンパイルとリンクを行うことをいうようです。ただのコンパイルとの違いは、ただのコンパイルは各ファイルを手動でコンパイルして、リンクして、としなければなりませんが、ビルドはIDEが全部やってくれるので、簡単です。RUNボタン押すだけで、全てやってくれるという感じでしょうか。メイク
調べてみるとどうも廃れつつある技術のようですが、概要としてはコンパイラにmakefileというレシピみたいなものを渡して、自動的にコンパイルとリンクをしてもらうという感じですかね。ただのコンパイルとの違いは、ただのコンパイルは分割ファイルをそれぞれコンパイルして、最後にリンクしなければならないのですが、メイクはmakefile内の指定したファイルをすべて勝手にコンパイル・リンクしてくれるというイメージです。まあ、ビルドと似たようなもんなのかな、と思います。ビルドと似たようなものだし、makefileを書く必要があるので、メイクの方が手間のかかる印象を受けます。IDEが登場して、しかもパソコンの性能もUPしているので、あまりメイク自体は使われなくなりつつあるのかと勝手に推理してます。
まあ、だいたい3種類くらいあるようですね。と言ってもビルドもメイクもコンパイルを内包しているんですが。ソースコードをコンパイルして、リンクする、という流れはすべて同じかと思われます。それをすべて手動でやるのか、ちょっと楽するのか、だいぶ楽するのかの違いなのかなあと素人考えでは思ってます。
あと試してみたのですが、gccのコンパイルはいくつかの.cファイルを一気にコンパイルすると勝手にリンクまでやってくれるようで、
gcc -o foo ./*.c
とやってやると、カレントディレクトリ内のすべての.cファイルをコンパイル・リンクしてfooという実行ファイルを作ってくれます。(たぶん)これができるならメイクいらなくね?とは思うのですが、素人にはわからない違いがあるんでしょうか。
あとわりと最近知ったのですが、上の例でいうとfooという実行ファイルをダブルクリックすると起動してくれるんですね。初めて知りました。ターミナルから起動しなくていいから便利です。
ってな感じで、新年早々長々と文章を書いてみました。久しぶりすぎて文章かけないですね。ってか久しぶりじゃなくても文章って書けなくなってますね。本読まないとだめですね。ってな感じで、またいずれ。
mac mini late 2012 メモリ増設
mac mini late 2012を2年前ぐらいにヤフオクで落札してそれ以降メディアサーバー的に使っているのですが、落札当初にSSD換装をしてからと言うもの全く内部を開けていじるようなことはしてきませんでした。まあ、端的にいうとメモリの増設をしていなかったというだけの話なんですが。
実際4GBしかなくともわりと快適に動いてきてくれましたし、意外とメモリって安くならんなとか思っていたら完璧に増設することを忘れてました。2日前くらいになんとなく思い立ってアマゾンを見てみると8GBの2枚セットのメモリが1万を切っていたので、メモリ増設するか―と思い立ちまして、今日換装しました。
で、写真付きで作業を解説しようかと思ったのですが、めんどくさいのでやめました。
実際増設した後の感想をば
まあ、元からSSD換装はしていたからなのか、そんなに体感できるほど速度が速くなったとは思えないです。ただ、iTunesの終了は気持ち速くなった気がしますね。とくにメモリを消費するような作業をするためにPCでもないので、こんなもんかなとは思います。実際アクティビティモニタでメモリの消費量を見たところ、2GBしか使ってないようだったので16GBもいらんかったなと思いました。増設後にエラーもなく起動できたのはわりとありがたかったですね。速度に関してはこれから使っていくうちに実感できるのかもしれないですね。
参考と購入したメモリ:
購入したのは以下の低電圧ではなく、標準を購入しました。
プログラミングのことを書くよりぜんぜん筆が進まないのは、なんでなんでしょうね。たまにはガジェット的なことも書きますよということで。
それでは
はてな記法からマークダウンへ
マークダウンに慣れたいと思ったので、はてブをマークダウン形式で書くことにしました。
とはいえそこまでマークダウンが書けるようになっているわけ
- でも
- ない
- ので
調べながら
練習
していきたいと思います。
といいつつさらっと なんかはかじったりもしてるので、数式書くのは
楽になる
かもです。
よみにくくて申し訳ないです。遊んでみました。 それではまたいずれ
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のところを指定してやると、どの幅でピークを見つけるかということを指定できるのだと思います。
このようなグラフ(先日取ったラマン分光のデータです)があったとき、デフォルト設定だとピークは
以上のように検出されます。大量ですね。
しかし、求めているピーク自体は1460あたりのシャープなピークです。
これは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とすると以下のようなグラフになりました。
これで一応やりたいことがpythonでできるようになりました。
matplotlibで図を作成する際の細かいところ
matplotlibでグラフを実際に書くことが多くなってきたのですが、実際使うとなるとデフォルト設定ではなくもう少しいじりたいなと思うことが多々あります。一回グラフを作成してから、プレビューで画像編集をしてもいいのですが、出来る限りプロセスは簡単である方が作る方としては楽です。今回までで調べた細かい設定と、自分なりに関数を作ったものを載せます。
まず、図の保存時の余白について
これは
plt.savefig(filename = 'sample.png', dpi = 300, transparent = True, bbox_inches = 'tight', pad_inches = 0)
として保存してやると、グラフの余白が全くない状態で図が保存されます。
参考:
www40.atwiki.jp
次にyticklabelsの表示なのですが、y軸の値の桁数が多くなるとと書きたくなります。
しかし、デフォルト設定だと(少なくとも自分の場合は)250000000とかふつうに表示されます。これでは有効数字もあったもんではないので、どうしたものかと調べていると、
villageofsound.hatenadiary.jp
こんな記事がありました。
しかし、各目盛りにがついていないのもなーと考えていたのですが、デフォルトでやり方がわからないなら関数化してしまえばいいじゃんと思い立ったので、実際にかいてみました。
以下その関数の定義です。
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 , yはそれぞれ仮数(mantissa)、指数(exponent)と呼ばれるそうです。
引数の常用対数をとると、その整数部分が指数となります。また、10の小数点以下の部分乗が仮数となります。
それぞれを文字列の値として埋め込んでやることで表記を可能にしています。
この関数をlist(map(exponent_mantissa, ytick))としてset_yticklabelsの引数として渡してやることで、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)])