ROOT


treeのinteractive modeでstd::vector::size()を呼ぶ

当然できると思っていて、実は一癖あった。
http://root.cern.ch/phpBB3/viewtopic.php?f=3&t=13564
デフォルトではvector自体ではなく、vectorの要素に対する動作になるみたい。
なので、vector自体の関数を呼びたいときは"@"をつけるそうな。
root[0] tree->Draw("coin@.size()")
とか。T野さんに聞かれるまで知らなかった...

.rootrcのTTF

これのtrue, falseの切り替えを行ってもなぜか変化がないときがある。
これは、.x hoge.C+とか.L hoge.C+でmacroを呼んだときは
コンパイルしたときのtrue, falseを受け継ぐみたい。

xとyのtitleのoffsetが異なるときのprojection yしたとき

なぜかxのtitleのoffsetがyのoffsetになる。
面倒なのでepsを直編集の方が早い感じ。
epsを開いて、中身をtitleで検索して、titleの位置だけ違うファイルを作って比較するとどこをいじればよいかわかる。
まぁ一ヶ所編集するだけなので勘で多分あたります。

gridがframeの上に書かれる

gridを書いたときに、端っこが切りのいい数字だとframeの上にgridが書かれる。
gridとframeの色が同じならよいが、gridの色を薄くしていたりするとかぶって汚い。
なので、
  TFrame* frame = gPad->GetFrame();
  frame->SetFillStyle(0);
  frame->Draw("same");
で解決。

横軸のメモリ間隔

TAttAxis::SetNdivitions(505)とか

Histogramとか軸全体の大きさ

フォントを大きくすとすぐに文字がはみ出す。
    gStyle->SetPadRightMargin(0.15);
    gStyle->SetPadLeftMargin(0.15);
    gStyle->SetPadTopMargin(0.14);
    gStyle->SetPadBottomMargin(0.14);
で解決。

Stat Size

右上のboxの大きさだが、gStyle->SetFitOpt(1)していると勝手に縦の大きさが変わる。
http://root.cern.ch/root/roottalk/roottalk98/0683.html
replyされているけど反映されずに放置されている。

NaNを積極的につかう。

NaNを非物理量に使いたいと思っていろいろ調べている。

NaNは浮動小数

考えれば当たり前だが、intでNaNを表すことはできない。
http://www.aerith.net/cpp/typical_bug-j.html
ということで、物理量計算においては一貫してdouble等を使う必要がある。
問題は、RawDataをintにしたいという意見がもちろん出るであろうこと。
4096程度ならDoubleでも正確に表せるので(15桁ぐらいは誤差なく表せる)、問題はないのだが、
RawDataもdoubleにするのは賛同が得られないかもしれない。
ridfからデータを取ってきて格納するときはintで格納して、
Reconstructで計算する時はdoubleにするのが現実的な案かと。

NaNにする利点

結局はRawDataが範囲外のときを除外したいだけなのだが、
従来の様に適当に-1000とかを使っていると、毎回毎回if文を書く必要があるし、
場合によっては打ち消しあってしまうことを恐れて小細工をする必要がある。
これが、NaNはいつも伝搬してくれるので(ただし、0*NaNもNaNになると思われる)、まったくif文が必要なくなる。
さらに、非物理量を一律NaNに統一してしまえば、検出器ごとの物理量の範囲を気にしなくて良くなり、
異なる検出器からデータを引っ張ってきて計算するときに特に楽になる。
また、NaNを読み飛ばすことで解析速度を上げることもできる。

ROOTでNaN等

ちょっとroottalkのmemo
http://comments.gmane.org/gmane.comp.lang.c%2B%2B.root/11063

NaNの生成

標準の関数があるけど、せっかくROOTがラップしてくれてるので、
TMath::QuietNaN();
を使う。もう一つ、
TMath::SignalingNaN()
なるものもあるけれど、これを呼ぶとNaNが予期せぬ時に発生した場合と区別がつかなくなるのでだめ。
sqrt(-1)とかでもNaNを発生できるけど、多分良くない。
ANAROOT全体で使うとなったときは使い方や癖をまとめる必要がある。

TH1にNaNをFill

特に何も問題は起きない。overflowのbinに詰められる。event数としては数えられる。
nan,infそれぞれの動作チェックの例
TH1* hnan  = new TH1D("hnan",  "title", 100,0,100);
TH1* hnannan  = new TH2D("hnannan",  "title", 100,0,100, 100,0,100);
TH1* hinfp = new TH1D("hinfp", "title", 100,0,100);
TH1* hinfm = new TH1D("hinfm", "title", 100,0,100);

double x = -1;
double y = 0;
double z = 1;

double nan = sqrt(x);
double infp = z/y;
double infm = x/y;

for(int i=0; i<1000; ++i){
  hnan->Fill(nan);
  hnannan->Fill(nan,nan);
  hinfp->Fill(infp);
  hinfm->Fill(infm);
}
このあとcint上で適当にDraw。

TTreeのBranchにNaNをFill

これも特に何も問題は起きない。Drawするとやはりoverflowのbinに詰められる。
TTree* tree = new TTree("tree", "title");

double x = -1;
double y = 0;
double z = 1;

double nan = sqrt(x);
double infp = z/y;
double infm = x/y;

tree->Branch("nan",  &nan,  "nan/D");
tree->Branch("infp", &infp, "infp/D");
tree->Branch("infm", &infm, "infm/D");

for(int i=0; i<1000; ++i){
  tree->Fill();
}
このあとcint上で適当にDraw。

結論

NaNはいけそう。ただし、一貫してdouble等浮動小数で計算する必要があり、解説が必要。


ROOTの描画が遅い問題

どうも、まずTTFont(true type font)が重いようで、
これを、.rootrcでfalseにすると軽くなる。だけどなぜか落ちるwww
TAttTextのページを見るとFont quality and speedなる項目がある。
また、その上にText Font and Precisionがある。
このPrecisionを0にできたら早い気がするが、どうやって設定するのか。。。
答え) 単にgStyle->SetxxxFont(130)とかするだけだった。

.rootrcのCanvas.SavePrecision

これも下げると早くなりそう。

.rootrcでExecを消せる



.rootrcでTTFをfalse(これが一番効く!!!)

TTFをfalseにするとなんだかかなり落ちる。死ね。
どうも、2Dにおいてy軸に名前を入れるとダメみたい。意味が分からない。
これならROOTtalkに書けば直してくれるかなー...

telnetの方が断然はやい??

http://lappweb.in2p3.fr/virgo/dataDisplay/tests.html
そもそもtelnetってX飛ばせないのか...

Canvasの生成のときにデフォルトコンストラクタの引数でmenubarを消せる




TPolyLine3Dでlogz?

どうも、logにするとバグるっぽい。というかTGraph2Dもなんか変。あせったー。

TThreadのexample

http://root.cern.ch/root/html/tutorials/thread/index.html
ほとんどpthreadと同じ。

