「PIONEチュートリアル」の版間の差分

提供: Eospedia
移動: 案内検索
行1: 行1:
'''PIONE'''チュートリアル
+
'''PIONE'''チュートリアル<br>
 ここでは、[[PIONE]]のチュートリアルを行います。
+
 ここでは、[[PIONE]]のチュートリアルを行います。始める前に[[PIONEのインストール]]をしておきましょう。
  
 
== 基本1(特定のファイルを出力する) ==
 
== 基本1(特定のファイルを出力する) ==

2014年10月31日 (金) 05:51時点における版

PIONEチュートリアル
 ここでは、PIONEのチュートリアルを行います。始める前にPIONEのインストールをしておきましょう。

基本1(特定のファイルを出力する)

 まず、PIONEを動かすにはルール定義書をつくる必要があります。 どんな言語でも最初に作成するHelloプログラムを作ってみましょう。この場合、出力ファイルをひとつ指定することになります。

 次の内容のファイル'HelloWorld.pione'を作成してみましょう。

Rule Main
	output 'message.txt'

Action
	echo "Hello PIONE world !" > message.txt
End

 この後、pione-clientを実行します。

$ pione-client HelloWorld.pione -b helloOutput

例えば、次のような出力が流れます。

 ==> &Anonymous:Root([],{})
   --> Rule Application: &Anonymous:Root([],{})
     --> Distribution: &Anonymous:Root([],{})
           >>> &Anonymous:Main([],{})
 ==> &Anonymous:Main([],{})
  SH ------------------------------------------------------------
  SH 	echo "Hello PIONE world !" > message.txt
  SH ------------------------------------------------------------
 <== &Anonymous:Main([],{})
     <-- Distribution: &Anonymous:Root([],{})
   <-- Rule Application: &Anonymous:Root([],{})
 <== &Anonymous:Root([],{})

その結果、helloOutputというディレクトリができます。その中に指定したファイルmessage.txtが出力されています。

$ cat helloOutput/output/message.txt
Hello PIONE world !

もう一度、実行すると今度は、実行の必要がないために次のようなものが出力されます。

 ==> &Anonymous:Root([],{})
   --> Rule Application: &Anonymous:Root([],{})
   <-- Rule Application: &Anonymous:Root([],{})
 <== &Anonymous:Root([],{})

さっきと比べると、Main Ruleが動いていないことが分かります。

さて、改めて設定したファイルを眺めてみます。

まず、最初に呼び出されるルール(Main)が定義されています。

Rule Main

Mainは、C言語などと同様に特別な意味をもつルールです。

次に、出力ファイルが定義されています。

	output 'message.txt'

ここに書かれたファイルが最終的に-bで指定されたディレクトリに出力として戻ってきます。 Action以降が実際に起動するプログラムになります。

Action
	echo "Hello PIONE world !" > message.txt

実際にはシェルスクリプトが動きますので、どんなものも実行が可能です。

  1. !/bin/csh

で始めれば、cshを使って記述することもできますし、スクリプト系の言語であれば自由に記述し、実行形式を実行出来ます。

最後に、RuleをEndで終了します。

End

これが、一番シンプルなルールの書き方です。入力ファイルがないので、出力ファイルがなければ作成し、あれば、作成しないという動作をします。必要以上の動作をしないところが通常のシェルスクリプトを実行する場合と異なる点です。

基本2(特定のファイルを入力し、出力する(更新判定))

 次に、入力ファイルから出力ファイルを作成する場合の定義書について作成してみましょう。

#Multiplying.pione

Rule Main
	input 'test.in'
	output 'test.out'

Action 
	awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
End

今回は、test.inという入力ファイルからその積算をして、test.outというファイルを作り出すルールです。入力ファイルの更新判定により、ルールを実行するかどうかが変わってきます。

awkの使い方については、別途勉強してみて下さい。ここではファイルの中にある行頭の数字を2倍して、出力することができます。

まず、

$ mkdir MultiplyingInput
$ pione-client Multiplying.pione -b MultiplyingOutput -i MultiplyingInput/

として、入力ファイルがあるディレクトリ(指定しなければ、現在のディレクトリ)を指定して実行してみます。

 ==> &Anonymous:Root([],{})
   --> Rule Application: &Anonymous:Root([],{})
   <-- Rule Application: &Anonymous:Root([],{})
 <== &Anonymous:Root([],{})

