CERNで開発されている、 素粒子・原子核物理分野でのデーター解析フレームワークです。 フレームワークを利用して出来る事は「無限」にあるといっても 言い過ぎではないかもしれません。 その中でも良く利用されるものを列記すると ROOTにはマクロ機能もあります。マクロの文法はC++に沿っています。 かなり処理能力は高いので、C++のインタプリターとしても使えます。 簡単なC++のプログラム(関数)ならば、コンパイルしなくても動かす 事が出来ます。C++の入門環境としても、悪い選択ではないと思います。 次の内容のテキストファイルを作る。編集はviでもemacsでもgeditでも 好きなものを使う。ファイルの名前を test.ccとして保存する。
{
  // キャンバスの準備
  TCanvas *c = new TCanvas( "test" ); 
  // 枠を書く 左下(0.0, 0.0) 右上(4.0, 10.0) 
  TH1 *frame = c->DrawFrame( 0.0, 0.0, 4.0, 10.0 );
  // データーの準備 
  double x[4] = { 0.0, 1.0, 2.0, 3.0 };
  double y[4] = { 0.0, 1.0, 4.0, 9.0 };
  // グラフを作る 
  TGraph *g = new TGraph( 4, x, y );
  g->SetMarkerStyle( 20 ); 
  g->SetMarkerSize( 1.0 );
  g->Draw( "PC" );        // グラフを書く 
  c->Print( "test.png" ); // グラフをファイルに出力 
}
ROOTにtest.ccを実行させる。
$ root -x test.cc
  *******************************************
  *                                         *
  *        W E L C O M E  to  R O O T       *
  *                                         *
  *   Version  5.18/00b     10 March 2008   *
  *                                         *
  *  You are welcome to visit our Web site  *
  *          http://root.cern.ch            *
  *                                         *
  *******************************************

ROOT 5.18/00b (branches/v5-18-00-patches@22563, Apr 06 2010, 02:11:00 on linuxx8664gcc)

CINT/ROOT C/C++ Interpreter version 5.16.29, Jan 08, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0] 
Processing test.cc...
Info in <TCanvas::Print>: file test.png has been created
root [1] 
となって、
が表示される。 軸のタイトルをつける場合は
  ....
  // 枠を書く 左下(0.0, 0.0) 右上(4.0, 10.0) 
  TH1 *frame = c->DrawFrame( 0.0, 0.0, 4.0, 10.0 );
  frame->GetXaxis()->SetTitle( "x" );
  frame->GetYaxis()->SetTitle( "y" );
  ....
を追加する。 データ点 (TGraphTH1等) を適当な関数でフィットすることも出来ます。 比較的簡単な方法は、関数クラス TF1 を使い、フィットで決定する関数を用意します。 例えば y = a x + b という関数を使ってabをフィットで決定する場合、
...
//  f1:        関数の名前
//  [0]*x+[1]: 関数
//  [0],[1]:   フィットで決めるパラメータ
  TF1 f1 = new TF1( "f1", "[0]*x+[1]" );
...
フィットの結果を図の上に表示する場合、
...
  gROOT->SetOptFit(0111);
...
を追加しておきます。 中の数字の切り替え(0←→1)で表示する内容を変更できます。

TGraphのデーターをフィットする

上記の例でつくったTGraphオブジェクトを つかってフィットを行うなら、
...
  g->Fit( f1 );
  // g->Fit( "f1" ) // 名前指定も可 
...
とするだけです。フィットの結果がターミナルやプロットに表示されます。 注意: フィットの結果に誤差が表示されますが、意味のある誤差を得るためには データにも適切な誤差を持たせなければなりません。誤差付きのグラフは TGraphErrorsクラスを使います。

フィットした関数の外挿

