KAHIBARO
Discord Login Register

Finding Coincidence Events

Coincidence Events in PET

In a PET simulation, coincidence events are the key link between individual detector hits and the reconstructed image. In Geant4, coincidences are not provided automatically. You must build coincidence logic on top of the hits you already record for each detector crystal.

This chapter focuses on how to identify coincidence events from detector hits and how to organize that information so that later steps, like building lines of response and image reconstruction, become straightforward.

What a Coincidence Event Is

In PET, a positron annihilates with an electron and produces two 511 keV photons. These photons travel in nearly opposite directions and may be detected in two different detector crystals. A coincidence event is a pair of detector hits that are interpreted as originating from the same annihilation.

Two ingredients define a coincidence:

  1. The two hits must be close in time, within a coincidence time window.
  2. The two hits must correspond to valid gamma detections, often within an energy window around 511 keV.

Later in the course you will use coincidence pairs to form lines of response, but here the goal is simply to find and record those pairs.

A coincidence event is usually defined by three rules:

  1. Two detector hits occur in different detectors.
  2. The time difference between the hits is less than a coincidence window $\Delta t_{\text{coin}}$.
  3. Each hit passes the energy selection (for example, within an energy window around 511 keV).
    Any pair that does not satisfy all three conditions must not be treated as a valid coincidence.

Timing Windows and Coincidence Logic

The central quantity in coincidence finding is the difference between the detection times of two hits. Each hit in your Geant4 simulation already has a time, typically derived from the global time of the step when the hit is recorded, or from a derived detector time that you define.

Given two hits with detection times $t_1$ and $t_2$, the coincidence condition in time is

$$
\Delta t = |t_1 - t_2| < \Delta t_{\text{coin}} ,
$$

where $\Delta t_{\text{coin}}$ is the coincidence time window. In real systems this can be a few nanoseconds or less. In your simulation you may choose a value that reflects your detector timing resolution.

Coincidence time rule
Two hits form a coincidence only if
$$
|t_1 - t_2| < \Delta t_{\text{coin}}.
$$
If you adjust $\Delta t_{\text{coin}}$ in your macros, make sure the same value is used in your analysis code, otherwise your coincidence selection will be inconsistent.

In a simple PET simulation, you often consider coincidences within the same Geant4 event. In that case, $t_1$ and $t_2$ are times within one simulated annihilation. For more advanced setups, such as continuous sources, you may simulate multiple annihilations in one event and must apply the timing window without relying on event boundaries.

When you implement coincidence logic, it helps to think in two coordinate systems:

Global time: the Geant4 global time of a hit, obtained from methods like GetGlobalTime(). This includes any delays between annihilation and detection.

Detector time: a shifted time that describes what the detector readout would see. You can build this from the global time plus simulated effects, such as light propagation delays or electronic shaping, which are introduced in other chapters.

For beginners, using the global time directly for coincidence logic is sufficient. You simply use the hit time stored in your hit class.

Implementing Coincidence Selection

Geant4 does not provide a coincidence finder, but it does provide all the ingredients you need. You typically implement coincidence selection in one of two places:

Within a user action that has access to all hits in an event, often EventAction.

In an analysis step after you have written all hits to a file, for example in ROOT.

For a first PET example it is often easier to implement coincidence logic inside EventAction, because you already have direct access to the hit collections for that event.

Accessing hits for a PET event

You already created a sensitive detector for the PET crystals and a hit class that stores, at a minimum, the detector ID, the energy deposited in that crystal, and the time of the hit. In your EndOfEventAction, you obtain the hit collection and loop over the hits.

In pseudocode, the logical steps look like this:

  1. Collect all hits in the PET detector for the current event.
  2. Apply an energy window to select valid gamma detections.
  3. Sort or group the remaining hits by their detection time.
  4. Form pairs of hits that satisfy the coincidence time condition.
  5. Reject pairs with hits in the same crystal, if your design requires distinct detectors.
  6. Store information about each valid pair as a coincidence event.

A simple way to manage step 4 is to consider all possible pairs of hits and check whether each pair satisfies the timing and detector conditions. For $N$ hits in the event, there are $N(N - 1)/2$ pairs. In typical PET events, $N$ is small, so this method is practical for a beginner example.

Single hit per detector and energy summation

In a physical detector, a single gamma may deposit its energy in several steps inside one crystal. In Geant4, that yields several hits or several steps. For coincidence logic you often want a single energy and time per detector.

You can achieve this by building one hit per detector crystal per event and accumulating energy in that hit. When a step occurs in a crystal:

If a hit for that crystal already exists in the current event, you add the new energy deposit to the hit and update the time if needed.

