2009-08-30

確率プロットの作成


ックスプロットで使ったデータを、確率プロットで表示してみました。凡例には、データ数とメディアンを表示しています。

# CDF PLOT SAMPLE
# =============================================================================
# chart.cdf
# =============================================================================

chart.cdf <- function(tbl, valX = "RAW_VALUE", colBy = "condition",
gTitle = "", xLab = "measured data") {
x <- tbl[, valX]
x <- x[!is.na(x)]
n <- length(x)
x <- sort(x)
y <- (1:n - 0.375) / (n + 0.25)

probs <- c(0.001, 0.01, 0.1, 1, 5, 10, 20, 30, 40, 50,
60, 70, 80, 90, 95, 99, 99.9, 99.99, 99.999) / 100
m <- length(probs)

x_min <- x[1]
x_max <- x[n]
x_pad <- (x_max - x_min) * 0.4

y_min <- qnorm(probs[1])
y_max <- qnorm(probs[m])
y_stp <- (y_max - y_min) * 0.1

plot(c(x_min, x_max + x_pad), c(y_min, y_max),
type = "n", yaxt = "n",
xlab = xLab, ylab = "Cumulative Percent",
main = gTitle, cex.main = 1)
axis(2, qnorm(probs), probs * 100)
abline(h = qnorm(probs), lty = 3, col = "#C0C0C0")
abline(h = 0, lty = 1, col = "#808080")

listBy <- sort(unique(tbl[, colBy]))
k <- length(listBy)
for (i in 1:k) {
valBy <- listBy[i]
x <- tbl[tbl[, colBy] == valBy, valX]
x <- x[!is.na(x)]
n <- length(x)
x <- sort(x)
y <- (1:n - 0.375) / (n + 0.25)

total <- length(x)
x.median <- median(x)
legend_label <- paste(valBy, ':', total, "/", x.median)

points(x, qnorm(y), type='o', col = i, pch = i)

legend_x <- x_max + x_pad * 0.05
legend_y <- y_max - y_stp * (i - 1)
legend_lty = 1
legend(legend_x, legend_y, legend_label, col = i,
lty = legend_lty, pch = i, ncol = 1, cex = 0.7, box.lty = 0)
}
}
# =============================================================================
# open.png
# =============================================================================

open.png <- function(imgName, picWidth = 640, picHeight = 400) {
png(filename = imgName, width = picWidth, height = picHeight,
units = "px", pointsize = 14, bg = "white", res = NA)
}
# -----------------------------------------------------------------------------
# MAIN
# -----------------------------------------------------------------------------
# _____________________________________________________________________________
# READ CSV DATA

file.name <- "./sample_box.csv"
tbl.data <- read.csv(file.name, header = T, as.is = T)
# _____________________________________________________________________________
# generate CDF PLOT

head.y <- names(tbl.data)[1]
head.x <- names(tbl.data)[2]
title.box <- paste("SAMPLE (n = ", length(tbl.data[, head.x]), ")",
sep = "")
label.x <- "Measurement"
chart.cdf(tbl.data, head.x, head.y, title.box, label.x)
# _____________________________________________________________________________
# generate PNG FILE

open.png("sample_cdf.png")

chart.cdf(tbl.data, head.x, head.y, title.box, label.x)
dev.off()
# ---
# END PROGRAM


実行例



Fedora で実行した例を示します。

$ R

R version 2.9.2 (2009-08-24)
Copyright (C) 2009 The R Foundation for Statistical Computing
ISBN 3-900051-07-0
...
(途中省略)
...
'q()'と入力すればRを終了します。

> source("cdf.R")

X Window 上では以下の様に表示されます。

出力された PNG ファイルはこんな感じになります。

 

2009-08-29

ボックスプロットの作成


数条件による測定データをボックスプロットにして表示するスクリプトを紹介します。データは CSV 形式で、一行目がヘッダーになっています。この例では一列目が条件、二列目がデータになっています。

# BOXPLOT SAMPLE
# =============================================================================
# chart.boxplot
# =============================================================================

chart.boxplot <- function(tbl, val_x, val_y,
gTitle = "", xLab = "", yLab = "") {
tmp <- data.frame(x = tbl[, val_x], y = tbl[, val_y])
y_max <- max(tmp$y, na.rm = TRUE)
y_min <- min(tmp$y, na.rm = TRUE)
yLimit <- c(y_min, y_max)

bp <- boxplot(y ~ x, data = tmp, ylim = yLimit,
main = gTitle, xlab = xLab, ylab =yLab,
col = "lightblue", cex.main = 1)
}
# =============================================================================
# open.png
# =============================================================================

