Elasticsearch+Kibana始めるよ

会社で使うことになったので elasticsearch、始めてみようかと思います。

raspberrypiの試運転がてら8GBのSDにpidora入れてelasticsearch+Kibanaのコードを入れて動くところまでは行きました。ノートのブラウザからも一応KibanaのUIが覗けるところまでは行きましたが、そこからは処理が追いつかなかったのか進まず。

本当はあんまりやりたくなかったのですがとりあえずさっさと試してみたかったのでノートで決行。ノートに色々突っ込んで環境設定をいじくるの苦手。

homebrewで落としてくるだけでできる、すばらしい。

これからいじり倒しそうなので brew install時に言われたコマンドを叩いてスタートアッププログラムにElasticsearchとKibanaを追加。

10 min walk throughを見ながらデータを突っ込んでみる。

curlってこう使うんだとか、これが会社で後輩が言ってたREST APIというものかとか、今更ながら今まで興味なかった基本的なところを「へぇ、これが」といちいち思いながら進めてく。

10 min walk through のシェイクスピアのデータでは正直データ解析をするというイメージがつかめなかったので、kibana test dataで検索して出てきた harukasan/kibana-testdata を使わせてもらう。

慣れないルビーの用語を調べつつ、この方法でなんでインポート出来るんだろうかと戸惑いながらもなんとかデータをインポート。

gem使うの久しぶりだとかbundlerなんてモノがあるんだとか、設定保存系とかバージョン切り替え系とか今まで苦手苦手でやってきたので読むの辛かった。

image

おお、できた。やっぱり時系列データって見やすいですね。

とりあえずハンズオンここまで。次は Basic Concepts 読みながら思想的なところを掴んで行こう

想像していたよりかなりお手軽だったので、お手軽ついでにWebフレームワークとして名高い Ruby on Rails も触ってみたい、と思いつつ自分って今まで本当cssにしか興味持ってこなかったんだなと若干ヘコむ。

Advertisements

TeXとBiBTeXとbashのgetoptの練習がてらに

texからpdfまでを一括で行うスクリプト。作ったけどtexbinの中に入ってそうだ。-bオプションを取得してBiBTeXの処理オプション、-cオプションを取得して中間ファイルの削除オプションもつけてみた。

function tex2pdf() {
    
    # set options
    BIBTEX=false
    CLEANING=true
    
    while getopts bc OPT; do
        case $OPT in
            b) BIBTEX=true;;
    	c) CLEANING=true;;
        esac
    done
    shift $((OPTIND - 1))
    
    # tex process
    platex $1
    if $BIBTEX; then
    	pbibtex $1
    	platex $1
    fi
    dvipdfmx $1
    
    # cleaning
    if $CLEANING; then
    	rm $1.{log,aux,dvi}
    	if $BIBTEX; then
    		rm $1.{bbl,blg,lof,lot,toc}
    	fi
    fi

}

使い方

第一引数にターゲットのtexファイルを拡張子抜きで指定。

$ tex2pdf texfile

bibtexする場合

$ tex2pdf texfile -b

中間ファイルを削除する場合

$ tex2pdf texfile -c

はじめはplatexとdvipdf打つのが面倒だなと思って作り始めたこんなのだった。

function tex2pdf() {
    platex $1
    dvipdfmx $1
}

こんなのになるまで

gnuplotでCSVのフィールド名とか

gnuplotでCSVファイルからデータを読み込んでプロットするときにフィールドをインデックス番号でなくフィールド名で指定する方法。

単純な方法だと

plot "filepath" using "time":"y"

数値を操作したい場合は

plot "filepath" using "time":(column("y") + 1)

文字列として操作したい場合は

plot "filepath" using "time":"y":("value: ".stringcolumn("label")) with labels

とかでできます。

データ処理のスクリプトを書いていると、開発の途中で新しいフィールドが追加されたり順番を変えたくなったりすることもありますが、はじめからフィールド名で指定しておけば、少なくともそういったときにフィールドの順序にとらわれることはなくなります。

何のデータを処理しているのか、コード的にもわかりやすくなりますね。

精神衛生的に、フィールド名が使える場合は使いたい。

  • Mac OSX 10.9 Mavericks
  • gnuplot 4.6

ProcessingでTerminalオンリーのWindow Systemもどきを作ってみた

ふとWindowSystemっぽいものを作ってみたくなってProcessingでゴリゴリと作ってみた。ソースコードはもう自分でも読みたくない。

image

機能としては、

  • 複数のウィンドウを描画
  • クリック、ドラッグでアクティベート
  • ドラッグで移動
  • 文字の入力、表示
  • 消去ボタン
  • ターゲットのポインティング、追跡

と、ウィンドウなら出来て当たり前のことばかりだけど、ゴリゴリ製作した身としては「機能なんだー!」と言ってしまいたい。

最後の「ターゲットのポインティング・追跡」機能はせっかくProcessingなんだから、ということで追加してみた。Processingで何か作った時にオブジェクトを追跡しながらステータス表示とか、そんな感じの賑やかし程度には使える気がする。

