16.3. Energy per Detector
Table of Contents
Detector IDs
When you have more than one detector element in your geometry, you must distinguish where each energy deposition occurred. Geant4 itself does not automatically tell you which specific crystal, strip, or pixel a hit belongs to. Instead, you define and use detector IDs.
A detector ID is typically an integer that uniquely labels a detector element. You can think of it as an index in an array. For example, if you have 100 identical scintillator bars in a calorimeter, you might assign IDs from 0 to 99, where each ID corresponds to one bar.
There are two common levels at which IDs are used:
- Geometrical copy numbers. When you place many copies of the same logical volume with
G4PVPlacementor replication / parameterization, each placed volume can have a copy number. You can obtain this from the touchable associated with a step. From theG4Step, you accessG4StepPoint, thenG4TouchableHandle, then queryGetCopyNumber(). That copy number is a natural detector ID for that volume. Many simple calorimeter and pixel detector implementations use the copy number directly as the detector ID. - Custom detector indices. Sometimes a single copy number is not enough, for instance in a 2D array of crystals or a layered detector. You may need indices like
(ix, iy)or(layer, strip). In such cases, you can: - Store the indices in the detector hit object directly as separate members.
- Or, encode them into a single integer ID using a scheme, for example
$$
\text{id} = ix + n_x \times iy
$$
where $n_x$ is the number of elements in the x direction. During analysis, you decode this integer back to(ix, iy).
The ID is typically attached to each hit object inside your sensitive detector. In your G4VSensitiveDetector::ProcessHits() implementation, you extract the relevant copy numbers (possibly at several depth levels in the touchable history), convert them into your chosen ID or indices, and store them in your hit. Later, in your event or run analysis, you can loop over hits and sum energy per detector ID.
A clear and consistent ID scheme is essential. You must:
- Define exactly how IDs map to detector elements.
- Use the same convention in the sensitive detector, analysis, and visualization.
- Avoid changing the scheme without updating all related code.
In many designs, the detector ID also serves as an index in arrays or histograms. For instance, you can keep a std::vector<G4double> where each element holds the total energy for one detector element in the current event, indexed by the detector ID. At the end of the event, you fill per-detector histograms or ntuple columns with these accumulated values.
Multiple detector elements
Energy per detector becomes important as soon as your geometry contains multiple active elements, for example a calorimeter with many cells, a strip tracker, or a PET detector ring. Conceptually, you are computing the same quantity, such as total deposited energy per event, but now separately for each detector element.
The usual workflow inside one event is:
- Each step that occurs in a sensitive volume produces a hit or contributes to an existing hit.
- The hit records the detector ID (or indices) together with the energy deposited in that step.
- At the end of the event you iterate over the hit collection and accumulate the energy for each detector ID.
This leads naturally to storing per-detector energy in a container indexed by ID. For example, if you have N detector elements with IDs from 0 to N-1, you can maintain a vector of length N initialized to zero at the start of every event. When you process a hit with detector ID id and deposited energy Edep, you add Edep to the corresponding entry. At the end of the event, the vector contains the total energy in each detector.
For detector arrays or multi-dimensional structures, you can choose between a 1D container with encoded IDs or multiple dimensions in C++. Both approaches are equivalent computationally, but the 1D encoding is usually simpler to integrate with Geant4 analysis and histogram indices.
A very common approach is to create one histogram per detector element, for example a separate energy spectrum for each crystal. However, if there are many detectors, this can quickly become unwieldy. An alternative is to use ntuples, where each row corresponds to a hit or to a detector element per event, and columns include the detector ID and energy. You can then perform per-detector analysis later, for example in ROOT, by selecting events or hits with a given ID and filling histograms offline.
When your geometry contains more than one type of detector, for example a tracker and a calorimeter, you often have different sensitive detectors and separate hit collections. In that case you handle energy per detector separately for each subsystem, but the principles remain the same: each hit belongs to exactly one logical detector element identified by an ID or indices, and you sum or analyze energies with that label.
To obtain correct energy per detector element you must ensure that:
- Each step in an active volume is associated with the correct detector ID.
- All steps in the same detector element during one event are combined.
- Different detector types or layers do not reuse IDs in a way that causes confusion in analysis.
With a well designed ID scheme and consistent accumulation of energy per detector, you can build detailed detector response maps, energy spectra per channel, and eventually realistic models of experimental readout and electronics on top of your Geant4 simulation.
Views: 10
KAHIBARO