open.png <- function(imgName, picWidth = 640, picHeight = 400) {
png(filename = imgName, width = picWidth, height = picHeight,
units = "px", pointsize = 14, bg = "white", res = NA)
}
# -----------------------------------------------------------------------------
# MAIN
# -----------------------------------------------------------------------------
# _____________________________________________________________________________
# READ CSV DATA

file.name <- "./sample_box.csv"
tbl.data <- read.csv(file.name, header = T, as.is = T)
# _____________________________________________________________________________
# generate BOXPLOT

head.x <- names(tbl.data)[1]
head.y <- names(tbl.data)[2]
title.box <- paste("SAMPLE (n = ", length(tbl.data[, head.x]), ")",
sep = "")
label.x <- "Condition"
label.y <- "Measurement"
chart.boxplot(tbl.data, head.x, head.y, title.box, label.x, label.y)
# _____________________________________________________________________________
# generate PNG FILE

open.png("sample_boxplot.png")

chart.boxplot(tbl.data, head.x, head.y, title.box, label.x, label.y)
dev.off()
# ---
# END PROGRAM


実行例



Fedora で実行した例を示します。

$ R

R version 2.9.2 (2009-08-24)
Copyright (C) 2009 The R Foundation for Statistical Computing
ISBN 3-900051-07-0
...
(途中省略)
...
'q()'と入力すればRを終了します。

> source("boxplot.R")

X Window 上では以下の様に表示されます。

出力された PNG ファイルはこんな感じになります。

 

2009-08-28

ヒストグラムの作成


用目的で測定データをヒストグラムにして表示するスクリプトを紹介します。データは CSV 形式で、一行目がヘッダーになっています。この例では一列目のデータをヒストグラムにしています。 X Window 上で表示するのに加えて PNG 画像にも出力するようにしました。

# HISTOGRAM SAMPLE
library(KernSmooth)
# =============================================================================
# chart.hist
# =============================================================================

chart.hist <- function(tbl, val_x, gTitle = "", xLab = "data") {
x <- sort(tbl[, val_x])
h <- try(dpih(x), TRUE)
if (!is.numeric(h)) {
h <- 10**round(log(range(x)[2] - range(x)[1]))
}
bins <- seq(min(x) - 0.1, max(x) + 0.1 + h, by = h)

x_max <- max(x, na.rm = TRUE)
x_min <- min(x, na.rm = TRUE)
xLimit <- c(x_min, x_max)

hg <- hist(x, breaks = bins, freq = FALSE,
main = gTitle, xlab = xLab, xlim = xLimit,
col = "lightblue", cex.main = 1, family = "mono")

points(x, dnorm(x, mean(x), sd(x), log = FALSE),
type='l', col = "magenta", lwd = 1)
points(density(x), type = 'l', col = "orange", lwd = 1)
}
# =============================================================================
# open.png
# =============================================================================

open.png <- function(imgName, picWidth = 640, picHeight = 400) {
png(filename = imgName, width = picWidth, height = picHeight,
units = "px", pointsize = 14, bg = "white", res = NA)
}
# -----------------------------------------------------------------------------
# MAIN
# -----------------------------------------------------------------------------
# _____________________________________________________________________________
# READ CSV DATA

file.name <- "./sample_hist.csv"
tbl.data <- read.csv(file.name, header = T, as.is = T)
# _____________________________________________________________________________
# generate HISTOGRAM

head.x <- names(tbl.data)[1]
title.hist <- paste("SAMPLE (n = ", length(tbl.data[, head.x]), ")",
sep = "")
label.x <- "Measurement"
chart.hist(tbl.data, head.x, title.hist, label.x)
# _____________________________________________________________________________
# generate PNG FILE

open.png("sample_hist.png")
chart.hist(tbl.data, head.x, title.hist, label.x)
dev.off()
# ---
# END PROGRAM


実行例



Fedora で実行した例を示します。

$ R

R version 2.9.2 (2009-08-24)
Copyright (C) 2009 The R Foundation for Statistical Computing
ISBN 3-900051-07-0
...
(途中省略)
...
'q()'と入力すればRを終了します。

> source("hist.R")
KernSmooth 2.23 loaded
Copyright M. P. Wand 1997-2009


X Window 上では以下の様に表示されます。

出力された PNG ファイルはこんな感じになります。

 

2009-08-22

リストの要素を変数に代入する(2)


名さんから lassign で良いのでは、というコメントをいただきました。ハイ、その通りです。ご指摘をありがとうございました。

