SensitiveDetectorしたい(G4VSensitiveDetector
)
測定器の有感検出器でのヒットを収集したい場合は、
G4VSensitiveDetector
クラスを継承したクラスを作成します。
親クラス
1explicit G4VSensitiveDetector(G4String name);
2virtual ~G4VSensitiveDetector() = default;
3virtual void Initialize(G4HCofThisEvent*) {};
4virtual void EndOfEvent(G4HCofThisEvent*) {};
5virtual G4bool ProcessHits(G4Step *aStep, G4TouchableHistory* /*ROhist*/) = 0;
親クラスのメンバー関数を抜粋しました。 コンストラクターとデストラクターは、このまま引き継げばよさそうです。
Initialize()
は、イベントの開始時に実行される関数です。
EndOfEvent()
は、イベントの終了時に実行される関数です。
これらの仮想関数は、目的に合わせて自作クラスでoverrideします。
ProcessHits()
は、ステップが有感検出器の中にあるときに実行される関数です。
この純粋仮想関数は、自作クラスでoverrideが必要です。
Sensorクラス
1// include/Sensor.hh
2
3#ifndef Sensor_h
4#define Sensor_h 1
5
6#include "SensorHit.hh"
7
8#include "G4HCofThisEvent.hh"
9#include "G4Step.hh"
10#include "G4TouchableHistory.hh"
11#include "G4VSensitiveDetector.hh"
12
13namespace ToyMC
14{
15
16class Sensor : public G4VSensitiveDetector
17{
18 public:
19 Sensor(const G4String &name);
20 ~Sensor() = default;
21
22 public:
23 void Initialize(G4HCofThisEvent *aHCE) override;
24 void EndOfEvent(G4HCofThisEvent *aHCE) override;
25 G4bool ProcessHits(G4Step *aStep, G4TouchableHistory *aTouchable) override;
26};
27
28 private:
29 // SensorHitクラスで定義した型エイリアスを使って
30 // 有感検出器で必要なヒット配列を準備する。
31 G4int fHcID = 0;
32 SensorHitsCollection *fHitsCollection{nullptr};
33
34}; // namespace ToyMC
35
36#endif // Sensor_h
上記サンプルでは、G4VSensitiveDetector
クラスを継承して、汎用的なセンサーを仮定したSensor
クラスを作成しました。
G4VSensitiveDetector
クラスは抽象基底クラスで、
Initialize
、ProcessHits
、EndOfEvent
の3つの仮想関数を持っています。
これらのメソッドをoverrideして定義します。
コンストラクター(Sensor::Sensor
)
1Sensor::Sensor(const G4String &name) : G4VSensitiveDetector{name}
2{
3 ;
4}
SensorHit
クラスのコンストラクターで、親のG4VSensitiveDetector
クラスの初期化が必要です。
引数(name
)をそのまま使って、初期化リストで初期化しています。
注釈
G4VSensitiveDetector
のコンストラクターにはexplicit
キーワードが付けられています。
これは、暗黙の型変換を防ぐ ためのキーワードです。
1// OK
2G4VSensitiveDetector detector{"DetectorName"};
3
4// NG
5// G4String -> G4VSensitiveDetector に勝手に変換されるのを防止
6G4VSensitiveDetector detector = "DetectorName";
初期化したい(Sensor::Initialize
)
1// src/Sensor.cc
2
3#include "Sensor.hh"
4
5void Sensor::Initialize(G4HCofThisEvent *aHCE)
6{
7 // ヒット配列を初期化
8 fHitsCollection = new SensorHitsCollection{};
9 aHCE->AddHitsCollection(fHcID, fHitsCollection);
10};
Initialize
は、G4EventManager
がイベント処理を開始する時に実行されます(BeginOfEventAction
より先に実行されます)。
G4HCofThisEvent
は、ひとつイベント(G4Event
)に紐づいたヒット配列(G4HitsCollection
)です。
イベントの開始時に、このヒット配列を初期化しておきます。
集計したい(Sensor::EndOfEvent
)
1// src/Sensor.cc
2
3#include "Sensor.hh"
4
5void Sensor::EndOfEvent(G4HCofThisEvent *aHCE)
6{
7 G4int entries = fHitsCollection->entries();
8 // ヒット配列を取得
9 aHCE->Get...
10
11};
EndOfEvent
はイベントの最後に呼ばれます。
G4HCofThisEvent
からヒット配列を取り出し、
ヒット配列のデータを集計したり、
ファイルに書き出したりできます。
ヒット処理したい(Sensor::ProcessHits
)
1// src/Sensor.cc
2
3#include "Sensor.hh"
4
5#include "G4Step.hh"
6
7G4bool Sensor::ProcessHits(G4Step *aStep, G4TouchableHistory* /* aTouchable */) {
8
9 // ヒットを残さない場合
10
11 // 例1: エネルギー損失がない
12 if (aStep->GetTotalEnergy() <= 0) {
13 return false;
14 }
15
16 // 例2: 中性粒子
17 if (aStep->GetTrack()->...粒子の電荷を取得 == 0) {
18 return false;
19 }
20
21 // ヒット処理の準備
22 auto pre_step = aStep->GetPreStepPoint();
23 auto track = aStep->GetTrack();
24 auto pv = aStep->GetPreStepPoint()->GetPhysicalVolume();
25 auto lv = pv->GetLogicalVolume();
26
27 // SensorHitオブジェクトを作成
28 auto hit = new SensorHit{};
29
30 // ヒット情報を代入
31 // - SensorHit::Fill(G4Step *aStep)のカスタム関数を追加
32 // - SensorHitの内部変数に値を代入
33 hit->Fill(aStep);
34
35 // 代入したヒット情報を確認
36 hit->Print();
37
38 // ヒット配列にヒット(SensorHit)を追加
39 fHitsCollection->insert(hit);
40
41 return true;
42};
ProcessHits
はSensitiveDetectorのヒット情報を処理するときのメインの関数です。
データを残すかどうかの条件や、
どのようなデータを取得するかは、
ユーザーがこの関数の中で実装します。
この関数は、ステップが有感検出器の中にあるとき、自動的に呼ばれます。
ひとつめの引数は(G4Step *aStep)
になっているので、
G4Step操作や
G4Track操作でできることを使って、
取得したい値を定義できます。
ふたつめの引数は(G4TouchableHistory*)
となっていますが、
これはもう使われてない(obsolete)そうです。
ヒント
おそらくUserSteppingActionの亜種です。 (たぶん)G4SDManagerが管理してくれているため、ステップが有感検出器の中にあるとき、ユーザーが境界判断しなくても、自動的に呼ばれます。 SensitiveDetectorを使う方が楽ちんです。
測定器のヒット情報を知りたい場合は、SensitiveDetectorだけを定義すればOKです。
有感検出器を設定したい(SetSensitiveDetector
)
1#include "Geometry.hh"
2#include "Sensor.hh"
3
4#include "G4SDManager.hh"
5
6void Geometry::ConstructSDandField()
7{
8 // Sensorを作成
9 auto sensor = new Sensor("検出器名");
10
11 // 論理ボリュームに割り当て
12 SetSensitiveDetector("論理ボリューム名", sensor);
13
14 // SDManagerに追加
15 auto sm = G4SDManager::GetSDMpointer();
16 sm->AddNewDetector(sensor);
17}
有感検出器として利用するためには、
Sensor
クラスのオブジェクトを論理ボリュームに割り当て、
さらにG4SDManager
に登録します。
G4VUserDetectorConstruction
から継承した
ConstructSDandField
関数の中で、
論理ボリュームを有感検出器(SensitiveDetector
)に設定します。
ここではG4VUserDetectorConstruction
が持っているprotectedなメンバー関数SetSensitiveDetector
を使っています。
この関数は、論理ボリュームの名前を使って有感検出器を設定できます。
参考
G4LogicalVolume
もpublicなメンバー関数SetSensitiveDetector
を持っています。
そちらを使って有感検出器を設定する方法もあります。