samtools 1.7 で `error: ‘SAMTOOLS_VERSION’ undeclared (first use in this function)`

使っていた環境に samtools が入っていなかったので入れようとしたら、$ make でタイトル通りのエラーが。

<samtools のルート>/misc/*.c での SAMTOOLS_VERSION の参照がエラーになる。

SAMTOOLS_VERSIONmake の最初の方で生成される <samtools のルート>/version.h の中で #define SAMTOOLS_VERSION "1.7" のように定義されている。

ところが、上記 <samtools のルート>/misc/*.c では #include "version.h" としていて、ヘッダがある正しいディレクトリと1階層ずれている。

$ make を一回走らせてエラーを食らった後、$ cp version.h misc/version.h として再度 $ make でOK。

(GitHub の Issue 立てろ)

Typora でエディタ(編集領域)の幅を広げる[Mac]

Kobito -> Bear -> Typora とマークダウンエディタを渡り歩いてきたが、現状 Typora にはとても満足していて、当分より良いマークダウンエディタ探しの旅には出なくて済みそう。Typora を使っていると期待しない動作や編集したファイルの一部が欠落する(!)といった問題挙動(再現性を詳しく調査したわけではないので自分のせいかもしれない)があるにも関わらずこの満足度というのはすごいと思う。

個人的には、あと

  • PDF を含めた(ローカルの)ファイルの添付機能(これは Bear にあった)
  • 埋め込み HTML のサポート(Plotly とかの図を貼り付けたい)

が追加されれば完璧といった感じ。後者は Issue でもけっこう激しく議論されているのでそのうちサポートされるかも(もっとも製作者の哲学としては不要との見解らしいが)。

さて、Typora はデフォルトだと(特に 15インチ MacBookPro を解像度最大で使っている自分のような人間にとっては)編集領域がけっこう狭い。この幅は通常、

${HOME}/Library/Application\ Support/abnerworks.Typora/themes/github.css

中の #writemax-width: 860px のように定義されている。この値を自由に変えればそのまま反映される。下記リンクを参考にした。

github.com

コマンド一発でリモートの Jupyter をローカルで開く

(余談: Jupyter Notebook か Jupter Lab か)

自分は最初 Notebook から入って途中 Lab の方がよくない?となったけれど最終的に Notebook でいいやとなった。

その理由は、

  • [Lab の方がよくない?]

    • Lab だと複数の Notebook を開いても1つのブラウザタブで済む
    • リモートシェルを Lab 内で起動できるからローカルのターミナルで ssh する必要がない(ターミナルから解放される)
    • あとは UI が洗練されている
  • [やっぱ Notebook でいいや]

    • 1つの Notebook を1つのタブでそれぞれ開くことは自分にとっては苦ではなかった(むしろブラウザのタブ移動コマンドで Notebook を移動できるので楽)
    • なんだかんだローカルのターミナルの方が操作しやすい。Alacritty + tmux で OK。あと Lab のターミナルは emacs 開いたりするとなぜか全部の文字に下線が引かれたりする(ls すると直る。なぜだ)
    • UI よりも使いやすさ(別に Notebook も UI 悪くない)。Lab はデフォルトのフォントが等幅フォントなのがとても良いが、別に Notebook でも custom.css をいじれば変えられる
    • そして何よりも大事なのが、Notebook の方が圧倒的に動作が軽い。これが一番の決め手で、Plotly とかで大きいデータの図を書くと Lab は途端に動作がものすごく重くなって、使い物にならなかった

なので以下では Jupyter Notebook を想定しているが、基本的に jupyter notebookjupyter lab に変えれば同じはず。

コマンド一発じゃないバージョンだとどうなるか

少なくとも以下の手順を踏む必要がある。

  1. リモートで Jupyter を実行
  2. ローカルでポートフォワードする ssh を実行
  3. ブラウザでローカルホストの URL を開く

具体的には以下の通り。

まずはリモートでポートフォワードを含めた諸々の Jupyter Notebook の設定。

Running a notebook server — Jupyter Notebook 6.0.0.dev0 documentation

後は(最初の方は上と被っているが)以下を参考にして、

coderwall.com

次のような流れで Jupyter をローカルのブラウザ上で実行することができる。

$ ssh ホスト名
> jupyter notebook
(別のターミナルウィンドウやタブを開く)
$ ssh -N -f -L ローカルでのポート番号:localhost:リモートのJUPYTERで設定したポート番号 ホスト名
(ブラウザを開いて "http://localhost:ローカルでのポート番号" にアクセス)

これを Jupyter Notebook を開くために毎回実行するのはすごくめんどくさい。ターミナルのタブも2つ使うし。

シェルスクリプトにまとめてコマンド一発で開く

結論から述べると、以下のようなスクリプト(remote_jupyter.sh とする)を書く (Mac 環境)。コードの中で日本語になっている箇所は適宜自分のものに書き換えることに注意。

HOST_NAME=${1:-任意のSSHホスト名}
PORT_ID_LOCAL=${2:-任意のローカルポート番号}
PORT_ID_REMOTE=${3:-上で指定したリモートJupyterのポート番号}

# 指定されたリモートホストで既に Jupyter が動いているか確認して、無かった場合にだけ起動する
N_JUPYTER_LAB_PROC=$(ssh ${HOST_NAME} "ps x" | grep "jupyter" | wc -l)
if [ ${N_JUPYTER_LAB_PROC} = 0 ]
then
    ssh ${HOST_NAME} "source ~/.bash_profile; nohup jupyter notebook >/dev/null 2>&1 &"
fi

# SSHでポートフォワードして、接続後に chrome のタブを開く
ssh -N \
    -f \
    -L localhost:${PORT_ID_LOCAL}:localhost:${PORT_ID_REMOTE} \
    -o PermitLocalCommand=yes \
    -o LocalCommand="open -a '/Applications/Google Chrome.app' http://localhost:${PORT_ID_LOCAL}" \
    ${HOST_NAME}

アピールポイントとしては、

  1. Jupyter を実行したいリモート先(とローカルで使用するポート番号)を指定できる(SSHホスト名は ~/.ssh/configHostNameUser などが指定されている必要がある)
  2. 最初に既に存在する Jupyter プロセスを確認することで、余剰プロセスを起動することを防げる
  3. 自動でブラウザのタブを開いてくれる

具体的な使い方は、上のスクリプトを記述したファイルを

$ bash script_file.sh [任意のSSHホスト名] [任意のローカルポート番号] [上で指定したリモートJupyterのポート番号]

のように(必要に応じて引数を指定して)実行するだけ。

ただし、一度接続した ssh はターミナルを閉じたりしても生き残り続ける(インターネット接続が切れたりすると死ぬ)ので、ssh プロセスが生きている限りはブラウザのタブを閉じてもアクセスし直すだけで大丈夫。なのでローカルホストの URL (http://localhost:ポート番号) をブックマークしておくと便利。ssh が死んだ時(これは URL を開いた時の表示で分かる)にだけ再度スクリプトを実行すれば良い。

リモートの Jupter を SGE や SLURM のようなスケジューラの上で走らせたい場合

共用のクラスターマシンとかだとコマンドを直走りさせるのは嫌われる行為なので、qsubsbatch を使って Jupyter Notebook を実行したい。

SGE だと普通に、

#!/bin/bash
#$ -N jupyter_nb
#$ -o sge.log
#$ -j y
#$ -S /bin/bash
#$ -cwd
#$ -V
#$ -q ノード名
#$ -pe smp 4

jupyter notebook

のようなスクリプト(run_jupyter.sh という名前でホームディレクトリに置いておく)を書いて qsub で投げるだけで良いので、上の remote_jupyter.sh

nohup jupyter notebook >/dev/null 2>&1 &

の部分を

qsub run_jupyter.sh

に変更するだけで対応できる。

一方で SLURM だとそもそも Jupyter Notebook を起動する際に PermissionError: [Errno 13] Permission denied: '/run/user/XXXX のようなエラーが出る。さらに、リモートの localhost で Jupyter Notebook を起動するとなぜかローカルから Port Forwarding できなくなってしまう。

これらの問題を回避するために、

#!/bin/bash
#SBATCH -p ノード名
#SBATCH -J jupyter_nb
#SBATCH -o sbatch_stdout
#SBATCH -e sbatch_stderr
#SBATCH -n 1
#SBATCH -N 1
#SBATCH -c 4
#SBATCH -t 24:00:00

jupyter notebook --ip=0.0.0.0

のようなスクリプト (run_jupyter.sh; SGE と同じくホームディレクトリに置いておく) を用意して、上の remote_jupyter.sh

nohup jupyter notebook >/dev/null 2>&1 &

の部分を

unset XDG_RUNTIME_DIR; sbatch run_jupyter.sh

に変更する。

Automatorシェルスクリプト実行をアプリケーション化する

自分はわざわざターミナルを開いてシェルスクリプトを実行するのも面倒なので、MacAutomatorシェルスクリプトを実行するアプリケーションを作って Dock に置いている。

具体的には、

nohup bash remote_jupyter.sh > /dev/null 2>&1 &

というシェルスクリプトを実行する Application を作って Dock に置いている。

github.com

記事中のスクリプトは↑のレポジトリにも置いてある。

"腸に効く"アイスは可能か?(細菌の定着の観点から)

以前とある事情から少し調査した内容(と一部私見)。

  • 胃腸の温度を冷やすと、消化機能が低下するらしい。もしかしたら"腸内バリア機能"も?(要出典)
    • -> 細菌が定着しやすくなる可能性はある?

  • Ericsson, A., Personett, A., Turner, G., Dorfmeyer, R. & Franklin, C. Variable Colonization after Reciprocal Fecal Microbiota Transfer between Mice with Low and High Richness Microbiota. Frontiers Microbiol 8, (2017).
    • FMTにおいてfrozen sampleはfresh fecesと同様の効果があった
      • frozenの方が良いわけではない
    • FMTはそもそも最初に抗生物質で元々いる細菌叢を崩してから行うので、単なる細菌の経口摂取で効果があるかは不明
    • frozenだとサンプル調整が楽らしい
  • David, L. et al. Diet rapidly and reproducibly alters the human gut microbiome. Nature 505, 559–563 (2014).
    • 食事由来の細菌は長期的には細菌叢の変化をもたらさないが、当日などの短期的には遺伝子発現を含めて変化させる
      • 腸内で増えることは増えるが、どうやって定着させるかが結局は問題
  • Donaldson, G., Lee, S. & Mazmanian, S. Gut biogeography of the bacterial microbiota. Nat Rev Microbiol 14, 20–32 (2016).
    • どの菌種が増えるかはprebiotics (それぞれの菌種が必要とする栄養)に依存する
    • ヒト腸内細菌叢の形成においては、乳などによってprebioticsがコントロールされている
      • BifidobacteriumとBacteroidesが寡占的となる
    • ヒト腸内には菌種組成を安定に保つ何らかの機構が存在する
      • 部位ごとに局所的にそれぞれ栄養を制限することで菌種組成を制御している
      • 抗生物質などで菌種組成が崩れた時に元に戻すための、細菌の保管場所のようなものが存在する
      • それならば、FMTで菌種組成が変わるのはなぜ?抗生物質は一応組成を変えることは変えるということか?
  • Anselmo, A., McHugh, K., Webster, J., Langer, R. & Jaklenec, A. Layer‐by‐Layer Encapsulation of Probiotics for Delivery to the Microbiome. Adv Mater 28, 9486–9490 (2016).
    • 多糖類のカプセルで細菌を包むと腸に届くまでに死ににくい
      • そりゃそうだ
    • 1時間後の増殖率しか見ていないので、定着は無理だったか
  • Chassaing, B. et al. Dietary emulsifiers impact the mouse gut microbiota promoting colitis and metabolic syndrome. Nature 519, 92–96 (2015).
    • 乳化剤が炎症を起こす
      • アイスにも入っていることが多い
  • Roberfroid, M. Prebiotics: the concept revisited. The Journal of nutrition (2007).
    • prebiotics = (腸内の)細菌の増殖を促進させるもの
    • トランスガラクト−オリゴ糖やイヌリン
  • Sanders, M. & Marco, M. Food Formats for Effective Delivery of Probiotics. Food Sci Technology 1, 65–85 (2010).
    • prebiotics + probioticsが効果を促進する
  • Lourens-Hattingh, A. & Viljoen, B. Yogurt as probiotic carrier food. Int Dairy J 11, 1–17 (2001).
    • ヨーグルトだと酸に耐性のない菌は入れにくい
    • Bifidobacteriumの増殖には37度が最適
      • アイスだと当然だが真逆

Bear: Markdownエディタ

Bearとかいう素晴らしいものを見つけてしまった。

Kobitoと比較した場合、個人的に特筆すべき点は、

  • UIがきれい
  • Markdownを書いたそばから解釈して修飾してくれる
  • メモ一覧にピン機能がある
  • メモのリンクが可能
  • チェックボックスを書ける
  • PDFその他ファイルを埋め込める、さらにAcrobatで開けるのでハイライト・コメント編集も可能
  • (Pro版だと)PDFにエクスポートできる(未確認)

すごい。ただ、現時点では以下のような至らない点もいくつかある。

  • 数式、表の入力ができない(LaTaXiTでPNGに出力してそれを貼り付けることはできる)
  • バックアップをどうするかまだよく分からない
  • Pro版は有料

数式と表は使いたいので少し痛いが、それを補っても余りあるほどのメリットがBearにはある。

すでにいくつかのメモをKobitoから以降したが、今後機能が順調に充実していけばおそらくBearに完全以降するだろう(このブログも怪しいと一瞬思ったが、短いメモや利用頻度の低いメモが一覧を圧迫するのが嫌いなので、そういったものや、今回のような一過性のメモについては今後もこちらに書くことになるだろう)。

あと余談だが、Bearはググラビリティが低すぎる。。。ググラビリティと使用率に相関があったりしないかなと考えたりするのだが、見つけたい人はちゃんと見つけるので大丈夫か。

Git(Hub) の使い方

レポジトリの作成・管理

  • まだどこにも存在しない新規 git レポジトリをローカルに作成
    • $ cd ディレクトリ名; git init
  • GitHub 等に存在する(自分の・他人の)リモートレポジトリをローカルにコピー
    • $ git clone URL
    • submodule も一緒に取得したい場合は--recursiveをつける
  • 現在のリモートリポジトリ一覧表示
    • $ git remote -v
  • リモートレポジトリを追加
    • $ git remote add エイリアス名 URL
    • URLhttps プロトコル (例: https://github.com/ユーザ名/レポジトリ名) か ssh プロトコル (例: git@github.com:ユーザ名/レポジトリ名) のどちらか
      • ssh プロトコルだと git push した際にパスワード認証が不要
      • ~/.gitconfig に以下のように記述しておくと、URL のプロトコルを自動で https から ssh に変えてくれる
[url "git@github.com:"]
        insteadof = https://github.com/
  • リモートレポジトリの URL を変更
    • $ git remote set-url エイリアス名 URL

レポジトリの状態の管理

  • 変更状況を確認
    • $ git status
  • ログツリーを表示
    • $ git log --oneline --graph --decorate
    • .bash_profile に以下のように記述しておくと $ git log だけで済む
git() {
    if [[ $@ == "log" ]]; then
        git log --oneline --graph --decorate
    else
        command git "$@"
    fi
}
  • ブランチの一覧表示
    • $ git branch

変更の反映

  • ローカル上の変更をリモートレポジトリに反映
    • $ git add .; git commit -m "コミットメッセージ"; git push
    • fatal: The current branch master has no upstream branch. と表示されたら $ git push origin master
  • リモートレポジトリを指定してプッシュ
    • $ git push -u エイリアス名
  • リモートレポジトリ上の変更をローカルに反映
    • $ git pull (origin master)

ブランチ

  • 新規ブランチの作成
    • $ git branch ブランチ名
  • ブランチの移動
    • $ git checkout ブランチ名

サブモジュール

  • サブモジュールの追加
    • $ git submodule add URL
  • 最新の commit に更新
    • $ cd サブモジュールディレクトリ名; git pull origin master
    • $ cd レポジトリルート; git add/commit/push (これをするまでstatusは更新されない)

SSH接続

  • ~/.ssh/configGitHub に登録した公開鍵に対応する秘密鍵を指定しておく
Host github.com
     User ユーザ名
     HostName ssh.github.com
     IdentityFile ~/.ssh/秘密鍵ファイル名
     ServerAliveInterval 60
  • Gtk-WARNING **: cannot open display と表示されたら$ unset SSH_ASKPASS

.gitignoreファイル

  • 複数のディレクトリに置くことができる
  • 深い階層の.gitignoreに書かれた指定の方が優先順位が高い
  • 以下の上の行から順に解釈される
    • /を含まない、もしくは末尾以外にのみ/を含む行(e.g. file, /file, path/to/file, /path/to/file)
    • 末尾が/の行(e.g. /path/to/directory/, path/to/directory/)
    • !で始まる行(e.g. !/path/to/file)
      • !以降のパターン文字列が示すファイルまたはディレクトリを無視しない
      • 前の無視指定を上書きする
      • 以降の無視指定に上書きされうる
    • 空行もしくは#で始まる行
      • 解釈されない
  • ワイルドカード(*, ?, [0-9]など)も使える