Tcl/Tk リリース履歴 の Tcl 8.5a1 and Tk 8.5a1 (2004-03-03) における特記事項に、自分でちゃんとこのコマンドを書いておりました。そればかりか、恥ずかしいことに、なんと「要素の値を変数へ代入」で lassign の説明すらしています。それなのに、全然利用していませんでした。利用しないと忘れます。未だに、サブルーチン(proc コマンド)から戻り値をリストで受けとると、値を lindex コマンドで変数に振り分けていました。少なくとも最近書いている Tcl のコードは書き直す必要があります。未熟な知識に反省です。

$ tclsh
% lassign [list 1 2 3] a b c
% puts $a
1
% puts $b
2
% puts $c
3
% exit

2009-08-21

リストの要素を変数に代入する


perl で、リストの要素を変数に代入する場合は次のように記述します。

$ perl
($a, $b, $c) = (1, 2, 3);
print $a, "\n";
print $b, "\n";
print $c, "\n";

^D1
2
3

$

とてもスマートにできます。


Tcl の場合だと次のようにします。perl の表現に比べると、とても武骨です。

$ tclsh
% set z [list 1 2 3]
1 2 3
% set a [lindex $z 0]
1
% set b [lindex $z 1]
2
% set c [lindex $z 2]
3
% exit
$

もっと簡単にできないかと考えたところ、名案が浮かびました。perl ほどではありませんが…。

$ tclsh
% foreach {a b c} [list 1 2 3] {}
% puts $a
1
% puts $b
2
% puts $c
3
% exit
$

考えてみると、だれか他の人の Tcl コードで既にこのように使われていた気がします。その時にはちゃんと理解できず見逃していたのでしょう。
 

2009-08-15

ReactOS 0.3.10 (2)

ReactOS が利用できるようになったので、早速いくつかのアプリケーションをインストールしてみようと、iso イメージを作り、ごく普通の方法でインストールして使えるかどうか試してみました。

まず、試してみるインストーラを適当なディレクトリ(この例では Apps)にコピーして、iso 形式のファイルを作成します。これを CD-ROM のドライブに指定して、qemu で ReactOS を起動します。

$ ls Apps
ActiveTcl8.5.7.0.290198-win32-ix86-threaded.exe jre-6u15-windows-i586-s.exe
Firefox Setup 3.5.2.exe tcltk8.6b1-017-20081224.exe
OOo_3.1.0_Win32Intel_install_en-US.exe winzip121.exe
$ genisoimage -r -l -J -o Apps.iso Apps
I: -input-charset not specified, using utf-8 (detected in locale settings)
4.90% done, estimate finish Sat Aug 15 22:06:33 2009
9.80% done, estimate finish Sat Aug 15 22:06:33 2009
:
(途中省略)
:
92.98% done, estimate finish Sat Aug 15 22:06:37 2009
97.87% done, estimate finish Sat Aug 15 22:06:37 2009
Total translation table size: 0
Total rockridge attributes bytes: 776
Total directory bytes: 0
Path table size(bytes): 10
Max brk space used 0
102189 extents written (199 MB)
$ qemu -m 1024 -smp 1 -cdrom Apps.iso -hda ReactOS.img

結論から言うと、ほとんどまともにインストールできませんでした。結果は以下の通り。

WinZip 12.1


インストールの最後の方でエラー発生でインストールできず。


Firefox 3.5.2


インストールは無事終了するが起動せず。


Java (JRE 6)


インストールの最後でエラー発生。しかし、バイナリーのコピーは終わっていそうだったので、ひきつづき OpenOffice.org をインストールしてみる。


OpenOffice.org 3.1.0 (w/o JRE)


なんと、インストールが終了しました、が、よく読んでみるとちゃんとインストールされたわけではなさそうです。



おまけにリブートすると OS が立ち上がらず…。結局 ReactOS を再インストールすることに。


Tcl/Tk


ActiveTcl は最初の段階でインストーラが止まってしまい(もしかすると、ずっと放置しておけばインストールできたかもしれないが)インストールできませんでした。結局まともにインストールできたのは、レジストリ操作などの作りが一番簡単だと思われる、自製の MinGW クロスコンパイル版の Tcl/Tk 8.6b1 だけでした。



ReactOS はまだアルファ段階(開発レベル)ですので、多くを期待することはできないかもしれません。しかし OpenOfice.org とインターネット関連のソフトウェアが動作するようになれば、Windows の代替として十分注目される OS になることでしょう。

