Deletions are marked like this. | Additions are marked like this. |
Line 73: | Line 73: |
これを実現したのがTAlSAMURAIAllExampleで、AnapawであったAnalyzer Flagも実装している。 | これを実現したのがTAlSAMURAIAllExampleで、AnapawであったAnalyzer Flagも実装している(AnaFileのページに一行使い方を書いた)。 |
Line 139: | Line 139: |
Contents
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の概要
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()で表示するためだけに存在する。
anapaw: valに詰める -> anaroot: Add関数
valに詰める代わりにAdd関数を使う。 このときanapawではデータが無いときに非物理量(-1000等)を詰めていたが、 anarootではAddしなければhistogramにはfillされない。 なので、非物理量を意識するという労が必要なくなる(実際にはやっぱりなくならない)。 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の書き方は限られる。
AnaLoopのMerge
各検出器ごとにAnaLoopを作っていたが、やはりこれをくっつけたくなる。 これを実現したのがTAlSAMURAIAllExampleで、AnapawであったAnalyzer Flagも実装している(AnaFileのページに一行使い方を書いた)。 とりあえず、この機能が必要なときはパクってください。
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のときの添字はとりあえず他とかぶらなければ何でもいい(かぶりのチェックが入るのでまぁ。数の大きさの制限はある。負もだめ)。
ということで、以上。