TH1のSetDirectory

Directory操作で単純にTDirectory::RemoveしたのちTDirectory::Appendとかすると、TH1はその後で困ったことがおこる。
SetDirectoryの中身を見てみるとfDirectoryをいちいち付け替えていて、これをしてやらないといけないらしい。
つまり、SetDirectoryがあるオブジェクトはそれを呼べと。知るか。
これのせいでdeleteした後に.lsすると落ちるとか死んでくれ。

TDirectory

TDirectoryを保存したいときは、逆に普通にWrite()を呼べばちゃんと保存してくれる。
だけど、違うroot fileに移して保存するにはどうも中身まで一緒に手で移してあげないといけないっぽい。

TList

TList自体を保存したい場合はWrite(0, TObject::kSingleKey)を呼ぶ。
そうすると内部のオブジェクトを展開しない。
これは、TGraphをTListの中に入れてたときは必要になる(かも)。

Directory

ROOTにはTDirectory,TFolder,TListと似通ってるけど違うものがある。
TDirectoryはTListを持っていて、これの中にオブジェクトがはいっている。
TFolderは良くわからんが、多分気にしなくていい。
で、Directoryの簡単な知識。
    gDirectory:グローバルなポインタで、現在のディレクトリをあらわす。
    gDirectory->cd():そのポインタのディレクトリに移動する。
    gDirectory->cd(".."):一個上のディレクトリに移動。
    gDirectory->cd("/aaa"):絶対パスで移動もできる。
    gDirectory->mkdir("aaa"):ディレクトリを作る。

ちなみに、TFileを生成したときにいるディレクトリはroot directoryであり、
gROOTがroot directroyではないっぽい。
だから、.rootを読んだあと、cd("..")とやってもどこにもいかない。

Padのpixelと座標

座標は左下が基準だけど、画像は左上が基準。
つまり、yのmin,maxがpixelと座標では逆になる。
かなりハマった。

TVirtualX

ポチポチ系のコマンドを実装するとき、オブジェクトを作ってそれを描画するとめっちゃ遅い。
かわりに、TVirtualXクラスで直接書くと早い。
参考にしたのはtutorialのhist/exec2.C
同じのを二度書くと消えてくれるっぽい?
これの答えはXOR描画というものらしい。
詳細 http://cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/XLIB/xlib7.html
canvas->FeedBackMode(kTRUE)
ってのでXOR描画がonになる。
なるほど。

TCutG

TCutGにはマニュアルでは見つからないメソッドがある。
これはTGraphを継承しているから。
だけどそれが何かオブジェクト図に出てないからぱっとわからなかった。
IsInsideってTGraphの関数なのね。

あと、cutgをオプションで渡すときは常に[ ]付きじゃないとだめ。良く忘れる。

TH1D

TH1Dとかの実体はTH1.cxxの中に書いてある。テンプレートだからかな?

がっつり

なにこれーーーーーーー
http://homepages.physik.uni-muenchen.de/~Otto.Schaile/hpr.pdf
http://www.bl.physik.uni-muenchen.de/marabou/html/
んー、何とも。

xyblowとcpro

xyblowはcproの特別を思えばいいのか。TCutGをうまく使って書くぞー。

THistPainter

THistPainterはTCutGへのポインタを持っている。これ結構重要かも。
また、fCutに対してIsInsideっていう関数で判定を返してくれる。
この辺を使うことによってcproっぽいことができるのね。

THistPainter::Paint()で今のhistをdrawしてくれるっぽい。何か早いコードがかけるかも?

gCurrentHistってのがあったからexternで無理やり取ってきてみたがこれ結局使ってないっぽい。はぁー。

THistPainter

TH1::GetPainterで取ってこれる。これを使いこなすと良いUIができるっぽい感じ。

Go4

http://www-linux.gsi.de/~go4/go4V04/doxygen/classTGo4PolyCond.html Go4のソースにCreateCutHistogramなるものがあった。

TObject::IsA()

これってまさか何か重要だったりする? TList::ls()を見てて思った。
多分TObject::IsA()はそのポインタの本当のクラス。
TObject::Class()はそのポインタのクラス。
ふーん。

TGlobal

http://sunhe.jinr.ru/docs/root/html/TGlobal.html
全てが見えてしまう。奥の手?

TCutGとTH2

実はTH2のオプションにTCutGを指定することができる。
http://web.physik.rwth-aachen.de/~harm/aixphysik/physikDV/ROOT/root_chapter3.pdf
つまり、TCutGを読んで、これをTH2に渡せば簡単にcproができる。
誰か明示的に紹介してよー。
てか、これの実体のソースがわからない。オプションで文字で渡されるとわかんねー。

hnとかの実装の仕方

TFile::ReadAllして全部のkeyをobjとして読み込み、TFile::GetListでTListを取ってくる。
あとはこれをTIterのコンストラクタに渡すと順次アクセスできるイテレータができる。
これで大体実装できるけど、何か使いにくい。
で、TObjLinkってのがあるんだけど、これがreference manualにのっていない。
だけど、ソースをあさるとTList.hにかかれているではないか。
TObjLinkは双方向にアクセスできるし、最初とか最後って概念もちゃんとあるので便利だじぇー。

ROOT用のコードのデバグ

root上、と言うかcint上だとデバッガが自動で走っているlikeでそっちに処理が奪われる?
これのせいでデバッガを正常に走らせられない。
これを回避するにはcint上で走らせるのではなくて、単独のプログラムとして書いて動かせばいい。
standalone的な。
難しいことはなくてマクロの関数の名前をmainにして必要なヘッダファイルを読み込むようにして、
あとはコンパイルするだけ。
ANAROOTにその例(Macros/standalone)があるのでそれを参考にやればよい。
gdbは便利だなー。

例外をデバッガで捕まえてbacktraceする方法

(参考・引用)http://d.hatena.ne.jp/odz/20070714/1184427916
$ g++ -g `root-config --cflags --libs` test.C -o test
$ gdb test
(gdb) b main
(gdb) run
(gdb) catch throw
(gdb) c
(gdb) bt


なぞエラー(コマンドラインでのコンパイルのみ!通らない)

まじでガチバグ。
意味がわからないが、モジュールとしてのコンパイルも通るし、コマンドラインでも関数が見える。
だけどマクロのコマンドラインでのコンパイルが通らない。
ディレクトリを変えたら関数が見えるようになってコンパイルが通るようになった。
死ね。