誰かもう作ってるだろう、と言うよりもっと便利なライブラリがあるような気がしてきたけど、それを目の当たりにすると心が折れそうなので今はまだ調べずにおく。

使い方はこんな感じで

WindowSystemと言いつつ、クラスの命名はTerminalだったりするのがまず分かりづらい。

グローバルにターミナルを管理するクラスTerminalManagerを作って、あとは適当な場所でTerminalを作ってTerminalManagerにガシガシ突っ込んでいく。

keyPressedイベントをTerminalManagerに渡してやれば、打ったキーはアクティブなTerminalに表示されるし、Terminalから直接print()メソッドを呼んで文字列を入力してもいいので、適当なオブジェクト内でTerminalを作れば上にも書いた通り簡易インスペクタとしても使える。

// ターミナルを管理するクラス
TerminalManager terminalManager;

// ターゲットとなる PVector
PVector target;

void setup() {
  
  size(480, 320);
  
  terminalManager  = new TerminalManager();

  target = new PVector(width/2, height/2);  
  
  // Terminal1
  Terminal terminal = new Terminal("Terminal1");
  terminal.setWindow(10, 10, 200, 200); // 場所とサイズ
  terminalManager.add(terminal); // マネージャに追加
  
  // Terminal2
  Terminal terminal2 = new Terminal("Terminal2");
  terminal2.setWindow(100, 100, 300, 300);
  terminal2.setLineNum(5); // heightを行数で上書き
  terminalManager.add(terminal2);
  
  // Terminal3: ターゲットを追跡する
  Terminal terminal3 = new Terminal("Terminal3");
  terminal3.setWindow(200, 50, 300, 200);
  terminal3.setTarget(target); // ターゲットをセット
  terminal3.setPositionRelatively(true); // ターゲットを追跡
  terminalManager.add(terminal3);
  
  // Terminal4: ターゲットをポイント
  Terminal terminal4 = new Terminal("Terminal4");
  terminal4.setWindow(200, 200, 200, 60);
  terminal4.setLineNum(10);
  terminal4.setTarget(target);
  terminalManager.add(terminal4);
}

void draw() {
  background(128);
  
  // ターゲットの移動
  target.x = width/2 + 100 * cos(0.01 * frameCount);
  target.y = height/2 + 100 * sin(0.01 * frameCount);

  // ターゲットの描画
  ellipse(target, 10);
  text("target", target.x + 5, target.y);
  
  // ウィンドウの更新・描画
  terminalManager.update();
  terminalManager.draw();
}

// 各種イベントを渡してやる
void keyPressed() { terminalManager.keyPressed(); }
void keyReleased() {}
void mouseMoved() { terminalManager.mouseMoved(); }
void mousePressed() { terminalManager.mousePressed(); }
void mouseReleased() { terminalManager.mouseReleased(); }
void mouseDragged() { terminalManager.mouseDragged(); }

そもそもGUIプログラミングしたこと無いのに一から作り始めるのはどうなんだろう。作っている最中は「だいたい思ったとおりの実装でいけるな」とか意気揚々としていたけど、使いやすさはどうせ既存の一般的なライブラリの方がいいんだろうな。

ソースコード:https://github.com/LightbulbCat/PTerm

  • Mac OS X 10.9 Marverics
  • Processing 2.0.3

Pythonはじめてひと月、標準ライブラリの充実ってやっぱりいいなとか

Python歴は今の時点でだいたい1ヶ月くらい。

本当は1年くらい前に、PythonでCSV読み込んでタイムスタンプのフォーマットを変えて、みたいな簡単なスクリプトを組んでたんだけど、それはもうそれっきりで、文法とかももうすっかり忘れて、1ヶ月前くらいから、また一からリファレンス読みながらのスクリプティングをしてきた。

これまでにやってきた言語といえばC、Java,C++。スクリプト言語だとweb系でPHP、Perlくらいなので、Pythonはコマンドラインから動かすことを考えたら始めてのスクリプト言語。

あんまり大きな声じゃ言えないけど、try-catchとかのエラー処理とか、よくわからないレベルの超ライトユーザなので、突っ込んだ話はできないけど、ここまでPythonに触れてきて「いいな、Python」と思ったことをちらほらと書いていく。だいたいがC++に比べて、って感じだけど…

見返してみると、「いいなPython」って言うより「いいなスクリプト言語」って感じ

コード量が少ない

同じ働きをするコードを書くと、C++と比べてPythonは30%くらいの行数になるんじゃないか、ってくらいのイメージ。

コード量が少ないと読むのにかかる時間がだいぶ違ってくる。プログラムを読む時って「この変数がここで使われてて…」とコード内を何度も往復して読んでるから、読むのにかかる時間はきっとコード量の2乗くらいで効いてくる。コード量が2倍なら理解に掛かる時間は4倍。根拠はないけど。