フィットの結果はデータのある範囲だけに表示されます。 データーのない領域まで線を伸ばして表示するには (フィット関数の外挿)、 関数で曲線を描く範囲を広げるだけです。もし -1.0 < x < 1.0 の範囲で表示したいのであれば
...
  f1->SetRange( -1.0, 1.0 );
  f1->SetLineColor( 2 );//区別のために色をかえる
  f1->SetLineStyle( 2 );//区別のために線種をかえる
  f1->Draw( "SAME" );
...
サンプルコードと出力例:

フィットした関数をつかった計算

グラフを書くのではなくて、関数をつかって任意のxでの値を計算する事もできます。TF1::Eval( x, .... )という関数が用意されているので、例えばx=0.5での値を計算したい場合
...
   double xv = 0.5;
   double yv = f1->Eval( xv );
...
の計算を行い、結果を別の変数に代入できます。

TH1のデーターをフィットする

基本的にはグラフに対するフィットと同じです。 データーにはそれぞれのビンに入っているイベントの統計誤差が 自動的に付加されているので、 フィットの結果についている誤差は統計誤差を表します。

少しだけ複雑なフィットの例

1600ch付近のピークをガウス分布+2次関数をつかってフィットしてみます。
  TH1 *hist = (TH1*) file->Get("histogram"); //適当なファイルからヒストグラムを読み込みます
...
  TF1 *func = new TF1( "fitfunc", "gaus+pol2(3)", 1300.0, 2000.0 );
  func->SetLineColor( kRed );
  hist->Fit( "fitfunc", "", "", 1300.0, 2000.0 );
...
と、ガウス関数+二次関数でフィットしてみます。 関数を定義するところでは関数の範囲を、またフィットする所では フィットするデーターの範囲を指定します。この例では両方同じに していますが、データ範囲が関数の範囲よりも小さくなっていても 問題ありません。 これでうまくフィットできれば良いのですが、 以下のようにうまくいかない場合があります。 いくつかのパラメータに適当な初期値を与えることでうまくフィットできる 場合があります。 この場合は、バックグランドはそれほど大きくありません。またガウス 関数で再現したいピークは、高さが4500程度、中心値が1650、幅が100程度です。 TF1::SetParameter関数でそれぞれのパラメーター の値を前もって与えておきます。
  TH1 *hist = (TH1*) file->Get("histogram"); //適当なファイルからヒストグラムを読み込みます
...
  TF1 *func = new TF1( "fitfunc", "gaus+pol2(3)", 1300.0, 2000.0 );
  func->SetLineColor( kRed );

  func->SetParameter( 0, 4500 );
  func->SetParameter( 1, 1650 );
  func->SetParameter( 2,  100 );
  func->SetParameter( 3,    0 );
  func->SetParameter( 4,    0 );
  func->SetParameter( 5,    0 );

  hist->Fit( "fitfunc", "", "", 1300.0, 2000.0 );
...
その結果うまくデーターをフィットする事ができました。フィットの結果、 パラメータは
 FCN=3395.02 FROM MIGRAD    STATUS=CONVERGED     351 CALLS         352 TOTAL
                     EDM=7.15429e-09    STRATEGY= 1      ERROR MATRIX ACCURATE 
  EXT PARAMETER                                   STEP         FIRST   
  NO.   NAME      VALUE            ERROR          SIZE      DERIVATIVE 
   1  p0           4.39127e+03   6.84304e+00   1.56889e-01   1.29175e-05
   2  p1           1.66738e+03   8.01861e-02   2.20261e-03  -9.28301e-04
   3  p2           5.95623e+01   7.05243e-02   1.33194e-03   4.15799e-04
   4  p3           3.09543e+03   4.17533e+01   8.87856e-03   7.48519e-05
   5  p4          -3.22700e+00   5.08032e-02   4.71718e-06   1.57189e-01
   6  p5           8.44200e-04   1.51240e-05   2.47868e-09   3.19518e+02
となりました。 もしピーク部分だけを表示したいなら、
  TH1 *hist = (TH1*) file->Get("histogram"); //適当なファイルからヒストグラムを読み込みます
