27.2. Creating Detector Blocks
Table of Contents
Detector modules
Detector blocks, or detector modules, are the intermediate building blocks between the full PET ring and the individual crystals. In most PET scanners you do not repeat single crystals directly around the ring. Instead, you group several crystals into a logical and physical unit, the module, and then repeat that module. Understanding this hierarchy is important because it affects geometry definition, detector identification, and digitizer configuration.
Conceptually, a PET detector hierarchy often looks like this:
| Level | Example role |
|---|---|
| World | Global simulation volume |
| PET ring | Logical grouping of all modules |
| Module | Detector block with several crystals |
| Crystal | Small scintillator element |
In GATE, a module is just another volume, usually a box, that acts as the parent volume for the crystals. The module itself may be filled with a support material, air, or left as a logical container depending on your modeling goals. You can also attach IDs at the module level to distinguish different blocks around the ring.
From a practical perspective, you define a module by specifying at least its size, material, placement relative to the ring, and a name that makes sense within your geometry tree. A typical sequence in OpenGATE looks like this in pseudocode:
m = sim.add_volume("Box", "module")
m.size = [module_x, module_y, module_z]
m.material = "Air"
m.mother = "pet_ring"
m.translation = [0, 0, 0] # local position inside the ring volume
The important point is that the module is a parent volume. Later, when you add crystals, you will set their parent with something like crystal.mother = "module". This guarantees that if you move or rotate the module, the crystals follow automatically without individual adjustments.
It is often useful to decide at this stage how many crystals you want in each module, for example an array of $N_x \times N_y$ crystals, and ensure that the module dimensions are large enough to contain all crystals plus any gaps or reflectors between them. A simple consistency relation is:
$$
\text{module\_size}_x \ge N_x \cdot \text{crystal\_size}_x + (N_x - 1)\cdot \text{gap}_x
$$
and similarly for the $y$ dimension. The $z$ dimension usually matches the crystal thickness, possibly with some margin for support material.
You typically do not record hits directly in the module, because the relevant interactions for PET are in the crystals. However, assigning a module ID is useful for later analysis or digitization. For example, you can configure the digitizer chain so that each single event contains both a crystal ID and its parent module ID.
When defining detector modules, keep in mind:
- The module is a logical container for a group of crystals.
- Its placement and rotation relative to the ring will be reused by all repeated modules.
- Its size must be consistent with the crystal array it will contain.
- It is a convenient level to attach identifiers used later by the digitizer and analysis.
By building and validating one single module layout first, including its internal crystal arrangement, you greatly simplify the task of creating the complete PET ring.
A detector module is a parent volume that groups multiple crystals, and all crystal positions are defined relative to the module coordinate system.
Repetition
Once a single module is correctly defined and populated with crystals, you rarely place the other modules one by one. Instead, you use repetition to create many identical modules around the PET ring in a systematic way. Repetition is essential for complex PET scanners because it keeps the geometry compact, readable, and easy to modify.
At the ring level, you usually define a circular array of modules. The basic idea is:
- Decide how many modules $N_{\text{mod}}$ you want around the ring.
- Place each module at a radius $R$ from the ring center.
- Rotate each module so that it faces the center.
The central angle between neighboring modules is:
$$
\Delta \phi = \frac{2\pi}{N_{\text{mod}}}
$$
For module index $k$ with $k = 0, 1, \dots, N_{\text{mod}} - 1$, the center position in the $x$ and $y$ directions is:
$$
x_k = R \cos(k \Delta \phi), \quad y_k = R \sin(k \Delta \phi)
$$
You do not usually compute these coordinates yourself in final code, but this relation helps you understand what the repetition utility does under the hood.
In OpenGATE, repetition is often handled by a repeated volume configuration rather than explicit loops of add_volume. A common pattern is to define a prototype module and then specify a repeat type such as a ring:
m = sim.add_volume("Box", "module")
# define size, material, parent, etc.
m.repeat.type = "ring"
m.repeat.nb = number_of_modules
m.repeat.radius = ring_radius
m.repeat.first_angle = 0.0
m.repeat.angle_range = 360.0 * gate.g4_units.deg
This instructs GATE to create number_of_modules copies of the module, uniformly spaced along a circle of given radius, over the specified angular range. The prototype volume stores the local shape and content (like crystals); GATE handles the placements automatically.
Repetition is often used at multiple hierarchy levels:
| Level | Typical repetition pattern |
|---|---|
| Ring | Modules repeated in a ring |
| Module | Crystals repeated in a grid |
Inside a module, you might use another kind of repeat to create a grid of crystals, for example:
c = sim.add_volume("Box", "crystal")
# define crystal size, material, and parent
c.mother = "module"
c.repeat.type = "linear"
c.repeat.repeat_vector = [Nx, Ny, 1]
c.repeat.spacing = [pitch_x, pitch_y, 0]In this way, one crystal definition generates an entire crystal array inside every repeated module. This hierarchical repetition is extremely powerful. Changing the crystal size or count in the module definition will then automatically update the whole scanner layout.
Repetition also affects detector identification. Each physical copy of the repeated volume receives an index. For modules in a ring, the index usually corresponds to the azimuthal position. For crystals in a module, the indices correspond to their position in the module grid. The digitizer chain can then combine these indices into a complete detector ID, which is important for PET events and later analysis.
It is important to verify that the repetition does not create overlapping volumes. Even if a single module and its internal array are valid, too many modules or an incorrect radius can cause overlaps. Use the geometry validation tools and visualization to check the ring after you apply repetition.
From a performance and maintainability perspective, the recommended workflow for detector blocks is:
- Define and test a single module with its crystal array.
- Use repetition at the module level to create the ring.
- Use repetition at the crystal level inside the module if appropriate.
- Validate the complete geometry visually and with overlap checks.
Always define and validate one prototype module with its crystals before using repetition. Repetition replicates the prototype exactly, so any error in the prototype will be repeated throughout the entire PET scanner.
Views: 11
KAHIBARO