Skip to content

Commit 25b3656

Browse files
Merge pull request UCL#1674 from KrisThielemans/TOF_improvements
TOF improvements: speed-up of Matrix projector by removing zeroes. Added extra tests.
2 parents 05bca88 + 095f932 commit 25b3656

File tree

5 files changed

+126
-206
lines changed

5 files changed

+126
-206
lines changed

documentation/release_6.4.htm

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,15 @@ <h4>Utilities</h4>
5151

5252
<h3>Changed functionality</h3>
5353
<ul>
54+
<li>When using a (ray tracing) matrix as projector, previously the matrix stored elements for the whole LOR,
55+
while many elements would be zero. We now only store the non-zero ones, resulting in a speed-up for the Siemens Vision Quadra of about a factor 1.7. Memory usage is also reduced.<br>
56+
<a href=https://github.com/UCL/STIR/pull/1674># 1674</a>.
57+
</li>
5458
<li>
5559
OpenMP parallelisation was added to the function to create a 2d histogram of hits per crystal
5660
from a proj data object, <code>make_fan_sum_data</code>.
5761
<br>
58-
<a href=https://github.com/UCL/STIR/pull/1667>PR #1667</a>
62+
<a href=https://github.com/UCL/STIR/pull/1667>PR #1667</a>.
5963
</li>
6064
</ul>
6165
<h4>Changes to examples</h4>
@@ -64,6 +68,11 @@ <h4>Changes to examples</h4>
6468

6569
<h3>Bug fixes</h3>
6670
<ul>
71+
<li>
72+
An important bug fix for the "ray tracing matrix" (or actually any "matrix") projector for TOF PET. Previously, oblique
73+
segments had problems, see <a href=https://github.com/UCL/STIR/issues/1537># 1537</a>.<br>
74+
<a href=https://github.com/UCL/STIR/pull/1675># 1675</a>. Extra tests were introduced in <a href=https://github.com/UCL/STIR/pull/1674># 1674</a>.
75+
</li>
6776
</ul>
6877

6978
<h3>Build system</h3>
@@ -93,9 +102,7 @@ <h3>Build system</h3>
93102
</ul>
94103

95104
<h3>Known problems</h3>
96-
<p>See <a href=https://github.com/UCL/STIR/labels/bug>our issue tracker</a>.<br>
97-
An important bug is for the "ray tracing matrix" projector for TOF PET. Oblique
98-
segments currently have problems, see <a href=https://github.com/UCL/STIR/issues/1537># 1537</a>.
105+
<p>See <a href=https://github.com/UCL/STIR/labels/bug>our issue tracker</a>.
99106
</p>
100107

101108

src/include/stir/recon_buildblock/ProjMatrixByBin.inl

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,21 @@ ProjMatrixByBin::apply_tof_kernel(ProjMatrixElemsForOneBin& probabilities) const
133133
const CartesianCoordinate3D<float> diff = point2 - middle;
134134
const CartesianCoordinate3D<float> diff_unit_vector(diff / static_cast<float>(norm(diff)));
135135