...
  TF1 *func = new TF1( "fitfunc", "gaus+pol2(3)", 1300.0, 2000.0 );
  func->SetLineColor( kRed );
  func->SetParameter( 0, 4500 );
  func->SetParameter( 1, 1650 );
  func->SetParameter( 2,  100 );
  func->SetParameter( 3,    0 );
  func->SetParameter( 4,    0 );
  func->SetParameter( 5,    0 );
  hist->Fit( "fitfunc", "", "", 1300.0, 2000.0 );


  TF1 *pe = new TF1( "p.e.", "gaus", 0, 4000 );
  pe->SetParameter( 0, func->GetParameter( 0 ) );
  pe->SetParameter( 1, func->GetParameter( 1 ) );
  pe->SetParameter( 2, func->GetParameter( 2 ) );
  pe->SetFillColor( kOrange );
  pe->SetLineWidth( 1 );
  pe->SetLineColor( kOrange );
  pe->SetFillStyle( 3015 );
  pe->Draw( "SAME" );

...
とすると、以下のように表示できます。

ファイルからデーターを読み込む

「ファイルからデーターを読み込んでグラフを作成する」という作業を 行う必要が出てくる場合があります。よくあるケースとして、テキスト ファイルに数字だけが羅列してあり、列毎にデータの種類が異なり、 一行で一グループというものがあります。つまり
   1   20  18
   2  100   6
   3   66   1
....
と、3列構造で、何行にも渡りデータが格納されている場合です。 データがいったい何行含まれているのか決まっていれば、その分の 配列を用意し、その配列からグラフを作成する事ができます。 一方で、データーの数が分からない場合は少々困った事になります。 十分大きな配列を用意して同じ事を行えば良いわけですが。。。 等々、問題のあるコードになります。そんな時はSTLのコンテナクラスを 利用するのが手っ取り早いのですが、それはそれで別の話し。 ROOTの場合も可変サイズの配列を扱うクラスがあるので、そちらを使うというのが より汎用性のあるコードになるかもしれませんが、そこまでしたくないという 場合は。。。
{
  ifstream ifs( "data.dat" );
  int a, b, c;
  TGraph *g = new TGraph();    // 空のグラフを用意
  while( ifs >> a >> b >> c ){
    int n = g->GetN();      // 現在のポイント数を取得
    g->Set( n + 1 );        // 一つ増やす
    g->SetPoint( n, a, b ); // 増やしたものに値を入力
    ....
  }

}
と、TGraphのポイント数を随時増やしなていくのが良いでしょう。 グラフ中にテキストを挿入するのはTLatexクラスを使います。
  ...
  TLatex *latex = new TLatex();// TLatexオブジェクトを作る
  latex->SetTextHeight( 0.03 );// 文字の大きさを決める
  //  (1.0, 6.0)の位置を先頭に Text を表示
  latex->DrawLatex( 1.0, 6.0, "Text" );
  ...
数式等もLaTeXに似た方法で表示できます。

文字の位置・向き

  ...
  //  
  latex->DrawLatex( 1.0, 6.0, "Text" );
  ...

マクロをつくって作業を簡略化する場合に、マクロに値を渡したくなる場合があります。 例えば、あるファイルをひらいてその中にあるヒストグラムを取得する場合を考えてみましょう。 ファイルの名前と、ヒストグラムのタイトルはケースバイケースで変わるものですが、 その他の部分は変化しません。ファイル毎にマクロを用意するのは「無駄」に思える でしょう。 マクロの呼び出し方法には2種類あります。
{
  ...
  ...
}
でまとめたマクロの場合と、例えばtest.ccという名前で
int test(){
  ...
  return 0;
}
のように、ファイルのbasenameの関数として用意する場合です。 関数を用意する場合、関数の引数を渡すことができます。例えば
#include <string>
#include <iostream>

