30 get_transformed_LOR(LORInAxialAndNoArcCorrSinogramCoordinates<float>& out_lor,
31 const RigidObject3DTransformation& transformation,
33 const ProjDataInfo& in_proj_data_info)
35 LORInAxialAndNoArcCorrSinogramCoordinates<float> lor;
36 in_proj_data_info.get_LOR(lor, bin);
37 LORAs2Points<float> lor_as_points;
38 lor.get_intersections_with_cylinder(lor_as_points, lor.radius());
47 const float z_shift = (in_proj_data_info.get_scanner_ptr()->get_num_rings() - 1) / 2.F
48 * in_proj_data_info.get_scanner_ptr()->get_ring_spacing();
49 lor_as_points.p1().z() += z_shift;
50 lor_as_points.p2().z() += z_shift;
51 LORAs2Points<float> transformed_lor_as_points(transformation.transform_point(lor_as_points.p1()),
52 transformation.transform_point(lor_as_points.p2()));
53 transformed_lor_as_points.p1().z() -= z_shift;
54 transformed_lor_as_points.p2().z() -= z_shift;
55 return transformed_lor_as_points.change_representation(out_lor, lor.radius());
58 static Coordinate4D<float>
59 lor_to_coords(
const LORInAxialAndNoArcCorrSinogramCoordinates<float>& lor)
61 Coordinate4D<float> coord;
62 coord[1] = lor.z2() - lor.z1();
63 coord[2] = (lor.z2() + lor.z1()) / 2;
65 coord[4] = lor.beta();
69 static Coordinate4D<int>
70 bin_to_coords(
const Bin& bin)
72 Coordinate4D<int> coord;
73 coord[1] = bin.segment_num();
74 coord[2] = bin.axial_pos_num();
75 coord[3] = bin.view_num();
76 coord[4] = bin.tangential_pos_num();
81 coords_to_bin(
const Coordinate4D<int>& coord)
85 bin.axial_pos_num() = coord[2];
86 bin.view_num() = coord[3];
87 bin.tangential_pos_num() = coord[4];
94 return x >= 0 ? 1 : -1;
97 inline Coordinate4D<int>
98 sign(
const Coordinate4D<float>& c)
100 return Coordinate4D<int>(sign(c[1]), sign(c[2]), sign(c[3]), sign(c[4]));
103 inline Coordinate4D<float>
104 abs(
const Coordinate4D<float>& c)
106 return Coordinate4D<float>(fabs(c[1]), fabs(c[2]), fabs(c[3]), fabs(c[4]));
110 add_to_bin(VectorWithOffset<shared_ptr<SegmentByView<float>>>& segments,
const Bin& bin,
const float value)
112 (*segments[bin.segment_num()])[bin.view_num()][bin.axial_pos_num()][bin.tangential_pos_num()] += value;
116 is_in_range(
const Bin& bin,
const ProjDataInfo& proj_data_info)
118 if (bin.segment_num() >= proj_data_info.get_min_segment_num() && bin.segment_num() <= proj_data_info.get_max_segment_num()
119 && bin.tangential_pos_num() >= proj_data_info.get_min_tangential_pos_num()
120 && bin.tangential_pos_num() <= proj_data_info.get_max_tangential_pos_num()
121 && bin.axial_pos_num() >= proj_data_info.get_min_axial_pos_num(bin.segment_num())
122 && bin.axial_pos_num() <= proj_data_info.get_max_axial_pos_num(bin.segment_num()))
124 assert(bin.view_num() >= proj_data_info.get_min_view_num());
125 assert(bin.view_num() <= proj_data_info.get_max_view_num());
133 standardise(
const Bin& in_bin,
const ProjDataInfo& proj_data_info)
136 bool swap_direction =
false;
137 if (bin.view_num() < proj_data_info.get_min_view_num())
139 swap_direction =
true;
140 bin.
view_num() += proj_data_info.get_num_views();
142 else if (bin.view_num() > proj_data_info.get_max_view_num())
144 swap_direction =
true;
145 bin.view_num() -= proj_data_info.get_num_views();
147 assert(bin.view_num() >= proj_data_info.get_min_view_num());
148 assert(bin.view_num() <= proj_data_info.get_max_view_num());
152 bin.tangential_pos_num() *= -1;
153 bin.segment_num() *= -1;
159 find_sampling(Coordinate4D<float>& sampling,
const Bin& bin,
const ProjDataInfo& proj_data_info)
161 LORInAxialAndNoArcCorrSinogramCoordinates<float> tmp_lor;
162 LORInAxialAndNoArcCorrSinogramCoordinates<float> lor;
163 proj_data_info.get_LOR(lor, bin);
164 for (
int d = 1; d <= 4; ++d)
166 Coordinate4D<int> neighbour_coords = bin_to_coords(bin);
167 neighbour_coords[d] += 1;
168 const Bin neighbour = standardise(coords_to_bin(neighbour_coords), proj_data_info);
169 if (!is_in_range(neighbour, proj_data_info))
170 return Succeeded::no;
171 proj_data_info.get_LOR(tmp_lor, neighbour);
172 sampling[d] = (lor_to_coords(tmp_lor) - lor_to_coords(lor))[d];
174 return Succeeded::yes;
178 bin_interpolate(VectorWithOffset<shared_ptr<SegmentByView<float>>>& seg_ptr,
179 const LORInAxialAndNoArcCorrSinogramCoordinates<float>& lor,
180 const ProjDataInfo& out_proj_data_info,
181 const ProjDataInfo& proj_data_info,
184 Coordinate4D<float> sampling;
186 if (find_sampling(sampling, Bin(0, 0, 0, 0), proj_data_info) != Succeeded::yes)
187 error(
"error in finding sampling");
189 const Bin central_bin = proj_data_info.get_bin(lor);
190 if (central_bin.get_bin_value() < 0)
192 LORInAxialAndNoArcCorrSinogramCoordinates<float> central_lor;
193 proj_data_info.get_LOR(central_lor, central_bin);
194 const Coordinate4D<float> central_lor_coords = lor_to_coords(central_lor);
195 const Coordinate4D<float> lor_coords = lor_to_coords(lor);
196 const Coordinate4D<int> central_bin_coords = bin_to_coords(central_bin);
197 const Coordinate4D<float> diff = (lor_coords - central_lor_coords) / sampling;
198 assert(diff[1] <= 1.001 && diff[1] >= -1.001);
199 assert(diff[2] <= .5001 && diff[2] >= -.5001);
200 assert(diff[3] <= .5001 && diff[3] >= -.5001);
201 assert(diff[4] <= .5001 && diff[4] >= -.5001);
202 const Coordinate4D<int> bin_inc = sign(sampling);
203 assert(bin_inc == Coordinate4D<int>(1, 1, 1, 1));
204 const Coordinate4D<int> inc = sign(diff);
205 Coordinate4D<int> offset;
208 for (offset[1]=0; offset[1]!=2*inc[1]; offset[1]+=inc[1])
209 for (offset[2]=0; offset[2]!=2*inc[2]; offset[2]+=inc[2])
210 for (offset[3]=0; offset[3]!=2*inc[3]; offset[3]+=inc[3])
211 for (offset[4]=0; offset[4]!=2*inc[4]; offset[4]+=inc[4])
213 for (offset[1] = -1; offset[1] != 2; offset[1]++)
214 for (offset[2] = -1; offset[2] != 2; offset[2]++)
215 for (offset[3] = -1; offset[3] != 2; offset[3]++)
216 for (offset[4] = -1; offset[4] != 2; offset[4]++)
219 const Bin target_bin = standardise(coords_to_bin(central_bin_coords + offset), proj_data_info);
220 if (is_in_range(target_bin, proj_data_info))
226 LORInAxialAndNoArcCorrSinogramCoordinates<float> new_lor;
227 proj_data_info.get_LOR(new_lor, target_bin);
228 Coordinate4D<float> new_lor_coords = lor_to_coords(new_lor);
229 Coordinate4D<float> new_diff = (lor_coords - new_lor_coords) / sampling;
230 if (fabs(new_diff[3]) > 2)
232 new_lor_coords[1] *= -1;
233 new_lor_coords[3] +=
_PI * sign(new_diff[3]);
234 new_lor_coords[4] *= -1;
235 new_diff = (lor_coords - new_lor_coords) / sampling;
239 assert(new_diff[1]<=1.001 && new_diff[1]>=-1.001);
240 assert(new_diff[2]<=1.101 && new_diff[2]>=-1.101);
241 assert(new_diff[3]<=1.001 && new_diff[3]>=-1.001);
242 assert(new_diff[4]<=1.001 && new_diff[4]>=-1.001);
245 Coordinate4D<float> weights = abs(new_diff);
246 if (weights[4] > 1 || weights[3] > 1 || weights[2] > 1 || weights[1] > 1)
248 const float weight = (1 - weights[1]) * (1 - weights[2]) * (1 - weights[3]) * (1 - weights[4]);
252 const Bin out_bin = target_bin;
255 const Bin out_bin = out_proj_data_info.get_bin(new_lor);
256 if (out_bin.get_bin_value()<0)
259 DetectionPositionPair<> detection_positions;
260 dynamic_cast<const ProjDataInfoCylindricalNoArcCorr&
>(proj_data_info)
261 .get_det_pos_pair_for_bin(detection_positions, target_bin);
263 if (dynamic_cast<const ProjDataInfoCylindricalNoArcCorr&>(out_proj_data_info)
264 .get_bin_for_det_pos_pair(out_bin, detection_positions)
267 if (!is_in_range(out_bin, out_proj_data_info))
272 add_to_bin(seg_ptr, out_bin, value * weight);
Declaration of class stir::Succeeded.
#define _PI
The constant pi to high precision.
Definition: common.h:134
defines various classes for specifying a line in 3 dimensions
Declaration of class stir::ProjDataInfoCylindricalNoArcCorr.
Import of std::shared_ptr, std::dynamic_pointer_cast and std::static_pointer_cast (or corresponding b...
Declaration of stir::error()
int view_num() const
get view number for const objects
Definition: ViewgramIndices.inl:36
Declaration of class stir::Bin.
defines the stir::VectorWithOffset class
int segment_num() const
get segment number for const objects
Definition: SegmentIndices.inl:32
Declaration of class stir::SegmentByView.
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition: error.cxx:42
defines the stir::Coordinate4D<coordT> class
Declaration of class stir::DetectionPositionPair.