136+
ProjMatrixElemsForOneBin tof_row(probabilities.get_bin());
137+
// Estimate size of TOF row such that we can pre-allocate.
138+
std::size_t max_num_elements;
139+
{
140+
const auto length = norm(point1 - point2);
141+
const auto kernel_width = 8 / r_sqrt2_gauss_sigma;
142+
const auto tof_bin_width = proj_data_info_sptr->tof_bin_boundaries_mm[probabilities.get_bin().timing_pos_num()].high_lim
143+
- proj_data_info_sptr->tof_bin_boundaries_mm[probabilities.get_bin().timing_pos_num()].low_lim;
144+
const auto fraction = (kernel_width + tof_bin_width) / length;
145+
// This seems to sometimes over-, sometimes underestimate, but it's probably not very important
146+
// as std::vector will grow as necessary.
147+
max_num_elements = std::size_t(probabilities.size() * std::min(fraction * 1.2, 1.001));
148+
}
149+
tof_row.reserve(max_num_elements);
150+
136151
for (ProjMatrixElemsForOneBin::iterator element_ptr = probabilities.begin(); element_ptr != probabilities.end(); ++element_ptr)
137152
{
138153
Coordinate3D<int> c(element_ptr->get_coords());
@@ -150,8 +165,23 @@ ProjMatrixByBin::apply_tof_kernel(ProjMatrixElemsForOneBin& probabilities) const
150165
const float high_dist
151166
= ((proj_data_info_sptr->tof_bin_boundaries_mm[probabilities.get_bin().timing_pos_num()].high_lim - d2));
152167

153-
*element_ptr = ProjMatrixElemsForOneBin::value_type(c, element_ptr->get_value() * get_tof_value(low_dist, high_dist));
168+
const auto tof_kernel_value = get_tof_value(low_dist, high_dist);
169+
if (tof_kernel_value > 0)
170+
{
171+
if (auto non_tof_value = element_ptr->get_value())
172+
tof_row.push_back(ProjMatrixElemsForOneBin::value_type(c, non_tof_value * tof_kernel_value));
173+
}
174+
else
175+
{
176+
// Optimisation would be to get out of the loop once we're "beyond" the TOF kernel,
177+
// but it is tricky to do. It requires that the input is sorted
178+
// "along" the LOR, i.e. d2 increases montonically, but that doesn't seem to be true.
179+
// if (tof_row.size() > 0)
180+
// break;
181+
}
154182
}
183+
probabilities = tof_row;
184+
// info("Estimate " + std::to_string(max_num_elements) + ", actual " + std::to_string(tof_row.size()));
155185
}
156186

157187
float

src/include/stir/recon_buildblock/ProjMatrixElemsForOneBin.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class ProjMatrixElemsForOneBin
8585
//! typedefs for iterator support
8686
typedef Element_vector::iterator iterator;
8787
typedef Element_vector::const_iterator const_iterator;
88+
typedef Element_vector::reverse_iterator reverse_iterator;
89+
typedef Element_vector::const_reverse_iterator const_reverse_iterator;
8890
typedef Element_vector::size_type size_type;
8991
typedef Element_vector::difference_type difference_type;
9092
typedef std::random_access_iterator_tag iterator_category;
@@ -117,6 +119,10 @@ class ProjMatrixElemsForOneBin
117119
inline const_iterator begin() const;
118120
inline iterator end();
119121
inline const_iterator end() const;
122+
inline reverse_iterator rbegin();
123+
inline const_reverse_iterator rbegin() const;
124+
inline reverse_iterator rend();
125+
inline const_reverse_iterator rend() const;
120126

121127
//! reset lor to 0 length
122128
void erase();

src/include/stir/recon_buildblock/ProjMatrixElemsForOneBin.inl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,30 @@ ProjMatrixElemsForOneBin::end() const
7373
return elements.end();
7474
};
7575

76+
ProjMatrixElemsForOneBin::reverse_iterator
77+
ProjMatrixElemsForOneBin::rbegin()
78+
{
79+
return elements.rbegin();
80+
}
81+
82+
ProjMatrixElemsForOneBin::const_reverse_iterator
83+
ProjMatrixElemsForOneBin::rbegin() const
84+
{
85+
return elements.rbegin();
86+
};
87+
88+
ProjMatrixElemsForOneBin::reverse_iterator
89+
ProjMatrixElemsForOneBin::rend()
90+
{
91+
return elements.rend();
92+
};
93+
94+
ProjMatrixElemsForOneBin::const_reverse_iterator
95+
ProjMatrixElemsForOneBin::rend() const
96+
{
97+
return elements.rend();
98+
};
99+
76100
ProjMatrixElemsForOneBin::iterator
77101
ProjMatrixElemsForOneBin::erase(iterator it)
78102
{

0 commit comments

Comments
 (0)