余白の書きなぐり

aueweのブログ

sshfsでリモートのディレクトリをマウント

リモートのデータをローカルにマウントする意義

多くの場合リモートの環境は貧弱で、そして解析すべき豊富なデータが眠っている。 一方ローカルの環境は最強だが、解析すべきデータは無い。 このミスマッチを解消するために、リモートの有用なディレクトリをローカルにマウントする作戦。筋が良い。

sshfsを使えばこの作戦が実行できる。 つまり @dokoka という名のリモートサーバー にある /achira/ ディレクトリを、 ローカルの空ディレクトリ /kochira/ にマウントできる。

何より便利なのは、ローカルにマウントした後、リモートの /achira を直接編集すると、ローカルの /kochira/ に即座に反映されるところ。 逆に、ローカルで /kochira/ を編集すると、リモートの /achira/に反映される。

具体的な効能としては、たとえばローカルにしかインストールされていないリッチなソフトでリモートのファイルを解析できる。 あるいはローカルの .zshrc や .vimrc の下でリモートのファイルを編集できる。 他には、リモートで gnuplot して得た pdf ファイルをローカルで直接開けるようになった。 リモートには X-window-system が無いので、今まで毎度毎度scpしていたが、今後は scp せずに済む。 ありがたい。

sshfsのインストール

LinuxMintならaptで一撃だった。 ローカルで以下のコマンドを実行すればよい。

$ sudo apt-get install sshfs

リモートのサーバーについては何も設定しなくてよい。

sshfsの使い方

前提として、リモートの @dokoka サーバーに ssh でアクセスできるとする。 sshfsを使うには、ローカルで以下のコマンドを実行すればよい。 /kochira/achiraは、適宜/home/auewe/datadir~/datadirのように読み替えること。

$ mkdir /kochira
$ sshfs username@dokoka:/achira /kochira
### scpでリモートのディレクトリをコピーするのと同じ構文

これで @dokoka という名のリモートサーバー にある /achira/ ディレクトリを、 ローカルにある空のディレクトリ /kochira/ にマウントできた。

アンマウントするには、ローカルで以下のコマンドを実行。

$ fusermount -u /kochira

参考 sshで他マシンのファイルシステムをマウントするには

はてなブログにLaTeXで数式を書く (Markdown記法用)

追記 2014/05/10 この記事は古いので、 はてなブログの LaTeX 数式表示がデフォルトで MathJax 化された を参照してください。

MathJaxを導入したら、はてなブログがMarkdown+LaTeXという夢の様な環境になって便利という話。

はてな記法で数式を書く

以前は以下の方法ではてなブログに数式を書いていた。 いわゆるはてな記法を使う方法。


[tex:{ \displaystyle
b_n = \sum_{m=0}^{N-1} a_m
}] 

{ \displaystyle
b_n = \sum_{m=0}^{N-1} a_m
}


この方式では数式が画像に変換されてしまい、よくない。

MathJaxで数式を書く

画像化するのではなく、javascriptでフォントの位置とサイズを整えて数式を表示するMathJaxという仕組みがある。 MathJaxはすでに有力な標準仕様で、画像化するより MathJaxを使ったほうが綺麗らしい ので乗り換えた。 LaTeXコマンドをそのままブログに書ける ので、かなり便利。 

導入の詳細は はてなブログで MathJax \( \alpha^{\beta^{\gamma}} \) (←リンク名にも数式が使えるのだ) や MathJaxでの数式表示を試す を参照。 要するにはてなブログのサイドバーに

<script
  type="text/javascript"
  src="https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
></script>

と書くだけ。むっちゃ簡単。

文中の数式は、以下のように\\(\\)で数式部を挟む。


京都北山 \\( \alpha \\) ステーション!

京都北山 \( \alpha \) ステーション!


普通のLaTeXでは$ \alpha $ とするけれど、 MathJaxでは $ 記号が推奨されない。 そのかわり、普通のMathJaxでは\( \alpha \)とするのが推奨されている。 ただしこのブログは Markdown で書かれてるのでエスケープを2重にしなければならない。 つまり\\( \alpha \\)とする。 エスケープ関連の問題はややこしいので追記に書いた。

別行立ての数式を書く時はalign環境を使う。