なぞエラー(#inlcudeとかがエラー文字にでる)

時間がかかる計算で、たまに謎落ちする。
これは例外が投げられているからと思われる。
大概はpush_backとか、そういうのが無限に続いてメモリ確保でエラーになってるとか。
メモリ確保で問題が起きなければ永遠に計算してくれる(はず)。

Draw

Drawにはまった。
macro内で宣言したTF1型のローカル変数のTF1::Drawをそのmacro内で呼ぶ。
一見問題ないように見えるが、Drawは実際はこの瞬間には行われなく、
macroの処理が全て終わってからcanvasが更新される。
この更新のタイミングにはローカルに宣言したTF1はもう存在しないので
まっとうにDrawできなくなる。
対処法としては、newで宣言してスコープを抜けても消えないようにするか、
TCanvas::Updateをmacro内で呼ぶ必要がある。

メンバ関数ポインタ

オーバーロードされたメンバ関数のポインタを渡したいときには、
    
static_cast( &CHoge::add )

とすればよいみたい。
http://eseken.dtiblog.com/blog-entry-21.html

これが必要になるのは、TF1でメンバ関数を渡すときとか。

TF1にメンバ関数を渡したい場合

どうもstaticだとだめっぽい。あとは公式のTF1に書いてあるとおりで良い感じ。
DでもEでもどちらも普通にいけた。staticが犯人かーー。
公式ではdoubleで書いてるがDouble_tでも問題ないっぽい。

んー、static宣言したメンバ関数は単なる関数として扱える(はず)なので、
どうも普通の関数としてわたせばいいっぽい。試してないけど。

TF2,TF3の場合には末尾のchar二個は省略できないっぽい。

MCシミュレーションでROOT標準のオブジェクト(TGraphとかTF1とか)を使う場合

何度もオブジェクトを生成・破棄するとかなりロスがある。
もちろん普通の変数もstaticにしておいて再度メモリ確保させない方が早いが、
これは計算速度の方が律速になると思われるので無視。
しかし、ROOT標準のオブジェクトはかなり巨大なのでメモリ確保がネックとなる。
だからstaticで宣言しておいて再利用するようにするとグッと早くなることがある。
staticで宣言した場合は状況に適した方法で初期化が必要なことは忘れずに。

TTree::Fillで文句を言われる

TTree::Fillを読んだときに、
This error is symptomatic of a Tree created as a memory-resident Tree
Instead of doing:
TTree *T = new TTree(...)
TFile *f = new TFile(...)
you should do:
TFile *f = new TFile(...)
TTree *T = new TTree(...)
というエラーが大量に吐かれるが、正常に動作するというのはたまにある。
これは、TFileでファイルを開くときに"READ"で開いていることが原因の場合が多い。
"READ"だとファイルに書き込み権限はないのでFillするときになにかおかしくなる、というイメージ
(実際にはメモリに持っておくので正常に動作する?)。
なんで、新しくTFileを開くとか、TTreeをSetDirectory(0)でディレクトリから抜いておくとかするとエラーがなくなる。
あとはROOTファイルを作成したROOTと解析しているROOTのバージョン違いでも出る気がした。

可変長配列(vectorとか)をTTreeに格納

普通にできるんですね。
いちいち/Iとか指定してTTreeに格納しなくても、
そのクラスをROOTに通知すればTTreeに格納できるみたい。
単純なstructとかだったらそれすらしなくてもいい。

TTreeのマニュアルの Case B の方法。
始めてROOT使うときはこの方法は使わないと思うが、
これによって可変長配列とかも扱える。
なんで、基本的に回収したいデータを何かのDataクラスとかでまとめちゃって、
それをぶち込むのが簡潔でただしいんだとおもう。
これでTrackerがよく例に出てくる理由がわかった。
一回のイベントでなんかトラックを得るんだけど、これを直接treeに格納しないと
めんどうだもんね。
解析するときはSetAddressとかMakeClassとかそういうのを使って解析する必要が有る。
Drawメソッドを実装しとけばTTree::Draw()で呼んだときにDrawを呼んでくれるかも。

以下はvectorを格納するためのtutorial
http://root.cern.ch/root/html/tutorials/tree/hvector.C.html

こんな感じでTH1を格納したら、名前が同じものを二回Drawすることによってフリーズした。
この辺の名前のかぶりはそれなりに気にしたほうがいいかも。
気にしなくてもうまくいくところはうまくいく。

簡素にvectorとTH1FをTreeに埋め込んで、それを取り出す sample macro

これがわかったのでけっこう使い方変わってくるなー。
あとはArrayManagerを完全に自作してるけど、TList系を使ったりとかでROOTにすりよって書きたい。


TTreeにオブジェクトを直接格納する場合の注意。

公式に書いてあるんだが、直感的に気にするのを忘れがちなこと。
Note: The pointer whose address is passed to TTree::Branch must not
be destroyed (i.e. go out of scope) until the TTree is deleted or
TTree::ResetBranchAddress is called.
つまり、TCut* cut = new TCut("cut", "title");
とかをこの方法(公式マニュアルのTTreeのCase B)で格納したときに、そのポインタのポインタ自体が消えてはならない。
まぁ、渡すものをnewして保持しておくのはよくあることだが、そんなの自分でもっといてよー。と思ってしまう。
半日これでつぶれたーーーーーーーーー。

ちなみに、ポインタのポインタを渡すのではなく、単にポインタを渡すバージョンもある。どちらが良いのかはよくわからない。

Branch("name/C")について

例えばクラスを、
class event{char[10] name; double x; double p;};
と定義していた場合に、
Branch("event", & event, "name/C:x/D:p/D")などとして名前を格納したくなるが、
後ろの変数にアクセスする場合にこのままだとおかしくなる。
で、name[10]と確保した場合はBranch("event", & event, "name[12]/C:x/D:p/D")とするとうまくいく。
[10]なのに[12]でうまくいく。
多分クラスで宣言したときのメモリの確保の仕様からくると思う。
試した感じだと、どうも4byteごとにメモリを確保してるっぽい。
つまり、name[]/Cの中身は確保したメモリを超える最小の4の公倍数っぽい。
8なら8, 10なら12, 11でも12みたいな。
g++だけの仕様かもしれない。

でも、こうやってメモリサイズを意識するのはバグの元、無駄、というものなので、格納する変数をクラスにまとめて、
そのクラスのbranchを作るか、あるいはTStringやstd::stringを格納しましょう。
doubleの配列とかも、std::vectorを格納すればよし。

ROOTでgdb

デフォルトでgdbのbtが実行されてる?で、ユーザーがつくったmacroとかも、コンパイルするときに
-gオプションをつけとけば、どの関数の何行目で落ちたかわかる。
また、コマンドラインでコンパイルする場合は、
gSystemp->CompileMacro("macro.C", "-g")
とすれば同じようにbtされる。
デバグが楽になるかな。

TGraphとかの点

点を消したいときは、
SetMarkerStyle(20) (塗りつぶし丸)
SetMarakerColor(0) (白塗り)
でとりあえず見えなくなる。
だめすぎる。

ROOTの基本思想

ROOTを使い始めたばかりだと、
単にpawをオブジェクト指向で書いただけのめんどくさい
プログラムに思えるかもしれない。
だけど、実際には高度なオブジェクト指向が実現されている。
と、だけ言うと抽象的で伝わらないので、何がどうなのか書いてみる。

・ROOTはまさにLINUXのような仮想環境を提供する(ちょっと大げさ)。
・TFileはLINUXでいうrootディレクトリを提供する。
・生成するオブジェクトは単にメモリ上にある構造ではなくて、
ファイルに対応し、ディレクトリごとに名前で管理される。

まさに「物」という概念が成立していて、TObjectクラスを継承する
ということはROOTの世界で物としての資格を得ることである。
例えばヒストグラムをnewしているが、これによりヒストグラム
形式のファイルが生成され、カレントディレクトリで管理される。
また、ほとんどのオブジェクトはROOT側が自動的に特定の
ディレクトリで管理してくれるので、ユーザーが
わざわざオブジェクトを管理する必要はない。
こういう仕様を受け入れると、名前でオブジェクトを呼び出せるのも
自然であることがわかる。
また、TFileでrootファイルを開いてからnewしたTTreeの
wirteメソッドを呼ぶが、これも自然であることが分かる。

どこかでこのwrite()の呼び方はオブジェクト指向を理解している人には
不自然と読んだことがある気がするが、
単に機構・機能を独立にしただけのオブジェクト指向だと
不自然だが、環境をまるごと提供するROOTのように高度に
オブジェクト指向が発達しているとむしろ自然となる。

ということで、ROOTは本質的にpawとは異なる。
で、こういう抽象的なことだけを言ってもfortran人間に訴求力はないので、
仮想環境が提供されることの良さを言ってみると、
人間世界の物と同じ様にオブジェクトを扱える、ということである。
なんで、本物のプログラマーには必要ないとも言える。
凡人にはトンカチと釘だけで家を建てることはできない、というのだろうか。
あいかわらずオブジェクト指向がなぜ重要なのか説明しきれない。

ROOTのファイル構造については、
http://root.cern.ch/download/doc/11InputOutput.pdf
を参照。

TCutはROOTは管理しないらしい

なので、TListに自分で登録しろ、だそうな。
RootTalk View topic - TCut and TGlobal
http://root.cern.ch/phpBB3/viewtopic.php?t=8344&p=35190

なんとなく見てたら答えがわかった。
http://www-numi.fnal.gov/computing/d120/releases/development/WebDocs/Companion/first_steps/inheritance.html
つまり、
TCut* cut = new TCut("cut", "title")
gROOT->Append(cut)
gROOT->FindObject("cut")
とすると普通に見える。

http://www.dw-sapporo.co.jp/technology/658766f830d530a130a430eb7f6e304d5834/root_usersguide_jp/8ObjectOwnership.pdf
メモリ管理についてマニュアルに載ってるのね。んー。
これを読む限りだと、結局開いたファイルを全部閉じてしまえばだいたい
綺麗になるのかな。

で、やっぱりgROOTに置くのは微妙なので、TListをカレントディレクトリに置いておいて(cutlistとか)、そこに登録しておくのがいい気がする。

メモリ不正アクセス

ROOTはオブジェクトを読み込んだつもりでも、大概読み込んでいない(というふうに見える)。
で、特定のコマンドを使うと実際にメモリに乗る。
この仕様のために、あるタイミングで取得したポインタをその後で使おうと思うと、
不正アクセスになることがある。
で、一つ分かったのはTTreeのGetEntriesでメモリに乗るみたい。
おそらく、他のもそうな気がするので、ポインタを保持しておきたいなら、先にこれらの関数を
読んでおいて、メモリに乗っけておかないと、正しくポインタを扱えない。

んー、穴居曲GetEntriesしててもやっぱりメモリが移動する。
そもそも、basketとかに落ちないと確定しないのか。よくわからん。

TKey::ReadObjを呼べばon memoryになる気がする。
そのアドレスを持っておけばいいのかなー。

THtml

詳しくはROOTのマニュアルを調べてほしいが、このクラスを使うと自動でROOTのHTMLっぽいものが
作れる、、、らしい。
やってみたら落ちた。あぼーん。

TFitResultPtr


これは書き方のミスとしか思えないが、TFitResultPtrを使うためにTFitResultPtr.h読み込みときは、
一緒にTFitResult.hを読み込まないと実際にはアクセスできない。
というか、なんかTFitResultPtrの実装が特殊っぽく、なんか.hhhで読み込まないといけなかったりで、んーって感じ。

TFile, TKey, TObject

TFileを読み込んだ時点ではまだ、中身はよみこまれていなくて、TKeyというオブジェクトで保持している。
これにアクセス素売るには、TKeyのListを取ってきて、それぞれをそんな感じの関数でメモリに乗っける。
これでTObjecgtとしてメモリに載ったのでアクセスできる。

gROOT->Reset()


rootlogon.C中でgROOT->Reset()を呼ぶとcout << 1とかで起こられるっぽい。
http://osdir.com/ml/lang.c++.root/2005-04/msg00037.html
これは直してほしいなー。
まぁ、逆に考えるとgROOT->Reset()を初めに呼ぶ必要はないのかもしれないが。

これResetは生成したオブジェクトを片付けるとかじゃなくて、
cintのスコープ内で宣言したものを片付けるだけなので、
cint以外で呼ぶ必要はないっぽい。
また、これを呼んでもnewしたオブジェクトが消されるわけではない。
newしたオブジェクトを全て消すにはROOTがオブジェクトをディレクトリで
管理していることを理解する必要がある。
ユーザーがdeleteするか、もしくはDelete()を呼べばデストラクタで
自動でROOTの管理から外れるっぽいので、別にdeleteを恐れる必要は
ないっぽい。ただ、TFileはrootディレクトリなので、
これを消すと内部のオブジェクトは全て消える。
この挙動がROOTの肝だと思う。

TFile, TKey, TObject

TFileを読み込んだだけではTKeyとして、memoryにすら乗っていない。
通常、Draw()したときとかに読み込まれるが、この仕様のために、
TFileの中にあるTH1を自動的に読み込むのに困った。
ということで、このマクロの中に答えが(tutorial読めとかいうつっこみはなし)。
http://root.cern.ch/root/html/tutorials/io/hadd.C.html

TTreeを用いた解析 TTree::MakeClass

http://rarfaxp.riken.go.jp/~oonishi/tips/root.html
MakeClassを用いると簡単みたい。これ使えないとだめっぽなー。

テキストの簡易よみこみ(thx to 横山くん)

横山くんに教えてもらったことのほぼ引用。
    
ROOTではTGraphの第一引数にファイル名を指定すると、
そのファイルについてPlotを行うというコンストラクタがあります。
------
void graph(char * file)
{
  TCanvas *c1 = new TCanvas("c1", "", 1000, 500);
  TGraph *gr1 = new TGraph(file, "%lf %lf", "");
  gr1->Draw("ap");
}
------
このように、第一引数にファイル名、第二引数に採用するデータ列を入力します。カンマ区切りなら、
"%lf,%lf"
などと指定します。もし、元ファイルのデータが「いらない数, いらない数, x, y」というようになっていたら、
"%*lf,%*lf,%lf,%lf"
と、「*」を入れることにより、Plot対象から外すことができます。
おそらく3次元に対してもできると思います。histgramに対しては、不明です。
最低限、上の3行のコードを覚えれば、最低限のPlotができることになります
(あとはgStyleなどを追加するだけなので)。


TTreeの扱い


TTreeにあたらしいBranchの追加は何となく公式のTTreeのところにに載っている。
また、なんかどっかのサイトに、あるオブジェクトを継承して一回のloopを記述すれば簡単に計算できるとか書いてあった。

で、異なるTreeのBranchを平行に扱うにはTTreeの関数であるAddFriendを使う。
TreeのBranchを直列(複数runのデータを同時に読み込むとか)に扱うにはTChainを使うみたい。
    
TChain* ch = new TChain("t;1");
ch->Add("run0.root");
ch->Add("run1.root");
ch->Draw("x");

公式のTChainに書いてあるのをちょこっと変えただけ。
詳しくは
http://heptech.web.fc2.com/root/basicana2.html
に普通に書いてあった。解析の話もあるね。

hist->Draw("")のoption


http://root.cern.ch/root/html/THistPainter.html#HP01c

Treeからヒストグラム

htempはそうなんだが、恒常的にヒストグラムにするには、
    
ここから引用(http://rarfaxp.riken.go.jp/~oonishi/tips/root.html)---->

Tree を histgram にする
tree.Draw("a>>h1")
TH1F *hnew = (TH1F*)gDirectory->Get("h1")
とか 
TH1F *hnew= new TH1F("hnew","title",80,-3,1);
tree.Draw("a>>hnew")

とすれば、hnew に histgraming されます。

<-----引用ここまで

らしい。
Moduleにこれ組み込まないとなー。

BinContents

いっつも迷う。
histの場合はhist->GetBinContent(10)とか。
引数はbinなのでxの値で指定するならTPadやTH1の適当な関数で変換できる。

で、TTree->Draw()を使ったときにhistとして操作したくなるけど、
これはhtempという名前でhistが登録されているのでこれを
TH1* h = (TH1*)gROOT->FindObject("htemp");
てな感じで拾ってこれる。

また、Dynamicな関数を作るときは、
    
TObject *select = pad->GetSelected();
if (select &&
  select->InheritsFrom("TH1")) {
  TH1 *h = (TH1*)select;
}
てな感じでとってこれる。 http://root.cern.ch/root/html524/tutorials/hist/exec1.C.html

root/include/Buttons.h


kButtonの定義はいろんなところにあるっぽいが、
とりあえずroot/include/Buttons.hを使えばいいんではないだろうか。

TPadを継承したのがTCanvas

TPadを継承したのがTCanvas。
知らないとちょっと困る。

TPad::waitprimitive()

この関数は、TPad上でオブジェクトを呼び出すのを捕まえる
引数なしで呼べばダブルクリックで抜けるので、
イベントループ発生に使えなくもない。

Dynamicなコマンド

この辺とか。
http://root.cern.ch/root/html/tutorials/hist/DynamicSlice.C.html
http://root.cern.ch/root/html/tutorials/hist/exec2.C.html
http://root.cern.ch/phpBB3/viewtopic.php?t=1236
これを読めば、だだだだだーーーっと なんか連続的に処理できるコマンドが作れる。

イベントループ

TPad::waitprimitive()の中身を見ていてやっとわかった。 (ここも参考にさせてもらいました。http://hep.planet-koo.com/index.php?g=root&sid=rt_g_gsystem_processevents)
while (!gSystem->ProcessEvents() && gROOT->GetSelectedPad()) {
  TPad* pad = (TPad*)gROOT->GetSelectedPad();
  Int_t event = pad->GetEvent();
  if (event == kButton1Double) {
    func();//ここで何か処理をする。
    return;
  }
  gSystem->Sleep(10);
}

とすれば、基本的なイベントループとなる。
kButton1Doubleはダブルクリックのことで、
#include "Buttons.h"
に定義されてる。
#include "TControlBarButton.h"
も重要かも。

xvalを探して


http://root.cern.ch/phpBB3/viewtopic.php?t=1236
ここに重要なヒントが載っていた。

TCutG

グラフィカルにCutを作る。(thx. to Kobawiki)
TCutG *cut = c->WaitPrimitive("CUTG", "CutG"); 
cut->Print();


さんざんハマったが、結局この一文が鍵だった。
Loop and sleep until a primitive with name=pname is found in the pad.
つまり、waitprimitiveの一つ目の引数はデフォルトの名前にしとかないと自動では抜けられない。
うほ

xvalっぽもの(失敗作その2)

#include 
#include 
#include "TCanvas.h"
#include "TLine.h"
#include "TSeqCollection.h"
#include "TROOT.h"
#include "TSystem.h"

namespace Nadeko
{
  void xyval();
  void Clickxyval();
}

void Nadeko::xyval()
{
  TSeqCollection* tsc = gROOT->GetListOfCanvases();
  TCanvas* c = (TCanvas*)tsc->Last();

  c->AddExec("Nadeko::Clickxyval","Nadeko::Clickxyval()");
  c->WaitPrimitive();
  c->DeleteExec("Nadeko::Clickxyval");
}

void Nadeko::Clickxyval()
{
  Int_t event = gPad->GetEvent();
  if(event != 1){return;}

  Int_t px = gPad->GetEventX();
  Int_t py = gPad->GetEventY();
  Double_t x = gPad->PixeltoX(px); 
  Double_t y = gPad->PixeltoY(py); 

  std::cout.precision(6);
  std::cout << "\nx:" << setw(10) << x << ", y:" << setw(10) << y << std::endl;
}

xvalっぽもの(失敗作だが、知識が含まれているので参考程度に)

#include < iostream >
#include "TCanvas.h"
#include "TLine.h"
#include "TSeqCollection.h"
#include "TROOT.h"

TLine* xval()
{
 TSeqCollection* tsc = gROOT->GetListOfCanvases();
 TCanvas* c = (TCanvas*)tsc->Last();
 
 double x1 = c->GetX1();
 double x2 = c->GetX2();
 double y1 = c->GetY1();
 double y2 = c->GetY2();
 
 //  std::cout << x1 << ' ' << x2 << ' ' << y1 << ' ' << y2 << std::endl;               
 
 double xm = (x1+x2)/2.0;
 //  double ym = (y1+y2)/2.0;                                                           
 
 //  std::cout << xm << ' ' << ym << std::endl;                                         
 
 TLine* l = new TLine(xm,y1,xm,y2);
 l->Draw();
 c->Update();
 
 c->WaitPrimitive();
 std::cout << "xval:" << l->GetX1() << std::endl;
 
 //  delete l;                                                                          
 
 return l;
}

コンパイル・ロード


下のほうでぐだぐだ書いてるが、ROOT上でコンパイルして、 できたものをLoadしてしまえばいいことが分かった。
.L macro.C++ (もしくは、gSystem->CompileMacro("macro.C"));
(http://hep.planet-koo.com/index.php?g=root&sid=rt_g_gsystem_compilemacro)
一回これをやればmacro_C.soができる。 次からは、
.L macro_C.so (もしくは、gSystem->Load("macro_C.so"));
(http://hep.planet-koo.com/index.php?g=root&sid=rt_g_gsystem_load)
macro();
と使える。
わざわざ面倒な事をしなくても動的ライブラリを作製できるんですね。
ただ、複雑なファイルの場合、なんかロードする順番によっては 落ちることもあるっぽい。ちゃんとしたものなら正当にコンパイルするべきかも。

雑多


gROOT->FindObject("");でとってこれる?

ヘッダファイル

基本的にはクラスの名前とヘッダファイル名は一致する。
特別なものは以下の通り。

http://hep.planet-koo.com/index.php?g=root&sid=rt_global
(ここの内容を一部転載。問題があったら言ってください。)
TROOT.h gROOT TROOT* TopレベルのROOTオブジェクト
TSystem.h gSystem TSystem* OSのシステムコントローラー
TEnv.h gEnv TEnv* ROOTリソース情報
TRandom.h gRandom TRandom* 乱数ジェネレータ
TStyle.h gStyle TStyle* デフォルトスタイル設定
? gBenchmark TBenchmark*ベンチマークツール

TObject


ROOTの中のクラスの全てのクラスの親クラス。なので、どのクラスでもこのポインタを取ってこれる。
これの基本機能に”名前”がありこれによってROOTでは名前でobjectを取ってこれる。

TTreeの格納


第2引数はvoid*と同等と思われる。ポインタを渡して、第3引数でサイズをしているかと。
オブジェクトの場合は、変数が並んでいることが保証されていると思われるので、順番に取ってくるのかと。
問題は一度登録したアドレスを変更する手立てがないことである。
方法募集中。

TTreeにfillしたくないとき


シミュレーションで、その変数に値を入れたくないときがよくある。
そういうときは、非物理量(-1000とか0とか)を入れたりもするが、
TTreeでは格納する量をstructer(クラスでもいいけど)にして、
そこの中にflagを持たせるのが良いかと。

rootのまとめ(主にコンパイルとか)

それなりにまじめなrootのまとめ。
rootを使う、ということの前の、rootに関するあれこれ。
おそらく、rootを使おうと思ったときに、気になる人は気になる様な内容。

rootを使うと言って、rootについてgoogle先生に聞くと、 大概、c++でソース書いてうんぬん、という記事が見つかる。
これはこれで読んでそういう使い方はできると思う。
だけど、コマンドラインとマクロとコンパイルしたときの違いとかは、 あんまり明確ではない。しかも、それぞれで微妙に動作が違うが、 これらを明解にまとめたものを見たことが無い(英語はしらん)。
この辺がまず気になると思う。
さらに、たかだかグラフ表示するのに毎回ソース書くのめんどくせー。 と思う。
実際、現場ではどういう風に使ってるか気になってくる。
この辺は回りにroot使いがいないので知らない。
とりあえず、 全部べたってことはなくて、主にTTreeクラスを使っていると思われる。
んで、それでも、原子核実験にはちょっと汎用的過ぎる気がする。
そのために、マクロを作ってマクロを主体としたコマンドラインベース の解析はないのかー。という気になってくる。
だけど、そういうドキュメントが見つからない(英語はしらん)。
で、マクロを作って見たけど、どうも期待通りにいかないとかなる。
ということで、マクロ作ってモジュール化する方法が大体わかったので、 メモしておく。

長くなったけど、ここで書くことは、 ぐらいをメモしていく。
つまり、rootの使い方と言うよりも、cintとかコンパイルに関する情報かな。

有用サイト

とりあえず有用サイト。
お世話になっております。
いつも通り勝手にリンク。問題があったら言ってください。

基本から

基本的なことは他のサイトでも書いてあるから適当に。
適当にインストールしたら、
> root
とか、
> root -l
とか。
> root hoge.root
で、rootファイルを開ける。
> TFile f("hoge.root");
rootファイルはとかでも開けるらしい。

雑多

TBrowse c;
でブラウザを開く。

ロードした関数はtab保管がきくから、多少長くても大丈夫だったりする。

複数ファイルに渡るソースの場合、
例えば、main.cc, test.hh, test.cc
がある場合、
.L main.cc
.L test.cc
と、両方ロードしないといけない。

コマンドライン

表示されたコマンドラインはcintっていうC++ライクな文法を解釈してくれる。
コマンドラインとするために、文法がいろいろ違う、というか、 スコープとか名前空間の概念が曖昧な気がする。
詳しくはあとで書くかも。
とりあえず、C++っぽく書けばいろいろできる。

cintのコマンド

.?って打つといろいろでてくるけど、cint標準のコマンドはドットから始まる。
逆にドットがないときはC++のコードとして解釈される。
cintのコマンドとして、
・.?: help
・.!: shell
・.x: マクロの実行、というかファイルの中身を実行。
・.L: マクロのロード、というかファイルの中身を読む。
・.L macro.C++: こうすると、コンパイルしてロードになるらしい。
・.q: rootの終了
・.ls: 存在しているgraphの表示。
とりあえずはこのくらいかと。

rootの不可解(と思ってしまう)な部分

冒頭でもなんかいろいろ書いたけど、 rootの敷居を高くしているのは、 コマンドラインがC++ライクなわりに、 マクロでがっつり書いたら正しい文法でも通らなかったり、 いろんな場合で動作が微妙に違ったり。
コンパイルすると純粋なc++になるんだけど、これのやり方とか、 コマンドライン上で読んだり、コマンドライン上でコンパイルしたときの動作の違いとか。
あとは、ベタ書きマクロは特別であるとか。
コンパイルして、その関数を呼ぶんだけど、呼ぶ側はcintなので、 いろいろだめだったり。
(オペレータのオーバーライドとか、vectorにvectorいれたもの にアクセスするとか。)
こうやって書いてても、やぱり暴発してしまうが、この辺を整理していく。

先にいっておく。

この文章の主題でもある、モード?の違いを先に整理しておく。
この情報は一番有用だと思う。
ここに書いてあることが意味分からんってひとは、先に後ろの文章を読むとまだマシかも。

1.command line べた
2.macroを実行
 2.1 べた書き
 2.2 file名と同じ関数から始まる、擬似C++
 2.3 マクロのロード
3. command line上でマクロのコンパイルして使う
4. マクロのライブラリ化してロード
5. c++のコードに埋め込む。
5.1 埋め込んで、関数を呼んで表示とかを、プログラム内で行う。
5.2 treeとかのデータ構造だけ作るとか、graphだけつくって、hoge.rootを作って、あとからrootで解析する。
と、多様な使い方があり、というかいくつかは明確にモードとして区別してもいいぐらいに、 動作が異なる。
モードと言う意味では、
1. コマンドライン(コマンドラインモード)
2. マクロを使った擬似c++(マクロモード)
3. 新のc++(C++モード)
の三つ(勝手に名前つけた)。
で、状況によってそれぞれがこれらが混ざるので、混乱の元になっている。
上で書いた1.と2.1は1.のコマンドラインモードに相当する。
2.2,2.3はマクロモード。
ただし、コマンドラインに戻ってきてその関数をコマンドラインで呼ぶときは、 コマンドラインモードなので、気をつけないとあかん。
3.から5.2はC++モード。
これはマクロモードは混ざらないけど、コマンドラインで 動的ライブラリ内の関数を使おうものなら、その瞬間はコマンドラインモードなので、 問題が起こることも。

で、じゃぁ、具体的になにをしたらだめなのかと。
実は、出きるかな?っていろいろ思ってしまうからあれもだめこれもだめってなるけど、 基本的にはC++的に正しければok。
その上で、文法適当でも通るものごとがいろいろあるが、それは後を読んで。

で、決定的にだめなものは、
    ・
・複雑な型
例)
vector< map > 
(typedefしてもだめ。)
・演算子のオーバーロード(これはあんまりチェックしてない。)
void operator+()
とかで作っても、この動作を呼んでくれない。
の二点かと。
では、以下駄文。

cint(コマンドライン)の癖

cintはずるずる文法なので、いろいろ自由が効く。

スコープ

。 自分のいる所は、グローバルなところと言うイメージ。
コマンドライン上で変数宣言したらそれはグローバル変数になる。
しかし、{}でスコープっぽいものを作っても、 完全無視される。
マクロとかのスコープとの兼ね合いはまたあとで。

末尾の;

> double x;
と宣言しておいて、
> x
> x;
この二つは、意味が違って、
> x
だと、値の評価をして表示してくれる。
> x;
だと、cの文法の様に参照して終わり。

namespace

勝手にusing namespace std;されてる感じ。
他のクラスの名前空間をusing namespaceで省略は可能。
だけど、名前空間を省略した名前に対して、tab保管は効かない。

マクロ

> .x hoge.cc
とか、
> .L hoge.cc
> hoge();
とかして使うマクロ。
このマクロには、実はベタ書きマクロとそうでないマクロの大きな違いがある。

ちなみにfile名はhoge.ccとか、ドットがないとおかしくなるっぽい。
emacsで編集しやすいので、.ccがおすすめ。

ベタ書きマクロ

ベタ書きというのは、こんな感じ。
//hoge.cc
{
 double x(1.0);
 cout << x << endl;
}
ファイル名は何でもよく、ファイル名と同じ名前の関数を作らない。
この時は特別で、 コマンドラインと同じスコープ、つまりグローバルなスコープで 実行していることになる(ここテストに出ます)。
なので、実行した後にコマンドラインで変数xにアクセスできる。
結局、コマンドラインで打つ変わりにファイルに書いたっていうイメージ。
ちなみに、始めと最後のカッコがないとだめ。

ここで、おもしろいのが、こういう風に書いたときは普通のマクロとは明らかに、 動作がことなり、内部にスコープ作ってもそれが無視される。
//hoge.cc
{
 double x(1.1);
 cout << x << endl;
 {
  double x(2.1);
  cout << x << endl;
 }
 cout << x << endl;
}
実行結果
1.1
2.1
2.1
となり、明らかにスコープが無視される。
だけど、同じ変数使ってるのに文句は言われない。
cintの心は広いんだか狭いんだか。

普通のマクロ

これはドキュメントがすぐ見つかる話。
> .x macro.cc
みたいな。
マクロの実行には規則があって、ファイル名と同名の関数から実行される。
あと、mainって名前の関数は衝突する?ので使わない方がいいかも。
関数のプロトタイプ宣言はなくても、下に書いた関数が使えたりする。
スコープは基本的に普通のcな感じ。
特別に、関数の外に書いたいわゆるグローバル変数は、 コマンドラインで見える、つまり、まぁ、グローバル変数として扱われる。
#includeするタイミングはたしか普通のCっぽく文頭でよい気がした。
関数に引数とか戻り値を持たせたときは、
> .x macro.cc(4.5)
とかでもできる気がしたが、マクロをロードすることをおすすめする。
> .L macro.cc
> cout << macro(4.5) << endl;
みたいな。

マクロ内でclassを新しく作ることはできる気がしたが、もうマクロでやらずに、 コンパイルした方がいいかも。
てか、自分で作ったクラスをインクルードしたりすると、 勝手にコンパイルが始まるかも。
このとき、大概エラーになるので、正式にコンパイルする手順に移行する。

勝手にコンパイルされるマクロ

上で書いたように、複雑になってくる(自作の.hhをインクルードすると??)と、 勝手にコンパイルし出す。
そんで勝手にエラーになる。
なんで、こうなったら、もうちゃんとコンパイルしてあげる。
ということで、次の項。

マクロというか、解析コードのコンパイル

コンパイルするっていうと、何かルートを埋め込んで、 解析コードないでroot表示。
とか考えるかもしれないけど、それはまた別。
まずは、cintで実行していたマクロをコンパイルして、 それをロードするっていう話。
この様に、さっきまで直で投げてたマクロを一旦コンパイルすると、 複雑な文法でもコンパイルはc++のネイティブな過程なのでちゃんと使える。
(ただし、コンパイルしたソースにあったclassをcint上で使うとなると、これはcintが解釈 しようとして落ちることはままある。
そういうのは、マクロにして、 そのマクロをコンパイルして実行すればok。
コマンドラインでやりたいってんなら、 cintが解釈できない複雑なもの(
typedef vector > VectorMap 
とかして名前変えた型でも確実に落ちる。)
は、関数で一旦ラッピングするしかない。)

コンパイル第一段

コンパイルする場合はネイティブなc++なので、ヘッダーファイルとか名前空間とか ちゃんと書かなきゃいかん。
あと、root標準の関数やオブジェクトを使うなら、
#include "TROOT.h"
#include "TH1.h"
とか、それぞれに対応するものが必要。
この辺はgoogle先生に。
で、書き終わったら、まずは普通にshell上でコンパイルしてみるとよい。
g++ -c hoge.cc `root-config --cflags`
とか。
ここでコンパイルが通らないならroot上では無理。
うまく行ったら、 rootを実行して、
> gSystem->CompileMacro("hoge.cc");
ってやると、コンパイルしてくれる。tab補完効くので(ry
.x hoge.cc++
とか、後ろに++をつけるとコンパイルしてくれるらしい。
あと、.Cでもemacsはccと同じように扱ってくれるのね。
これで、勝手にこのソースを動的ライブラリにしてリンクしてロードまでしてくれる。
なんで、hoge.ccの中身が、
#include 

int hoge()
{
  std::cout << "aaa" << std::endl;

  return 0;
}
とかだったら、
> gSystem->CompileMacro("hoge.cc");
> hoge();
aaa
>
って感じで関数が使えるようになる。

いいところ。
モジュール化のためのお約束が必要ない。
勝手にモジュールが作られて、
勝手にロードされる。
だから、そのセッションだけはモジュールとして使える。

.L macro.cc
gSystem->CompileMacro("macro.cc")
これは、あとの動作的に、同じように見えるが、 上は、cintが解釈。
下は、C++でコンパイルして動的ライブラリを作ってロード。
だから、上はincludeとか適当でも動く。
下は文法はちゃんとしなきゃいけない。

コンパイル第二段

上の例だと、毎回root上でコンパイルしなきゃならん。
しかし、これ意外と遅いので、あらかじめライブラリにしておきたくなる。
ということで。
この辺の話は理屈は分かっていない。ので、ソースだけ紹介。
ここで書いただけでコンパイルしてないからなにか抜けてるかも。
//hoge.hh
#include  // これが必要らしい。

class Choge
{
public:
  Choge();
  ~Choge();

public:
  ClassDef(Choge,0) // 末尾にコロンはいらないらしい。あっても多分大丈夫だけど。
};

//hoge.cc
#include 
#include "hoge.hh"

ClassImp(Choge) // 上に同じ

using namespace

Choge::Choge()
{
  cout << "コンストラクタ" << endl;
}

Choge::~Choge()
{
  cout << "デストラクタ" << endl;
}

//hogelinkdef.h
#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class Choge;
//#pragma link C++ function func; // globalなfunc()っていう関数を作ったときはこんな感じ。

#endif

//makefile
all:
	rootcint -f hogedef.cc -c hoge.hh hogelinkdef.h
	g++ `root-config --cflags --libs` -shared hoge.cc hogedef.cc -o libhoge.so
最後のmakefileの中のhogedef.ccはそういうなまえで勝手に生成してねってこと。
なんか、作ったオブジェクトをrootに登録するための手続き??
で、これでlibhoge.soができるので、root上で、
    > gSystem->Load("libhoge");
として、ロードする。
この行をデフォルトの何かに書いておけばいいんじゃないかな!!
(たぶんディレクトリまで書かないとあかんが)
とりあえず、ここまでやると、tab補完も効くし、 オリジナルなライブラリができる。
なんで、Draw関数とかをのっとって、 簡単なコマンドにしてしまえばオンライン解析とかで便利かも。
そのときはグローバルな関数にしてしまい、 さらに、
gROOT->ProcessLine("コマンドでうつコマンドをそのまま書く")
っていう関数("TROOT.h")を使えばなんでもコマンドを簡単化できる。

コンパイル第三段

最後は、自分で書いたプログラムに埋め込む話。
すべてのrootの動作を関数でプログラムに生めてしまう。
そうするとできる。
これはいろいろドキュメントあるし、そっちを参照。

コンパイル第三段亜種

全部埋め込むのはそれはそれでナンセンスなので、 .rootファイルを吐くようにし、 これをコマンドラインで解析する。
    TFile* file = new TFile("temp.root", "RECREATE", "app");
    thd->Write();
とかで、ファイルに書いていくことができる。
たぶんtree(class TTree)を作って、これを.rootとして保存するのがいいのかと。
この辺は、しかるべきものを調べてまとめて教えてください。

グローバルなオブジェクト

なんか、graphとかはnewしてるけど、 これはじつはグローバルなオブジェクトとして勝手に名前をもとに作られている。 そんで、スコープの内側でnew TH1F("h", "aaaa", 100, 0.0, 24.0)とかしても、
h->Draw();	    
のように、登録した名前のオブジェクトをつかってgraphを操作できる。 一般的には
gROOT->Get何とか
でオブジェクトをとってこれるらしい。

graphのプロット

ファイル読んでgraphをプロットしてみた。 普通は配列をつくるけど、それでは面白くないので、 標準のTVectorDクラスを使ってみた。
まぁ、vectorに格納して、要素数と先頭アドレス返せばいいんだけど。
それを標準で実装していない理由がわからん。
ちなみにvector内部でアドレスが連続してるのは保証されてるので、 先頭のイテレータをとってきて、それの要素のアドレスを返せばよい。
(イテレータそのものは渡したらだめ)
vector v;
vector::iterator it1 = v.begin();
Tgraph(v.size(), &(*it1), &(*it2));
一方で、せっかくだから標準で実装してるTVectorDを使ってみた。
使い方がどこまで正しいかはよく知らない。
#include 
#include 
#include 

void graph(const char* filename){

  std::ifstream ifs(filename);
  if(!ifs.good()){
    std::cout << "bad open" << std::endl;
    return;
  }    
    
  int buf1, buf2;
  char cbuf;
  Int_t n(100);
  TVectorD x(n), y(n);

  Int_t index(0);
  while(1){
    ifs >> buf1 >> cbuf >> buf2;
    //    std::cout << buf1 << cbuf << buf2 << std::endl;
    if(ifs.eof()){
      break;
    }
    if(index >= n){
      n *= 2;
      x.ResizeTo(n);
      y.ResizeTo(n);
    }
    x(index) = buf1;
    y(index) = buf2;
    ++index;
  }

  for(int i = 0; i < index; ++i){
    //    std::cout << x[i] << ' ' << y[i] << std::endl;
  }

  TGraph* graph = new TGraph(x, y);
  graph->Draw("AP");

  return;
}

マクロでインチキにスコープを解決する方法

macroを実行すると、普通に書くとスコープ内で完結するので、内部の変数に アクセスできない。だから、graphを書いてもそのgraphをいじれない。
(graphはグローバルなオブジェクトとして登録されるので実はいじれる。) これでは困るので、スコープ外、つまり、グローバル変数として定義しておく 方法が考えられる。
コマンドライン上のスコープはグローバルな感じなので、 macroに書いたグローバル変数はアクセスできる。
ちなみに、cintはグローバル変数の扱いが変な気がする。
で、長くなったけど、グローバルにgraphを定義しておいて、 macro内でそれにアドレスを返す、
TGraph* graph;
void graph(){
graph = new TGraph(n, x, y);
}
で、namespaceでグローバル変数囲っとけばいいかとも思う。
少しこったことをするなら、 戻り値でそのgraphのアドレスを返すとか。
でも、あとでdeleteしなければならないことを考えると、 classを作ったほうがいいか。
なんか、ここまで来ると標準でなんか実装しているclassを使えということになる。

こんな感じのmacroを作ったら、使うには、
.L graph.cc
TGraph* graph;
graph = graph("temp.txt");
で、あとからコマンドラインでgraphポインタで操作できる。