2010年09月01日 オブジェクト指向言語R(uby)
_ Rのオブジェクトプログラミング
Rはオブジェクト指向の言語らしい。しかし、どのように書くとオブジェクト指向っぽくなるのかよく分からない。The R language definitionを少し読んで、どのように使うのかを調べてみた。
まず、オブジェクトのクラスを指定するためには、"class"という属性に文字列で指定するだけでよい。したがって、どんな名前のクラスにもできる。
a<-2 attr(a,"class")<-"num" b<-"2" attr(b,"class")<-"str"
次に、オブジェクト毎に、異なった挙動をするメソッドを定義する必要がある。これは、UseMethodを使って、関数名とオブジェクト名をピリオドでつないだ関数を自動的に呼ぶようにすることで実現する。
dub<-function(x) UseMethod("dub") dub.default<-function(x) x dub.num<-function(x) 2*x dub.str<-function(x) paste(x,x,sep="")
こうすると、dub(a)を呼び出すと4が、dub(b)を呼び出すと"22"となる。
しかし、rubyのように、インスタンス変数を定義して、それに値を代入したり、いろいろなデータ構造を持たせるにはどのようにすれば良いのかよく分からない。Rのオブジェクト指向を使った良い例が見つかると分かりやすいのだが、まだ見つけていない。
2010年09月02日 オブジェクトの活用
_ Rとtcltk
Rでは、require(tcltk)とすれば、tkが使えるようになる。しかし、tkのコマンドはあまり馴染みが無いので、なかなか使いにくい。これが多少は使いやすくなるように、ツールを作って、個人的に利用している。しかし、気に入らない点がある。それは、tkで入力した値を取り出すときの方法が統一的ではないということである。tclVarのときには、tclvalue()で値を呼び出す。一方、tklistboxは、tkcurselection()を使って選ばれているものを取り出す。本当はどれでも同じ関数で値を取り出したい。
そこで、tclvalueを調べてみると、UseMethod("tclvalue")となっている。つまり、オブジェクトの種類によって、実行されるメソッドが違うのだ。そこで、attr(,"class")をつかってクラス名を調べると、tclVarはそのままtclVarで、tklistboxはtkwinとなっている。他のtkのオブジェクトもtkwinであるようだが、値を呼び出す必要があるのは、listboxだけなので、次のように定義した。
tclvalue.tkwin <- function(x) as.integer(tkcurselection(x))
こうすると、tclvalue()でtklistboxを呼ぶと、tkcurselection()が呼ばれて、値が取得できるのだ。
これで、tclvalue()のみで値の取得ができるようになった。残る問題は値の代入だ。tclVarはtclvalue(x)<-1などで値を設定できるが、当然tklistboxではだめだ。値を代入できるような関数をどのように書くかが分からない。一つの解決策としては、全く別のメソッドをつくってしまって、例えば、my_set(x,1)とすると、値が代入されるようにして、my_set.tclVarとmy_set.tkwinを定義する方法がある。しかし、tclvalue(x)<-1という形でできるようにできないのかな。
2010年09月03日 RのGUI
_ Rのグラフ作成支援
しばらくRネタが続いているが、その理由は、測定をしながらグラフを書くためのツールを作っていて、そのために必要なRのテクニックを学んでいたからだ。ようやく、多少は使えるものができたので、homepageに公開した。まあ、誰が使ってくれるわけでは無いとは思うが、測定用のPCにそのファイルを取ってくるときに、自分が便利にはなるだろう。
必要なルーチンは三つのファイルに分割した。一つは先に紹介したtktool.rで、tcltkを自分なりに使いやすくしたものだ。グラフの描画のデータ構造はplot.rに記述した。そして、GUI部分はgraphtk.rにまとめた。こうゆうプロクラムは、GUI部分が一番面倒である。実際、ファイルサイズも大きい。使うときには、
source("graphtk.rb")
として、出てきたメニューから使用する。以前使っていたigorに少しだけ影響を受けている。まだ最小限の機能しか使えないし、おそらくバグもあるだろう。imageやrglも機能限定ながら使えるようにしてみた。
このプログラムの前身として、rsrubyとrubytkを使って、rubyで書いたものがあった。昔の記録を見ると、2006年ぐらいには作っていたようだ。しかし、rsrubyでは描画したグラフが別のwindowが上を通ったときに消えたり、debianにrsrubyをうまくインストールできなかったり、という問題が生じてきて、あまり使えなかった。そして、2008年にRから直接tcltkを使ってGUIを作ろうと思って、書き始めてはいたが、Rではrubyのように思ったことが簡単に実現できないので、途中でしばらく放置してあった。最近、Rの知識も増えてきたので、思い出したように作っていたのだ。
ツールとしては使いやすくなったのだが、いろいろなグラフを一つのデータ構造で記述するには、なかなか工夫を必要とした。少し汚いやり方もしている。また、まだできないことも多い。上下に分割したグラフや、labelの位置調節など、コマンドラインからは簡単にできるのだが、それにGUIをつけるのは、非常に面倒だ。
一応beta versionが完成したので、しばらく使ってみて、気が向いたら機能を拡張していこう。
2010年09月04日 Rの特殊な関数
_ Rの関数への代入
Rの通常の関数は、x<-sqrt(2)のように使って、値を返す。しかし、attr(x,"class")<-"name"のように、関数に代入しているように見えるような使い方ができる関数もある。このような関数は、以下のように定義することができる。"test<-" <- function(x,value) x<-value^2 x<-1 test(x)<-2この結果として、xには4は代入されることになる。ここで重要なのは、第二引数の名前をvalueにすることである。そうでないとエラーが生じる。これを応用すると、tklistboxのselectionをtclvalueを使って変更することが可能になる。
"tclvalue<-.tkwin" <- function(x,value){ tkselection.clear(x,0,'end') tkselection.set(x,value) }このように定義しておけば、tclvalue(lb)<-3とすると、tklistboxの3番目が選ばれる。
2010年09月05日 データの場所の特定
_ Rのファイル操作
Rからファイルを読み込む際に、ファイルに余分なヘッダーがあると問題が生じる。これを避けるためには、例えばdata frameを読み込むときには、最初の何行かは除去するように指定することができる。しかし、様々な形式のファイルを扱うためには、最初の何行が余分なヘッダーかを判定する必要がある。Rでファイルから文字列を読み込む方法も分かって来たので、試しに書いてみた。fl<-file("data.txt","r") ttl<-"" repeat{ num<-readLines(fl,1,ok=FALSE) if( regexpr("^s*[\\d\\.]",num,perl=TRUE)!=-1 ){break} ttl<-num } close(fl) cat(ttl) cat(num)最初に数字かピリオドが来るまで一行ずつ読んで行くようにしてみた。データが無いときには、エラーが出るように、readLinesではok=FALSEとした。これで少しは扱えるファイルの種類が増えるかな。
2010年09月06日 Rでsocket
_ rsrubyとsocket
以前、Rをrubyから使うためにrsrubyを使ったことがある。しかし、debianのバージョンが上がったときに、うまくインストールできなくなったので、使うのを止めてしまった。しかし、もっと単純にrubyからRを使う方法を発見した。
Rの関数を調べていたら、socketConnectionというものを発見した。socketの読み書きをするためのものらしい。これを使えば、rubyと通信できるのではということで試してみた。
まずは、rubyをserverにして、Rをclientにする場合として、次のようなコードを書いた。まずはR側。
sock<-socketConnection(host = "localhost", 12343) repeat{ write("Hello, R server.",sock) str<-readLines(sock,1) eval(parse(text=str)) }
そして、ruby側。
require 'socket' require 'thread' s=TCPServer.new(12343) Thread.start(s.accept){|cl| begin i=0 cl.each{|cmd| puts cmd cl.puts "plot(%d:%d,%d:%d)"%[i,i+10,i+10,i+20] i+=1 } ensure cl.close end } while true
Rで待ちを入れる関数を知らないので、ひたすらグラフを更新するが、一応うまく動く。次は逆にrubyをclientにして、Rをserverにする場合。Rでserverの処理を書くのは面倒かとも思ったが、意外に短くかける。
sock<-socketConnection(host = "localhost", 12343 ,server=TRUE) repeat{ cmd<-readLines(sock,1) eval(parse(text=cmd)) }
そして、rubyのclient。
require 'socket' s=TCPSocket.open('localhost',12343) i=0 loop{ s.puts("plot(%d:%d,%d:%d)"%[i,i+10,i+20,i+30]) i+=1 sleep 5 }
Rのサーバーは命令を実行しても応答が帰って来ないが、clientが接続すると返ってくる。おそらくsingle connectionで、だからコードも短くかけるのだろう。
これで、Rとrubyをソケットでつないで、命令を実行できることが実証された。Rの実行結果を文字列で戻して、それをrubyで解釈すれば、実行結果を返すこともできるだろう。rsrubyの代わりに使おうと思えば、使える気がする。
しかし、問題はある。これはrsrubyも同じなのだが、plotで書いたグラフは、制御を奪われている間は更新されないようで、その上を別のwindowが通過すると、消えてしまう。これを回避する手段はないかな。
2010年09月07日 GPIBからRS232Cへ
_ RS232Cでの制御の難しさ
普段、GPIBで制御している装置を、RS232Cで制御する必要があって、プログラムを書き換えていたが、意外に苦労してしまった。ボーレートやパリティの設定などは当然として、他にもいろいろと変えないといけないことが分かった。
あくまで、今回の装置に関してだが、以下のような変更をした。まず、命令の後にリターンコードをつけないといけない。GPIBだと、データの終了を示す信号があるので、区切りが分かるが、RS232Cだとその代わりにリターンコードを使う。次に、リモートモードへの移行コマンドを実行する必要があった。GPIBではRENラインがその役割をしてくれているのかも知れない。そして、writeとreadの間にwaitを入れる必要があった。GPIBではhand shakeをしているので、問題がないが、データが準備できていない時に読み出しに行くと、良くないのだろう。
一瞬でプログラムを書き上げるつもりだったが、つまらないこれらの問題点を発見するまでに、一時間ぐらいかかってしまった。
2010年09月08日 XPの販売終了
_ 測定系に用いるOS
自作の測定装置は、できるだけLinuxで構築するようにしている。現在は測定にWindowsを用いる人が多いようで、Linuxでシステムを構築するためには、情報も少ないために、慣れていない場合には時間がかかるだろう。しかし、長期的な使用を考える場合には、Linuxの方が優れているように思う。
とうとう、WindowsXPも販売終了するようだ。XPで動いている測定システムは結構あると思うが、今後それらはどうなるのか心配になる。Windows98でないと動かないような測定システムも存在するが、それを使っている人はすでに困っているらしいが、その問題が今度はXPで起ころうとしている。メーカーがOSの切り替えをサポートしてくれればよいが、当然コストはかかるし、サポートが期待できない場合もある。
研究室にある古いWindowsの測定システムの一部は、LinuxのWine上で動かすことに成功して、現在は安定して満足している。幸運だったのは、それがシリアルポートしか使っていなかったからである。Wineのversionによっては動かなかったが、GPIBなどを使わなければいけない場合にはどうすれば良いのだろう。
2010年09月09日 Rのバグ取り
_ Rのバグの原因
まだ、Rを少しずついじっているが、プログラムを組んでいるといろいろとバグが見つかる。Rは比較的くせが強いので、慣れないせいでバグが生じてしまうのであろう。
まず面倒なのが、indexが1から始まるという点だ。関数の引数では0を取るものもあるので、いろいろとややこしい。+1をする必要がある場合と無い場合があり、これがバグを引き起こすときがある。
次に問題になるのが、関数によっては、引数にベクトルを渡すとベクトルが返ってくる場合があるためである。例えば、is.na(1)とするとFALSEとなるが、is.na(c(1,NA))とするとc(FALSE,TRUE)となる。c(1,NA)はNAではないので、FALSEを返して欲しいのだが、そうするためにはどうしたら良いのか分からない。all(is.na(c(1,NA)))とか、is.na(c(1,NA))[1]とすれば、今の例では良いのだが。複雑なデータ構造を使う場合には、これが問題になる。
あとは、ベクトルの連結も少し奇妙な挙動をする。c(c(1,2),3)はc(1,2,3)となり、list(list(1,2),3)はそのままだ。しかし、c(list(1,2),list(3))はlist(1,2,3)となる。c(list(1,2),3)でもlist(1,2,3)となる。この二つの結果が一致するのは変な気がする。そして要素を取り出すときには、、c()は[]を、list()は[[]]を使う。だんだん訳が分からなくなってくる。
他にもいろいろとあるだろうが、このあたりの感覚が、他の言語と少し変わっていて、つい好ましくないコードを書いてしまってバグが生じやすくなっている気がする。さらに、エラーメッセージも親切では無いので、バグ取りもなかなか難しい。もう少し慣れないといけないな。
2010年09月10日 線形回帰と多項式回帰
_ Rの多項式fit
Rの直線での回帰は、次のように簡単にできる。
x<-c(1,2,3,4,5) y<-c(1,4,8,11,18) plot(x,y) fit1<-lm(y~x) abline(fit1)
しかし、多項式fitは面倒である。以前は、次のようにしていた。
fit2<-lm(y~x+I(x^2))
当たり前なのだが、つぎのようにしてもできるらしい。
x2<-x^2 fit3<-lm(y~x+x2)
実際に使うときには、どちらが良いのだろう。メモリを食わないという意味では、前者の方が良いような気もするし、後者の方が計算コストが少ない気もする。
2010年09月11日 ssh server
_ Mac OSXのssh
linuxを使っていると、sshで別のマシンに入って作業をすることがある。Windowでは、時代遅れのtelnetは使えても、sshは標準では使えない。windowsを使っていた頃は、cygwinのsshを使っていた。
debianでは、ssh serverは標準ではインストールされない設定になっている。いくつか前のsargeとかでは、たしか標準でインストールされてしまっていたので、動かさないように設定することもあった気がする。
BSDのMac OSXではどうなのだろうと思って調べてみたら、設定でリモートログインを許可すると、ssh serverが働く用になっているらしい。
2010年09月12日 Debian Lenny
_ Debian GNU/Linux 5.0.6
本日、久々にaptitude update; aptitude upgradeしたら、100以上のパッケージが入れ替わった。なぜこんなに多いんだろうと思ったら、9/4にDebian GNU/Linux 5.0.6がリリースされていたからだった。おそらく、あと半年ぐらいすれば、squeezeがリリースされると思うが、Debianもここ数年で、ますます使いやすいものになってきた。素人向けになったとも言えるが。一方、多くのユーザーを抱えるWindowsは、2000の頃からあまり変わった気がしない。サーバとしてはともかく、クライアントとしてはある程度使い易いものになっているので、見た目以外は大きく変化しないのかも知れないが、安定性の低さもあまり変わっていないように思う。しかし、Linuxユーザーはあまり増えている気がしない。個人で使うときの使いやすさからすれば、Windowsとそれほど変わらないと思うのだが、他の人とデータのやり取りをしたり、プリンターなどのメーカーがLinuxのサポートをしていない外部の機器を使うときには、不便を感じるだろう。しかし、これは、ユーザーの数が少ないからそうなるので、ユーザーが多くなれば解決すると思うのだが。未だに身近にLinuxユーザーはほとんどいない。Macユーザーはいるんだけど。
2010年09月15日 from etch to lenny
_ 最後のetchマシン
研究室で稼働しているLinuxマシンに一台だけetchがあった。昨日、updateしようとしたら、not foundがいろいろと出てきた。source.listの設定はあっていると思うのだが、何かが変なのかも知れない。折角なので、本日lennyに入れ替えた。すぐに終わると思ったが、xorgの設定でつまってしまった。マシンはHPのproliant ML115というサーバーマシンで、RS232Cで装置の制御に使っている。やはり、/etc/X11/xorg.confの書き換えが必要で、以下のようにした。
Section "Device" Identifier "Videocard0" Driver "vesa" VideoRam 2048 BusID "PCI:5:0:0" EndSection Section "Screen" Identifier "Default Screen" Monitor "Configured Monitor" Device "Videocard0" DefaultDepth 16 SubSection "Display" Viewport 0 0 Depth 16 Modes "1024x768" "800x600" EndSubSection EndSection
実は共通のPCにはまだ一台etchが残っているのだが、私の一存だけで再インストールはできないので、もう少し放置かな。
2010年09月20日 autorun.inf
_ MAL_OTORUN
Linuxを使っていると、Windows用のウィルスには感染しないので、その辺りの事情に疎くなってしまう。MAL_OTORUNというウィルスが流行っていることも、今日初めて知った。autorun.infを利用して感染するものらしい。
windowsの自動実行は、いつも鬱陶しいと思っていた。こっちが起動するように指示したときだけ起動すれば良いのに、勝手に起動する。これがデフォルトで有効になっているのが、感染拡大の助けになっている。マヌケな話だ。メールの添付ファイルを勝手に開いたり、windowsのデフォルトの設定には疑問なものが多い。
MAL_OTORUNに感染した場合には、USBメモリに隠しファイルでautorun.infと本体を書き込む。そして、ウィルスを除去しようとしても、既にウィルスが常駐しているので、消そうと思っても、すぐにまた復活する。まあ、Linuxだと隠しファイルも簡単に見えてしまうので、対応は簡単だが。
2010年09月21日 RのGUI
_ Rcmdr
Rの本を呼んでいたら、Rcmdrというものを見つけた。まずは、aptitude install r-cran-rcmdrでインストールする。そして、Rを立ち上げて、library(Rcmdr)とすると、tcltkを使ったGUIが立ち上がる。Rは非常に便利で高性能なツールだが、コマンドを覚えなければ使えない。私も、GUIをつければコマンドを覚えなくても使えるようになるのでは無いかというように考えて、plotを使ってグラフを作る補助として、tcltkを使ってツールを作ったことがある。まだ地道に進行中であるが。これと同じような思想で作られたものなのだろう。少し使ってみたら、グラフに関しては、それほど細かい指定はできないものの、いろいろなコマンドに関して、基本的な使い方が見れて、なかなか面白いし、コマンドを覚えるためにも便利そうだ。今度、少しいじってみよう。
2010年09月24日 久々の日本橋
_ 液晶と水晶
およそ二年半ぶりだと思うが、日本橋に行ってきた。まずはデジットに行こうと思ったら、そのすぐそばに千石があって驚いた。日本橋にも支店ができたらしい。
さて、面白い部品が無いかなと思っていろいろと物色していたが、液晶をいくつかと、水晶を買った。水晶は12MHzのもので100円だったが、USB用に使おうと考えている。知りたかったのは足の間隔で、約5mmだったので、2/10インチなのだろう。
液晶は前回買ったものがあったら買おうと思っていたが、さすがに無かった。代わりにいくつかの種類を見つけた。まずは、確実に動かせそうなものとして、OPTREXのPWB842Bが200円であったので、買ってみた。信号は8pinで使い方を調べた人がいるようで、これを参考にすれば、AVRでも使えると期待したい。ちなみに、ピン配置をメモしておくと、1:/RESET, 2:/SCK, 3:SI, 4:/BUSY, 5:CMD,/DATA, 6:/CS, 7:5V, 8:GNDらしい。
その他に、epsonのLD-BV9332AZという液晶を30円でゲット。元は音楽プレーヤー用のもののようで、四桁の数字といくつかの記号などを表示できる。
千石も覗いてみたが、ホール素子を発見した。磁場の簡易センサーでも作ろうと思っていたのだが、適当なものがなくて、探していたのだ。東芝のTHS119, 123, 126, 130があった。違いがよく分からなかったので購入しなかった。しかし、webショップには無いようだ。後で買おうと思ったら、どこで買えばよいのかな。tiny261と液晶表示なんかをつければ、簡易磁場センサーができると思うのだが。
ちなみに、いつこれらを動かしてみるだけの時間が確保できるかな。
2010年09月26日 アキバの液晶
_ またまた液晶
日本橋に続いて、秋葉でも液晶を買ってしまった。最初は秋月で何かの液晶を買おうと思っていたのだが、液晶工房に行ったところ、面白そうな液晶がいろいろとあったので、その中からお買い得そうなものを買ってしまった。
一つは、16x2のキャラクタ表示用のSC162Aというものだ。バックライト付で\300というのは激安だった。これまで、キャラクタ表示用の液晶は秋月かデジットで買っていたのだが、液晶工房も捨てがたいことが分かった。
もう一つは、シャープ製5.5インチカラーSTN液晶モジュールのLM6Q40Aというものが、これも\300で売っていたので買ってしまった。インターフェースは、RGBとSYNCで、15kHzらしい。これらの信号の意味を調べないと、これを使うことはできないだろう。目標はこれをマイコンから動作させることだ。
ちなみに、今日は人と一緒だったので、秋月に行くのが後回しになってしまった。液晶はさすがにもう買うべきではないと判断して、mega8を買ってみた。AVRはtiny2313(or at90s2313)とtiny261に続いて三種類目だが、megaは初めてだ。28pinなので、書き込みようの部品が必要になるかも知れない。