次のバージョン 0.3.11 は早ければ来月にリリースされるとのことですので、新しいバージョンでもこういった評価をしてみたいと考えています。

それまでに qemu でネットワークの設定を正しくできるようにして、さらに qemu の使い方をもっとマスターしておくようにします。
 

2009-08-14

ReactOS 0.3.10 (1)

ReactOS は、Windows NT 互換のオペレーティングシステム (OS) のフリーソフトウェアおよびオープンソースの開発プロジェクトです。ライセンスは GNU GPL に従います。ReactOS については、以下に詳しい解説(日本語)があります。

About ReactOS - ReactOS ウェブサイト

表現が悪いかもしれませんが、いわゆる Windows クローンの使い勝手を試してみたくなり、Fedora 11 に PC エミュレータ QEMU を導入し ReactOS 0.3.10 をインストールしてみました。

まず、ReactOS をインストールする C ドライブ(Linux 的には hda)に相当する仮想ディスクを、適当なディレクトリ内に用意します。とりあえず、10GB を確保しました。

$ qemu-img create -f qcow ReactOS.img 10GB
Formatting 'ReactOS.img', fmt=qcow, size=10485760 kB

次に、ReactOS のインストール CD のイメージ (ReactOS-0.3.10-REL-iso.zip) を下記からダウンロードして、用意した仮想ディスクと同じディレクトリ内に展開しておきます。

Download - ReactOS ウェブサイト


$ unzip ReactOS-0.3.10-REL-iso.zip
Archive: ReactOS-0.3.10-REL-iso.zip
inflating: ReactOS.iso

これでインストールの準備が整いました。同じディレクトリ上で QEMU を起動して ReactOS をインストールしてみます。

$ qemu -m 512 -smp 1 -boot d -cdrom ReactOS.iso -hda ReactOS.img -net user -net
nic,model=rtl8139,vlan=0,macaddr=52:54:00:12:34:56 -k ja -localtime


ネットワークを使えるようにして起動したつもりだったのですが、結局使えませんでした。指定の仕方が悪いのかもしれません。正直なところ、QEMU のネットワークの設定については、まだ理解が足りません。なおメモリは 512MB、CPU は 1 つとしました。

QEMU のウィンドウが開いて、ReactOS のインストーラが起動します。言語設定の画面では、インストール中の言語を指定します。Japanese も選択できますが、すべてカタカナの説明されたインストール画面で、却って見にくいので、デフォルトの English (United States) を選択したインストールを紹介します。Enter を押して次に進みます。



Welcome 画面です。Enter を押して次に進みます。



この Setup プログラムはまだ開発初期段階で機能に制約がある旨が表示されます。Enter を押して次に進みます。



現在のデバイス設定が表示されます。Enter で次に進みます。



インストール先のドライブを指定します。この場合、ひとつしかありません。Enter を押して次に進みます。



インストール先の C ドライブを FAT 形式で初期化(フォーマット)するか聞いてきますので、そのまま Enter を押して次に進みます。



確認のメッセージが出ますので Enter で実行します。



フォーマット中の画面です。



OS のインストール先を指定します。Windows の C:\Windows に相当します。Enter を押して次に進みます。



インストールが始まりました。少々時間がかかります。



ブートローダーをどこに書き込むか聞いてきます。そのまま Enter で次に進みます。



必要なファイルのコピーが終わり、インストールメディアを取り外して Enter を押すようにメッセージが出ます。ここではそのまま Enter を押します。



仮想 PC が再起動しますので、F12 を押してブートするデバイスを表示させ 2 を押してハードディスクから起動します。



ReactOS の起動画面です。



最初の起動では Windows と同様、セットアップ・ウィザードの画面が現れます。Next をクリックして次へ進みます。



開発に関係したオープンソース・プロジェクトに対する謝辞が表示されます。Next をクリックして次に進みます。



使用者の名前(と会社名)を入力して Next をクリックして次に進みます。



コンピュータ名とシステム管理者のパスワードを設定します。Next をクリックして次に進みます。



地域設定をします。ここで日本語設定ができますが、このバージョンでは、私の環境ではうまく日本語設定ができなかったので、日本語環境をあきらめこのまま Next をクリックして次に進みます。



時刻設定をします。Next をクリックして次に進みます。



(レジストリへの)設定が始まります。



デバイス (PCI Memory) の設定をします。Next をクリックします。



設定失敗のメッセージが出ます。しかたがないので、このまま Finish をクリックします。この後同様に Ethernet についてもデバイス設定の画面が出ますが、同様に設定に失敗します。



