Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Triple events, multiples strategy and changed CoincidenceEvent #20

Merged
merged 3 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cpp/prd_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ main(int argc, char* argv[])

for (auto& event : time_block.prompt_events)
{
energy_1 += energy_mid_points[event.energy_1_idx];
energy_2 += energy_mid_points[event.energy_2_idx];
energy_1 += energy_mid_points[event.energy_indices[0]];
energy_2 += energy_mid_points[event.energy_indices[1]];
}
}

Expand Down
8 changes: 4 additions & 4 deletions cpp/prd_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ get_events(const prd::Header& header, std::size_t num_events)
{
const auto detectors = get_random_pair(header.scanner.NumberOfDetectors());
prd::CoincidenceEvent e;
e.detector_1_id = detectors.first;
e.detector_2_id = detectors.second;
e.energy_1_idx = get_random_energy_value();
e.energy_2_idx = get_random_energy_value();
e.detector_ids[0] = detectors.first;
e.detector_ids[1] = detectors.second;
e.energy_indices[0] = get_random_energy_value();
e.energy_indices[1] = get_random_energy_value();
e.tof_idx = get_random_tof_value();
events.push_back(e);
}
Expand Down
11 changes: 6 additions & 5 deletions model/CoincidenceEvent.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# All information about a coincidence event specified as identifiers or indices (i.e. discretized).
# All information about a coincidence event specified as identifiers or indices (i.e. discretized). Indices start from 0.
# TODO: this might take up too much space, so some/all of these could be combined in a single index if necessary.
CoincidenceEvent: !record
fields:
detector1Id: uint
detector2Id: uint
# the pair of detector elements
detectorIds: uint*2
# an index into the tofBinEdges field in the ScannerInformation
tofIdx: uint
energy1Idx: uint
energy2Idx: uint
# a pair of indices into the energyBinEdges field in the ScannerInformation
energyIndices: uint*2
5 changes: 3 additions & 2 deletions model/Protocol.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ TimeBlock: !record
# list of prompts in this time block
# TODO might be better to use !array
promptEvents: CoincidenceEvent*
# list of delayed coincidences in this time block
# optional list of delayed coincidences in this time block
delayedEvents: CoincidenceEvent*?

# optional list of triple coincidences in this time block
tripleEvents: TripleEvent*?
16 changes: 16 additions & 0 deletions model/ScannerInformation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,25 @@ Detector: !record
y: float
z: float

# Type definition for how to encode how the scanner handles multiple coincidences
MultipleCoincidenceStrategy: !enum
values:
- rejectMultiples # multiples will be rejected
- storeMultiplesAsPairs # multiples will be stored as a sequence of pairs, e.g. a triple leads to 3 pairs
KrisThielemans marked this conversation as resolved.
Show resolved Hide resolved


ScannerInformation: !record
fields:
modelName: string?

# list of geometric information for all detector elements
# TODO will be adjusted when properly encoding geometry
detectors: Detector*

# edge information for TOF bins in mm (given as from first to last edge, so there is one more edge than the number of bins)
# 0 corresponds to the same arrival time. Negative numbers indicate that the first detector detected first.
# For instance, a coincidence event is stored as 2 detectorIds, denoting the arrival time at the first
# detector t1 and the arrival time at the second detector t2, we store (t1-t2)*c/2.
# TODO: this currently assumes equal size for each TOF bin, but some scanners "stretch" TOF bins depending on length of LOR
tofBinEdges: !array
items: float
Expand All @@ -32,6 +45,9 @@ ScannerInformation: !record
# duration of each time block in ms
listmodeTimeBlockDuration: uint

# encode how the scanner handles multiple coincidences
multipleCoincidenceStrategy: MultipleCoincidenceStrategy

computedFields:
numberOfDetectors: size(detectors)
numberOfTOFBins: size(tofBinEdges)-1
Expand Down
11 changes: 11 additions & 0 deletions model/TripleEvent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# All information about a triple event specified as identifiers or indices (i.e. discretized).
TripleEvent: !record
fields:
detectorIds: uint*3
# timing differences (converted to mm) w.r.t. first event, stored as
# indices into the tofBinEdges field in the ScannerInformation
# Note: only 2, corresponding to the arrival time differences of the second and third detectorId
# listed w.r.t. the first detectorId
tofIndices: uint*2
# indices for each single event into the energyBinEdges field in the ScannerInformation
energyIndices: uint*3
4 changes: 2 additions & 2 deletions python/prd_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
last_time = time_block.id * header.scanner.listmode_time_block_duration
num_prompts += len(time_block.prompt_events)
for event in time_block.prompt_events:
energy_1 += energy_mid_points[event.energy_1_idx]
energy_2 += energy_mid_points[event.energy_2_idx]
energy_1 += energy_mid_points[event.energy_indices[0]]
energy_2 += energy_mid_points[event.energy_indices[1]]

print(f"Last time block at {last_time} ms")
print(f"Number of prompt events: {num_prompts}")
Expand Down
8 changes: 4 additions & 4 deletions python/prd_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ def get_events(header: prd.Header, num_events: int) -> Iterator[prd.CoincidenceE
detector_count = header.scanner.number_of_detectors()
for _ in range(num_events):
yield prd.CoincidenceEvent(
detector_1_id=random.randrange(0, detector_count),
detector_2_id=random.randrange(0, detector_count),
energy_1_idx=random.randrange(0, NUMBER_OF_ENERGY_BINS),
energy_2_idx=random.randrange(0, NUMBER_OF_ENERGY_BINS),
detector_ids = [random.randrange(0, detector_count),
random.randrange(0, detector_count)],
energy_indices = [random.randrange(0, NUMBER_OF_ENERGY_BINS),
random.randrange(0, NUMBER_OF_ENERGY_BINS)],
tof_idx=random.randrange(0, NUMBER_OF_TOF_BINS),
)

Expand Down
Loading