int test( const string name ){
  ...
  cout << name << endl;
  ...
  return 0;
}
となります。このtest.ccを実行させると、
root [0] 
Processing test.cc...
Error: Function test() is not defined in current scope  :0:
*** Interpreter error recovered ***
のようなエラーが発生します。ファイルの中で引数なしのtest()関数が 定義されていないよ!という訳です。そこで
$ root -l 'test.cc("hogehoge")'
のように、マクロを呼び出すときに変数を指定してあげると、
root [0] 
Processing test.cc("hogehoge")...
hogehoge
(int)0
マクロ呼び出し時に指定した値を使って、マクロを実行できます。

マクロからマクロを呼ぶ

ファイル名と同じ名前をもつ関数は特別な存在です。特にC++は 関数の多重定義が可能になっていて、同じファイルの中に引数が違うけれど、 同じ名前の関数を複数用意する事もできます。引数の種類によって、 実行する内容のコントロールが可能になります。 ファイル名と異なる名前をもつ関数も定義できます。これらの関数は ROOTから直接利用する事はできませんが、関数ないからの使用には制限ありません。 いろいろな関数を用意していくと、異なる「マクロ」から同じ関数を再利用 したい場合が出てきます。そういう場合は再利用したい関数のみを別のファイル (例えばfunction.hh)に保存し、マクロの中に取り込みます。
#include "function.hh"
#include <string>
#include <iostream>

int test( const string name ){
  ...
  ...
};

別ファイルを作るときの注意(多重読み込みの防止)

解析をすすめていくにつれ、マクロの量が増えていきます。 量が増えるのと並行し、マクロの中に別のマクロを読み込み、読み込まれたマクロが さらに別のマクロを呼びこむといったようなマクロの多層化が進んだりもします。 階層構造が複雑になっていくと同じファイルを、その階層構造の中で、複数回読み込んで しまう可能性が出てきます。引数の種類まで含めてまったく同じ関数が2度あらわれると、 ROOTはエラーを出力し、停止します (とおもいきや停止しません、よくできたインタープリターです)。
#ifndef _functions_hh_ #define _function_hh_
.. int test( const string name ){ .. return 0; } .. #endif
多重定義をさけるために、適当なキーワードを決め、そのキーワードが定義されていない 時のみ、関数を定義するようにしておきます。この例ではキーワード_functions_hh_ が未定義であることを確認しています。 マクロではなくて、C++プログラムの中から直接ROOTを利用する事もできます。

ヒストグラムを作成・保存

ただヒストグラムなどを作って、ファイルに保存するだけであれば 至極簡単にできます。 たとえば次のようなソースファイルをtest2.ccという名前 で作ります。
#include <TFile.h>   // ROOTファイルを使用
#include <TH1.h>     // ヒストグラムを使用
#include <TRandom.h> // 乱数を使用
int main( int argc, char* argv [] ){
  TFile file( "test3.root", "RECREATE" );      // 保存用ファイルの作成
  TH1F hist( "test3", "test3", 100, 0.0, 1.0 );// ヒストグラムの作成
  TRandom random;                              // 乱数の準備
  // ヒストグラムを埋める
  for( int i = 0; i < 10000; i++ ){hist.Fill( random.Uniform() );}
  file.Write();  // ファイルにヒストグラムデーターを書き出し
  file.Close();  // ファイルを閉じる
  return 0;
};
ソースファイルができたら、
$ g++ test3.cc -o test3 `root-config --cflags --libs` 
と入力し、実行ファイルtest3を作ってください。あとは
$ ./test3
とできた実行ファイルを実行します。 test.rootというファイルができていると思うので、
$ root -l test3.root
root [0] 
Attaching file test3.root as _file0...
root [1] test3->Draw();

