ヒット配列したい(G4VHitsCollection / G4THitsCollection

1G4THitsCollection<SensorHit> hit_collection;
2
3// テンプレートクラスを使うことで、任意の型を持った変数を定義できます。
4// ここでは
5// hit_collection = [SensorHit1, SensorHit2, SensorHit3, ...]
6// のようなSensorHitオブジェクトが詰まったコンテナー配列を定義しています。

ひとつイベントで発生した複数のヒットは、SensorHit型を持つヒット配列として保存します。 ヒット配列はG4THitsCollectionテンプレートクラスを使って定義します。

G4THitsCollectionG4VHitsCollectionを継承したテンプレートクラスですが、そのさらに親をたどるとstd:vectorをベースにしているようです。

親クラス

1G4VHitsCollection() = default;
2G4VHitsCollection(G4String detector_name, G4String collection_name);
3virtual ~G4HitsCollection() = default;
4virtual void DrawAllHits(){};
5virtual void PrintAllHits(){};
6virtual G4VHit* GetHit(size_t) const {return nullptr;};
7virtual size_t GetSize() const {return 0;};

G4THitsCollectionクラスは、G4VHitsCollectionクラスを継承したテンプレートクラスです。 コンストラクターとデストラクターは、親クラスのものをそのまま使っているようです。 GetHitGetSizeは、テンプレートクラスでoverrideして再定義しています。

テンプレートクラス

 1G4THitsCollection();
 2G4THitsCollection(G4String detector_name, G4String collection_name);
 3~G4THitsCollection() override;
 4inline void* operator new(size_t);
 5inline void operator delete(void* aHC)
 6void DrawAllHits() override;
 7void PrintAllHits() override;
 8inline size_t insert(T* aHit);
 9inline size_t entries() const;
10G4VHit* GetHit(size_t i) const override { return ((std::vector<T*>*)theCollection)[i]; };
11size_t GetSize() const override { return ((std::vector<T*>*)theCollection)->size(); };

G4THitsCollectionクラスのメンバー関数を抜粋しました。 コンストラクターとデストラクターの引数は、親クラスを引き継いで定義されています。 GetHitGetSizeは、内部変数theCollectionに対する処理として再定義されています。 またその内部変数にヒットを追加するためのinsertが追加されています。

型エイリアスしたい(using / typedef

1// C++11で導入された文法
2// using コレクション名 = G4THitsCollection<ヒットクラス名>;
3using SensorHitsCollection = G4THitsCollection<SensorHit>;
4SensorHitsCollection hit_collection{};
5SensorHitsCollection hit_collection{"DetectorName", "CollectionName"};

G4THitsCollection<SensorHit>型は名前が長いため、型エイリアスを定義して SensorHitsCollection型という名前で使えるようにします。

注釈

usingはC++11以降で使える型エイリアスの宣言です。 以前はtypedefが使われていました。 基本的には同じことができるそうなのですが、高機能なusingを使えばよいようです。

1// C言語から使われている文法
2// typedef G4THitsCollection<ヒットクラス名> コレクション名;
3typedef G4THitsCollection<SensorHit> SensorHitsCollection;
4SensorHitsCollection hit_collection();
5SensorHitsCollection hit_collection("DetectorName", "CollectionName");

SensorHitクラス

SensorHitsCollection型はSensorHitクラスのファイルの中で定義し、Sensorクラスの中で使います。

1// 0. SensorHit.hh で型エイリアスを定義する
2using SensorHitsCollection = G4THitsCollection<SensorHit>;

SensorHitsCollectionを初期化したい

1void Sensor::Initialize(G4HCofThisEvent* /*aHCE*/)
2{
3  // Sensor::Initializeで初期化
4  // 1. ヒット配列を初期化
5  // fSensorHitsCollection はprivate変数で定義
6  auto fSensorHitsCollection = new SensorHitsCollection{"DetectorName", "CollectionName"};
7}

SensorHitsCollectionにSensorHitを追加したい

 1G4bool Sensor::ProcessHits(G4Step *aStep)
 2{
 3  // Sensor::ProcessHitsの処理
 4  // 2. ヒット(SensorHit)を新しく作成
 5  SensorHit *hit = new SensorHit{};
 6  hit->Fill(aStep);  // G4Step *aStep とする
 7
 8  // 3. ヒット配列にヒットを追加
 9  // ここでは同じヒットを複数回追加しているが、
10  // 実際には別のステップで取得したヒットを追加する
11  hitCollection->insert(hit);
12  hitCollection->insert(hit);
13  hitCollection->insert(hit);
14  hitCollection->insert(hit);

G4EventにSensorHitsCollectionを渡したい

 1void Sensor::EndOfEvent(G4HCofThisEvent *aHCE)
 2{
 3  // EndOfEventの処理
 4  // 4. データを確認
 5  G4int entries = hitCollection->entries();
 6  for (G4int i = 0; i < entries; i++)
 7  {
 8      //SensorHit * h = (*hitCollection)[i]
 9      SensorHit *h = hitCollection->GetHit(i);
10      h->Print();
11  }
12
13  // 5. HCEにSensorHitsCollectionを追加
14  aHCE->AddHitsCollection(0, fSensorHitsCollection);
15}

G4EventでSensorHitsCollectionを取得したい

 1void EventAction::EndOfEventAction(const G4Event *aEvent)
 2{
 3    // このイベントのヒット配列を取得する
 4    G4HCofThisEvent *hce = aEvent->GetHCofThisEvent();
 5    // ヒット配列の数を確認する
 6    G4int n_collections = hce->GetNumberOfCollections();
 7    for (G4int i = 0; i < n_collections; i++)
 8    {
 9        // ヒット配列の配列からヒット配列を取得する
10        auto hc = hce->GetHC(i);
11
12        // ヒット配列の中のヒット数を確認する
13        G4int n_hits = hc->entries();
14        for (G4int j = 0; j < n_hits; j++)
15        {
16            // ヒット配列からヒットを取得する
17            auto h = hc->GetHit(j);
18
19            // ヒットの中身を表示する
20            h->Print();
21
22            // ファイルに保存する処理はここに書くとよい
23            h->ToCsvString();
24        }
25    }
26}

有感検出器でヒットがあった場合のヒット配列の処理の流れを、 ユーザー定義が必要な関数と対応させてみました。