diff --git a/documentation/release_5.2.htm b/documentation/release_5.2.htm
index a11ca8f5d6..e3d005fb89 100644
--- a/documentation/release_5.2.htm
+++ b/documentation/release_5.2.htm
@@ -136,6 +136,9 @@
Minor (?) bug fixes
sample_function_on_regular_grid
did not handle offset correctly in all places
issue #1178.
PR #1172.
+ Ray tracing projection for BlocksOnCylindrical scanner geometries contained a bug where some bins were swapped across oblique segments
issue #1223. This sometimes lead to large artifacts in reconstructions.
+
PR #1231.
+
Documentation changes
diff --git a/src/include/stir/LORCoordinates.inl b/src/include/stir/LORCoordinates.inl
index f7754c3981..e17685a0a0 100644
--- a/src/include/stir/LORCoordinates.inl
+++ b/src/include/stir/LORCoordinates.inl
@@ -342,12 +342,11 @@ find_LOR_intersections_with_cylinder(LORAs2Points& intersection_coords,
}
const coordT2 root = static_cast(sqrt(argsqrt));
- auto l1 = static_cast((-b + root) / a);
- auto l2 = static_cast((-b - root) / a);
+ auto l1 = static_cast((-b - root) / a);
+ auto l2 = static_cast((-b + root) / a);
- // TODO won't work when coordT1!=coordT2
- intersection_coords.p1() = d*l1 + c1;
- intersection_coords.p2() = d*l2 + c1;
+ intersection_coords.p1() = d * l1 + c1;
+ intersection_coords.p2() = d * l2 + c1;
assert(fabs(square(intersection_coords.p1().x())+square(intersection_coords.p1().y())
- square(radius))
_p1;
- CartesianCoordinate3D _p2;
- find_cartesian_coordinates_of_detection(_p1, _p2, bin);
- CartesianCoordinate3D p2_minus_p1 = _p2 - _p1;
- return p2_minus_p1.z() / (sqrt(square(p2_minus_p1.x())+square(p2_minus_p1.y())));
+ LORInAxialAndNoArcCorrSinogramCoordinates lor;
+ get_LOR(lor, bin);
+
+ return (lor.z2() - lor.z1()) / (2 * lor.radius());
}
float
diff --git a/src/include/stir/ProjDataInfoGenericNoArcCorr.inl b/src/include/stir/ProjDataInfoGenericNoArcCorr.inl
index 2a796e42a4..01c0ac5c88 100644
--- a/src/include/stir/ProjDataInfoGenericNoArcCorr.inl
+++ b/src/include/stir/ProjDataInfoGenericNoArcCorr.inl
@@ -88,43 +88,7 @@ get_s(const Bin& bin) const
{
LORInAxialAndNoArcCorrSinogramCoordinates lor;
get_LOR(lor, bin);
- // REQUIREMENT: Euclidean coordinate of 3 points, a,b and c.
- // CALCULATION: // Equation of a line, in parametric form, given two point a, b: p(t) = a + (b-a)*t
- // // Let a,b,c be points in 2D and let a,b form a line then shortest distance between c and line ab is:
- // // || (p0-p1) - [(p0-p1)*(p2-p1)/||p2-p1||^2]*(p2-p1) ||
- // p1 = _p1, p2=_p2 and p0=(0,0,0)
- // OUTPUT: replace the ring_radius*sin(lor.beta()) with distance from o to ab.
-
- // Can't access coordinate of detection from this class so we have to recalculate where it is:
-
- CartesianCoordinate3D _p1;
- CartesianCoordinate3D _p2;
- find_cartesian_coordinates_of_detection(_p1, _p2, bin);
-
- // // Get p1-p0 and p2-p1 vector.
- CartesianCoordinate3D p2_minus_p1 = _p2 - _p1;
- CartesianCoordinate3D p0_minus_p1 = CartesianCoordinate3D(0,0,0) - _p1;
- float p0_minus_p1_dot_p2_minus_p1 = p0_minus_p1.x()* p2_minus_p1.x() + p0_minus_p1.y()*p2_minus_p1.y();
- float p2_minus_p1_magitude = square(p2_minus_p1.x()) + square(p2_minus_p1.y());
- float x = 0;
- float y = 0;
- float sign = sin(lor.beta());
- if (p2_minus_p1_magitude > 0.01)
- {
- x = p0_minus_p1.x() - (p0_minus_p1_dot_p2_minus_p1/p2_minus_p1_magitude)*p2_minus_p1.x();
- y = p0_minus_p1.y() - (p0_minus_p1_dot_p2_minus_p1/p2_minus_p1_magitude)*p2_minus_p1.y();
- }
- else
- {
- error("get_s(): 2 detection points are too close to each other. This indicates an internal error.");
- }
- float s = sqrt(square(x) + square(y));
-
- if(sign < 0.0){
- return -s;
- }else{
- return s;
- }
+ return lor.s();
}
void
diff --git a/src/test/test_proj_data_info.cxx b/src/test/test_proj_data_info.cxx
index 0247b1c32a..242d8727ee 100644
--- a/src/test/test_proj_data_info.cxx
+++ b/src/test/test_proj_data_info.cxx
@@ -148,7 +148,7 @@ ProjDataInfoTests::test_generic_proj_data_info(ProjDataInfo& proj_data_info)
#endif
for (int segment_num = proj_data_info.get_min_segment_num(); segment_num <= proj_data_info.get_max_segment_num(); ++segment_num)
{
- for (int view_num = proj_data_info.get_min_view_num(); view_num <= proj_data_info.get_max_view_num(); view_num += 3)
+ for (int view_num = proj_data_info.get_min_view_num(); view_num <= proj_data_info.get_max_view_num(); view_num += 1)
{
// loop over axial_positions. Avoid using first and last positions, as
// if there is axial compression, the central LOR of a bin might actually not
@@ -176,10 +176,13 @@ ProjDataInfoTests::test_generic_proj_data_info(ProjDataInfo& proj_data_info)
{
const Bin new_bin = proj_data_info.get_bin(lor);
#if 1
- const int diff_segment_num = intabs(org_bin.segment_num() - new_bin.segment_num());
- const int diff_view_num = intabs(org_bin.view_num() - new_bin.view_num());
+ // the differences need to also consider wrap-around in views, which would flip tangential pos and segment
+ const int diff_segment_num = intabs(org_bin.view_num() - new_bin.view_num()) < proj_data_info.get_num_views() - intabs(org_bin.view_num() - new_bin.view_num()) ?
+ intabs(org_bin.segment_num() - new_bin.segment_num()) : intabs(org_bin.segment_num() + new_bin.segment_num());
+ const int diff_view_num = min(intabs(org_bin.view_num() - new_bin.view_num()), proj_data_info.get_num_views() - intabs(org_bin.view_num() - new_bin.view_num()));
const int diff_axial_pos_num = intabs(org_bin.axial_pos_num() - new_bin.axial_pos_num());
- const int diff_tangential_pos_num = intabs(org_bin.tangential_pos_num() - new_bin.tangential_pos_num());
+ const int diff_tangential_pos_num = intabs(org_bin.view_num() - new_bin.view_num()) < proj_data_info.get_num_views() - intabs(org_bin.view_num() - new_bin.view_num()) ?
+ intabs(org_bin.tangential_pos_num() - new_bin.tangential_pos_num()) : intabs(org_bin.tangential_pos_num() + new_bin.tangential_pos_num());
if (new_bin.get_bin_value() > 0)
{
if (diff_segment_num > max_diff_segment_num)
@@ -220,10 +223,13 @@ ProjDataInfoTests::test_generic_proj_data_info(ProjDataInfo& proj_data_info)
lor.get_intersections_with_cylinder(lor_as_points, lor.radius());
const Bin new_bin = proj_data_info.get_bin(lor_as_points);
#if 1
- const int diff_segment_num = intabs(org_bin.segment_num() - new_bin.segment_num());
- const int diff_view_num = intabs(org_bin.view_num() - new_bin.view_num());
+ // the differences need to also consider wrap-around in views, which would flip tangential pos and segment
+ const int diff_segment_num = intabs(org_bin.view_num() - new_bin.view_num()) < proj_data_info.get_num_views() - intabs(org_bin.view_num() - new_bin.view_num()) ?
+ intabs(org_bin.segment_num() - new_bin.segment_num()) : intabs(org_bin.segment_num() + new_bin.segment_num());
+ const int diff_view_num = min(intabs(org_bin.view_num() - new_bin.view_num()), proj_data_info.get_num_views() - intabs(org_bin.view_num() - new_bin.view_num()));
const int diff_axial_pos_num = intabs(org_bin.axial_pos_num() - new_bin.axial_pos_num());
- const int diff_tangential_pos_num = intabs(org_bin.tangential_pos_num() - new_bin.tangential_pos_num());
+ const int diff_tangential_pos_num = intabs(org_bin.view_num() - new_bin.view_num()) < proj_data_info.get_num_views() - intabs(org_bin.view_num() - new_bin.view_num()) ?
+ intabs(org_bin.tangential_pos_num() - new_bin.tangential_pos_num()) : intabs(org_bin.tangential_pos_num() + new_bin.tangential_pos_num());
if (new_bin.get_bin_value() > 0)
{
if (diff_segment_num > max_diff_segment_num)