「ImageJマクロを使う」シリーズでは、ImageJを使って生命科学系の画像解析をするにあたって必要な知識をまとめていきます。
今回は、マクロを使って選択したディレクトリにフォルダを作るをできるようにしていきます。
「細胞の核を数える」シリーズで描いたフローチャートの「ココ」の部分をやっていきます。
フォルダを作る関数"File.makeDirectory"を使う
NIHのImageJサイト、「Built-in Macro Functions」のページによると...
"File.makeDirectory"の引数は"path"となっています。
どういうことかというと...
フォルダを作りたい場所のパスを入れておけば、そこにフォルダが作れるということ。
今回は下記の場所にフォルダを作っていきたいと思います。
フォルダを作る前に、これまでの振り返りをしていきましょう。
まず、ディレクトリを選ぶ"getDirectory"関数を使って、解析用の写真フォルダを選択しました。
変数"chooseDir"に関数"getDirectory"を使って解析する写真が入っているフォルダのパスを入れました。
変数と関数に関しては、こちらの記事をご覧下さい。
変数"chooseDir"と関数"File.makeDirectory"を使って、フォルダを作ることを考えてみましょう。
上のように、"File.makeDirectory"の引数を"chooseDir+"フォルダ名/""としてしまうと、作りたいと思っていた階層の一つ下にフォルダが作られてしまいます。
今回は、解析したい写真が入っているフォルダと同じ階層にフォルダを作りたいので、もう少し試行錯誤が必要なようです。
解析したい写真が入っているフォルダと同じ階層にフォルダを作るためには...
"File.makeDirectory"関数の引数を工夫したほうが良さそうです。
"chooseDir+"フォルダ名/""とすると一つ下の階層にフォルダが作られてしまうので、パスの中身を下のようにしていきます。
解決策① 一つ上の階層のパスを別の変数に入れる
一番簡単なのは、もう一度、関数"getDirectory"を使って、一つ上の階層のフォルダパスを取得する方法。
上の図のように指定して、"File.makeDirectory"の引数を"resultDir+"フォルダ名/""とすれば、簡単に一つ上の階層にフォルダを作ることができます。
これは、簡単ですが"getDirectory"が動くたびにダイアログ画面が出てきていちいちフォルダを選択しなければならないので、少しめんどくさい...
できれば、"getDirectory"を動かすのは一回(フォルダを選択するのは一回)にしたいですよね。
解決策② パスの文字列を操作してフォルダを作る
今のところ取得できている"chooseDir"の文字列を操作して、ディレクトリを選ぶ作業を省いてみましょう。
そのときに必要な関数が、"split"と"replace"です。
それぞれの関数に関しては、後ほど詳しくみていきましょう。
「文字列を操作する」と言われてもピンとこない人もいるかもしれません。
どういうことをやりたいかと言うと...
順番に見ていきましょう。
split関数とreplace関数を使って文字列を操作する
文字列を分割するsplit関数を使う
まずは、step1の「split関数で分割して最後の文字列を取ってくる」をしていきましょう。
文字列を分割すsplit関数とは...
基本的な関数の形は、"split"の後に第一引数に文字列、第二引数に区切る記号を書いてきます。
具体的な使い方こんな感じ↓
3行目にsplit関数を使って、変数"chooseDir"に入っている文字列を"/"で分割しました。
※パスは基本的には"/"で区切られています。
2行目に、変数"chooseDir"の中に入っている文字列をprint関数で出力。
4行目にsplit関数を使って分割できているかを確認するために、"Array.print"関数を使って出力しています。
結果の1行目が"chooseDir"に入っている文字列、2行目が分割された結果(","で区切られている)になっています。
上の作業をイメージにしてみると...
ImageJでは、一つの車両に乗っているものを表示させる場合は"print"関数、複数の車両に一つずつものが乗っているものを表示させる場合は"Array.print"関数を使います。
余談ですが...
変数にどんなものが入っているか?自分がした操作でどんなふうに変化しているか?を調べるために、print関数はよく使います。
文字列を分割することができたので、次は「特定の車両に乗っている文字列を取得する」をしていきましょう。
print関数を使って文字列を取得できるかどうか?をやっていきましょう。
「車両番号」を指定する場合には、変数名の後に"[]"を使います。
プログラミング言語では0から始まる言語がほとんどです(Rは1から始まりますが...)。
なので、0番目の車両を指定すると最初の"Users"が表示されるのがわかるかと思います。
今回取得したいのは、最後の"photo"の部分。今回の場合は、"[5]"と指定すれば取得できることがわかりました。
これは、フォルダの階層の深さで変わってきてしまいますよね。
もっと汎用性を高めるために、一般化していきましょう。
一般化するために、変数a(電車の車両)の長さを返してくれる関数".length"を使います。
変数名の後に".length"をつければ、車両の長さを数値として返してくれます。
が、注意が必要なのが車両の長さなので今回の場合は"6"と返ってきてしまうのです。
知りたいのは、最後の車両なので「◯車両目」と言うのを指定する場合は必ず"-1"をしなければいけません。
変数名"a"の後に「◯車両目」を指定する"[]"に"a.length-1"を入れて、printしてみるとちゃんと"photo"が返ってきました。
文字列を書き換えるreplace関数を使う
split関数を使って文字列"photo"を取り出せるようになったので、replace関数を使って"photo"の部分を新しいフォルダ名に変えていきましょう。
文字列を書き換えるreplace関数とは...
基本的な使い方は、第一引数に全体の文字列、第二引数に書き換えたい文字列、第三引数に書き換える文字列を入れます。
実際に使ってみましょう
"photo"が"count_results"に変わりました。
ここまでくれば、後一息です。
File.makeDirectoryを使ってフォルダを作る
"photo"の部分を"count_results"に書き換えた文字列を変数"b"に入れました。
bに入っているパスを使って"File.makeDirectory"を動かしてみましょう。
目論見通り、"photo"(解析用の写真が入っているフォルダ)と同じ階層に"count_results"という名前のフォルダが作られました。
同じ要領でROIの結果を保存する"ROI_results"フォルダも簡単に作れます。
次回は、解析用の写真フォルダ内にサブフォルダがあるかどうか?を見極める"if文"を組んできます。