Skip to content

Commit

Permalink
add DetectionEfficiencies to model
Browse files Browse the repository at this point in the history
  • Loading branch information
KrisThielemans committed Oct 27, 2024
1 parent 4c29bca commit 99f3d46
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
58 changes: 58 additions & 0 deletions model/DetectionEfficiencies.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Detection efficiencies for every detecting element and energy window
# If size along energyBinIdx is 1, the effiencies are assumed to be the same for every energy bin
# Constraint: size(DetElEfficiencies, "energyBinIdx") == scannerInformation.numberOfEnergyBins or 1
DetElEfficiencies: float[detElIdx, energyBinIdx]

# Efficiency for two detecting elements (det_els) in a pair of modules.
# This is one component (often called "geometric") of the detection efficiency model.
ModulePairEfficiencies: !record
fields:
# Detection efficiency for a pair of detecting elements
# detElIdx1 and detElIdx2 run from 0 to the number of det_els in each module
values: float[detElIdx1, energyBinIdx1, detElIdx2, energyBinIdx2]
# Symmetry Group Identifier (SGID)
# This should be a number between 0 and numberOfSGIDs-1
sgid: uint


# Lookup table for SGIDs
# For every module pair, give the SGID. If -1, the module-pair is not in coincidence
# Values run from -1 ... (numberOfSGIDs-1)
ModulePairSGIDLUT: uint[moduleIdx1, moduleIdx2]

ModulePairEfficienciesVector: ModulePairEfficiencies*

# Component-based information on detection efficiencies
# This encodes a simple model for the detection efficiency of (true) coincidences
# consisting of the product of the efficiency of the two detecting elements (det_els)
# and a (geometric) component determined by their location in the two modules.
# The former are stored in detElEfficiencies, and the latter in modulePairEfficienciesVector
# (a list of ModulePairEfficiencies, each entry corresponding to a module pair).
#
# Most PET scanners have some kind of geometric symmetry, e.g. rotation over a full
# module, or translation along the axis of the scanner. Module-pairs that are related
# by such a symmetry often have the same geometric detection efficiencies. PETSIRD
# calls this a "symmetry group" (SG). Each SG had an identifier (SGID). To save memory,
# the modulePairEfficienciesVector needs to contain only one of element for each SGID.
# The SGID for a module-pair can be found in modulePairSGIDLUT.
#
# Finding the total detection efficiency therefore follows these steps:
# (the following pseudo-code ignores energy bins for simplicity)
# 1. find modules for each det_el
# 2. find det_el indices "inside" each module
# 3. SGID = modulePairSGIDLUT[mod1, mod1]
# 4. if (SGID < 0) return 0
# 5. module_pair_efficiencies = modulePairEfficienciesVector[SGID]
# 6. return detElEfficiencies[det_el1] * detElEfficiencies[det_el2] * module_pair_efficiencies[det_el_in_mod1, det_el_in_mod2]
#
# If either of the components is not present, its value is considered to be 1.
DetectionEfficiencies: !record
fields:
# Detection efficiencies for every detecting element
detElEfficiencies: DetElEfficiencies?
# Lookup table for SGIDs.
# Also indicates if coincidences between a module-pair are recorded.
modulePairSGIDLUT: ModulePairSGIDLUT?
# Vector of all modulePairEfficiencies (one for each SGID)
# Constraint: size(modulePairEfficienciesVector) == max(modulePairSGIDLUT) + 1
modulePairEfficienciesVector: ModulePairEfficienciesVector?
3 changes: 3 additions & 0 deletions model/ScannerInformation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ ScannerInformation: !record
# Encode how the scanner handles multiple coincidences
coincidencePolicy: CoincidencePolicy

# coincidence detection efficiencies
detectionEfficiencies: DetectionEfficiencies

computedFields:
numberOfTOFBins: size(tofBinEdges)-1
numberOfEnergyBins: size(energyBinEdges)-1

0 comments on commit 99f3d46

Please sign in to comment.