Skip to content

Commit eb60569

Browse files
Merge pull request #74 from KrisThielemans/analysis_improvements
extra features for petsird_analysis
2 parents 3eed512 + f9ebe2b commit eb60569

File tree

2 files changed

+117
-27
lines changed

2 files changed

+117
-27
lines changed

cpp/petsird_analysis.cpp

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,73 @@ using petsird::binary::PETSIRDReader;
2020
#include <xtensor/xio.hpp>
2121
#include <iostream>
2222
#include <variant>
23+
#include <cstdlib>
24+
25+
void
26+
print_usage_and_exit(char const* prog_name)
27+
{
28+
std::cerr << "Usage:\n"
29+
<< prog_name << " \\\n"
30+
<< " [--print_events] [--input petsird_filename]\n\n"
31+
<< "Options:\n"
32+
<< " -e, --print-events: Print event info\n"
33+
<< " -i, --input : Filename to read\n\n"
34+
<< "Currently, the following (deprecated) usage is also allowed:\n"
35+
<< prog_name << " [options] [---] petsird_filename\n"
36+
<< "Use of '--' is then required if the filename starts with -\n";
37+
38+
std::exit(EXIT_FAILURE);
39+
}
2340

2441
int
25-
main(int argc, char* argv[])
42+
main(int argc, char const* argv[])
2643
{
44+
auto prog_name = argv[0];
45+
46+
bool print_events = false;
47+
std::string filename;
48+
// option processing
49+
while (argc > 1 && (strncmp(argv[1], "-", 1) == 0))
50+
{
51+
if (strcmp(argv[1], "--print_events") == 0 || strcmp(argv[1], "-e") == 0)
52+
{
53+
print_events = true;
54+
}
55+
else if (strcmp(argv[1], "--input") == 0 || strcmp(argv[1], "-i") == 0)
56+
{
57+
filename = argv[2];
58+
++argv;
59+
--argc;
60+
}
61+
else if (strcmp(argv[1], "--") == 0)
62+
{
63+
// next argument is filename
64+
++argv;
65+
--argc;
66+
break;
67+
}
68+
else
69+
print_usage_and_exit(prog_name);
70+
++argv;
71+
--argc;
72+
}
2773
// Check if the user has provided a file
28-
if (argc < 2)
74+
if (!filename.empty() && argc > 1)
75+
print_usage_and_exit(prog_name);
76+
else if (filename.empty())
2977
{
30-
std::cerr << "Please provide a file to read" << std::endl;
31-
return 1;
78+
if (argc < 2)
79+
print_usage_and_exit(prog_name);
80+
else
81+
filename = argv[1];
3282
}
3383

3484
// Open the file
35-
PETSIRDReader reader(argv[1]);
85+
PETSIRDReader reader(filename);
3686
petsird::Header header;
3787
reader.ReadHeader(header);
3888

39-
std::cout << "Processing file: " << argv[1] << std::endl;
89+
std::cout << "Processing file: " << filename << std::endl;
4090
if (header.exam) // only do this if present
4191
std::cout << "Subject ID: " << header.exam->subject.id << std::endl;
4292
std::cout << "Types of modules: " << header.scanner.scanner_geometry.replicated_modules.size() << std::endl;
@@ -65,6 +115,7 @@ main(int argc, char* argv[])
65115
// Process events in batches of up to 100
66116
float energy_1 = 0, energy_2 = 0;
67117
std::size_t num_prompts = 0;
118+
std::size_t num_delayeds = 0;
68119
float last_time = 0.F;
69120
while (reader.ReadTimeBlocks(time_block))
70121
{
@@ -73,29 +124,37 @@ main(int argc, char* argv[])
73124
auto& event_time_block = std::get<petsird::EventTimeBlock>(time_block);
74125
last_time = event_time_block.start;
75126
num_prompts += event_time_block.prompt_events.size();
76-
std::cout << "===================== Events in time block from " << last_time << " ==============\n";
127+
if (event_time_block.delayed_events)
128+
num_delayeds += event_time_block.delayed_events->size();
129+
if (print_events)
130+
std::cout << "===================== Prompt events in time block from " << last_time << " ==============\n";
77131

78132
for (auto& event : event_time_block.prompt_events)
79133
{
80134
energy_1 += energy_mid_points[event.energy_indices[0]];
81135
energy_2 += energy_mid_points[event.energy_indices[1]];
82136

83-
std::cout << "CoincidenceEvent(detectorIds=[" << event.detector_ids[0] << ", " << event.detector_ids[1]
84-
<< "], tofIdx=" << event.tof_idx << ", energyIndices=[" << event.energy_indices[0] << ", "
85-
<< event.energy_indices[1] << "])\n";
86-
const auto module_and_elems
87-
= petsird_helpers::get_module_and_element(header.scanner.scanner_geometry, event.detector_ids);
88-
std::cout << " "
89-
<< "[ModuleAndElement(module=" << module_and_elems[0].module << ", "
90-
<< "el=" << module_and_elems[0].el << "), ModuleAndElement(module=" << module_and_elems[0].module << ", "
91-
<< "el=" << module_and_elems[0].el << ")]\n";
92-
std::cout << " efficiency:" << petsird_helpers::get_detection_efficiency(header.scanner, event) << "\n";
137+
if (print_events)
138+
{
139+
std::cout << "CoincidenceEvent(detectorIds=[" << event.detector_ids[0] << ", " << event.detector_ids[1]
140+
<< "], tofIdx=" << event.tof_idx << ", energyIndices=[" << event.energy_indices[0] << ", "
141+
<< event.energy_indices[1] << "])\n";
142+
const auto module_and_elems
143+
= petsird_helpers::get_module_and_element(header.scanner.scanner_geometry, event.detector_ids);
144+
std::cout << " "
145+
<< "[ModuleAndElement(module=" << module_and_elems[0].module << ", "
146+
<< "el=" << module_and_elems[0].el << "), ModuleAndElement(module=" << module_and_elems[0].module
147+
<< ", "
148+
<< "el=" << module_and_elems[0].el << ")]\n";
149+
std::cout << " efficiency:" << petsird_helpers::get_detection_efficiency(header.scanner, event) << "\n";
150+
}
93151
}
94152
}
95153
}
96154