のように、実行ファイルで作成・保存したヒストグラムを表示できます。 保存できるものはヒストグラム・グラフ(TGraph)など、ROOTので 使えるいろいろなデータ形式です。
Makeの利用
コンパイルするために、 いちいちコマンドラインで長いオプションを指定するのが面倒な 場合、makeを利用するとよいでしょう。 (面倒だから使うわけではないが、まあそれはそれとして) 以下の内容で、ソースファイルと同じディレクトリにMakefileという 名前のファイルをつくってください。
CPPFLAGS += `root-config --cflags`
LDLIBS   += `root-config --libs`
そして、以下のように入力しましょう。
$ make test3
すると、makeプログラムが適切なコンパイル・リンクオプションを 利用して、
g++  `root-config --cflags`   test3.cc  `root-config --libs` -o test3
とコンパイルしてくれたのではないでしょうか?便利ですね。 この例の場合、Makefileを作らなくても、適切にシェルの環境変数を 設定しておけば、まったく同じ動作をさせる事もできます。が、後々のために Makefileを作っておくことにしましょう。

ヒストグラムを表示

C++から直接ヒストグラムを作れる+操作できるのであれば、 表示だってしたくなるのが人の子というものです。それなら
...
  hist.Draw();
...
なんて一行をいれて、コンパイルしてみましょう。 ・・・・・ コンパイルはできます。実行してみましょう。実行されますが、
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
と表示されど、ヒストグラムは表示される気配はありません。 もしかしたら一瞬表示されてすぐに消えているのか?と
...
#include <TCanvas.h>
...
  TCanvas c;
  hist.Draw();
  c.Draw();
  c.WaitPrimitive();
...
としてもやはりダメです。 ROOTが画面表示を行う準備ができていないため、 いくらDrawメソッドを呼び出そうと、目的は果たす事ができません。 一番簡単な解決方法は、TApplicationオブジェクトを作る事です。 たとえば
#include <TFile.h>   // ROOTファイルを使用
#include <TH1.h>     // ヒストグラムを使用
#include <TRandom.h> // 乱数を使用
#include <TCanvas.h> // キャンバス
#include <TApplication.h> // アプリケーションオブジェクト
int main( int argc, char* argv [] ){
  TApplication app( "app", &argc, argv );      // 準備
  TFile file( "test3.root", "RECREATE" );      // 保存用ファイルの作成
  TH1F hist( "test3", "test3", 100, 0.0, 1.0 );// ヒストグラムの作成
  TRandom random;                              // 乱数の準備
  // ヒストグラムを埋める
  for( int i = 0; i < 10000; i++ ){hist.Fill( random.Uniform() );}
  TCanvas c; // キャンバス作成
  hist.Draw(); // ヒストグラム描写
  c.Draw(); // キャンバス描写
  c.WaitPrimitive(); // 入力待ち
  file.Write();  // ファイルにヒストグラムデーターを書き出し
  file.Close();  // ファイルを閉じる
  return 0;
};
としてみましょう。TApplicationオブジェクトの初期化時に、画面表示などの 準備も行われます。実行してみると、ヒストグラムが表示されるはず。

少し凝った例

上のサンプルプログラムをもうちょっとC++っぽくしてみましょう。 次のようなコードをtest4.ccとしてつくってみます。
#include <TFile.h>        // ROOTファイルを使用
#include <TH1.h>          // ヒストグラムを使用
#include <TRandom.h>      // 乱数を使用
#include <TCanvas.h>      // キャンバス
#include <TApplication.h> // アプリケーションオブジェクト
 // 
 // TApplication を継承して新しいクラスをつくる
 // 
class MyApp : public TApplication {
public:
  // オブジェクト生成ルール
  MyApp( int argc, char* argv[] ) :
    TApplication( "MyApp", &argc, argv ),   // 
    file( "test.root", "RECREATE" ),        // ファイルを開く
    hist( "test", "test", 100, 0.0, 1.0 ),  // ヒストグラムの用意
    random(),                               // 乱数の用意
    c()                                     // キャンバスの用意
  {
  }
  // オブジェクト消滅ルール
  virtual ~MyApp(){
    file.Write();
    file.Close();
  }
  // Run関数のオーバーロード
  virtual void Run( Bool_t retrn = kFALSE ) {
    for( int i = 0; i < 10000; i++ ) hist.Fill( random.Uniform() );
    hist.Draw();
    c.Draw();
    c.WaitPrimitive();
  }
private:
  TFile file;
  TH1F  hist;
  TRandom random;
  TCanvas c;
};

