ImageJで多重染色画像をチャンネルごとに並べてひたすらパワポにコピペするだけのマクロ

dir = getDirectory("Select a Directory");
//画像(ここでは3-channel multi-tifを想定)が入ったフォルダを選択
filelist = getFileList(dir)

for (i = 0; i < lengthOf(filelist); i++) {
    if (endsWith(filelist[i], ".tif")) { 
        open(dir + File.separator + filelist[i]);

		waitForUser; //画像に矢印など入れたい場合はここで入れる

                run("RGB Color"); //マージ画像も載せる
		run("Scale...", "x=0.25 y=0.25 interpolation=Bilinear average create");
                //画像サイズを0.25倍している

		selectWindow(filelist[i]);
		Stack.setDisplayMode("grayscale");
		run("Make Montage...", "columns=3 rows=1 scale=0.25 border=1");
		
		run("Combine...", "stack1=Montage stack2=[" + filelist[i] + " (RGB)-1]");
		run("Select All");
		run("Copy to System");
		
		close("*");
		
		waitForUser; //パワポなどにコピペしたらOKを押す
    } 
}

NGS DRY解析教本の発現解析の項で詰まったところと解決法

今までNGSのデータを扱う機会がなかったのだけど、少しくらい知っていた方がいいかと思って、以前から評判の良かった次世代シーケンサーDRY解析教本に沿って自習を始めた......のだけど、さすがに執筆されたのが3年前ということもあって書いてある通りにやってみても動かない。特にHomebrewを使ってインストールしているツールの多くがインストールできなくなっている。以下、自分なりにググって調べた解決法。