97155
std::cout << "Last time block at " << last_time << " ms\n";
98156
std::cout << "Number of prompt events: " << num_prompts << std::endl;
157+
std::cout << "Number of delayed events: " << num_delayeds << std::endl;
99158
if (num_prompts > 0)
100159
{
101160
std::cout << "Average energy_1: " << energy_1 / num_prompts << std::endl;

python/petsird_analysis.py

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,40 @@
33
#
44
# SPDX-License-Identifier: Apache-2.0
55

6+
import argparse
67
import sys
78

89
import petsird
910
from petsird_helpers import (get_detection_efficiency, get_module_and_element,
1011
get_num_det_els)
1112

13+
14+
def parserCreator():
15+
parser = argparse.ArgumentParser(
16+
prog='petsird_analysis',
17+
description='Example program that lists basic content of a PETSIRD file'
18+
)
19+
parser.add_argument('-e', '--print_events', action='store_true')
20+
parser.add_argument(
21+
"-i",
22+
"--input",
23+
type=str,
24+
default=None,
25+
help="File to read from, or stdin if omitted",
26+
)
27+
return parser.parse_args()
28+
29+
1230
if __name__ == "__main__":
13-
with petsird.BinaryPETSIRDReader(sys.stdin.buffer) as reader:
31+
args = parserCreator()
32+
file = None
33+
if args.input is None:
34+
file = sys.stdin.buffer
35+
else:
36+
file = open(args.input, "rb")
37+
print_events = args.print_events
38+
39+
with petsird.BinaryPETSIRDReader(file) as reader:
1440
header = reader.read_header()
1541
if header.exam is not None:
1642
print(f"Subject ID: {header.exam.subject.id}")
@@ -42,28 +68,33 @@
4268
header.scanner.detection_efficiencies.module_pair_sgidlut)
4369
energy_1, energy_2 = 0.0, 0.0
4470
num_prompts = 0
71+
num_delayeds = 0
4572
last_time = 0
4673
for time_block in reader.read_time_blocks():
4774
if isinstance(time_block, petsird.TimeBlock.EventTimeBlock):
4875
last_time = time_block.value.start
4976
num_prompts += len(time_block.value.prompt_events)
77+
if time_block.value.delayed_events is not None:
78+
num_delayeds += len(time_block.value.delayed_events)
5079
print("===================== Events in time block from ",
5180
last_time, " ==============")
5281
for event in time_block.value.prompt_events:
5382
energy_1 += energy_mid_points[event.energy_indices[0]]
5483
energy_2 += energy_mid_points[event.energy_indices[1]]
55-
56-
print(event)
57-
print(
58-
" ",
59-
get_module_and_element(header.scanner.scanner_geometry,
60-
event.detector_ids),
61-
)
62-
print(" efficiency:",
63-
get_detection_efficiency(header.scanner, event))
84+
if print_events:
85+
print(event)
86+
print(
87+
" ",
88+
get_module_and_element(
89+
header.scanner.scanner_geometry,
90+
event.detector_ids),
91+
)
92+
print(" efficiency:",
93+
get_detection_efficiency(header.scanner, event))
6494

6595
print(f"Last time block at {last_time} ms")
6696
print(f"Number of prompt events: {num_prompts}")
97+
print(f"Number of delayed events: {num_delayeds}")
6798
if num_prompts > 0:
6899
print(f"Average energy_1: {energy_1 / num_prompts}")
69100
print(f"Average energy_2: {energy_2 / num_prompts}")

0 commit comments

Comments
 (0)