int main( int argc, char* argv [] ){
  MyApp app( argc, argv ); // アプリ準備
  app.Run();               // アプリ実行
  return 0;
};
同じ動作をするのですが、行数が増えて面倒な事をやっているなぁ?と思うかもしれませんが、、、、

さらに頑張ってみる

ファイルを増やします。 MyApp.hh
#ifndef _MyApp_hh_ // おやくそく
#define _MyApp_hh_
#include <TFile.h>        // ROOTファイルを使用
#include <TH1.h>          // ヒストグラムを使用
#include <TRandom.h>      // 乱数を使用
#include <TCanvas.h>      // キャンバス
#include <TApplication.h> // アプリケーションオブジェクト
 // 
 // TApplication を継承して新しいクラスをつくる
 // 
class MyApp : public TApplication {
public:
  MyApp( int argc, char* argv[] );            // オブジェクト生成ルール
  virtual ~MyApp();                           // オブジェクト消滅ルール
  virtual void Run( Bool_t retrn = kFALSE );  // Run関数のオーバーロード
private:
  TFile file;
  TH1F  hist;
  TRandom random;
  TCanvas c;
};
#endif
MyApp.cc
#include "MyApp.hh"
// オブジェクト生成ルール
MyApp::MyApp( int argc, char* argv[] ) :
  TApplication( "MyApp", &argc, argv ),   // 
  file( "test.root", "RECREATE" ),        // ファイルを開く
  hist( "test", "test", 100, 0.0, 1.0 ),  // ヒストグラムの用意
  random(),                               // 乱数の用意
  c()                                     // キャンバスの用意
{
}
// オブジェクト消滅ルール
MyApp::~MyApp(){
  file.Write();
  file.Close();
}
 // Run関数のオーバーロード
