Locked History Actions

Diff for "ANAROOT/Manual/analoop"

Differences between revisions 12 and 13
Deletions are marked like this. Additions are marked like this.
Line 4: Line 4:

=== AnaLoopの2つの使い方 ===
==== libraryに組み込み ====
source/AnaLoop以下に正しく作れはroot上で見える。
標準的なものを作ってblack boxとしてユーザーに使わせるのに向いている。

==== 手元にmacroとして置いておいて動的にload ====
libraryに組み込むのと同じソースをroot上で動的にloadすることもできる。
{{{
root[i] .L macros/TArtAnaLoopUser.C+
}}}
こう書くとコンパイルしてロードしてくれる。
.xはコンパイルして実行なのでだめ。
ちょくちょく書き換える場合やrootに慣れていて直接TH1とかをanaloopクラス内で
constructする場合に向いている。
Line 49: Line 34:
=== AnaLoopの2つの使い方 ===
==== libraryに組み込み ====
source/AnaLoop以下に正しく作れはroot上で見える。
標準的なものを作ってblack boxとしてユーザーに使わせるのに向いている。

==== 手元にmacroとして置いておいて動的にload ====
libraryに組み込むのと同じソースをroot上で動的にloadすることもできる。
{{{
root[i] .L macros/TArtAnaLoopUser.C+
}}}
こう書くとコンパイルしてロードしてくれる(.xはコンパイルして実行なのでだめ)。
ちょくちょく書き換える場合やrootに慣れていて直接TH1とかをanaloopクラス内で
constructする場合に向いている。

=== AnaLoopを継承した特殊なクラスTAlEncExample ===
TAlEncExampleではTAlEncSubを継承したクラスを登録して、それを登録した順に解析する特殊なAnaLoop。
手動で登録する場合は、
{{{
root[i] TAlEncExample* alencexample = new TAlEncExample;
root[i] alencexample->Register(new TAlEncSAMURAIExample);
root[i] alencexample->Register(new TAlEncDALIExample);
root[i] alencexample->Register(new TAlEncNEBULAExample);
root[i] book(alencexample);
root[i] push("ridf/sm_com/sdaq02/run0140.ridf");
root[i] start();
}}}
という感じで登録する。
anafileを使う場合はanafileで<analys>を使うことで自動的に登録作業が行われる。
{{{
# hoge.ana
<analys> 0,15,12,
}}}
あとは普通に、
{{{
root[i] book(new TAlEncExample, "hoge.ana");
root[i] push("ridf/sm_com/sdaq02/run0140.ridf");
root[i] start();
}}}
とすればよい。
TAlEncExampleを使う場合はstopとかも使える。

=== 自前の計算ルーチンを組み込む ===
TAlEncSubを継承したクラスを自作してRegisterすればよい。
これの作り方はTAlEncUser.CとTAlEncUser.hhを参考にしてください。
Line 70: Line 100:

=== AnaLoopのMerge ===
各検出器ごとにAnaLoopを作っていたが、やはりこれをくっつけたくなる。
で、一度TAlSAMURAIAllExampleで各AnaLoopを多重継承して実現したけど、これだとコントロールの自由度が低いので、
結局TAlSuperというAnaLoopクラスを作り、その中ではTAlSubという基底クラスを登録してもらって
動的に解析するものやその順序を変更できるようにした。

=== AnaLoopを改造して自分のAnaLoopを作ろうの巻 ===
まずはコピー。
{{{
$ anarootlogin hoge
ないし、
$ acd
$ cp ./src/sources/AnaLoop/src/TAlSAMURAIAllExample.cc ./macros/analoop/TAlSAMURAIAll.C
$ cp ./src/sources/AnaLoop/include/TAlSAMURAIAllExample.hh ./macros/analoop/TAlSAMURAIAll.hh
}}}
名前のExampleを取るのが良いかと思う。習慣的に.ccは.Cに変更。
file名に合わせてクラスの名前も変更。
{{{
$ emacs -nw ./macros/analoop/TAlSAMURAIAll.C
$ emacs -nw ./macros/analoop/TAlSAMURAIAll.hh
}}}
emacsの文字置換とかを使ってTAlSAMURAIAllExampleを全てTAlSAMURAIAllに変更。
あと、.hhの一行目二行目もEXAMPLEの文字を消しておく。