入力ファイルがありませんので、何もする事がないとして終了してしまいます。先ほどとの違いに気がついたでしょうか。

 次に、ファイルを作成して、実行してみます。

$ echo "3"   > MultiplyingInput/test.in
$ echo "5" >> MultiplyingInput/test.in
$ cat MultiplyingInput/test.in
3
5
$ pione-client Multiplying.pione -b MultiplyingOutput -i MultiplyingInput/
 ==> &Anonymous:Root([test.in],{})
   --> Rule Application: &Anonymous:Root([test.in],{})
     --> Distribution: &Anonymous:Root([test.in],{})
           >>> &Anonymous:Main([test.in],{})
 ==> &Anonymous:Main([test.in],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
     <-- Distribution: &Anonymous:Root([test.in],{})
   <-- Rule Application: &Anonymous:Root([test.in],{})
 <== &Anonymous:Main([test.in],{})
 <== &Anonymous:Root([test.in],{})

$ cat MultiplyingOutput/output/test.out 
6
10

となり、確かに2倍の値のファイルができあがっていることが分かります。 もう一度、実行すると、

$ pione-client Multiplying.pione -b MultiplyingOutput -i MultiplyingInput/
 ==> &Anonymous:Root([test.in],{})
   --> Rule Application: &Anonymous:Root([test.in],{})
   <-- Rule Application: &Anonymous:Root([test.in],{})
 <== &Anonymous:Root([test.in],{})

となり、ここでも何も実行しません。つまり、入力ファイルに比べて出力ファイルのほうが新しいので、更新判定の結果、実行しなくてよいと判断したことになります。賢いですね。

さて、ここで、ファイルを更新してみましょう。3行目に7を付け加えます。

$ echo "7"   >> MultiplyingInput/test.in

そして、実行してみましょう。 $ pione-client Multiplying.pione -b MultiplyingOutput -i MultiplyingInput/

 ==> &Anonymous:Root([test.in],{})
   --> Rule Application: &Anonymous:Root([test.in],{})
     --> Distribution: &Anonymous:Root([test.in],{})
           >>> &Anonymous:Main([test.in],{})
 ==> &Anonymous:Main([test.in],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
     <-- Distribution: &Anonymous:Root([test.in],{})
 <== &Anonymous:Main([test.in],{})
   <-- Rule Application: &Anonymous:Root([test.in],{})
 <== &Anonymous:Root([test.in],{})

$ cat MultiplyingOutput/output/test.out 
6
10
14

今度は実行されました。これが更新判定によりルールが実行されるかどうかが判定されているということです。 もう一度実行しても、今度は実行されません。

$ pione-client Multiplying.pione -b MultiplyingOutput -i MultiplyingInput/
 ==> &Anonymous:Root([test.in],{})
   --> Rule Application: &Anonymous:Root([test.in],{})
   <-- Rule Application: &Anonymous:Root([test.in],{})
 <== &Anonymous:Root([test.in],{})

さて、出力ファイルを削除してみるとどうなるでしょうか。

$ rm  MultiplyingOutput/output/test.out 

今度は、実行されますね。

 では、内容は変えずに、touch コマンドを使って、入力ファイルの修正時刻を変えるとどうなるでしょうか。

$ touch MultiplyingInput/test.in

今回も、予想通り、動作しました。

 もし、動作しないようだったら、バグです。すぐに、GITHUB/PIONEに報告しましょう。

 さて、この基本2が理解できれば、まず、PIONEの動きの基本が理解できたことになります。

 ところで、Actionで定義した動作の中に、見慣れない記号( {$I[1]}, {$O[1]} )が現れています。

Action 
	awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
End

{$I[1]}は入力ファイル、{$O[1]}は出力ファイルを表しています。それぞれの[]の中の数字1は、 input/outputで定義したそれぞれの1番目ということを意味しています。次の基本3での複数ファイルの入出力では1以外が使われることになります。  まだ、何が便利か少し分かりづらいと思いますが、例えば、Multiplying2.pioneとして、次のように記述するとどのように動作するでしょうか。

Rule Main
	input 'test.in'
	output '{$I[1]}.out'

Action 
	awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
End

少し考えてみて下さい。そして、動作させてみましょう。

$ pione-client Multiplying2.pione -b MultiplyingOutput -i MultiplyingInput/

MultiplyingOutput/outputのディレクトリにはどんなファイルができあがったでしょうか。

そうですね。test.in.outができあがっています。何故かを考えてみましょう。

基本3(複数ファイルの入力と複数ファイルの出力)

 さて、更新判定が理解できたところで、複数ファイルの入出力について考えてみましょう。test1.in, test2.inから、それぞれ2倍した数が格納された、test1.out, test2.outが出力できるPIONE定義書を作成してみましょう。ここで、名前をMultiplyingFiles.pioneとして作成してみましょう。


 問題1:上記のMultiplyingFiles.pioneを作成して実行してみて下さい。


 解答例1:

Rule Main
	input 'test1.in'
	input 'test2.in'
	output 'test1.out'
	output 'test2.out'

Action 
	awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
	awk '{ print $1*2 }' {$I[2]} > {$O[2]} 
End

 どうでしょうか。思ったように動きましたか。複数のファイルがあれば、複数書き並べればよいのです。

 でもなんだか、同じ事をするのに何度も行を書くのは嫌だなと思いませんか。もし、2倍を5倍に変えたくなったら全ての行を書き換えなくてはなりませんね。10行ぐらいならそれでもよいけれど、100個、1000個とファイルが増えてきたらどうでしょうか。だんだん嫌になってきましたか。  では、どうすれば良いでしょうか。例えば、シェルスクリプトが得意なひとは次の様なプログラムを設定することも出来ます。


 解答例2:

Rule Main
	input 'test1.in'
	input 'test2.in'
	output 'test1.out'
	output 'test2.out'

Action 
       for i in `ls *.in`; do
            awk '{ print $1*2 }' $i > `basename $i .in`.out 
       done
End

これでも、ファイルが増えるたびにinput/outputを書き換える必要があります。 そこで、全てのファイルを入力し、全てのファイルを出力するように入出力を表現することも出来ます。


 解答例3:

Rule Main
	input '*.in'.all
	output '*.out'.all

Action 
       for i in `ls *.in`; do
            awk '{ print $1*2 }' $i > `basename $i .in`.out 
       done
End

どうでしょうか。うまく動作したでしょうか。ここで、

	input '*.in'.all
	output '*.out'.all

の部分は、*は任意の文字列を表現します。つまり、*.inは、ファイルの最後が.inで終了しているファイル全て、*.outは、ファイルの最後が、.outで終了しているファイル全てを表します。.allがついていると、全てのファイルを取り扱うことを意味しています。逆に、.allが付いていないときには、.eachがついていることがdefaultとして決まっています。一つ一つのファイルを別々に実行するという意味になります。

 これでずいぶんと記述しやすくなりました。

 でも、これだと、*.inのどれかのファイルが更新されていると全て変更になってしまいます。試してみて下さい。なんだか無駄ですね。また、同時にできるはずのことをfor文を使って順次実行しているので、時間も無駄ですね。このくらいのタスクであれば、たいして時間がかかるわけではないのですが、もっと時間のかかるタスクだったらどうでしょうか。必要なファイルの更新だけを、できれば複数のホストや一台でも最近のPCだったら、マルチコアCPUをもっているので、同時に動かすともっと早く終了できるようになるはずです。

 さて、それではどのようにすればよいのでしょうか。それが次の基本4になります。だんだんPIONEらしくなってきます。

基本4(複数ファイルの入力と複数ファイルの出力の並列処理)

次は、さっきと違ってallが付いていません。なにが起きるかを考えてみましょう。

Rule Main
	input '*.in'
	output '{$I[1][1]}.out'
Action
   awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
End

下は実行した例です。

 $ pione-client MultiplyingFilesEach.pione -b MultiplyingFilesEachOutput -i MultiplyingFilesInput/  -t 4
 ==> &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   --> Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
     --> Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
           >>> &Anonymous:Main([test1.in],{})
           >>> &Anonymous:Main([test2.in],{})
           >>> &Anonymous:Main([test3.in],{})
           >>> &Anonymous:Main([test4.in],{})
           >>> &Anonymous:Main([test5.in],{})
           >>> &Anonymous:Main([test6.in],{})
           >>> &Anonymous:Main([test7.in],{})
 ==> &Anonymous:Main([test1.in],{})
 ==> &Anonymous:Main([test2.in],{})
 ==> &Anonymous:Main([test3.in],{})
 ==> &Anonymous:Main([test4.in],{})
  SH ------------------------------------------------------------
  SH awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
  SH ------------------------------------------------------------
  SH awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
  SH ------------------------------------------------------------
  SH awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
  SH ------------------------------------------------------------
  SH awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
 <== &Anonymous:Main([test2.in],{})
 <== &Anonymous:Main([test1.in],{})
 <== &Anonymous:Main([test3.in],{})
 <== &Anonymous:Main([test4.in],{})
 ==> &Anonymous:Main([test5.in],{})
 ==> &Anonymous:Main([test6.in],{})
 ==> &Anonymous:Main([test7.in],{})
  SH ------------------------------------------------------------
  SH awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
  SH ------------------------------------------------------------
  SH awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
  SH ------------------------------------------------------------
  SH awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
 <== &Anonymous:Main([test6.in],{})
 <== &Anonymous:Main([test5.in],{})
 <== &Anonymous:Main([test7.in],{})
     <-- Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   <-- Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
 <== &Anonymous:Root([test1.in,test2.in,test3.in,...],{})

4つのタスクが並列に動いている様子が分かるでしょうか。確かに4つずつのタスク( ==> &Anonymous:Main([testN.in],{}))が並列に動作しているようです。 もう一度実行してみると下のようになります。

$ pione-client MultiplyingFilesEach.pione -b MultiplyingFilesEachOutput -i MultiplyingFilesInput/  -t 4
 ==> &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   --> Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   <-- Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
 <== &Anonymous:Root([test1.in,test2.in,test3.in,...],{})

今度は実行されません。そこで、ひとつファイルを更新してみます。

$ touch MultiplyingFilesInput/test3.in 
$ pione-client MultiplyingFilesEach.pione -b MultiplyingFilesEachOutput -i MultiplyingFilesInput/  -t 4
 ==> &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   --> Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
     --> Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
           >>> &Anonymous:Main([test3.in],{})
 ==> &Anonymous:Main([test3.in],{})
  SH ------------------------------------------------------------
  SH awk '{ print $1*2 }' {$I[1]} > {$O[1]} 
  SH ------------------------------------------------------------
 <== &Anonymous:Main([test3.in],{})
     <-- Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   <-- Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
 <== &Anonymous:Root([test1.in,test2.in,test3.in,...],{})

となり、test3.inだけが更新されているのが分かります。これがeachとしての振る舞いです。

基本5(直列:フロールールの設定 )

 さて、もう少し複雑なルールについて設定してみましょう。 まず、ふたつのルールを組み合わせて、並列計算することを考えてみます。

Rule Main
	input   '*.in'.all
	output  '*.out'.all
Flow
	rule First
	rule Second
End

Rule First
	input   '*.in'
	output  '{$I[1][1]}.route'
Action
	awk '{ print $1*2 }' {$I[1]} > {$O[1]}	
End

Rule Second
	input   '*.route'
	output  '{$I[1][1]}.out'
Action
	awk '{ print $1+1 }' {$I[1]} > {$O[1]}	
End

 実行結果を以下に示します。最初に5つのタスク(First)が並列で動いているのがわかります。 その後、終了した順に、次のルールが動いています。

$ pione-client Serial2.pione -i SerialInput/ -b Serial2Output
 ==> &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   --> Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
     --> Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
           >>> &Anonymous:Main([test1.in],{})
           >>> &Anonymous:Main([test2.in],{})
           >>> &Anonymous:Main([test3.in],{})
           >>> &Anonymous:Main([test4.in],{})
           >>> &Anonymous:Main([test5.in],{})
 ==> &Anonymous:Main([test1.in],{})
   --> Rule Application: &Anonymous:Main([test1.in],{})
     --> Distribution: &Anonymous:Main([test1.in],{})
           >>> &Anonymous:First([test1.in],{})
 ==> &Anonymous:Main([test2.in],{})
   --> Rule Application: &Anonymous:Main([test2.in],{})
     --> Distribution: &Anonymous:Main([test2.in],{})
           >>> &Anonymous:First([test2.in],{})
 ==> &Anonymous:Main([test3.in],{})
   --> Rule Application: &Anonymous:Main([test3.in],{})
     --> Distribution: &Anonymous:Main([test3.in],{})
           >>> &Anonymous:First([test3.in],{})
 ==> &Anonymous:Main([test4.in],{})
   --> Rule Application: &Anonymous:Main([test4.in],{})
     --> Distribution: &Anonymous:Main([test4.in],{})
           >>> &Anonymous:First([test4.in],{})
 ==> &Anonymous:Main([test5.in],{})
   --> Rule Application: &Anonymous:Main([test5.in],{})
     --> Distribution: &Anonymous:Main([test5.in],{})
           >>> &Anonymous:First([test5.in],{})
 ==> &Anonymous:First([test1.in],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1*2 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:First([test1.in],{})
     <-- Distribution: &Anonymous:Main([test1.in],{})
     --> Distribution: &Anonymous:Main([test1.in],{})
           >>> &Anonymous:Second([test1.route],{})
 ==> &Anonymous:First([test2.in],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1*2 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:First([test2.in],{})
     <-- Distribution: &Anonymous:Main([test2.in],{})
     --> Distribution: &Anonymous:Main([test2.in],{})
           >>> &Anonymous:Second([test2.route],{})
 ==> &Anonymous:First([test3.in],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1*2 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:First([test3.in],{})
     <-- Distribution: &Anonymous:Main([test3.in],{})
     --> Distribution: &Anonymous:Main([test3.in],{})
           >>> &Anonymous:Second([test3.route],{})
 ==> &Anonymous:First([test4.in],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1*2 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:First([test4.in],{})
     <-- Distribution: &Anonymous:Main([test4.in],{})
     --> Distribution: &Anonymous:Main([test4.in],{})
           >>> &Anonymous:Second([test4.route],{})
 ==> &Anonymous:First([test5.in],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1*2 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:First([test5.in],{})
     <-- Distribution: &Anonymous:Main([test5.in],{})
     --> Distribution: &Anonymous:Main([test5.in],{})
           >>> &Anonymous:Second([test5.route],{})
 ==> &Anonymous:Second([test1.route],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1+1 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:Second([test1.route],{})
     <-- Distribution: &Anonymous:Main([test1.in],{})
   <-- Rule Application: &Anonymous:Main([test1.in],{})
 <== &Anonymous:Main([test1.in],{})
 ==> &Anonymous:Second([test2.route],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1+1 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:Second([test2.route],{})
     <-- Distribution: &Anonymous:Main([test2.in],{})
   <-- Rule Application: &Anonymous:Main([test2.in],{})
 <== &Anonymous:Main([test2.in],{})
 ==> &Anonymous:Second([test3.route],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1+1 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:Second([test3.route],{})
     <-- Distribution: &Anonymous:Main([test3.in],{})
   <-- Rule Application: &Anonymous:Main([test3.in],{})
 <== &Anonymous:Main([test3.in],{})
 ==> &Anonymous:Second([test4.route],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1+1 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:Second([test4.route],{})
     <-- Distribution: &Anonymous:Main([test4.in],{})
   <-- Rule Application: &Anonymous:Main([test4.in],{})
 <== &Anonymous:Main([test4.in],{})
 ==> &Anonymous:Second([test5.route],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1+1 }' {$I[1]} > {$O[1]}	
  SH ------------------------------------------------------------
 <== &Anonymous:Second([test5.route],{})
     <-- Distribution: &Anonymous:Main([test5.in],{})
   <-- Rule Application: &Anonymous:Main([test5.in],{})
     <-- Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
 <== &Anonymous:Main([test5.in],{})
   <-- Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
 <== &Anonymous:Root([test1.in,test2.in,test3.in,...],{})

一度、終了しましたので、次は実行されません。

$ pione-client Serial2.pione -i SerialInput/ -b Serial2Output
 ==> &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   --> Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   <-- Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
 <== &Anonymous:Root([test1.in,test2.in,test3.in,...],{})

さて、ここで、ファイルをひとつ(test6.in)増やしてみましょう。

$ pione-client Serial2.pione -i SerialInput/ -b Serial2Output
 ==> &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   --> Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
     --> Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
           >>> &Anonymous:Main([test6.in],{})
 ==> &Anonymous:Main([test6.in],{})
   --> Rule Application: &Anonymous:Main([test6.in],{})
     --> Distribution: &Anonymous:Main([test6.in],{})
           >>> &Anonymous:First([test6.in],{})
 ==> &Anonymous:First([test6.in],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1*2 }' test6.in > test6.route	
  SH ------------------------------------------------------------
 <== &Anonymous:First([test6.in],{})
     <-- Distribution: &Anonymous:Main([test6.in],{})
     --> Distribution: &Anonymous:Main([test6.in],{})
           >>> &Anonymous:Second([test6.route],{})
 ==> &Anonymous:Second([test6.route],{})
  SH ------------------------------------------------------------
  SH 	awk '{ print $1+1 }' test6.route > test6.out	
  SH ------------------------------------------------------------
 <== &Anonymous:Second([test6.route],{})
     <-- Distribution: &Anonymous:Main([test6.in],{})
   <-- Rule Application: &Anonymous:Main([test6.in],{})
     <-- Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
 <== &Anonymous:Main([test6.in],{})
     --> Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
     <-- Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   <-- Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
 <== &Anonymous:Root([test1.in,test2.in,test3.in,...],{})

新しくできたファイルだけが作られていることがわかります。 それでは、ファイルの更新がかかったときはどうなるでしょうか。test2.inをtouchコマンドで更新してみました。

$ pione-client Serial2.pione -i SerialInput/ -b Serial2Output2
 ==> &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   --> Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
     --> Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
           >>> &Anonymous:Main([test2.in],{})
           >>> &Anonymous:Main([test6.in],{})
 ==> &Anonymous:Main([test2.in],{})
   --> Rule Application: &Anonymous:Main([test2.in],{})
   <-- Rule Application: &Anonymous:Main([test2.in],{})
 <== &Anonymous:Main([test2.in],{})
 ==> &Anonymous:Main([test6.in],{})
   --> Rule Application: &Anonymous:Main([test6.in],{})
   <-- Rule Application: &Anonymous:Main([test6.in],{})
 <== &Anonymous:Main([test6.in],{})
     <-- Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
     --> Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
     <-- Distribution: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
   <-- Rule Application: &Anonymous:Root([test1.in,test2.in,test3.in,...],{})
 <== &Anonymous:Root([test1.in,test2.in,test3.in,...],{})

となり、新しいファイルであるtest2.in, test6.inに関しては、変更の可能性があるので起動し始めますが、何のルールも適用されないまま終了しています。

応用1(フローの制御)

さて、ここまでの基本1から5を組み合わせて、次の問題を考えてみましょう。

*.mrcと*.prametersで指定される入力ファイルがあります。
*.mrcのそれぞれのファイルから最大値を中心として切り出した*.roiを出力するCenterGet.pioneを考えてみましょう。
但し、*.parametersは以下のフォーマットで切り出しサイズ(Sx, Sy, Sz)を格納しているファイルとします。


*.parametersのフォーマット
Sx Sy Sz



 応用問題1:上記のCenterGet.pioneを作成してみましょう。



解答例1:

Rule Main
	input '*.mrc'.all
	input '*.parameters'.all
	output '*.roi'.all
Flow
	rule First
	rule Second
End

Rule First
	input '*.mrc'
	output '{$I[1]}.info'
Action
	mrcImageInfo -I -i {$I[1]} \
	| head -2 | tail -1 \
	| awk '{printf("%s %s %s", $3, $4, $5)}' \
	| tr -c '[0-9]' ' ' \
	> {$O[1]}
End

Rule Second
	input '*.mrc'
	input '*.info'
	input '{$I[1][1]}.parameters'
	output '{$I[1][1]}.roi'
Action
	Center_x=$(awk '{printf("%s\n", $1)}' {$I[2]})
	Center_y=$(awk '{printf("%s\n", $2)}' {$I[2]})
	Center_z=$(awk '{printf("%s\n", $3)}' {$I[2]})
	N_x=$(awk '{printf("%s\n", $1)}' {$I[3]})
	N_y=$(awk '{printf("%s\n", $2)}' {$I[3]})
	N_z=$(awk '{printf("%s\n", $3)}' {$I[3]})
	mrcImageCenterGet -i {$I[1]} -o {$O[1]} \
		-Cx $Center_x -Cy $Center_y -Cz $Center_z \
		-Nx $N_x -Ny $N_y -Nz $N_z
End