HEPtech     - 私的ユーティリティー:TUtilクラス -
トップページ | Tips | Topics
<私的ユーティリティー:TUtilクラス>

 ここでは私のROOTの使い勝手の向上を目的として開発している私的ユーティリティー:TUtilクラスを紹介します。 ダウンロードはコチラから。

 TUtilクラスは、私がROOTを用いる上でしばしば必要とするさまざまな機能を担ったユーティリティークラスです。 もちろんコンパイルして実行できるように(正しく)記述されています。 主な機能としては以下のようなものがあります(TUtil v0.5.0_20090922版に準拠)。
  • セッションの初期化
    • Styleの初期化
    • Canvas生成とPadの分割
    • PostScript/PDFファイルの出力
    • ROOTファイルの出力
  • プロットの描画管理
    • 必要に応じたPadの移動
    • 重ね書き時の線とマーカーの色処理
  • その他の機能
    • ROOTファイルに保存されるTGraphなどの生成
    • ROOTファイルから特定のヒストグラムの抽出&描画
このユーティリティーのそもそもの開発動機というか、ウリは何と言っても二つ目の描画管理です。 以下ではこれらの機能について説明していきます。


 まず始めにセッションの初期化についてです。 gStyleによる自分好みのスタイルへの初期化、Canvasの生成と複数のPadを用いる人はPadの分割、 描画したグラフのPostScriptへの出力、生成したオブジェクトのROOTファイルへの出力。 これらの操作は多くの場合毎回必要とされる操作であり、 当たり前のように毎回同じように処理される方が(少なくとも私にとっては)使い勝手がよいです。 TUtilクラスはオブジェクトを生成するだけで、これらが全て自動で行われます。 デフォルトの設定ではそれぞれ、白黒でフラットなシンプルなスタイル、 Canvasは画面左上から縦長の640x856(私の作業環境 MacBookPro 1440x900 基準)、 PadはこのCanvasを2x3に分割、 出力するPostScriptファイル名とROOTファイル名はそれぞれ "t.ps" と "t.root" になっていますが、 これらは自分の好みに合わせて比較的簡単に変更する事ができます。 これらの出力ファイルは、上書き実行時でも一世代だけリネームして残すようになっています。 また、最初はPadの分割を2x3で描画し、途中から3x4に増やしたり、1x2に減らしたりする事もできます。 このクラスの用い方は以下のようにします。

#include "TUtil.C"

TUtil* u=new TUtil;
...
...
delete u;

注意点としては、このオブジェクトは最後にちゃんと delete してください。 ROOTファイルの書き出しやPostScript/PDFファイルのクローズをデストラクタで行っているので、 delete を行わないとこれらが正しく出力できない恐れがあります。


 次にプロットの描画管理について説明します。 Padを分割している場合、プロットを描画する手順は「ログスケールの設定→プロット描画→Pad移動」、 或は重ね書きをする場合は「線色等の変更→プロット描画→Pad移動」という流れになると思います。 TUtilクラスではこれらを1行で一括して行う事ができ、 しかもTH1F, TH2Dなどのヒストグラム、TTreeやTGraphなどを同様に操作する事ができます。 引数の順序は1つ目に描画したいオブジェクト(又はそのポインタ)を指定する点を除き、 以降は通常の引数と同じ順序になっているので使い勝手は損ないません。 またヒストグラムに至ってはDrawだけでなくFitも同様に扱う事が出来ます。 さらにPadの移動では、現在何番目のPadにいるかを意識する必要はなく、 最後まで行ったら自動的にPostScript/PDFを新しいページにして1つ目のPadに移動します。 以下に示すのは左がROOTの通常使用時に期待されるコードで、右が同じ操作をTUtilクラスを用いて書いた例です。 TUtilクラスを用いると非常にコンパクトで分かりやすいコードになっているのがお分かりいただけますでしょうか? (tree, hist, graph, c1, ps, u はそれぞれTTree, TH1, TGraph, TCanvas, TPostScript, TUtilへのポインタです)