\begin{align\*}
b_n = \sum_{m=0}^{N-1} a_m
\end{align\*}

\begin{align} b_n = \sum_{m=0}^{N-1} a_m \end{align}


算数のおべんきょうが捗る。

2014/02/17 追記

id:tosh1ki さんに指摘されたので追記します。
参考 : はてなブログ(Markdown記法)+MathJaxの記入例

MathJax環境内では _,*[]() の文字をエスケープしないと、 数式化されない場合がある。一例を上記ブログから引用する。

アンダースコアを全てエスケープした場合
\\(
\mathcal{Z}[x\_{n}]=\sum\_{n=-\infty}^{\infty} x\_{n}z^{-n}\\
\\)

\( \mathcal{Z}[x_{n}]=\sum_{n=-\infty}^{\infty} x_{n}z^{-n}\ \)

↑正しく数式化された。

アンダースコアのエスケープを外した場合
\\(
\mathcal{Z}[x_{n}]=\sum_{n=-\infty}^{\infty} x_{n}z^{-n}\\
\\)

\( \mathcal{Z}[x{n}]=\sum{n=-\infty}^{\infty} x_{n}z^{-n}\ \)

↑数式化されない!!

きちんとエスケープしましょう。

C言語からLAPACKを呼んで逆行列を求める(LU分解する)

数値解析の授業で逆行列は求めちゃダメって言われたけど、気にしない気にしない。

実行列の逆行列を求める

FortranDGETRF でLU分解した後、 DGETRI逆行列を求める。

/*
 * hoge.c
 * SIZE*SIZE型の実行列の逆行列を計算
 * 元の行列は
 *  (2 3  )
 *  (1 0.5)
 */

#define SIZE 2
#include <stdio.h>

int main(void){
  int    m       = SIZE ; // 行のサイズ
  int    n       = SIZE ; // 列のサイズ
  int    lda     = SIZE ; // mと同じ値
  double A[SIZE*SIZE]   ; // m x n の行列成分。この行列の逆行列を求める。
  A[0] = 2.0 ;A[2] = 3.0;
  A[1] = 1.0 ;A[3] = 0.5;
  int    info           ; // 計算が成功すれば0を返す
  int    ipiv[SIZE]     ; // 要素数はm,nのうち小さい方とする
  int    lwork   = SIZE ; // nと同じ値
  double work[SIZE]     ; // 要素数はlworkと同じ値

  // LAPACKのdgetrfサブルーチンを呼んで、行列AをLU分解
  // 引数は全て参照渡し
  dgetrf_( &m, &n, A, &lda, ipiv, &info);

  // LU分解後の行列から逆行列を求める
  // 逆行列は元の配列Aに入る
  dgetri_( &n, A, &lda, ipiv, work, &lwork, &info);

  printf("%+8.5lf %+8.5lf\n", A[0], A[2]);
  printf("%+8.5lf %+8.5lf\n", A[1], A[3]);
}

コンパイルと実行結果

$ gcc hoge.c -llapack -lblas -lm
$ a.out
-0.25000 +1.50000
+0.50000 -1.00000

引数の詳細については、下手な解説を見るより dgetrfdgetri を読むのが一番わかりやすい。

CとFortranの配列形式の違いについては、 CとFortranで行列の添字が異なる点への注意喚起 に書いた。

複素行列の逆行列を求める

Fortarnの ZGETRF でLU分解した後、 ZGETRI逆行列を求める。 実行列の場合との違いは、行列Aと配列workの型がdoubleからdouble _Complexに変わったところ。

/*
 * hoge.c
 * SIZE*SIZE型の複素行列の逆行列を計算
 * 元の行列は
 *  (0.5+i 1.0+0.5i)
 *  (2.0   1.0     )
 */

#define SIZE 2   // 2*2型の行列
#include <stdio.h>
#include <complex.h>