これなら標準ライブラリの実装とかも眺められるんじゃないかと思ってスレッド周りのライブラリをチラ見してみたけど案の定のカオスっぷり&英語コメント読めないで諦めた。

僕のスキルなんてまあ、こんなもの。

標準ライブラリの充実さ

CSV読むのも標準ライブラリで一発だし、スレッドも簡単に使えるし。Cとかだとboostである程度標準化されてる気がするけど、でもこういうプログラムで一般的に使われる要素がPythonだと「標準」として組み込まれていて、この辺が強いんじゃないかなと。

C++11だとboostがsdtに組み込まれてsdt::threadとかで使えるんだっけ

「標準」の安心感って初心者にはとても心強い。リファレンスも多そうだし、なによりPythonの仕様とか実装を決めてるコミュニティの人たちが煮詰めて煮詰めて作ったんでしょ、みたいな根拠は薄いけどとりあえずいい感じのパフォーマンスを発揮してくれるんだろう、みたいな安心感がある。

もっと書こうと思ったんだけど

もっと書こうと思ったけど書きづらい。Python、すごく使いやすいけど他の言語と比べて具体的にどうこう、とかは自分のレベルじゃあんまり具体的に思いつかない。

どういう要素が働いているか解らないけれど、なぜか作りたいものが作りたいときに「ぱっと」作れるようになってるんだな、ってことぐらいしか、今はまだ書けない。

よくわからないけど、Python、よくできてる気がする。

PythonでOpenCVのwaitKey()はメインスレッドじゃないと動かない?

マルチスレッドとOpenCVの勉強を同時進行でやろうと、PythonでOpenCVをマルチスレッドで動かそうとした時にちょっとハマったのでメモ。

初めのコード

やりたかったのは、描画するウィンドウ関係の処理は全部それ用のスレッドに投げてしまって、メインスレッドはスレッドを起動するだけ、みたいなこと。どうせスレッドたくさん立てる事態になったらこういうことしたくなるんだろうな、と。

import threading
import cv2

# 描画スレッド
class ImageProcessing(threading.Thread):

	def __init__(self):

		threading.Thread.__init__(self)

		self.windowname = "ImageProcessing"
		cv2.namedWindow(self.windowname)
		self.capture = cv2.VideoCapture(-1)

	def run(self):

		while True:
			ret, frame = self.capture.read()
			cv2.imshow(self.windowname, frame)

			if cv2.waitKey(10) == 27: # ESC
				break

# メインスレッド
if __name__ == "__main__":

	ip = ImageProcessing()
	ip.start()

	ip.join()

で、動きませんでした。初めの画像が映るだけで画像が更新されない静止画状態。ついでにwaitKey() も反応しない。ウィンドウが完全にフリーズしたような状態。

そして当のスレッドは走りっぱなしなのでターミナルを強制終了したり立ち上げたりが本当に面倒だった。

何が悪いのか

取得した frame を適当にターミナルに出力してみると値自体は更新されているようなので、問題はウィンドウの更新らへんにありそう。でもその辺りのことはあまり詳しくない。 試行錯誤の途中、スレッドを走らせる際の start() を run() に書き換えると画像も更新されてwaitKey()も反応するようになった。

if __name__ == "__main__":
    ip = ImageProcessing()
    ip.run()
    ip.join()

ただこれだと、スレッディングではなくメイン文の中で描画ループを回しているだけ。

で、検索してみた結果、C++だけど似たような報告があったので、どうやらwaitKey()はメインスレッドじゃないと動かないってことでいいのかな。不便だけど、もしそうなら他の人はどうしてるんだろう。

imshow() and waitkey() from within a thread –> not updating the display

結局処理をメインスレッドに

というわけで描画ウィンドウの生成と waitKey() はメインスレッドに移した。ついでに終了処理を渡したりするのが面倒なのでデーモンスレッドに

import threading
import cv2

class ImageProcessing(threading.Thread):

	# 描画ウィンドウ名を受け取るように
	def __init__(self, windowname):

		threading.Thread.__init__(self)

		# デーモンスレッドに
		threading.Thread.daemon = True

		self.windowname = windowname
		self.capture = cv2.VideoCapture(-1)

	def run(self):

		while True:
			ret, frame = self.capture.read()
			cv2.imshow(self.windowname, frame)

if __name__ == "__main__":

	# 描画ウィンドウ生成をメインスレッド内に
	windowname = "ImageProcessing"
	cv2.namedWindow(windowname)

	ip = ImageProcessing(windowname)
	ip.start()

	# waitKey() をメインスレッド内に
	while True:
		if cv2.waitKey(10) == 27: # ESC
			break

これで画像も更新されて waitKey() も動作するようになった。imshow() はメインスレッドじゃなくても動きそう。 でもこれだと、結局何がしたかったんだか…ってことに。メイン文が太るのはあんまり好きじゃない。何かいい方法はないものか。

  • Mac OS X 10.9
  • Python 2.7.4
  • OpenCV 2.4.4