<通常使用時にありそうなコード> <TUtilを用いた同じ内容のコード>
gPad->SetLogz();
tree->Draw("y:x","k>0","colz");
c1->cd(2);
gPad->SetLogx();
gPad->SetLogy();
tree->Draw("x","y<0");
hist->SetLineColor(2);
hist->SetMarkerColor(2);
hist->Draw("sameE");
c1->cd(3);
gPad->SetLogy();
hist2->Fit("gaus","Q");
c1->cd(4);
graph->Draw("AP");
graph2->SetLineColor(2);
graph2->SetMarkerColor(2);
graph2->Draw("P");
...
c1->Update();
ps->NewPage();
c1->cd(1);
u->Draw(tree,"y:x","k>0","colz",001);
u->Draw(tree,"x","y<0","",110);
u->Draw(hist,"sameE");
u->Fit(hist2,"gaus","Q",010);
u->Draw(graph,"AP");
u->Draw(graph2,"P");

大体直感的に分かるかとは思いますが、いくつかコメントを付け加えて説明します。 使い方は基本的には上で述べたように、描画したクラスオブジェクトの次に通常描画時の引数が続きます。 引数の最後にある3桁の数字は左からxyzの順でログスケール描画のフラグです。 描画オプションに"same"が含まれていれば(TGraphの場合は"A"が無ければ)、 直前に書いたプロットに重ね書きをし、そうでない場合は次のPadに移動します。 重ね書き時には自動的に線とマーカーの色を変えて描画します。 重ね書き時に用いる色の順序はデフォルトでは「黒→赤→青→...」と続きますが、 これは TUtil::SetColorTable(std::vector<int> colorTable) で自分で指定する事が出来ます。 TTreeをDrawした場合は、返り値がTH1へのポインタになっているので、 これを受ける事で、TTreeからProjectして作ったヒストグラムのように続けて操作する事が可能です。 補足事項として、TUtilクラスによる描画管理はヒストグラムのFitは同様に扱えますが、 TGraphのFitは扱えるようにしていません。 これは、そもそもTH1::Fitはフィッティングオプションに "0" や "N" を指定しない限り、 TH1::Fitとするだけでフィットした関数と共にヒストグラムも描画されますが、 TGraph::Fitは一切の表示しない仕様であるため、これに合わせた仕様にしています。


 その他の機能として(特定の操作をしなくても)ROOTファイルに出力される空のTGraphなどの生成と ROOTファイルから特定のヒストグラムの抽出&描画があります。 はっきり言ってこれらはこのTUtilクラスのメンバー関数である必要性は皆無なのですが、 まぁユーティリティーではあるということだけで、全く必然性も無くTUtilの機能として追加されました。 ROOTでは何故かTGraph系列の取り扱いだけ他と異なるようで、 newで生成しただけではROOTファイルに出力されません。 また gDirectory->Append(graph); などとしても "Graph;1" などという味気ない名前で出力されます。 これではROOTファイルから読み出す時に随分とメンドウな事になります。 TUtil::NewTGraph("graphName") はこれらの問題を解決します。 ROOTファイルからのヒストグラムの抽出&描画機能 TUtil::ViewHistsは、 ヒストグラムを含むROOTファイルから、指定したキーワードを含む名前のヒストグラムのみを連続して描画することができます。 キーワードを省略すると含まれる全てのヒストグラムを描画します。


 最後にこのTUtilクラスを用いたrootlogon.Cとrootlogoff.Cについて少しだけ。 Styleを初期化し、Canvasを開き、Padを分割し、PostScript/PDFとROOTファイルを出力するという基本的な操作を自動で行う仕様上、 このクラスを用いると、大変簡潔にrootlogon.Cを記述する事が出来ます。 以下はその例です。

  "rootlogon.C"
#include "TUtil.C"

TUtil* u;
void rootlogon(void){
  u=new TUtil;
}

  "rootlogoff.C"
void rootlogoff(void){
  delete u;
}

このようにしておくと、TUtilへのポインタをROOTセッション上で扱う事が出来ます。 上でも述べましたが、最後にrootlogoff.Cで delete するのを忘れないでください。 注意点としては、PostScript/PDFファイルやROOTファイルに出力したいオブジェクトは、 ROOTセッション内では new で生成するようにしてください。 ROOTファイルを吐き、PostScript/PDFファイルを閉じる操作を行うデコンストラクタは、 rootlogoff内で delete される時に実行されますが、 ROOTセッション内で通常の変数として定義されたものはrootlogoffが呼ばれる時には 既に消滅してしまっているため、PostScriptファイルやROOTファイルには反映されません。
[追記] v0.2.0以降で、PostScript/PDFファイルには反映されるようになりました。
2005-2017 HEPtech All rights reserved. Link/Unlink free.
inserted by FC2 system