int main(void){
  int    m       = SIZE        ; // 行のサイズ
  int    n       = SIZE        ; // 列のサイズ
  int    lda     = SIZE        ; // mと同じ値
  double _Complex A[SIZE*SIZE] ; // m x n の行列成分。この行列の逆行列を求める。
  A[0]= 0.5+I ; A[2]= 1.0+0.5*I;
  A[1]= 2.0   ; A[3]= 1.0;
  int    info                  ; // 計算が成功すれば0を返す
  int    ipiv[SIZE]            ; // 要素数はm,nのうち小さい方とする
  int    lwork   = SIZE        ; // nと同じ値
  double _Complex  work[SIZE]  ; // 要素数はlworkと同じ値

  // LAPACKのzgetrfサブルーチンを呼んで、行列AをLU分解
  // 引数は全て参照渡し
  zgetrf_( &m, &n, A, &lda, ipiv, &info);

  // LU分解後の行列から逆行列を求める
  // 逆行列は元の配列Aに入る
  zgetri_( &n, A, &lda, ipiv, work, &lwork, &info);

  printf("%+8.5lf%+8.5lfI %+8.5lf%+8.5lfI\n", creal(A[0]), cimag(A[0]), creal(A[2]), cimag(A[2]));
  printf("%+8.5lf%+8.5lfI %+8.5lf%+8.5lfI\n", creal(A[1]), cimag(A[1]), creal(A[3]), cimag(A[3]));
}

コンパイルと実行結果

$ gcc hoge.c -llapack -lblas -lm
$ a.out
-0.66667-0.00000I +0.66667+0.33333I
+1.33333+0.00000I -0.33333-0.66667I

引数の詳細は zgetrfzgetri を読むべし。 またCとFortranの配列形式の違いについては、 CとFortranで行列の添字が異なる点への注意喚起 を読むべし。

Linux Mint にVim7.4をインストール

正式なaptリポジトリVimはVer7.3で残念な感じだけど、ちょっと頑張ればVer7.4を入れることができる。

$ sudo add-apt-repository ppa:fcwu-tw/ppa
$ sudo apt-get update
$ sudo apt-get install vim

これでインストールできる。簡単だった。バージョンの確認は

$ vim --version |head
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Aug 12 2013 09:20:12)
Modified by pkg-vim-maintainers@lists.alioth.debian.org
Compiled by buildd@
...以下はコンパイルオプションの羅列...

+luaは嬉しいけど、-python3は悲しい。

Gvimもインストールする場合は、更に以下のコマンドを実行

$ sudo apt-get install vim-gtk

Ver7.4が使いたくて今まで自力でコンパイルしてきたけど、こんなに簡単に入るのか。あーあ


参考:
http://linuxg.net/how-to-install-vim-7-4-on-ubuntu-13-10-13-04-12-04-linux-mint-16-15-13-and-debian-sid/
https://gist.github.com/usufu/6398966

仮想環境のLinux MintにVmware Tools入れる時にkernel headersが見つからない問題

VMware Player にゲストOSとして Linux Mint を入れて、そこに VMware Tools をインストールするという話。 VMware Toolsを入れれば、仮想環境Windowを全画面にできるし、クリップボードが ホストOSとイケイケになるし、ディレクトリを共有できるし、かなり便利だ。

インストールの手順としては、ゲストOSの Linux Mint を立ち上げて、上タブの 仮想マシン-VMware Toolsのインストールをクリックすれば、DVDがマウントされる。 そのDVDの中に入っている VMware-Tools-8.8.6-12345.tar.gz のような圧縮ファイルを解凍すれば vmware-tools-distrib というディレクトリが生成される。 その中に vmware-install.pl というperlスクリプトが入っている。

このvmware-install.plをsudoで実行して、エンターキーを押して進んでいくと、途中で kernel headersのpathがどうたらこうたらで怒られてストップする(ことがある)。

解決方法

まず uname -aして3.8.0-25-genericのような文字列を探す。

$ uname -a
Linux auewe-virtual-machine 3.8.0-25-generic #37-Ubuntu SMP Thu Jun 6 20:47:30 UTC 2013 i686 i686 i686 GNU/Linux

/usr/src/3.8.0-25-generic 以下にシンボリックリンクを貼る

/usr/src/linux-headers-3.8.0-26-generic/include/generated/uapi/linux/version.h
という実体へのシンボリックリンク
/usr/src/linux-headers-3.8.0-26-generic/include/linux/version.h
に作成する。

$ sudo ln -s \
/usr/src/linux-headers-3.8.0-26-generic/include/generated/uapi/linux/version.h \
/usr/src/linux-headers-3.8.0-26-generic/include/linux/version.h

最後に vmware-install.plを実行

