解析マネージャーしたい(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
CreateH1
、CreateH2
、CreateH3
でヒストグラムを準備できます。
ヒストグラムの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を作成します。
CreateNtupleDColumn
や
CreateNtupleIColumn
でカラムを定義します。
FinishNtuple
でNtupleを閉じます。
これを繰り返すことで複数のNtupleを作成できます。
AnalysisManagerを使いたくない
G4AnalysisManager
を使わなくてもファイルに出力できます。
その場合、C++の標準ライブラリを使い、
ユーザーのお好みで
std::tuple
、
std::map
、
std::vector
などを使います。
G4VAnalysisManagerを使って、ファイルに出力できます。 Geant4は独自のデータベース形式を持たない代わりに、 ユーザー自身がいろいろなフォーマットに出力できるようになっています。
ファイル操作(設定/開く/閉じる)はランごとに実行すればよいため、RunAction
の中で動作を定義します。
ユーザーが編集する必要があるユーザーフック関数は以下の3箇所です。
RunAction::RunAction
:RunAction
クラスのコンストラクターで、ファイル名や出力形式を設定します。 また、データを保存する「箱の形」を用意します。RunAction::BeginOfRunAction
: ラン開始時にファイルを開きます。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
クラスで定義します。