Skip to content

Commit d0df0b2

Browse files
markus-jehlMarkus Jehl
andauthored
OpenMP implementation of make_fan_sum_data and cope with mashing (#1667)
make_fan_sum_data now handles mashed data and is parallelised. Also minor change to ProjDataInMemory::get_bin _value to make it a const member --------- Co-authored-by: Markus Jehl <markus.jehl@positrigo.com>
1 parent a38a083 commit d0df0b2

File tree

4 files changed

+61
-25
lines changed

4 files changed

+61
-25
lines changed

documentation/release_6.4.htm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ <h4>Utilities</h4>
5151

5252
<h3>Changed functionality</h3>
5353
<ul>
54+
<li>
55+
OpenMP parallelisation was added to the function to create a 2d histogram of hits per crystal
56+
from a proj data object, <code>make_fan_sum_data</code>.
57+
<br>
58+
<a href=https://github.com/UCL/STIR/pull/1667>PR #1667</a>
59+
</li>
5460
</ul>
5561
<h4>Changes to examples</h4>
5662
<ul>

src/buildblock/ML_norm.cxx

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,36 +1453,66 @@ make_fan_sum_data_help(Array<2, float>& data_fan_sums,
14531453
const int half_fan_size = fan_size / 2;
14541454
data_fan_sums.fill(0);
14551455

1456-
shared_ptr<SegmentBySinogram<float>> segment_ptr;
1456+
const auto non_tof_proj_data_info_sptr = std::dynamic_pointer_cast<TProjDataInfo>(proj_data_info.create_non_tof_clone());
14571457
Bin bin;
14581458

14591459
for (bin.segment_num() = proj_data.get_min_segment_num(); bin.segment_num() <= proj_data.get_max_segment_num();
14601460
++bin.segment_num())
14611461
{
1462-
// for (bin.timing_pos_num() = proj_data.get_min_tof_pos_num(); bin.timing_pos_num() <= proj_data.get_max_tof_pos_num(); ++
1463-
// bin.timing_pos_num())
1464-
{
1465-
segment_ptr.reset(
1466-
new SegmentBySinogram<float>(proj_data.get_segment_by_sinogram(bin.segment_num() /*,bin.timing_pos_num()*/)));
1467-
1468-
for (bin.axial_pos_num() = proj_data.get_min_axial_pos_num(bin.segment_num());
1469-
bin.axial_pos_num() <= proj_data.get_max_axial_pos_num(bin.segment_num());
1470-
++bin.axial_pos_num())
1471-
for (bin.view_num() = 0; bin.view_num() < num_detectors_per_ring / 2; bin.view_num()++)
1472-
for (bin.tangential_pos_num() = -half_fan_size; bin.tangential_pos_num() <= half_fan_size; ++bin.tangential_pos_num())
1473-
{
1474-
int ra = 0, a = 0;
1475-
int rb = 0, b = 0;
1476-
1477-
proj_data_info.get_det_pair_for_bin(a, ra, b, rb, bin);
1478-
1479-
const float value = (*segment_ptr)[bin.axial_pos_num()][bin.view_num()][bin.tangential_pos_num()];
1480-
data_fan_sums[ra][a] += value;
1481-
data_fan_sums[rb][b] += value;
1482-
}
1483-
}
1462+
for (bin.axial_pos_num() = proj_data.get_min_axial_pos_num(bin.segment_num());
1463+
bin.axial_pos_num() <= proj_data.get_max_axial_pos_num(bin.segment_num());
1464+
++bin.axial_pos_num())
1465+
{
1466+
const auto sinogram = proj_data.get_sinogram(bin);
1467+
#ifdef STIR_OPENMP
1468+
# if _OPENMP >= 200711
1469+
# pragma omp parallel for collapse(2) // OpenMP 3.1
1470+
# else
1471+
# pragma omp parallel for // older versions
1472+
# endif
1473+
#endif
1474+
for (int view_num = proj_data.get_min_view_num(); view_num <= proj_data.get_max_view_num(); ++view_num)
1475+
{
1476+
for (int tangential_pos_num = -half_fan_size; tangential_pos_num <= half_fan_size; ++tangential_pos_num)
1477+
{
1478+
// Construct bin with appropriate values
1479+
// Sadly cannot be done in the loops above for OpenMP 2.0 compatibility
1480+
Bin parallel_bin(bin);
1481+
parallel_bin.view_num() = view_num;
1482+
parallel_bin.tangential_pos_num() = tangential_pos_num;
1483+
1484+
std::vector<DetectionPositionPair<>> det_pos_pairs;
1485+
non_tof_proj_data_info_sptr->get_all_det_pos_pairs_for_bin(
1486+
det_pos_pairs, parallel_bin); // using the default argument to ignore TOF here
1487+
for (const auto& dp_pair : det_pos_pairs)
1488+
{
1489+
const auto& p1 = dp_pair.pos1();
1490+
const auto& p2 = dp_pair.pos2();
1491+
const auto count = sinogram[parallel_bin.view_num()][parallel_bin.tangential_pos_num()];
1492+
#if defined(STIR_OPENMP)
1493+
# if _OPENMP >= 201012
1494+
# pragma omp atomic update
1495+
# else
1496+
# pragma omp critical(STIRCREATEPROMPTHISTOGRAM)
1497+
{
1498+
# endif
1499+
#endif
1500+
data_fan_sums[p1.axial_coord()][p1.tangential_coord()] += count;
1501+
#if defined(STIR_OPENMP)
1502+
# if _OPENMP >= 201012
1503+
# pragma omp atomic update
1504+
# endif
1505+
#endif
1506+
data_fan_sums[p2.axial_coord()][p2.tangential_coord()] += count;
1507+
#if defined(STIR_OPENMP) && _OPENMP < 201012
1508+
}
1509+
#endif
1510+
}
1511+
}
1512+
}
14841513
}
14851514
}
1515+
}
14861516

14871517
void
14881518
make_fan_sum_data(Array<2, float>& data_fan_sums, const ProjData& proj_data)

src/buildblock/ProjDataInMemory.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ ProjDataInMemory::read_from_file(const std::string& filename)
350350
}
351351

352352
float
353-
ProjDataInMemory::get_bin_value(Bin& bin)
353+
ProjDataInMemory::get_bin_value(const Bin& bin) const
354354
{
355355
return buffer[this->get_index(bin)];
356356
}

src/include/stir/ProjDataInMemory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class ProjDataInMemory : public ProjData
103103
~ProjDataInMemory() override;
104104

105105
//! Returns a value of a bin
106-
float get_bin_value(Bin& bin);
106+
float get_bin_value(const Bin& bin) const;
107107

108108
void set_bin_value(const Bin& bin);
109109

0 commit comments

Comments
 (0)