$ sudo perl vmware-install.pl

メモ:
export LANG=en は意味なかった。

Python3の計算結果をGnuplotでグラフ化(subprocess Popenを使う)

ディスプレイにグラフを表示させる

pythonからgnuplotを使う上で、これが最も簡単な方法。

from subprocess import call
call( ["gnuplot", "-e", "plot sin(x); pause -1"])

qを押せばグラフは消える。

グラフをファイルに保存

gnuplotの設定は長くなるので、 gnuplotCommand という文字列にまとめた。

from subprocess import call

gnuplotCommand ='''
set terminal png;
set output "sin.png";
plot sin(x);
'''

call( [ "gnuplot", "-e", gnuplotCommand])

Pythonで計算したデータをプロット

これが案外ハマる。 UNIX系なら echo で計算結果を標準出力に流して PIPE で gnuplot に食わせれば良いけれど、 Windowsでは echo が使えない(エラーが出る)。 代わりに Gow に含まれる printf 関数を使った。

from subprocess import Popen, PIPE

data = '''
1 5
2 10
3 15
'''

gnuplotCommand = '''
plot '-' ;
pause -1
'''

printData = Popen( [ 'printf', data], stdout=PIPE)
Popen( [ 'gnuplot', '-e', gnuplotCommand], stdin=printData.stdout)

シェルスクリプトからPython3に移行する人のために ~標準入出力・ファイル管理編~

汚いシェルスクリプトを保守する作業に嫌気がさしてきたので、Python3に乗り換えた。 せっかくなので必要になった知識を整理しておく。 同じようにシェルスクリフトから乗り換える人の役に立つと思う。

とりあえず IO 関連とファイル名の操作が重要な気がしたので、そのへんから書き始める。

環境変数の取得

# Python
import os
home = os.environ.get('HOME', "")

カレントディレクトリのパスを取得

# Bash ... もともと $PWDに入っているが
current_path=`pwd`
# Python
import os
current_path = os.getcwd()

# スクリプトのあるディレクトリの絶対パスは
script_path = os.path.abspath(os.path.dirname(__file__))

ファイル名とディレクトリ名の結合

シェルスクリプトではファイルやディレクトリを文字列として扱い、 適当に切ったり貼ったりしていたけれど、 Pythonでは os.path.join を使って行儀よく扱う必要がある。

# Bash
tmp_dir="$HOME/tmp"
tmp_file="${tmp_dir}/tmp.txt"
# Python
import os
home = os.environ.get('HOME', "")
tmp_dir  = os.path.join( home , "tmp"   )
tmp_file = os.path.join( tmp_dir, "tmp.txt")

# 諸事情でパスの区切り文字を変更したくなったら
tmp_dir_unix = tmp_dir.replace(os.path.sep, '/')   # /path/to/tmp_dir
tmp_dir_win  = tmp_dir.replace(os.path.sep, '\\')  # path\to\tmpdir

ディレクトリの作成

「同名のディレクトリの存在を確認して、無ければ作成」という定形作業

# Bash
if [ ! -d ${tmp_dir} ] ;then
    mkdir ${tmp_dir}
fi
# Python

import os
if not os.path.exists(tmp_dir):
  os.makedirs(tmp_dir)  # 再帰的作成

ディレクトリの削除

いくつか方法があるけれど、一番強力なやつは

# Bash
rm -rf ${tmp_dir}
# Python
import shutil
shutil.rmtree(tmp_dir)

ファイルへの書きこみ

# Bash
echo "hoge\npiyo" > ${tmp_file}
#Python
import codecs
f_out = codecs.open(tmp_file, "w", "utf-8")
print("hoge\npiyo", file=f_out)
f_out.close()

ファイルの読みこみ

# Bash
cat ${tmp_file}
# Python
import codecs
f_in = codecs.open(tmp_file, "r", "utf-8")
for line in f_in.readlines():
  print(line)
f_in.close()

外部プログラムの実行とパイプ処理

# Bash
cat ${tmp_file} | wc -l
# Python
from subprocess import Popen, PIPE
cat = Popen(["cat", tmp_file],                   stdout=PIPE)
wc  = Popen(["wc" , "-l"]    , stdin=cat.stdout, stdout=PIPE)
output = wc.stdout
for line in output:
  print(line)