If not, you create a new hit, record the crystal ID, the energy, and the time.

By the end of the event, you have at most one hit per detector crystal. Coincidence logic then operates on detector level hits, not on individual steps.

If you design your hit class to already represent a full detector signal, then coincidence finding becomes much cleaner and more realistic.

Energy and Time Conditions for Coincidences

Coincidence selection almost always combines timing and energy requirements. You already defined an energy window to select gamma detections. Now you use that same energy window as a first filter before comparing times.

For a hit with measured energy $E$, a simple energy window around 511 keV is

$$
E_{\min} < E < E_{\max}.
$$

Only hits that pass this energy window are considered candidates for coincidence. In practice, $E_{\min}$ and $E_{\max}$ are chosen based on the detector energy resolution. You will explore this in more detail when applying detector effects and energy smearing.

The typical order of operations is:

  1. Start from all detector hits in the event.
  2. Discard hits outside the energy window.
  3. Work with the remaining hits to form coincidence pairs based on time.

You may also require that the energy in each hit is not too low to avoid random coincidences from noise or scattered photons.

A valid PET coincidence hit should satisfy both:

  1. Energy selection: $E_{\min} < E < E_{\max}$.
  2. Timing selection when paired: $|t_1 - t_2| < \Delta t_{\text{coin}}$.
    Skipping the energy filter can dramatically increase the rate of accidental coincidences.

In some PET systems, additional logic is applied to reduce ambiguities, such as requiring that an event has exactly two valid hits in the time window. You can experiment with these conditions as an extension to the basic example.

Storing Coincidence Information

Once you identify a pair of hits that forms a coincidence, you must decide what to store. Later chapters on lines of response and analysis with ROOT will use this stored information. A clean representation at this stage will simplify those steps.

For each coincidence event you typically want:

The detector ID of the first hit.

The detector ID of the second hit.

The energies of both hits.

The detection times of both hits, or at least their time difference.

The event ID, or some unique ID, for bookkeeping.

Optionally, the positions of the detector crystals, which can be reconstructed later from the detector IDs and geometry.

If you already use G4AnalysisManager, it is natural to define an ntuple that stores coincidence events. Each row of the ntuple corresponds to one coincidence pair. You fill this ntuple in EndOfEventAction, after you have built the coincidence list for that event.

A simple conceptual table for coincidence data could look like this:

Column nameDescription
eventIDGeant4 event number
detID1ID of first detector
detID2ID of second detector
E1Energy in first detector
E2Energy in second detector
t1Time of first detector hit
t2Time of second detector hit
dtTime difference, $t_2 - t_1$

With this information, later you can:

Reconstruct the geometry positions for each detector ID.

Check timing distributions and optimize the coincidence window.

Apply further selection cuts in external analysis tools, such as ROOT.

To avoid double counting, ensure that each detector pair is stored only once per coincidence. You can enforce an ordering rule, for example, always treat the hit with earlier time as hit 1, or always require detID1 < detID2.

Random and Multiple Coincidences

In an idealized simulation with a single annihilation per event and no background, every coincidence you find might be a true coincidence. In more realistic PET simulations, you must deal with random and multiple coincidences.

A random coincidence occurs when two unrelated gamma detections accidentally fall within the coincidence time window. Multiple coincidences occur when more than two detectors fire within the time window and several possible pairs could be constructed.

You can experiment with these effects even in a simple Geant4 simulation by increasing the activity of the positron source, or by grouping multiple annihilations into a single event.

To handle multiple hits in one event with coincidence selection, you may:

Allow all valid pairs within the time window and study how many pairs appear.

Impose a rule that only one pair is accepted per event, for example, the pair with the highest sum of energies or the smallest time difference.

Flag events with more than two valid hits and treat them separately in later analysis.

These choices replicate real system behaviors and can strongly influence image quality, but the underlying Geant4 implementation remains the same: you still operate on the set of hits, apply energy and time filters, and record pairs that satisfy your chosen rules.

Summary

Coincidence finding is the bridge from low level detector hits to PET specific observables. In your Geant4 PET simulation you identify coincidences by:

Building clear detector hits that store energy, time, and detector ID.

Selecting hits that pass an energy window around 511 keV.

Applying a coincidence time window to pairs of hits in different detectors.

Recording each valid pair as a coincidence event in an ntuple or other data structure.

With this machinery in place, the next steps, such as recording detector positions and creating lines of response, become an exercise in geometry and analysis rather than low level detector bookkeeping.

Views: 8

Comments

Please login to add a comment.

Don't have an account? Register now!