解析マネージャーしたい(G4VAnalysisManager

1auto am = G4AnalysisManager::Instance();

G4AnalysisManagerは、Geant4のシミュレーションで得られた結果を管理するインスタンスです。 このクラスのおかげでROOT形式、CSV形式、XML形式への出力が標準機能として利用できます。

G4AnalysisManager::Instanceは、 シングルトンとして設計されており、マルチスレッド環境にも対応しています。

注釈

G4AnalysisManagerは Geant v10.0で導入されました。 このクラスは、抽象基底クラスであるG4VAnalysisManagerを継承した具体クラスであり、 ユーザーは通常このG4AnalysisManagerを通じてヒストグラムやNtupleを操作します。

ラン情報を記録したい

 1// include/RunAction.hh
 2
 3#ifndef RUN_ACTION_HH
 4#define RUN_ACTION_HH
 5
 6#include "G4UserRunAction.hh"
 7#include "G4String.hh"
 8#include "globals.hh"
 9
10class RunAction : public G4UserRunAction {
11  public:
12    RunAction();
13    virtual ~RunAction();
14
15    virtual void BeginOfRunAction(const G4Run* aRun) override;
16    virtual void EndOfRunAction(const G4Run* aRun) override;
17
18  private:
19    // 必要に応じてメンバー変数を追加
20    // - 値が一定(immutable)の変数
21    // - 複数のメンバー関数で共有したい変数
22    G4int fRunId = -1;
23    G4double fStartTime = 0;
24    G4String fSeedFileName;
25};
26
27#endif // RUN_ACTION_HH

ラン情報を記録するために、 G4UserRunActionを継承したユーザー定義のRunActionクラスを作成します。

このクラスの コンストラクターにG4AnalysisManagerの初期化 BeginOfRunActionにファイルを開く操作、 EndOfRunActionにデータ保存とファイルに書き出す操作を実装します。

初期化したい(RunAction::RunAction

 1void MyRunAction::RunAction() {
 2  auto am = G4AnalysisManager::Instance();
 3
 4  // ログ詳細レベル(0-4)
 5  am->SetVerboseLevel(1);
 6  // 出力ファイル名
 7  am->SetFileName("my_output");
 8  // 出力形式("root", "csv", "xml")
 9  am->SetDefaultFileType("root");
10  // ヒストグラム用ディレクトリ
11  am->SetHistDirectoryName("hist");
12  am->CreateH1("h1", "Edep in detector", 100, 0., 10.);
13
14  // Ntuple用ディレクトリ
15  am->SetNtupleDirectoryName("ntuple");
16  am->SetNtupleMerging(true);  // マルチスレッド対応
17
18  // ラン情報用Ntuple
19  am->CreateNtuple("runinfo", "Run Metadata");
20  am->CreateNtupleIColumn("runId");
21  am->CreateNtupleIColumn("nEvents");
22  am->CreateNtupleDColumn("startTime");  // unixtime
23  am->CreateNtupleDColumn("endTime");
24  am->CreateNtupleSColumn("fileName");
25  am->CreateNtupleSColumn("seedFile");
26  am->FinishNtuple();
27}

出力するファイル名や形式、 必要なヒストグラムやNtupleの定義は、 RunActionクラスのコンストラクターの中で初期化します。

ラン開始時の処理(RunAction::BeginOfRunAction

 1void MyRunAction::BeginOfRunAction(const G4Run* aRun) {
 2  fStartTime = std::time(nullptr);
 3  fRunId = run->GetRunID();
 4
 5  // 出力ファイルを開く
 6  auto am = G4AnalysisManager::Instance();
 7  am->OpenFile();  // 出力ファイルを開く
 8
 9    //
10  fSeedFileName = "seed_run" + std::to_string(runId) + ".rndm";
11  CLHEP::HepRandom::saveEngineStatus(seedFileName);
12
13}

シミュレーションがはじまると、BeginOfRunActionが呼ばれます。 出力ファイルを開く操作(OpenFile)はここで実行します。

ラン終了時の処理(RunAction::EndOfRunAction

 1void MyRunAction::EndOfRunAction(const G4Run* aRun) {
 2  G4int nEvents = aRun->GetNumberOfEvents();
 3  G4double endTime = std::time(nullptr);
 4  auto am = G4AnalysisManager::Instance();
 5
 6  // 出力ファイル名を取得
 7  G4String outputFileName = am->GetFileName();
 8
 9  // 保存
10  am->FillNtupleIColumn(0, fRunId);
11  am->FillNtupleIColumn(1, nEvents);
12  am->FillNtupleDColumn(2, fStartTime);
13  am->FillNtupleDColumn(3, endTime);
14  am->FillNtupleSColumn(4, outputFileName);
15  am->FillNtupleSColumn(5, fSeedFileName);
16  am->AddNtupleRow();
17
18  am->Write();
19  am->CloseFile()
20}

シミュレーションの終了時にEndOfRunActionが呼ばれます。 出力したファイルに書き込む操作(Write)と、 閉じる操作(CloseFile)は、 この中で実行します。

マルチスレッド環境で実行した場合、 各スレッドで記録されたデータは、ランの終了時に 自動的にマスターで集約され、 ひとつのファイルにまとめて保存されます。

注釈

CloseFileだけでは結果が保存されません。 必ずWriteを先に呼ぶ必要があります。

イベント情報したい

 1// include/EventAction.hh
 2
 3#ifndef EVENT_ACTION_HH
 4#define EVENT_ACTION_HH
 5
 6#include "G4UserEventAction.hh"
 7#include "G4Event.hh"
 8#include "globals.hh"
 9
10class EventAction : public G4UserEventAction {
11  public:
12    EventAction();
13    virtual ~EventAction();
14
15    virtual void BeginOfEventAction(const G4Event* aEvent) override;
16    virtual void EndOfEventAction(const G4Event* aEvent) override;
17
18  private:
19    G4int fEventId = -1;
20    G4double fEnergyDeposit = 0;
21};
22
23#endif // EVENT_ACTION_HH

イベント開始時の処理(EventAction::BeginOfEventAction

1void EventAction::BeginOfEventAction(const G4Event* aEvent) {
2  fEventId = event->GetEventID();
3  fEnergyDeposit = 0;  // 初期化
4}
1void EventAction::EndOfEventAction(const G4Event* aEvent) {
2    auto am = G4AnalysisManager::Instance();
3    am->FillNtupleIColumn(0, fEventId);
4    am->FillNtupleDColumn(1, fEnergyDeposit);
5    am->AddNtupleRow();
6}

イベント終了時の処理(EventAction::EndOfEventAction

ランアクションしたい

1void ActionInitialization::Build() const {
2    SetUserAction(new MyRunAction{});
3}

ユーザー定義したMyRunActionクラスは ActionInitializationへの登録が必要です。

ファイル名を変更したい(SetFileName

1auto am = G4AnalysisManager::Instance()
2am->SetFileName("ファイル名.root");  // ROOT形式
3am->SetFileName("ファイル名.csv");   // CSV形式
4am->SetFileName("ファイル名");

ファイル名は拡張子をつけて設定できます。 拡張子がない場合は、SetDefaultFileTypeで指定した形式の拡張子が追加されます。

ファイル形式を変更したい(SetDefaultFileType

1auto am = G4AnalysisManager::Instance()
2am->SetDefaultFileType("csv");  // CSV形式
3am->SetDefaultFileType("root");  // ROOT形式

一般的なユーザーであればCSV形式で出力するとよいと思います。 CSV形式であれば、ユーザーが使い慣れているツールで解析できます。

HEP業界のユーザーであればROOT形式のほうが使いやすいと思います。 AnalysisManagerを使った付属サンプルのほとんどがROOTファイルで出力されるようになっています。

参考

同様の設定はマクロコマンドでもできます。

/analysis/setDefaultFileType csv
/analysis/setDefaultFileType root

サブディレクトリを作成したい(SetHistoDirectoryName / SetNtupleDirectoryName

1am->SetHistoDirectoryName("histo");
2am->SetNtupleDirectoryName("ntuple");

CSV形式のファイルを保存するディレクトリを設定できます。 ディレクトリはあらかじめ作成しておく必要があります。

ヒストグラムを作成したい(CreateH1 / CreateH2 / CreateH3

 1auto am = G4AnalysisManager::Instance()
 2// 1Dヒストグラム
 3am->CreateH1(
 4    "name1",  // オブジェクト名
 5    "title",  // ヒストグラムのタイトル
 6    xbins,    // ビンの数
 7    xmin,     // ビンの最小値
 8    xmax      // ビンの最大値
 9);  // h1 Id = 0
10
11am->CreateH1("name2", "title", xbins, xmin, xmax);  // h1 Id = 1
12
13// 2Dヒストグラム
14am->CreateH2("name3", "title", xbins, xmin, xmax, ybins, ymin, ymax);  // h2 Id = 0
15am->CreateH2("name4", "title", xbins, xmin, xmax, ybins, ymin, ymax);  // h2 Id = 1

CreateH1CreateH2CreateH3でヒストグラムを準備できます。

ヒストグラムのIDを取得したい(GetH1Id / GetH2Id / GetH3Id

1// ヒストグラムのIDを取得
2G4int id1 = am->GetH1Id("name1");
3G4int id2 = am->GetH1Id("name2");
4G4int id3 = am->GetH2Id("name3");
5G4int id4 = am->GetH2Id("name4");

ヒストグラムを作成したときの名前を使って、ヒストグラムのIDを取得できます。 EventActionクラスで、ヒストグラムに値をフィルするときに利用できます。

ヒストグラムにフィルしたい(FillH1 / FillH2 / FillH3

1am->FillH1(id, value, weight);
2am->FillH2(id, xvalue, yvalue, weight);
3am->FillH3(id, xvalue, yvalue, zvalue, weight);

ヒストグラムIDを指定して値をフィルできます。

ヒストグラムを確認したい(GetH1 / GetH2 / GetH3

1auto h1 = am->GetH1(id);
2G4String name = am->GetH1Name(id);
3
4G4double mean = h1->mean();
5G4double rms = h1->rms();

ヒストグラムIDを指定して、ヒストグラムを取得できます。 取得したヒストグラムを使って、平均値などを取得できます。

1G4int nH1s = am->GetNofH1s;
2for ( G4int i=0; i<nH1s; ++i) {
3    auto h1 = am->GetH1(i);
4    if (h1 == nullptr) continue;
5    G4String name = am->GetH1Name(i);
6    G4cout << "Name: " << name << G4endl;
7    G4cout << "Mean: " << h1->mean() << G4endl;
8    G4cout << "Rms: " << h1->rms() << G4endl;
9}

GetNofH1でヒストグラムの数が取得できます。 その数だけループして確認できます。

Ntupleを作成したい(CreateNtuple / CreateNtupleDColumn / FinishNtuple

1am->CreateNtuple("Ntuple1", "title1");  // ntuple Id = 0
2am->CreateNtupleIColumn("name1");  // column Id = 0
3am->CreateNtupleDColumn("name2");  // column Id = 1
4am->FinishNtuple();
5
6am->CreateNtuple("Ntuple2", "title2");  // ntuple Id = 1
7am->CreateNtupleIColumn("name3");  // column Id = 0
8am->CreateNtupleDColumn("name4");  // column Id = 1
9am->FinishNtuple();

CreateNtupleでNtupleを作成します。 CreateNtupleDColumnCreateNtupleIColumnでカラムを定義します。 FinishNtupleでNtupleを閉じます。

これを繰り返すことで複数のNtupleを作成できます。

AnalysisManagerを使いたくない

G4AnalysisManagerを使わなくてもファイルに出力できます。 その場合、C++の標準ライブラリを使い、 ユーザーのお好みで std::tuplestd::mapstd::vectorなどを使います。

G4VAnalysisManagerを使って、ファイルに出力できます。 Geant4は独自のデータベース形式を持たない代わりに、 ユーザー自身がいろいろなフォーマットに出力できるようになっています。

ファイル操作(設定/開く/閉じる)はランごとに実行すればよいため、RunActionの中で動作を定義します。 ユーザーが編集する必要があるユーザーフック関数は以下の3箇所です。

  1. RunAction::RunAction: RunActionクラスのコンストラクターで、ファイル名や出力形式を設定します。 また、データを保存する「箱の形」を用意します。

  2. RunAction::BeginOfRunAction: ラン開始時にファイルを開きます。

  3. RunAction::BeginOfRunAction: ラン終了時にデータを保存し、ファイルを閉じます。

以下は、付属サンプルB4dとB5から該当箇所を抜粋して、説明を追加してみました。

 1// //////////////////////////////////////////////////
 2// include/RunAction.hh
 3// //////////////////////////////////////////////////
 4
 5#include "G4UserRunAction.hh"
 6#include "G4Run.hh"
 7
 8class RunAction : public G4UserRunAction
 9{
10    public:
11      RunAction();
12      ~RunAction() override = default;
13
14      void BeginOfRunAction(const G4Run* aRun) override;
15      void EndOfRunAction(const G4Run* aRun) override;
16
17    private:
18      // (オプション)
19      // EventAction* fEventAction = nullptr;
20}
 1// //////////////////////////////////////////////////
 2// src/RunAction.cc
 3// //////////////////////////////////////////////////
 4
 5// RunActionのコンストラクタ(初期化)
 6RunAction::RunAction()
 7{
 8    // G4AnalysisManagerのインスタンスを作成する
 9    // このインスタンスはシングルトンになっている
10    auto am = G4AnalysisManager::Instance();
11
12    // 表示レベルを設定する(オプション)
13    am->SetVerboseLevel(1);
14
15    // ファイル名を設定する(オプション)
16    // マクロファイルで変更可能
17    am->SetFileName("ファイル名");
18
19    // ファイル形式を指定する(オプション)
20    // ファイル名に拡張子がない場合はROOT形式になる
21    am->SetDefaultFileType("csv");
22    // am->SetDefaultFileType("root");
23
24    // /////////////////////////
25    // ユーザー独自の設定
26    // 目的に合わせて自分で考える部分
27    ///////////////////////////
28
29    // 1Dヒストグラムを作成する
30    // am->CreateH1("name", "title", nbins, xmin, xmax);
31    am->CreateH1("Chamber1", "Drift Chamber 1 # Hits", 50, 0., 50); // h1 Id = 0
32    am->CreateH1("Chamber2", "Drift Chamber 2 # Hits", 50, 0., 50); // h1 Id = 2
33
34    // 2Dヒストグラムを作成する
35    // am->CreateH2("name", "title", nxbins, xmin, xmax, nybins, ymin, ymax);
36    am->CreateH2("Chamber1 XY", "Drift Chamber 1 X vx Y", 50, -1000., 1000., 50, -300., 300.);  // h2 Id = 0
37    am->CreateH2("Chamber2 XY", "Drift Chamber 2 X vx Y", 50, -1000., 1000., 50, -300., 300.);  // h2 Id = 1
38
39    // Ntupleを作成する
40    // am->CreateNtuple("name", "title);
41    am->CreateNtuple("B5", "Hits");
42    // am->CreateNtupleIColumn("name");
43    am->CreateNtupleIColumn("Dc1Hits");  // column Id = 0
44    am->CreateNtupleIColumn("Dc2Hits");  // column Id = 1
45    // am->CreateNtupleDColumn("name");
46    am->CreateNtupleDColumn("ECEnergy");  // column Id = 2
47    am->CreateNtupleDColumn("HCEnergy");  // column Id = 3
48    am->CreateNtupleDColumn("Time1");     // column Id = 4
49    am->CreateNtupleDColumn("Time2");     // column Id = 5
50    // am->CreateNtupleDColumn("name", vector);
51    am->CreateNtupleDcolumn("ECEnergyVector", fEventAction->GetEmCalEdep());  // column Id = 6
52    am->CreateNtupleDcolumn("HCEnergyVector", fEventAction->GetHadCalEdep());  // column Id = 7
53    am->FinishNtuple();
54
55    // Ntupleのファイル名を設定する
56    // am->SetNtupleFileName(id, "fileName");
57    am->SetNtupleFileName(0, "B5ntuple");
58}
 1// //////////////////////////////////////////////////
 2// src/RunAction.cc
 3// //////////////////////////////////////////////////
 4
 5// ラン開始時の処理
 6void RunAction::BeginOfRunAction(const G4Run* aRun)
 7{
 8    // ラン番号を表示する
 9    G4cout << "Run started: " << run->GetRunID() << G4endl;
10
11    // AnalysisManagerのインスタンスを取得する
12    // AMがシングルトンなので、作成済みのインスタンスが取得できる
13    auto am = G4AnalysisManager::Instance()
14
15    // 前のランの結果をリセットする
16    // 付属サンプルB5は、ラン終了時に自動リセットせず、
17    // ラン開始時にリセットしている
18    am->Reset();
19
20    // ファイルを開く
21    // ファイル名はコンストラクタで設定済み
22    am->OpenFile();
23    G4cout << "File opened: " << am->GetFileName() << G4endl;
24}
 1// //////////////////////////////////////////////////
 2// src/RunAction.cc
 3// //////////////////////////////////////////////////
 4
 5// ラン終了時の処理
 6void RunAction::EndOfRunAction(const G4Run* aRun)
 7{
 8    // AnalysisManagerのインスタンスを取得する
 9    // AMがシングルトンなので、作成済みのインスタンスが取得できる
10    auto am = G4AnalysisManager::Instance()
11
12    // 取得したデータをファイルに出力する
13    am->Write();
14
15    // ファイルを閉じる
16    am->CloseFile(false);
17    // サンプルB5では、ラン終了時にデータ(ヒストグラム)を
18    // 保持したままにしている
19    // デフォルトは自動リセットされる
20    // am->CloseFile(reset=true);
21    G4cout << "File closed: " << am->GetFileName() << G4endl;
22}

ヒント

データ取得はイベントごとやステップごとに値を取得するため、 EventActionクラスやSteppingActionクラスで定義します。

リファレンス