STIR 6.4.0
CListRecordECAT962.h
Go to the documentation of this file.
1//
2//
3/*
4 Copyright (C) 2003- 2011, Hammersmith Imanet Ltd
5 This file is part of STIR.
6
7 SPDX-License-Identifier: Apache-2.0
8
9 See STIR/LICENSE.txt for details
10*/
19
20#ifndef __stir_listmode_CListRecordECAT962_H__
21#define __stir_listmode_CListRecordECAT962_H__
22
29#include "stir/IO/stir_ecat_common.h" // for namespace macros
30#include "stir/Succeeded.h"
31#include "stir/ByteOrder.h"
33#include "stir/round.h"
34#include "boost/static_assert.hpp"
35#include "boost/cstdint.hpp"
36
37START_NAMESPACE_STIR
38START_NAMESPACE_ECAT
39START_NAMESPACE_ECAT7
40
42
57{
58public:
59 inline bool is_prompt() const { return delayed == 0; }
60 inline Succeeded set_prompt(const bool prompt = true)
61 {
62 if (prompt)
63 delayed = 0;
64 else
65 delayed = 1;
66 return Succeeded::yes;
67 }
68
71 void get_sinogram_and_ring_coordinates(int& view, int& tangential_pos_num, unsigned int& ring_a, unsigned int& ring_b) const;
72
74 void set_sinogram_and_ring_coordinates(const int view_num,
75 const int tangential_pos_num,
76 const unsigned int ring_a,
77 const unsigned int ring_b);
78
79private:
80 /* ring encoding. use as follows:
81 This organisation corresponds to physical detector blocks (which
82 have 8 crystal rings). Names are not very good probably...
83 */
84 /* 'delayed' bit:
85 1 if event is Delayed (it fell in delayed time window) */
86 /* bin field is shifted in a funny way, use the following code to find
87 bin_number:
88 if ( bin > NumProjBinsBy2 ) bin -= NumProjBins ;
89 */
90
91#if STIRIsNativeByteOrderBigEndian
92 unsigned type : 1; /* 0-coincidence event, 1-time tick */
93 unsigned block_A_ring_bit1 : 1;
94 unsigned block_B_ring_bit1 : 1;
95 unsigned block_A_ring_bit0 : 1;
96 unsigned block_B_ring_bit0 : 1;
97 unsigned block_B_detector : 3;
98 unsigned block_A_detector : 3;
99 unsigned scatter : 1;
100 unsigned delayed : 1;
101 unsigned multiple : 1;
102 unsigned bin : 9;
103 unsigned view : 9;
104#else
105 // Do byteswapping first before using this bit field.
106 unsigned view : 9;
107 unsigned bin : 9;
108 unsigned multiple : 1;
109 unsigned delayed : 1;
110 unsigned scatter : 1;
111 unsigned block_A_detector : 3;
112 unsigned block_B_detector : 3;
113 unsigned block_B_ring_bit0 : 1;
114 unsigned block_A_ring_bit0 : 1;
115 unsigned block_B_ring_bit1 : 1;
116 unsigned block_A_ring_bit1 : 1;
117 unsigned type : 1; /* 0-coincidence event, 1-time tick */
118
119#endif
120}; /*-coincidence event*/
121
122#if 0
124class CListEventECAT962 : public CListEventCylindricalScannerWithViewTangRingRingEncoding<CListEventDataECAT962>
125{
126 public:
127 CListEventECAT962() :
129 {}
130
131 Succeeded init_from_data_ptr(const void * const ptr)
132 {
133 const char * const data_ptr = reinterpret_cast<const char * const >(ptr);
134 std::copy(data_ptr, data_ptr+sizeof(this->raw), reinterpret_cast<char *>(&this->raw));
135 return Succeeded::yes;
136 }
137 inline bool is_prompt() const { return this->data.delayed == 0; }
138 inline Succeeded set_prompt(const bool prompt = true)
139 { if (prompt) this->data.delayed=0; else this->data.delayed=1; return Succeeded::yes; }
140
141 private:
142 BOOST_STATIC_ASSERT(sizeof(CListEventDataECAT962)==4);
143 union
144 {
145 CListEventDataECAT962 data;
146 boost::int32_t raw;
147 };
148};
149#endif
150
152
155{
156public:
157 inline unsigned long get_time_in_millisecs() const { return static_cast<unsigned long>(time); }
158 inline Succeeded set_time_in_millisecs(const unsigned long time_in_millisecs)
159 {
160 time = ((1U << 28) - 1) & static_cast<unsigned>(time_in_millisecs);
161 // TODO return more useful value
162 return Succeeded::yes;
163 }
164 inline unsigned int get_gating() const { return gating; }
165 inline Succeeded set_gating(unsigned int g)
166 {
167 gating = g & 0xf;
168 return gating == g ? Succeeded::yes : Succeeded::no;
169 } // TODONK check
170private:
171 friend class CListRecordECAT962; // to give access to type field
172#if STIRIsNativeByteOrderBigEndian
173 unsigned type : 1; /* 0-coincidence event, 1-time tick */
174 unsigned gating : 4; /* some info about the gating signals */
175 unsigned time : 27; /* since scan start */
176#else
177 // Do byteswapping first before using this bit field.
178 unsigned time : 27; /* since scan start */
179 unsigned gating : 4; /* some info about the gating signals */
180 unsigned type : 1; /* 0-coincidence event, 1-time tick */
181#endif
182};
183
185
187class CListRecordECAT962 : public CListRecordWithGatingInput,
188 public ListTime,
189 public ListGatingInput,
190 public CListEventCylindricalScannerWithViewTangRingRingEncoding<CListRecordECAT962>
191{
192public:
193 typedef CListEventDataECAT962 DataType;
194 DataType get_data() const { return this->event_data; }
195
196public:
197 CListRecordECAT962()
198 : CListEventCylindricalScannerWithViewTangRingRingEncoding<CListRecordECAT962>(
199 shared_ptr<Scanner>(new Scanner(Scanner::E962)))
200 {}
201
202 bool is_time() const { return time_data.type == 1U; }
203 bool is_gating_input() const { return this->is_time(); }
204 bool is_event() const { return time_data.type == 0U; }
205 virtual CListEvent& event() { return *this; }
206 virtual const CListEvent& event() const { return *this; }
207 virtual ListTime& time() { return *this; }
208 virtual const ListTime& time() const { return *this; }
209 virtual ListGatingInput& gating_input() { return *this; }
210 virtual const ListGatingInput& gating_input() const { return *this; }
211
212 bool operator==(const CListRecord& e2) const
213 {
214 return dynamic_cast<CListRecordECAT962 const*>(&e2) != 0 && raw == static_cast<CListRecordECAT962 const&>(e2).raw;
215 }
216
217 // time
218 inline unsigned long get_time_in_millisecs() const { return time_data.get_time_in_millisecs(); }
219 inline Succeeded set_time_in_millisecs(const unsigned long time_in_millisecs)
220 {
221 return time_data.set_time_in_millisecs(time_in_millisecs);
222 }
223 inline unsigned int get_gating() const { return time_data.get_gating(); }
224 inline Succeeded set_gating(unsigned int g) { return time_data.set_gating(g); }
225
226 // event
227 inline bool is_prompt() const { return event_data.is_prompt(); }
228 inline Succeeded set_prompt(const bool prompt = true) { return event_data.set_prompt(prompt); }
229
230 virtual Succeeded init_from_data_ptr(const char* const data_ptr,
231 const std::size_t
232#ifndef NDEBUG
233 size // only used within assert, so don't define otherwise to avoid compiler warning
234#endif
235 ,
236 const bool do_byte_swap)
237 {
238 assert(size >= 4);
239 std::copy(data_ptr, data_ptr + 4, reinterpret_cast<char*>(&raw)); // TODO necessary for operator==
240 if (do_byte_swap)
242 return Succeeded::yes;
243 }
244 virtual std::size_t
245 size_of_record_at_ptr(const char* const /*data_ptr*/, const std::size_t /*size*/, const bool /*do_byte_swap*/) const
246 {
247 return 4;
248 }
249
250private:
251 union
252 {
253 CListEventDataECAT962 event_data;
254 CListTimeDataECAT962 time_data;
255 boost::int32_t raw;
256 };
257 BOOST_STATIC_ASSERT(sizeof(boost::int32_t) == 4);
258 BOOST_STATIC_ASSERT(sizeof(CListEventDataECAT962) == 4);
259 BOOST_STATIC_ASSERT(sizeof(CListTimeDataECAT962) == 4);
260};
261
262END_NAMESPACE_ECAT7
263END_NAMESPACE_ECAT
264END_NAMESPACE_STIR
265
266#endif
Definition of STIRIsNativeByteOrderBigEndian and STIRIsNativeByteOrderLittleEndian preprocessor symbo...
This file declares the stir::ByteOrder class.
Definition of class stir::CListEventCylindricalScannerWithViewTangRingRingEncoding.
Declarations of classes stir::CListRecord, and stir::CListEvent which are used for list mode data.
Declarations of class stir::ListGatingInput, which is used for list mode data.
Declarations of class stir::ListTime which is used for list mode data.
Declaration of class stir::ProjDataInfoCylindricalNoArcCorr.
Declaration of class stir::ProjDataInfoCylindrical.
Declaration of class stir::Succeeded.
static void swap_order(NUMBER &value)
swap the byteorder of the argument
Definition ByteOrder.h:122
Helper class for listmode events when using 2d sinograms and ring-pairs is most efficient.
Definition CListEventCylindricalScannerWithViewTangRingRingEncoding.h:62
Class for storing and using a coincidence event from a list mode file.
Definition CListRecord.h:53
virtual Succeeded set_prompt(const bool prompt=true)
Changes the event from prompt to delayed or vice versa.
Definition CListEvent.cxx:29
Class for records in a PET list mode file.
Definition CListRecord.h:67
A class recording external input to the scanner (normally used for gating)
Definition ListGatingInput.h:39
A class for storing and using a timing record from a listmode file.
Definition ListTime.h:47
A class for storing some info on the scanner.
Definition Scanner.h:108
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition Succeeded.h:44
Class for storing and using a coincidence event from a listmode file.
Definition CListRecordECAT962.h:57
void set_sinogram_and_ring_coordinates(const int view_num, const int tangential_pos_num, const unsigned int ring_a, const unsigned int ring_b)
Definition CListRecordECAT962.cxx:55
void get_sinogram_and_ring_coordinates(int &view, int &tangential_pos_num, unsigned int &ring_a, unsigned int &ring_b) const
Definition CListRecordECAT962.cxx:36
unsigned int get_gating() const
get gating-related info
Definition CListRecordECAT962.h:223
Succeeded set_prompt(const bool prompt=true)
Changes the event from prompt to delayed or vice versa.
Definition CListRecordECAT962.h:228
A class for storing and using a timing 'event' from a listmode file.
Definition CListRecordECAT962.h:155
Declaration of the stir::round functions.
Declaration of routines which convert ECAT things into our building blocks and vice versa.