void MyApp::Run( Bool_t retrn ) {
  for( int i = 0; i < 10000; i++ ) hist.Fill( random.Uniform() );
  hist.Draw();
  c.Draw();
  c.WaitPrimitive();
}
test5.cc
#include "MyApp.hh"
int main( int argc, char* argv [] ){
  MyApp app( argc, argv ); // アプリ準備
  app.Run();               // アプリ実行
  return 0;
};
そしてMakefile
CPPFLAGS += `root-config --cflags`
LDLIBS   += `root-config --libs

test5: MyApp.o test5.cc 
と変更します。その後メイクすると
$ make test5
g++  `root-config --cflags`  -c -o MyApp.o MyApp.cc
g++  `root-config --cflags`   test5.cc MyApp.o  `root-config --libs` -o test5
と、適切にそれぞれのソースファイルをコンパイルし、実行ファイルtest5が作成されます。

対話的プログラムの作成

ROOTを実行すると、対話的(インタラクティブ)にROOTを操作できます。 上記の例では対話モードではなく、プログラム道理に処理を実行し、 実行後プログラムは自動的に終了します。 ROOTを使えば、対話モードのプログラムも簡単に作成できます。 上記のTApplicationのかわりにTRintクラスを利用します。 TRint利用の利点は、 適切なルールに従って設計した独自のクラスを対話的に、ということはさらに マクロの中で利用できることにあります。 目的としているデータ処理等に必要なクラスを事前に用意しておいて、 など、マクロ等の利点を活用し、柔軟にいろいろなことに対処できます。

ROOTベースGUIプログラム作成

ヒストグラム等の出来合いの物ではなくて、対話的なモードに加えて、 自前のGUIを用意したい時も、ROOTは便利です。かつて「ウィジェット」とも よばれたGUI用のインターフェースライブラリが含まれています。 具体的にはボタンとかテキスト表示領域とかリストとか、GUI設計に 必要な基本的なパーツは揃っています。 プログラムを永続させようとすると、なにかしらのループバックを作らないと いけませんが、あまり面倒な事は考えずに、TRintを使って、 CUIベースの対話型プログラムとしておくのが比較的簡単な方法です。 対話型に一応しておきますが、基本的な操作はGUIも用意しておけばよいでしょう。 データベースファイル的な使い方をする時は TTree クラスを使います。 よくある例は、計測実験で適当な検出器からの信号の
  1. ADC
  2. TDC
情報を記録ような場合です。一度の測定で2つの値を記録しなければなりません。 テキストファイルに保存したり、表計算ソフトで読めるようなCSV形式で保存 する等方法はいろいろありますが、データの数・種類が多くなってくると、 保存はそれほど単純にはいかなくなります。また保存したデータの処理も 同時に複雑になります。
取り扱うデータの例
No.ADCTDC
120450
248430
32339
TTreeクラスは、 データの種類毎にTBranch(枝)を 用意します。 枝は定められた種類TLeaf(葉)の データを蓄積します。
{
  int adc;
  int tdc;
  ...
  TTree *tree = new TTree("name","title");  //TTree作成
  tree->Branch( "ADC", &adc, "ADC/I" );     //Branch準備
  tree->Branch( "TDC", &tdc, "TDC/I" );     //Branch準備
  ...
  while( ){
    adc = ...;     //ADCの値を代入
    tdc = ...;     //TDCの値を代入
    ...
    tree->Fill();  //TTreeに書き込み
  }
}
SQLデータベースに対するクラスライブラリも提供されています。 ライブラリとしてROOTを利用するのであれば、必ずしも必要ないとは思いますが、 マクロでの利用時には重宝するはず。 SQLには代表的に MySQL と PostgreSQL があります。 クォーク研の偏極標的開発研究では PostgreSQL によるデータ管理をしているので、 ここでは PostgreSQL を例に説明します。

ROOTの準備

PostgreSQLサーバーに接続するためには、ROOTに追加機能を付加する必要があります。 PostgreSQL用のライブラリを用意し、ROOTの再構築が必要かもしれません。 Ubuntu であれば libpglibpg-dev 等をインストールし、 ROOTを再コンパイルする事になります。 libpgxxlibpgxx-devをインストールしておくと、ライブラリと して利用するときにちょっとだけ便利になります。

サーバーへの接続

サーバーへの接続はTPgSQLServerクラスを使います。
#include <TPgSQLServer.h>
...
  TPgSQLServer server( "pgsql://HOST:PORT/DB", "USER", "PASSWORD" );
...
HOST、PORT、DB、USER、PASSWORD は適宜変更してください。 サーバーにクエリをかけるのは
#include <TSQLResult.h>
#include <string>
...
  string sql = "SELECT ......";

  TSQLResult *res = server.Query( sql.c_str() );
...
と、適当なSQL命令を用意し、TPgSQLServer::Query( const char * ) でサーバーに問い合わせします。問い合わせの結果はTSQLResult*として 返されます。
#include <TSQLRow.h>
#include <cstdlib>
...
  int nField = res->GetFieldCount(); // フィールド数
  TSQLRow *row;
  while( row = res->Next() ){ // 最終行までループ
    double f0 = atof( row->GetField( 0 ) ); // 最初のフィールドを浮動少数で取得
  }
...
取得した結果からTSQLRowを使ってデータを取り出します。 フィールド指定は 0 から始まる事に注意してください。 例えば、すべてのフィールドを標準出力に出すのであれば
#include <iostream>
#include <iomanip>
...
  while( row = res->Next() ){
    for( int i = 0; i < nField; i++ )
      cout << setw(12) << row->GetField( i ) << flush;
    cout << endl;
  }
...
となります。 ROOTを使える環境にするには、いくつかの方法があります。 簡単かもしれない方から上げると
  1. すでに用意されている計算機を利用する。
    例えばネットワークセンターのサーバーや、研究室のサーバーで ROOTが用意されていれば、ログインして使いましょう。
  2. インストール直後からROOTが使えるようなOSをパソコンにインストールする。
    たとえば 等はROOTをはじめ、様々なツールがセットアップされています。
    ライブDVDで使える?
  3. ROOTがパッケージ化されたOSを使う。 かつてはUbuntuでもROOTのパッケージがありました。 Scientific Linuxには存在する? Fedora Spinにあるので、FedoraならOK?
    MacOSはこれに該当するかな?適当なレポジトリを使用しましょう。
  4. バイナリで用意されているOSを使う。 ROOTのホームページで確認しましょう。 Windows版も用意されています。
  5. ソースをダウンロードしてコンパイル・インストールする。
ここでは、最後のソースを利用したインストールについて説明します。 対象となるOSはLinuxを想定しています。

ROOTSYS環境変数を指定してインストールする方法

  1. 環境変数を設定。システム全体の設定とする場合は /etc/profile.d/root.shとして、 以下の内容のファイルを作成。
    if [ -z "${ROOTSYS}" ]
    then
      export ROOTSYS=/usr/local/root
      export PATH=$ROOTSYS/bin:$PATH
    fi
    
  2. ホームページからROOTをダウンロード
    $ wget ftp://root.cern.ch/root/root_v5.32.03.source.tar.gz
    
  3. /usr/local/rootとして展開
    $ sudo tar -z -x -v -C /usr/local -f root_v5.32.03.source.tar.gz
    
  4. 展開したディレクトリに移動して、設定&コンパイル。
    $ cd /usr/local/root
    $ sudo ./configure
    $ sudo make
    
    configure時に、いろいろなものが無いと言われたら、 適宜欠けているものをインストール。 パッケージでほとんどのものが入手できるはずです。 逆にパッケージで入手できないものは、 必ずしも必要ないものなので情報収集をおこないましょう。
  5. ダイナミックライブラリの設定をする。 ldconfigであつかえるように、サーチPATHに追加。 /etc/ld.so.conf.d/root.confを作る。
    # sudo sh -c "echo /usr/local/root/lib > /etc/ld.so.conf.d/root.conf"
    # sudo ldconfig
    

より一般的(?)な方法

上記とほぼ同じですが、インストールする場所とコンパイルする場所が 違う場合: (例:ソースファイルは~/buildの下に展開。 コンパイル後に/usr/localの下にインストール。)
  1. ソースをダウンロード
  2. 適当なところに展開する。例えば ~/build/
    $ mkdir ~/build
    $ tar -z -x -v -C ~/build -f root_v5.32.03.source.tar.gz
    
  3. インストール先を指定して、設定&コンパイル。
    $ cd ~/build/root
    $ ./configure --prefix=/usr/local
    $ make
    $ sudo make install
    

Windowsで利用する

Windows用のバイナリもROOTホームページからダウンロードできます。 使用するにはVisual C++のランタイムライブラリを必要とするので、 別途インストールしておく必要があります。導入方法は
  1. ROOTホームページの"Download"ページから"Pro"バージョンのページへ移動。
  2. Windows用倍バイナリの説明中に"no-cost version of Visual Studio"への リンクがあるので、その先のページからVidsual Studio Expressをダウンロードし、 インストールを済ませておく。
    "for Windows"は Windows 8 用。Windows 7 用は "for Windows Desktop"。
  3. インストールされているVidusal C++ のバージョンにあった MSIファイルを ダウンロード、インストールする。最新のVidual Studio Express をインストール したのであれば、番号の大きな方をインストールしておけばよい(?)。