Ruby/Tkで少しだけインタラクティブなグラフを表示する
はじめに
以前書いたように、Ruby/TkとPlotchartでグラフを表示できるのですが、それだけではつまらないので、ちょっとだけマウスと連動させてみます。
コード
#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'csv' require 'tk' require 'tkextlib/tcllib/plotchart' # plotchart.rb を修正するモンキーパッチ module Tk::Tcllib::Plotchart class XYPlot def pixel_to_coords(x, y) list(tk_call_without_enc('::Plotchart::pixelToCoords', @path, x, y)) end end end # データを読み込み en, cn = CSV.parse(DATA).map { |r| [r[0].to_f, r[1].to_i] }.transpose # データをプロット pl = Tk::Tcllib::Plotchart::XLogYPlot .new([0, en.size, 10**Math.log10(en.size).floor], [1, 10**Math.log10(cn.max).ceil], width: 600, height: 400) do title 'Spectrum' xtext 'Channel' ytext 'Counts/Channel' dataconfig('series1', color: :red) cn.each_with_index { |c, i| plot('series1', i, c) } pack(fill: :both) end # マウスカーソルの位置の値を表示 label = TkLabel.new.pack pl.bind(:Motion, '%x %y') do |x, y| ch = pl.pixel_to_coords(x, y)[0].to_i if 0 <= ch && ch < en.size label.text(sprintf('%10d ch, %10.1f keV, %10d counts', ch, en[ch], cn[ch])) end end # イベントループ Tk.mainloop __END__ 32.78,1074 62.72,12131 92.70,13944 122.72,13110 152.79,11859 182.90,13204 213.05,11647 243.24,8780 273.47,7412 303.75,6632 334.07,6460 364.43,6369 394.83,6503 425.28,6566 455.76,5250 486.29,2766 516.86,1574 547.48,1062 578.13,914 608.83,3532 639.57,15018 670.35,18992 701.18,6495 732.04,660 762.95,177 793.90,157 824.89,134 855.93,154 887.00,131 918.12,124 949.28,129 980.48,113 1011.73,96 1043.01,103 1074.34,112 1105.72,92 1137.13,95 1168.58,86 1200.08,85 1231.62,66 1263.20,50 1294.83,29 1326.49,40 1358.20,33 1389.95,47 1421.74,93 1453.57,111 1485.45,67 1517.37,41 1549.33,19 1581.33,17 1613.38,11 1645.46,13 1677.59,18 1709.76,15 1741.98,10 1774.23,6 1806.53,13 1838.87,15 1871.25,11 1903.67,6 1936.14,8 1968.64,6 2001.20,8
実行結果
OSX Yosemiteで実行した結果です。下記のように、マウスカーソルの位置の値がグラフの下に表示されます。
Ruby 2.2.0同梱のplotchart.rbのバグ
グラフ内におけるマウスカーソルの座標を取得するためにTk::Tcllib::Plotchart::XLogYPlot#pixel_to_coords
を使ったのですが、Ruby 2.2.0 同梱のplotchart.rb
にはバグがあるので、下記のようにモンキーパッチを当てています。
module Tk::Tcllib::Plotchart class XYPlot def pixel_to_coords(x, y) list(tk_call_without_enc('::Plotchart::pixelToCoords', @path, x, y)) end end end
既に修正が本家に取り込まれたようなので、そのうち必要なくなると思います。
最後に
Ruby/TkとPlotchartさえ入っていればWindowsでも動きます。しかし、WindowsはPlotchartを使えるようにするまでがちょっと面倒でした(こちらに書きました)。
Ruby 2.2.0でRuby/TKを使えるようにするconfigureオプション
はじめに
rbenvとruby-buildでそのままRuby 2.2.0を入れると、たいていRuby/Tkが使えないので、configureオプションを設定します。ちなみに、こちらのパッチは必要無くなったようです。
Debian SidやUbuntu 14.10 (64bit)の場合
$ apt-get install tk-dev $ RUBY_CONFIGURE_OPTS="--with-tcltkversion=8.6 \ --with-tcl-lib=/usr/lib/x86_64-linux-gnu \ --with-tk-lib=/usr/lib/x86_64-linux-gnu \ --with-tcl-include=/usr/include/tcl8.6 \ --with-tk-include=/usr/include/tk8.6 \ --enable-pthread --enable-shared" \ rbenv install 2.2.0
FreeBSD 10.1の場合
$ pkg install tk86 $ RUBY_CONFIGURE_OPTS="--with-tcltkversion=86 \ --with-opt-dir=/usr/local \ --with-tcl-include=/usr/local/include/tcl8.6 \ --with-tk-include=/usr/local/include/tk8.6 \ --enable-pthread --enable-shared" \ rbenv install 2.2.0
最後に
iCloudのどこでもMy MacでMosh (mobile shell)を使う
はじめに
iCloudのどこでもMy Macを使うと、こちらで紹介されているように、出先から自宅のMacにSSHでログインできます。今回はさらに「SSHよりも高速」というMoshを、どこでもMy Macで使えるようにします。Moshの仕組みについては、こちらが詳しいです。
Moshのインストール
サーバとクライアントの両方のMacにMoshの最新版をインストールします。Homebrewを使えば簡単です。
$ brew install --HEAD mosh
これでSSHで接続する時と同様にクライアントから
$ mosh hoge@fooMac.999999999.members.btmm.icloud.com
などとすれば、サーバに接続できそうな気がするのですが、
/usr/local/bin/mosh: Could not resolve hostname fooMac.999999999.members.btmm.icloud.com ssh_exchange_identification: Connection closed by remote host /usr/local/bin/mosh: Did not find remote IP address (is SSH ProxyCommand disabled?).
と言われてうまくいきません。そこで、こちらに書かれているようにクライアント側のmosh
コマンドを以下のように修正します。1行加えるだけです。
--- /usr/local/opt/mobile-shell/bin/mosh.orig 2014-12-05 13:18:17.000000000 +1100 +++ /usr/local/opt/mobile-shell/bin/mosh 2014-12-05 13:23:49.000000000 +1100 @@ -36,6 +36,7 @@ use strict; use Getopt::Long; use IO::Socket; +use IO::Socket::INET6; $|=1;
これで
$ mosh -6 hoge@fooMac.999999999.members.btmm.icloud.com
とすれば、サーバに接続できるようになりました。
OSXにHomebrewで入れたnkfでman nkfするとfatal error: invalid device `nippon'と言われるのをなんとかする
はじめに
OSX YosemiteにHomebrewでnkfやw3mなどを入れているのですが、
$ man nkf
とすると
/usr/bin/groff: can't find `DESC' file /usr/bin/groff:fatal error: invalid device `nippon'
と言われて表示できません。しかし、こちらで紹介されている通りにやると、nkfのmanを日本語で閲覧することができました。
Homebrewでgroffをインストール
こちらで紹介されている通りに、Homebrewでgroffをインストールします。
$ brew tap homebrew/dupes
$ brew install groff
/etc/man.confの修正
$ sudo -e /etc/man.conf
で以下のように修正します。
--- /etc/man.conf.orig 2014-09-10 09:16:35 +++ /etc/man.conf 2014-12-03 22:10:24 @@ -92,7 +92,7 @@ # TROFF /usr/bin/groff -Tps -mandoc -c NROFF /usr/bin/groff -Wall -mtty-char -Tascii -mandoc -c -JNROFF /usr/bin/groff -Tnippon -mandocj -c +JNROFF /usr/local/bin/groff -Dutf8 -Tutf8 -mandoc -mja -E EQN /usr/bin/eqn -Tps NEQN /usr/bin/eqn -Tascii JNEQN /usr/bin/eqn -Tnippon @@ -102,8 +102,8 @@ PIC /usr/bin/pic VGRIND GRAP -PAGER /usr/bin/less -is -BROWSER /usr/bin/less -is +PAGER /usr/bin/less -isr +BROWSER /usr/bin/less -isr HTMLPAGER /bin/cat CAT /bin/cat #
これで
$ man nkf
とすると
nkf(1) nkf(1 NAME nkf - ネットワーク用漢字コード変換フィルタ SYNOPSIS nkf [-butjnesliohrTVvwWJESZxXFfmMBOcdILg] [file ...] DESCRIPTION nkf はネットワークでメールやニュースの読み書きをするために作られた、漢字コードの変換フィルタであ る。 ...
このように日本語で表示されるようになりました。
w3mのmanをUTF-8に変換
ところが、
$ man w3m
とすると文字化けします。/usr/local/opt/w3m/share/man/ja/man1/w3m.1
がEUCなのが原因なので、UTF-8に変換します。
$ nkf -w --overwrite /usr/local/opt/w3m/share/man/ja/man1/w3m.1
これで、w3mのmanも読めるようになりました。
Lubuntu 14.04のTcl/Tk 8.6とrbenvに入れたRuby 2.1.5でRuby/Tkを使う
はじめに
前の記事で「現時点でRuby/Tkは8.6には対応してない」と書いたばかりなのですが、こちらのサイトでパッチが公開されていて、Ruby/TkでTcl/Tk 8.6が使えます。(注: Ruby 2.2.0ではパッチが必要なくなったようです。こちらを参照のこと。12/02/15追記)
Tcl/Tk 8.6のインストール
apt-get
でtk-dev
をインストールするとtk8.6-dev
が入ります。
$ sudo apt-get install tk-dev
パッチを当てて、Ruby 2.1.5をビルド
こちらのサイトから、「Ruby-2.1.3 p242用パッチ」tk-diff-ruby-2.1.3-p242.gz
を、ありがたくいただいてきます。2.1.3用となってますが、2.1.5でも問題無いようです。
ruby-buildにはパッチを当てる機能があるのですが、stripのレベルを指定できないようなので、今回はruby-buildを使いません。まず、Rubyの公式サイトから、Ruby 2.1.5のソースruby-2.1.5.tar.gz
をダウンロードし、以下のようにパッチを当ててビルドします。
$ tar zxf ruby-2.1.5.tar.gz $ cd ruby-2.1.5 $ zcat ../tk-diff-ruby-2.1.3-p242.gz | patch -p1 $ ./configure --prefix=$HOME/.rbenv/versions/2.1.5-tk8.6 \ --with-tcltkversion=8.6 \ --with-tcl-lib=/usr/lib/x86_64-linux-gnu \ --with-tk-lib=/usr/lib/x86_64-linux-gnu \ --with-tcl-include=/usr/include/tcl8.6 \ --with-tk-include=/usr/include/tcl8.6 \ --enable-pthread $ make
ビルドが問題なく完了したら、インストールして有効化します。
$ make install
$ rbenv global 2.1.5-tk8.6
$ rbenv rehash
サンプルを動かしてみます。
$ ruby ext/tk/sample/cd_timer.rb 10
うまく動きました。
最後に
記事のタイトルが長い…
Lubuntu 14.04にrbenvとruby-buildで入れたRuby 2.1.5でRuby/Tkを使う
はじめに
ちょっとした数値データを処理してグラフを表示するためにRuby Gnuplotを使っていたのですが、ここを見てRuby/Tkの素晴しさを知り、早速Lubuntu 14.04にrbenvとruby-buildで入れたRuby 2.1.5でRuby/Tkを使おうとしたところ、環境構築にてこずりました。
Tcl/Tk 8.5のインストール
まず、Tcl/Tkをインストールします。apt-get
でtk-dev
をインストールするとtk8.6-dev
が入りますが、現時点でRuby/Tkは8.6には対応してないそうなので(注: パッチを当てると使えます。こちらを参照のこと。11/23/14追記)(注: Ruby 2.2.0ではパッチが必要なくなったようです。こちらを参照のこと。12/02/15追記)、以下のようにtk8.5-dev
を入れます。
$ sudo apt-get install tk8.5-dev
Ruby 2.1.5のインストール
次にRubyとRuby/Tkをrbenvとruby-buildでインストールします。普通は
$ rbenv install 2.1.5
だけでいいと思うのですが、今回はこのままではTcl/Tkのヘッダやライブラリを認識せず、Ruby/Tkがコンパイルされません。ここでだいぶ時間をロスしました。こちらのサイトでは、必要なライブラリにシンボリックリンクを張って対応しています。それでも良いと思いますが、/usr/lib
にパッケージシステム管理外のシンボリックリンクがあるのは何となく気持ち悪いので、以下のようにconfigue
のオプションでどうにかします。32bitの場合はx86_64-linux-gnu
をi386-linux-gnu
などに適宜変更してください。
$ RUBY_CONFIGURE_OPTS="--with-tcltkversion=8.5 \ --with-tcl-lib=/usr/lib/x86_64-linux-gnu \ --with-tk-lib=/usr/lib/x86_64-linux-gnu \ --with-tcl-include=/usr/include/tcl8.5 \ --with-tk-include=/usr/include/tcl8.5 \ --enable-pthread" rbenv install 2.1.5 -v $ rbenv global 2.1.5 $ rbenv rehash
私の環境では、これでRuby/Tkがインストールされました。サンプルを動かしてみます。
$ ruby ext/tk/sample/24hr_clock.rb
うまく動いているようです。
最後に
そもそも拡張TkパッケージPlotchartを使いたくてがんばっているわけですが、まだ使えていません。
$ sudo apt-get install tklib
という感じでPlotchartを入れたのですが、サンプルを実行すると下記のようにエラーになります。
$ ruby ext/tk/sample/tkextlib/tcllib/plotdemos1.rb /home/gzalt/.rbenv/versions/2.1.5/lib/ruby/2.1.0/tk/package.rb:86:in `rescue in require': TkPackage attempt to provide package Plotchart 2.1.0 failed: package Plotchart 2.0.1 provided instead (RuntimeError)
道のりは長い…
Plotchartのバグ(23/11/14追記)
ここによると、どうもPlotchartのバグのようです。下記のように修正します。
--- /usr/share/tcltk/tklib0.6/plotchart/plotchart.tcl.orig 2013-03-14 17:01:30.000000000 +1100 +++ /usr/share/tcltk/tklib0.6/plotchart/plotchart.tcl 2014-11-23 19:11:59.456417506 +1100 @@ -2849,4 +2849,4 @@ # Announce our presence # -package provide Plotchart 2.0.1 +package provide Plotchart 2.1.0
サンプルを動かしてみます。
$ ruby ext/tk/sample/tkextlib/tcllib/xyplot.rb
うまく表示されました。
Yosemiteで動かなくなったCUPS-PDFの代わりにVipRiserを使う
はじめに
Wineskinという素晴しいソフトウェアのおかげで、とても有名な2D CADであるJw_cadをOSX上で使用することができます。この場合、OSXに接続されたプリンタから印刷可能なのですが、OSXの通常の印刷ダイアログは表示されないので、PDFに出力したい時に困ります。これまでは、Homebrewでインストールした仮想プリンタCUPS-PDFを使っていたのですが、Yosemiteで動かなくなってしまいました(詳しくはここ)。しかし、VipRiserという別の仮想プリンタがうまく動きました。
VipRiserのインストール
VipRiserのサイトから、VipRiser.zipをダウンロードして中のVipRiser.appをアプリケーションフォルダにコピーするだけです。
仮想プリンタの登録
VipRiser.appを実行すると最初にプリンタドライバのインストールが行われます。ドライバのインストール後に表示されるダイアログに従って、「システム環境設定」→「プリンタとスキャナ」で、「+」をクリックしてPrint to VipRiserを下記のように登録します。
CUPS-PDFを使ったことがあると、既にPrint to VipRiserが登録されていたりしますが、一度「-」で削除して、再度登録した方が無難です。これで、VipRiserを起動すれば、仮想プリンタが使えるようになります。下記のようにメニューバーのアイコンからPDFの出力先を指定できるので、CUPS-PDFより便利です。
下記のようにWineskin上のJw_cadからもPDFに出力できるようになりました。
最後に
VipRiserのアイコンは何なのだろう…