STIR  6.2.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 */
20 #ifndef __stir_listmode_CListRecordECAT962_H__
21 #define __stir_listmode_CListRecordECAT962_H__
22 
25 #include "stir/listmode/ListTime.h"
29 #include "stir/IO/stir_ecat_common.h" // for namespace macros
30 #include "stir/Succeeded.h"
31 #include "stir/ByteOrder.h"
32 #include "stir/ByteOrderDefine.h"
33 #include "stir/round.h"
34 #include "boost/static_assert.hpp"
35 #include "boost/cstdint.hpp"
36 
37 START_NAMESPACE_STIR
38 START_NAMESPACE_ECAT
39 START_NAMESPACE_ECAT7
40 
42 
57 {
58 public:
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 
79 private:
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
123 class 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  {
146  boost::int32_t raw;
147  };
148 };
149 #endif
150 
152 
155 {
156 public:
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
170 private:
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 
187 class CListRecordECAT962 : public CListRecordWithGatingInput,
188  public ListTime,
189  public ListGatingInput,
191 {
192 public:
194  DataType get_data() const { return this->event_data; }
195 
196 public:
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)
241  ByteOrder::swap_order(raw);
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 
250 private:
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 
262 END_NAMESPACE_ECAT7
263 END_NAMESPACE_ECAT
264 END_NAMESPACE_STIR
265 
266 #endif
Declarations of class stir::ListTime which is used for list mode data.
This file declares the stir::ByteOrder class.
A class recording external input to the scanner (normally used for gating)
Definition: ListGatingInput.h:38
Declaration of class stir::Succeeded.
Declaration of class stir::ProjDataInfoCylindricalNoArcCorr.
A class for storing and using a timing &#39;event&#39; from a listmode file.
Definition: CListRecordECAT962.h:154
Class for storing and using a coincidence event from a listmode file.
Definition: CListRecordECAT962.h:56
Succeeded set_prompt(const bool prompt=true)
Changes the event from prompt to delayed or vice versa.
Definition: CListRecordECAT962.h:228
Declaration of class stir::ProjDataInfoCylindrical.
Class for records in a PET list mode file.
Definition: CListRecord.h:66
A class for storing some info on the scanner.
Definition: Scanner.h:107
Class for storing and using a coincidence event from a list mode file.
Definition: CListRecord.h:52
Declarations of class stir::ListGatingInput, which is used for list mode data.
unsigned int get_gating() const
get gating-related info
Definition: CListRecordECAT962.h:223
Declaration of the stir::round functions.
Definition of class stir::CListEventCylindricalScannerWithViewTangRingRingEncoding.
Definition of STIRIsNativeByteOrderBigEndian and STIRIsNativeByteOrderLittleEndian preprocessor symbo...
A class for a general element of a listmode file.
Definition: CListRecordECAT962.h:187
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition: Succeeded.h:43
Declarations of classes stir::CListRecord, and stir::CListEvent which are used for list mode data...
A class for storing and using a timing record from a listmode file.
Definition: ListTime.h:46
Helper class for listmode events when using 2d sinograms and ring-pairs is most efficient.
Definition: CListEventCylindricalScannerWithViewTangRingRingEncoding.h:61
Declaration of routines which convert ECAT things into our building blocks and vice versa...