STIR 6.5.0
ProjDataInfoCylindricalNoArcCorr.inl
Go to the documentation of this file.
1//
2//
14/*
15 Copyright (C) 2026, University Medical Center Groningen
16 Copyright (C) 2000- 2005, Hammersmith Imanet Ltd
17 This file is part of STIR.
18
19 SPDX-License-Identifier: Apache-2.0
20
21 See STIR/LICENSE.txt for details
22*/
23
24#include "stir/Bin.h"
25#include "stir/Succeeded.h"
26#include "stir/round.h"
27#include <math.h>
28
29START_NAMESPACE_STIR
30
31void
32ProjDataInfoCylindricalNoArcCorr::initialise_uncompressed_view_tangpos_to_det1det2_if_not_done_yet() const
33{
34 // for efficiency reasons, use "Double-Checked-Locking(DCL) pattern" with OpenMP atomic operation
35 // OpenMP v3.1 or later required
36 // thanks to yohjp:
37 // http://stackoverflow.com/questions/27975737/how-to-handle-cached-data-structures-with-multi-threading-e-g-openmp
38#if defined(STIR_OPENMP) && _OPENMP >= 201012
39 bool initialised;
40# pragma omp atomic read
41 initialised = uncompressed_view_tangpos_to_det1det2_initialised;
42
43 if (!initialised)
44#endif
45 {
46#if defined(STIR_OPENMP)
47# pragma omp critical(PROJDATAINFOCYLINDRICALNOARCCORR_VIEWTANGPOS_TO_DETS)
48#endif
49 {
50 if (!uncompressed_view_tangpos_to_det1det2_initialised)
51 initialise_uncompressed_view_tangpos_to_det1det2();
52 }
53 }
54}
55
56void
57ProjDataInfoCylindricalNoArcCorr::initialise_det1det2_to_uncompressed_view_tangpos_if_not_done_yet() const
58{
59 // as above
60#if defined(STIR_OPENMP) && _OPENMP >= 201012
61 bool initialised;
62# pragma omp atomic read
63 initialised = det1det2_to_uncompressed_view_tangpos_initialised;
64
65 if (!initialised)
66#endif
67 {
68#if defined(STIR_OPENMP)
69# pragma omp critical(PROJDATAINFOCYLINDRICALNOARCCORR_DETS_TO_VIEWTANGPOS)
70#endif
71 {
72 if (!det1det2_to_uncompressed_view_tangpos_initialised)
73 initialise_det1det2_to_uncompressed_view_tangpos();
74 }
75 }
76}
77
78float
80{
81 return ring_radius * sin(bin.tangential_pos_num() * angular_increment);
82}
83
84float
86{
87 return angular_increment;
88}
89
90void
92 int& det2_num,
93 const int view_num,
94 const int tang_pos_num) const
95{
96 assert(get_view_mashing_factor() == 1);
97 this->initialise_uncompressed_view_tangpos_to_det1det2_if_not_done_yet();
98
99 det1_num = uncompressed_view_tangpos_to_det1det2[view_num][tang_pos_num].det1_num;
100 det2_num = uncompressed_view_tangpos_to_det1det2[view_num][tang_pos_num].det2_num;
101}
102
103bool
105 int& tang_pos_num,
106 const int det1_num,
107 const int det2_num) const
108{
109 assert(det1_num != det2_num);
110 this->initialise_det1det2_to_uncompressed_view_tangpos_if_not_done_yet();
111
112 view_num = det1det2_to_uncompressed_view_tangpos[det1_num][det2_num].view_num / get_view_mashing_factor();
113 tang_pos_num = det1det2_to_uncompressed_view_tangpos[det1_num][det2_num].tang_pos_num;
114 return det1det2_to_uncompressed_view_tangpos[det1_num][det2_num].swap_detectors;
115}
116
118ProjDataInfoCylindricalNoArcCorr::get_bin_for_det_pair(
119 Bin& bin, const int det_num1, const int ring_num1, const int det_num2, const int ring_num2, const int timing_pos_num) const
120{
121 if (get_view_tangential_pos_num_for_det_num_pair(bin.view_num(), bin.tangential_pos_num(), det_num1, det_num2))
122 {
123 bin.timing_pos_num() = timing_pos_num;
124 return get_segment_axial_pos_num_for_ring_pair(bin.segment_num(), bin.axial_pos_num(), ring_num1, ring_num2);
125 }
126 else
127 {
128 bin.timing_pos_num() = -timing_pos_num - (get_num_tof_poss() % 2 == 0);
129 return get_segment_axial_pos_num_for_ring_pair(bin.segment_num(), bin.axial_pos_num(), ring_num2, ring_num1);
130 }
131}
132
133Succeeded
135{
136 return get_bin_for_det_pair(bin,
137 dp.pos1().tangential_coord(),
138 dp.pos1().axial_coord(),
139 dp.pos2().tangential_coord(),
140 dp.pos2().axial_coord(),
141 this->get_tof_mash_factor() == 0
142 ? 0 // use timing_pos==0 in the nonTOF case
143 : stir::round((float)dp.timing_pos() / this->get_tof_mash_factor()));
144}
145void
147 int& det_num1, int& ring_num1, int& det_num2, int& ring_num2, const Bin& bin) const
148{
149 // if (bin.timing_pos_num()>=0)
150 // {
152 get_ring_pair_for_segment_axial_pos_num(ring_num1, ring_num2, bin.segment_num(), bin.axial_pos_num());
153 //}
154 // else
155 //{
156 // get_det_num_pair_for_view_tangential_pos_num(det_num2, det_num1, bin.view_num(), bin.tangential_pos_num());
157 // get_ring_pair_for_segment_axial_pos_num( ring_num2, ring_num1, bin.segment_num(), bin.axial_pos_num());
158 // }
159}
160
161void
163{
164 // This is a bit complicated as DetectionPositionPair<>::timing_pos() was an unsigned int at some point,
165 // while Bin uses an int. So swap detectors around.
166
167 // lousy work around because types don't match (short/int). TODO remove!
168 int t1, a1, t2, a2;
169 get_det_pair_for_bin(t1, a1, t2, a2, bin);
170 if (bin.timing_pos_num() >= 0)
171 {
172 dp.pos1().tangential_coord() = t1;
173 dp.pos1().axial_coord() = a1;
174 dp.pos2().tangential_coord() = t2;
175 dp.pos2().axial_coord() = a2;
176 }
177 else
178 {
179 dp.pos1().tangential_coord() = t2;
180 dp.pos1().axial_coord() = a2;
181 dp.pos2().tangential_coord() = t1;
182 dp.pos2().axial_coord() = a1;
183 }
184
185 dp.timing_pos() = std::abs(bin.timing_pos_num()) * this->get_tof_mash_factor();
186}
187
188END_NAMESPACE_STIR
Declaration of class stir::Bin.
Declaration of class stir::Succeeded.
A class for storing coordinates and value of a single projection bin.
Definition Bin.h:49
int tangential_pos_num() const
get tangential position number
Definition Bin.inl:76
int axial_pos_num() const
get axial position number
Definition Bin.inl:70
A class for storing 2 coordinates-sets of a detection, together with a timing-position index (for TOF...
Definition DetectionPositionPair.h:41
void get_det_num_pair_for_view_tangential_pos_num(int &det1_num, int &det2_num, const int view_num, const int tang_pos_num) const
This routine gets det_num1 and det_num2.
Definition ProjDataInfoCylindricalNoArcCorr.inl:91
void get_det_pair_for_bin(int &det_num1, int &ring_num1, int &det_num2, int &ring_num2, const Bin &bin) const
This routine gets the detector pair corresponding to a bin.
Definition ProjDataInfoCylindricalNoArcCorr.inl:146
bool get_view_tangential_pos_num_for_det_num_pair(int &view_num, int &tang_pos_num, const int det1_num, const int det2_num) const
This gets view_num and tang_pos_num for a particular detector pair.
Definition ProjDataInfoCylindricalNoArcCorr.inl:104
void get_det_pos_pair_for_bin(DetectionPositionPair<> &, const Bin &) const
This routine gets the detector pair corresponding to a bin.
Definition ProjDataInfoCylindricalNoArcCorr.inl:162
Succeeded get_bin_for_det_pos_pair(Bin &, const DetectionPositionPair<> &) const
This gets Bin coordinates for a particular detector pair.
Definition ProjDataInfoCylindricalNoArcCorr.inl:134
float get_angular_increment() const
Gets angular increment (in radians).
Definition ProjDataInfoCylindricalNoArcCorr.inl:85
float get_s(const Bin &) const override
Gets s coordinate in mm.
Definition ProjDataInfoCylindricalNoArcCorr.inl:79
virtual int get_view_mashing_factor() const
Get the mashing factor, i.e. how many 'original' views are combined.
Definition ProjDataInfoCylindrical.inl:207
void get_ring_pair_for_segment_axial_pos_num(int &ring1, int &ring2, const int segment_num, const int axial_pos_num) const
Find a ring pair that contributes to a segment and axial position.
Definition ProjDataInfoCylindrical.cxx:336
int get_tof_mash_factor() const
Get TOF mash factor.
Definition ProjDataInfo.inl:114
int segment_num() const
get segment number for const objects
Definition SegmentIndices.inl:32
int timing_pos_num() const
get TOF index for const objects
Definition SegmentIndices.inl:44
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition Succeeded.h:44
int view_num() const
get view number for const objects
Definition ViewgramIndices.inl:36
int round(const float x)
Implements rounding of floating point numbers.
Definition round.inl:59
Declaration of the stir::round functions.