ここで一旦rootで使ってみる。
{{{
$ root -l
root[0] .L ./macros/analoop/TAlSAMURAIAll.C+
どばどばー
root[1] book(new TAlSAMURAIAll, "ana/hoge.ana")
root[2] push("ridf/sm_com/sdaq2/run0140.ridf")
root[3] start()
}}}
この時点ではTAlSAMURAIAllExampleを使ったときと同じ動作をするはず。
ここまでokなら、あとは適当にいじっていくだけ。
基本的には、TAlSAMURAIAll.CのCalculate()のところに、
{{{
void TAlSAMURAIAll::Calculate()
{
  if(fAnalyserFlag[Analyser::GLOBAL]) TAlSAMURAICoinExample::Calculate();
  if(fAnalyserFlag[Analyser::NEBULA]) TAlNEBULAExample::Calculate();
  if(fAnalyserFlag[Analyser::DALI]) TAlDALIExample::Calculate();
  if(fAnalyserFlag[Analyser::SAMURAIPLA]) TAlSAMURAIPlaExample::Calculate();
  if(fAnalyserFlag[Analyser::SAMURAIHOD]) TAlSAMURAIHODExample::Calculate();
  if(fAnalyserFlag[Analyser::SAMURAIDC]) TAlSAMURAIDCExample::Calculate();

  for(int i=0; i<144; ++i){
    double quraw;
    bool quraw_flag = Get(Analyser::NEBULA,WNum::NEBULA::QURaw,i,quraw);
    if(quraw_flag){
      std::cout << "id: " << i << ", val: " << quraw << std::endl;
    }
  }
  double quraw1, quraw2;
  double quraw1_flag = Get(Analyser::NEBULA,WNum::NEBULA::QURaw,1,quraw1);
  double quraw2_flag = Get(Analyser::NEBULA,WNum::NEBULA::QURaw,2,quraw2);
  if(quraw1_flag && quraw2_flag){
    Add(101,1,102,quraw1-quraw2); //他とかぶらなければ三つの添字は何でもいい。
    Add(101,2,102,sqrt(quraw1*quraw2));
  }
}
}}}
のように、Get関数で値が取ってこれる。
Getの第1引数はAnalyser, 第2引数はwnum, 第3引数はindex(ch), 第4引数は値を格納したい変数を渡す(参照渡し), 戻り値は真偽値。
Addしていない値をGetしに行った場合は、戻り値が偽となるので、必ずチェックすること。
あとは適当に計算して、Addすればanafileからアクセスできる。
Addのときの添字はとりあえず他とかぶらなければ何でもいい(かぶりのチェックが入るのでまぁ。数の大きさの制限はある。負もだめ)。

ということで書いたけど、AlSuperクラスを使ったのでだいぶ話が変わってしまった。
あー。。。とりあえず直接教えます。

AnaLoopの概要

AnaLoopとは解析の流れ、およびコントロールをするインターフェースクラス。 TArtAnaLoopが正確な名前でこれを継承したクラスを作成し、解析内容を実装する。 子クラスではConstruct(), Calculate(), Destruct(), ClassName()の実装が 要求される。 以下に各関数の説明を書くが、macros/analoopにあるsampleやsourceを見るほうがわかりやすい気もする。

Construct()

TArtCalibNEBULAとかをnewする。 TH1とかのnewはConstruct()やコンストラクタではなく、 book関数をオーバーロードしてその中で行なってください。 具体的には、TArtAnaLoopUserクラスを作った場合なら、

void book(TArtAnaLoopUser* analoop)

という関数を作るということです。 具体例がmacros/analoop/TArtAnaLoopUser.Cにあるはずです。 newしたTH1のdeleteはデストラクタで。

Calculate()

毎loop呼ばれるので、oneloopの処理を書く。 手動でif文で条件別けして途中で抜けるのは構わない。

Destruct()

newしたTArtCalibNEBULAとかをdeleteする。

ClassName()

これは実は単にstatus()で表示するためだけに存在する。

AnaLoopの2つの使い方

libraryに組み込み

source/AnaLoop以下に正しく作れはroot上で見える。 標準的なものを作ってblack boxとしてユーザーに使わせるのに向いている。

手元にmacroとして置いておいて動的にload

libraryに組み込むのと同じソースをroot上で動的にloadすることもできる。

root[i] .L macros/TArtAnaLoopUser.C+

こう書くとコンパイルしてロードしてくれる(.xはコンパイルして実行なのでだめ)。 ちょくちょく書き換える場合やrootに慣れていて直接TH1とかをanaloopクラス内で constructする場合に向いている。

AnaLoopを継承した特殊なクラスTAlEncExample

TAlEncExampleではTAlEncSubを継承したクラスを登録して、それを登録した順に解析する特殊なAnaLoop手動で登録する場合は、

root[i] TAlEncExample* alencexample = new TAlEncExample;
root[i] alencexample->Register(new TAlEncSAMURAIExample);
root[i] alencexample->Register(new TAlEncDALIExample);
root[i] alencexample->Register(new TAlEncNEBULAExample);
root[i] book(alencexample);
root[i] push("ridf/sm_com/sdaq02/run0140.ridf");
root[i] start();

という感じで登録する。 anafileを使う場合はanafileで<analys>を使うことで自動的に登録作業が行われる。

# hoge.ana
<analys> 0,15,12,

あとは普通に、

root[i] book(new TAlEncExample, "hoge.ana");
root[i] push("ridf/sm_com/sdaq02/run0140.ridf");
root[i] start();

とすればよい。 TAlEncExampleを使う場合はstopとかも使える。

自前の計算ルーチンを組み込む

TAlEncSubを継承したクラスを自作してRegisterすればよい。 これの作り方はTAlEncUser.CとTAlEncUser.hhを参考にしてください。

anapaw: valに詰める -> anaroot: Add関数

valに詰める代わりにAdd関数を使う。 このときanapawではデータが無いときに非物理量(-1000等)を詰めていたが、 anarootではAddしなければhistogramにはfillされない。 でも、非物理量を意識する必要はやっぱりあり、今NaNを使う方針が進行している。 TDCのover flowとかを詰めたいのなら詰めて構わないがその分パフォーマンスは落ちる。

EAnalyser and EWNum

EAnalyserとEWNumはAnaFileでIDで物理量を指定するための列挙体。

src/source/AnaLoop/include/EAnalyser.hh
src/source/AnaLoop/include/EWNum.hh

に書く。 わかりやすいように定義の後ろに数字を書いているが、 現在はroot上で

root[i] lv();

と打てば見れるので書かなくてもいい。 ただし、C++の文法に完全に対応した処理をしているわけではないのである程度EAnalyser.hhとEWNum.hhの書き方は限られる。