これで ReactOS が使えるようになります。デスクトップは、アイコンが画面上に横並びになっていますが、Windows のデスクトップに非常によく似た作りになっています。



今回は、QEMU の仮想環境に ReactOS をインストールする方法を紹介しました。開発中とは言え、なかなか良くできたインストーラです。再起動を何回かしなければならないことも Windows にそっくりです。

次回は実際に Windows のアプリケーションを ReactOS にインストールしてみようと思います。

ちなみに、QEMU のウィンドウから、Linux のデスクトップへのマウスポインタのコントロールの切り替えは Ctrol + Alt で行います。

[1] Frontpage - ReactOS Website
[2] Universal ATA対応で8GB超の領域が利用可能に「ReactOS 0.3.10」 | パソコン | マイコミジャーナル
 

2009-08-11

chan create

chan は、Tcl 8.5 で追加されたコマンドです。チャネルを操作するコマンドで、従来の opensocket コマンドと同じことが出来るだけでなく、chan create コマンドでチャネルを独自に定義することもできます。

簡単なサンプルとして、チャネルの出力先を text ウィジェットにした例を紹介します。

# -----------------------------------------------------------------------------
# NAMESPASE textOut
# -----------------------------------------------------------------------------

namespace eval textOut {
variable subCmds [list initialize finalize watch write]
variable m; # pathName of text widget to display message

namespace ensemble create -subcommands $subCmds
namespace export regist

# initialize
proc initialize {channelId mode} {
variable subCmds

return $subCmds
}

# finalize
proc finalize {channelId} {
# NOP
}

# watch
proc watch {channelId eventspec} {
# NOP
}

# write
proc write {channelId data} {
variable m

set msgout [encoding convertfrom [encoding system] $data]
$m configure -state normal
$m insert end $msgout
$m see end
$m configure -state disable
update
return [string length $data]
}

# regist
# The namespace specific command to remember pathName

proc regist {pathName} {
variable m

if {![winfo exists $pathName]} {
error "$pathName does not exist."
}
if {[winfo class $pathName] ne "Text"} {
error "$pathName is not text widget."
}
set m $pathName
$m configure -state disable
return $m
}
}

chan create コマンドで利用する、チャネルを操作するコマンド(この例では textOut)では、定められた名前のサブコマンドを用意する必要があります。前回紹介した、namespace ensemble コマンドを利用すると簡単にできます。(これが唯一の方法というわけではありません。)

上記のスクリプトを textOut.tcl というファイル名で保存した後、コンソール上で wish あるいは tclsh を起動、source コマンドで読み込んで実行した例を以下に示します。

$ tclsh
% package require Tk
8.5.6
% pack [text .t]
% source textOut.tcl
% textOut::regist .t
.t
% set out [chan create write textOut]
rc0
% chan configure $out -buffering line
% puts $out "これは出力テストです。"
%



出力先の text ウィジェットのパス名を textOut::regist で名前空間内の変数に登録してから利用します。なお、chan configure コマンドで -buffering line を指定して、バッファに出力が溜まらないようにしています。デフォルトでは、flush しないと(バッファが一杯になるまで)出力はバッファに溜まったままになります。

この例は、特定のチャネルを通じて、text ウィジェットに文字列を出力するだけの簡単なものですが、chan create コマンドによるチャネルの定義は、いろいろ応用できる分野がありそうです。
 

2009-08-07

namespace ensemble

namespace ensemble(アンサンブル)は Tcl 8.5 で加わった namespace のサブコマンドです。

名前空間をコマンド名、proc コマンドで定義した名前空間内のユーザーコマンド(手続き)をサブコマンド名として、名前空間の外から扱えるようになります。サブコマンドとして扱うコマンドは -subcommands オプションにリストで指定します。

簡単なサンプルを紹介します。

namespace eval test {
namespace ensemble create -subcommands [list abcd efgh]

proc abcd {} {
puts "-- subcommand 'abcd'! --"
}
proc efgh {} {
puts "-- subcommand 'efgh'! --"
}
proc ijkl {} {
puts "-- command 'ijkl' in namespace test --"
}
}

このサンプルを test.tcl というファイル名で保存し、tclsh を起動して source コマンドで保存したファイルを読み込んで、コマンドを実行してみます。

$ tclsh
% source test.tcl
% test
wrong # args: should be "test subcommand ?argument ...?"
% test abcd
-- subcommand 'abcd'! --
% test efgh
-- subcommand 'efgh'! --
% test ijkl
unknown or ambiguous subcommand "ijkl": must be abcd, or efgh
% test::ijkl
-- command 'ijkl' in namespace test --