作業環境
MacBookPro (Retina Mid 2012)
MacOS Mojave (直前にクリーンインストール

出版社のサイトからレファレンスファイルをダウンロードできない
以下のサイトの正誤表というところに正しいurlがある

Homebrewで検索してもインストールしたいパッケージが見つからない
⇒類似のパッケージマネージャであるbiocondaを使ってインストールできる。
ただし、一部のツールはbiocondaでインストールできるバージョンでは上手く動かない可能性がある。実際、自分はtophatとcufflinksはbiocondaでインストールしたものは途中でハングしてしまった。この場合は本家のサイトから古いバージョンのバイナリをダウンロードすることで解決した。biocondaの使い方はググればいろいろ出てくるので省略(biocondaからのインストールはpython2.7の仮想環境にて行なった)。

以下、詳細。

tophat
biocondaでv2.1.1をインストールできるがこれをMacで動かすと途中でハングする(このサイトでも言及されている)。v2.0.14では動くらしいがbiocondaにはないので、本家のサイトからバイナリをダウンロードして解凍(右側のカラムにあるReleasesのところをクリックすると古いバージョンのリストが出てくるのでtophat-2.0.14.OSX_X86_64.tar.gzを落とす)。
使用するにはコマンドサーチパスを通す必要がある。勉強のために使用するだけなら、

export PATH=〈tophatのフォルダのパス〉:$PATH

でよい(ターミナルを閉じるまでの間はパスが通る)。〈tophatのフォルダのパス〉の部分はFinderからtophatのフォルダをドラッグ&ドロップすれば入る。
なお、tophat自体はすでに開発が終了していて製作者が後継版であるHISAT2の使用を推奨しているので本気で使うつもりなら、HISAT2の使用法を勉強した方がよい(このあたりとかを参考?)。

cufflinks
こちらもv2.2.1がbiocondaでインストールできるが、これを使うと途中でハングした。本家のサイトからv2.1.1のバイナリをダウンロードして解決。パスを通すあたりはtophatと同様に。

cummeRbund
RStudioから手順通りに進めると最新版をソースファイルからコンパイルするか聞いてくるがそれをするとコケる。noにすると一つ古いバイナリがインストールされるはず。

FastQC
Homebrewでもbiocondaでも入る。

fastx_toolkit
biocondaで入る。

これで本に書いてある内容はだいたい再現できた(ただし、ツールのバージョンが違うからか本の結果と全く同じではなかったが)。ただ、調べているとこのやり方は業界的にはすでにoutdatedの模様。だいたい何をやっているのかを学ぶには役立ったけれど仕事で使うには新しいやり方をちゃんとキャッチアップしないといけないっぽい。

過去に作ったmovファイルをImageJ/Fijiで開きたい

元々、ImageJはQuickTime形式をサポートしていたので、タイムラプス観察などの画像スタックをプレゼン用の動画にするためにmovファイルに変換したりしていた。ところが、64bit化を期にQuickTime形式がサポートされなくなったため、昔作ったmovファイルを変更するために最新のFijiで開こうとしても開くことができない。元の画像スタックも手元にない。こんなときどうするか?

FFMPEGプラグインを導入することで開くことができる。

Fijiでの手順は以下。


ImageJ Updaterを開く(Help > Update...)

Manage update sitesをクリック

FFMPEGにチェックを入れてClose

ImageJ UpdaterにFFMPEG関連のアップデートが表示されるのでApply changes

インストールが終わったらFijiを再起動

File > Import以下にMovie (FFMPEG)...という項目が追加されているのでクリックして対象のmovファイルを選択

optionを選択するダイアログが出てくるので適当に指定してOK(ファイルが大きくない限りVirtual Stackのチェックは外したほうがよい?)


これで開くはず。

ImageJ2のパラメータ記法を使ってスクリプト書きをちょっとだけ楽する

忙しいんですけど、現実逃避のためのエントリ。

さて、みんな大好きImageJですが、実は数年前からImageJ2というものが開発されています。2014年にRC版が公開されました。

ImageJ2はSciJavaと呼ばれるフレームワークをベースにして完全に新しく作り直されたもので、Plugin作成の際に使用するライブラリも従来のImageJ1.xのものとは全く異なっています。ただし、後方互換性に非常に気を使って作られているので、これまでのImageJ1.x用のPluginやScirpt、Macroも問題なく動きますし、ユーザーレベルだと今のところあまり大きな違いはありません。実際、現在のFijiにはすでにImageJ2が同梱されています。


ImageJ2の細かい説明はこのへん


で、ImageJ2は従来のImageJでは限界があった部分がいろいろと改良されており、いずれは移行するべきなのでしょうけど、正直、一からScriptの書き方を勉強し直すのも面倒くさい一部機能がベータ版だったりと発展途上ではあるので、とりあえずまだ様子見でいいんじゃないかと思います。ただ、ImageJ2の機能を使うとScript書きが楽になる場面があったりするので今回はそれの紹介です。

これまでのImageJ1.xにおいて、ScriptやMacroの実行時にファイルやディレクトリを指定する、またはパラメータを入力する、などといった場合にはOpenDialogやDirectoryChooser、GenericDialogといったものが使われていました。しかし、これをScriptの中に実装しようとすると微妙に面倒くさい。


たとえば、とあるディレクトリを指定するためのダイアログを表示させるためのJython Scriptだと

from ij.io import DirectoryChooser  
  
dc = DirectoryChooser("Choose a folder")  
folder = dc.getDirectory()  
  
if folder is None:  
  print "User canceled the dialog!"  
else  
  print "Selected folder:", folder

こんな感じ(ここから参照しました)。

パラメータを入力するときは、

from ij.gui import GenericDialog

def getName():
	gd = GenericDialog("What's your name?")
	gd.addStringField("name", "Masuda")
	gd.showDialog()

	if gd.wasCanceled():  
		print("User canceled dialog!")
		return
		
	input_name = gd.getNextString()

	return input_name

name = getName()

if name is not None:
	print("Your name is " + name + "!")

パラメータが増えると、

from ij.gui import GenericDialog

def getPersonalData():
	gd = GenericDialog("enter your personal data")
	gd.addStringField("name", "Masuda")
	gd.addNumericField("age", 17, 0)
	bloodtypes = ["A", "B", "O", "AB"]
	gd.addChoice("blood type", bloodtypes, bloodtypes[0])
	gd.showDialog()

	if gd.wasCanceled():  
		print("User canceled dialog!")
		return
		
	name   = gd.getNextString()
	age    = gd.getNextNumber()
	b_type = gd.getNextChoice()
	
	return name, age, b_type

data = getPersonalData()

if data is not None:
	name, age, b_type = data
	print name, age, b_type

面倒くさい。

そこで、#@parameterという記法を使います。たとえば、

#@String name
print("Your name is " + name)

として実行すると、文字列を入力するためのダイアログが出てくる。入力したダイアログは変数nameに格納される。


#@output <変数型> <変数名>で出力もできる。

#@String name
#@output String result

result = "Your name is " + name


いろいろできる。

#@String(label = "What's your name?", value = "Masuda") name
#@output String result

result = "Your name is " + name

GenericDialogを用いて作った上の例は

#@String(label = "name", value = "Masuda") name
#@Integer(label = "age", value = 17) age
#@String(label = "blood type", choices = {"A", "B", "O", "AB"}, style = "listBox") b_type

print name, age, b_type

と書ける。


ディレクトリを指定したいときは

#@File(label = "select a directory", style = "directory") my_dir

print(my_dir)


また、表示している画像オブジェクトを取得したいときは

#@ImagePlus img

print(img.getTitle())

とするとactive windowのImagePlusオブジェクトが取得できる。

今回のScriptはJythonだけど、他のScript言語やMacroでも同じように使える(らしい)。また、従来のImageJ1.xのAPIを用いた記述と混ぜて使うこともできる。

細かいことは以下のリンクを参考に。

https://imagej.net/Script_Parameters
http://imagej.github.io/presentations/2015-09-04-imagej2-scripting/#/

今のところ、まだお試し程度にしか使っていないので自己責任で。

(追記)

これ書きながら、Scriptを繰り返し実行したときにデフォルト値がvalueで指定した値にならずに前の入力を引きずっているのが気になっていたんだけど、Forumを検索していて原因がわかった。parameterにはpersistというpropertyがあってデフォルトではtrueになっている。これがtrueになっていると前回の入力がvalueで指定した値を上書きするらしい。なので、

#@String(label = "What's your name?", value = "Masuda", persist = false) name
#@output String result

result = "Your name is " + name

のように書くと正しくvalueの値がデフォルト値として参照される。

Miji/MIJを用いてMatlabでmulti-tiffファイルを一括処理する

普段、ImageJで使用しているtime-lapse imageなどのmulti-tiff画像をMatlab上で一括処理したいのだけど、Matlabではmulti-tiffをコマンド一発で開くことができない?みたい。

ググッたらループを回して一枚ずつ読み込むようなスクリプトが紹介されていたりするがなんか面倒臭い。

そこでMijiを使ってImageJ経由でMatlabにmulti-tiff画像データを読み込ませることを試してみた。

addpath('/Applications/Fiji.app/scripts'); % Mijiにpathを通す。Macの場合
Miji; %Mijiを起動

DirName = uigetdir; % ファイルが入ったディレクトリを選択

FileList = dir([DirName, '/*.tif']) % ファイルのリストを取得。ワイルドカードの部分を変更することでファイル名で絞り込むことも可能

for i = 1:size(FileList, 1)

    ImagePath = [DirName, '/', FileList(i).name]; % 各ファイルのパスを取得
    [path, ImageName, ext] = fileparts(FileList(i).name); %ファイル名から拡張子を除いたものを取得(保存時に使用)。pathとextは使わない

    MIJ.run('Open...', ['path=', ImagePath]); % ImageJで画像を開く
    img = MIJ.getCurrentImage(); % Matlabに読み込む
    MIJ.run('Close'); % ImageJ上の画像を閉じる
    
% 何かの処理
    
    MIJ.createImage(img); % 処理した画像をImageJに戻す
    MIJ.run('Save', ['save=[', DirName, '/', ImageName, '_treated.tif]']); % ファイル名を変更して保存
    MIJ.run('Close');
end


現状、Mijiには直接ファイルを開いたり保存したりするコマンドがないため、runコマンドを用いてImageJを操作することになる。

ちょっと躓いたのがrunコマンド内で'Open...'や'Save'を使うときのpathの指定方法。MacroやAPIとはちょっと違うので注意。

Matlab上からImageJのAPIを直接叩けるともっと便利なんだけど...。

ImageJ/FijiとJava 8

(16/06/24 追記)

最新のFijiとJava8でアニメーションの遅延は解消されているのを確認。

(追記ここまで)


動作環境:iMac (late2011), Core i7 2.8GHz, memory 16GB, yosemite

2015-06-15 - Major updates in the works - ImageJ
2015-06-17 - Better behavior on OS X - ImageJ

ImageJ/FijiがJava 8に対応したらしく気がついたらFijiがJava 8上で起動してた(Java8自体は前にインストールしてた)。
ああ、やっとかと思ったんだけど、しばらく使ってるとなんか妙に画像の描画が遅い。1024x1024のスタック画像がまともにアニメーションしてくれない。もしやと思ってJava 8をアンインストールしたら元に戻った。アンインストールの方法は下記参照。

MacでのJavaのアンインストール方法

このままずっとJava 6というのもまずそうだけど、そのうち直りそうな気もするのでとりあえず暫くの間はJava 6のままで。
512x512くらいの画像であれば普通にアニメーションしてたのでそれくらいの画像を扱う人ならアップデートしてもいいのかも。

MIJ/Mijiを用いてMatlabとImageJ/Fijiの間でデータをやりとりする

*2017/06/05 追記*

突然、Matlab上でMijiが起動しなくなった。
調べてみたところ、Fiji.app/jars内にあるはずのmijのjarファイルがアップデートの過程で消えてしまった模様。
復旧するには、Update...でImageJ Updaterを開き、Manage update sitesでBIG-EPFLを追加。Advanced modeでview all filesにしてmijで検索。出てきたmij.jarを選択してinstallボタンを押しApply changes。これでFiji.app/jars/内にmij-1.3.6-fiji2.jarみたいなファイルが追加されていれば使えるようになるはず。

他のpluginでも突然消えてしまった場合には同様の方法で対処できるかも。

*追記終わり*

Matlabで画像解析を始めたんだけど、画像の表示、GUIによる画像操作、ファイルの入出力あたりがどうもストレスフルで、このへんを使い慣れたImageJでできないかと探してみたら見つけた。詳細は以下のリンクを参照。

Miji - ImageJ
MIJ

簡単に言うとMatlabの上でImageJ/Fijiを起動させるプログラム。現行のFijiにはプリインストールされているのでFijiを使っているなら新たに何かをインストールする必要はない。

使用方法はまずFiji.app/scriptsにMatlabのサーチパスを通す。MacだとGUIからは.app以下が見えないので以下のMatlabコマンドを使用する。

addpath('/Applications/Fiji.app/scripts')

で、

Miji;

とコマンドを入力するとFijiが立ち上がる。注意点として、Matlab上で動かすJAVAプログラムが使用できるメモリはデフォルトではかなり少なく設定されているので、もし大きな画像ファイルを扱いたいのであれば事前に使用可能なメモリ容量を増やしておく必要がある。具体的には、Matlab > 設定 > 一般 > JAVA ヒープ メモリのところの値を増やす。

起動したImageJ上で画像ファイルを開き、

img = MIJ.getCurrentImage;

で画像データを配列として読み込める。一枚の画像であれば2次元配列、画像スタックであれば3次元配列になる。ハイパースタックであったとしてもその設定は無視されて通常のスタック扱いで3次元配列として読み込まれるので注意。

逆にMatlab上の配列は、

MIJ.CreateImage(img);

で、ImageJ上で画像として開くことができる。

終了したいときは、

MIJ.exit;

その他、使用できる機能については以下のリンクを参照。

Bi-directional communication and data exchange from Matlab to ImageJ

使用してみた感想としては、unsigned 16-bitのデータが32-bitで読み込まれたり、ところどころで挙動が怪しかったりするけど上記の目的にはわりと使えそう。あとImageJの方で指定したROIの座標を読み込むこともできるのでそのあたりでも使えそうかな。