STIR  6.2.0
CListRecordECAT966.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_CListRecordECAT966_H__
21 #define __stir_listmode_CListRecordECAT966_H__
22 
25 #include "stir/listmode/ListTime.h"
28 #include "stir/IO/stir_ecat_common.h" // for namespace macros
29 #include "stir/Succeeded.h"
30 #include "stir/ByteOrder.h"
31 #include "stir/ByteOrderDefine.h"
32 #include "stir/round.h"
33 #include "boost/static_assert.hpp"
34 #include "boost/cstdint.hpp"
36 
37 START_NAMESPACE_STIR
38 
39 START_NAMESPACE_ECAT
40 START_NAMESPACE_ECAT7
41 
43 
55 {
56 public:
59  void get_sinogram_and_ring_coordinates(int& view, int& tangential_pos_num, unsigned int& ring_a, unsigned int& ring_b) const;
60 
62  void set_sinogram_and_ring_coordinates(const int view_num, const int tangential_pos_num, const int ring_a, const int ring_b);
63 
64  /* ring encoding. use as follows:
65  #define CRYSTALRINGSPERDETECTOR 8
66  ringA = ( block_A_ring * CRYSTALRINGSPERDETECTOR ) + block_A_detector ;
67  in practice, for the 966 block_A_ring ranges from 0 to 5.
68 
69  This organisation corresponds to physical detector blocks (which
70  have 8 crystal rings). Names are not very good probably...
71  */
72  /* 'delayed' bit:
73  1 if event is Delayed (it fell in delayed time window) */
74  /* bin field is shifted in a funny way, use the following code to find
75  bin_number:
76  if ( bin > NumProjBinsBy2 ) bin -= NumProjBins ;
77  */
78 
79 #if STIRIsNativeByteOrderBigEndian
80  unsigned type : 1; /* 0-coincidence event, 1-time tick */
81  unsigned block_B_ring : 3;
82  unsigned block_A_ring : 3;
83  unsigned block_B_detector : 3;
84  unsigned block_A_detector : 3;
85  unsigned delayed : 1;
86  unsigned bin : 9;
87  unsigned view : 9;
88 #else
89  // Do byteswapping first before using this bit field.
90  unsigned view : 9;
91  unsigned bin : 9;
92  unsigned delayed : 1;
93  unsigned block_A_detector : 3;
94  unsigned block_B_detector : 3;
95  unsigned block_A_ring : 3;
96  unsigned block_B_ring : 3;
97  unsigned type : 1; /* 0-coincidence event, 1-time tick */
98 
99 #endif
100 }; /*-coincidence event*/
101 
104 {
105 private:
106 public:
108  DataType get_data() const { return this->data; }
109 
110 public:
113  shared_ptr<Scanner>(new Scanner(Scanner::E966)))
114  {}
115 
116  Succeeded init_from_data_ptr(const void* const ptr)
117  {
118  const char* const data_ptr = reinterpret_cast<const char* const>(ptr);
119  std::copy(data_ptr, data_ptr + sizeof(this->raw), reinterpret_cast<char*>(&this->raw));
120  return Succeeded::yes;
121  }
122  inline bool is_prompt() const { return this->data.delayed == 0; }
123  inline Succeeded set_prompt(const bool prompt = true)
124  {
125  if (prompt)
126  this->data.delayed = 0;
127  else
128  this->data.delayed = 1;
129  return Succeeded::yes;
130  }
131 
132 private:
133  BOOST_STATIC_ASSERT(sizeof(CListEventDataECAT966) == 4);
134  union
135  {
137  boost::int32_t raw;
138  };
139 };
140 
142 
147 {
148 public:
149 #if STIRIsNativeByteOrderBigEndian
150  unsigned type : 1; /* 0-coincidence event, 1-time tick */
151  unsigned gating : 4; /* some info about the gating signals */
152  unsigned time : 27; /* since scan start */
153 #else
154  // Do byteswapping first before using this bit field.
155  unsigned time : 27; /* since scan start */
156  unsigned gating : 4; /* some info about the gating signals */
157  unsigned type : 1; /* 0-coincidence event, 1-time tick */
158 #endif
159 };
160 
162 
165 {
166 public:
167  Succeeded init_from_data_ptr(const void* const ptr)
168  {
169  const char* const data_ptr = reinterpret_cast<const char* const>(ptr);
170  std::copy(data_ptr, data_ptr + sizeof(this->raw), reinterpret_cast<char*>(&this->raw));
171  return Succeeded::yes;
172  }
173  bool is_time() const { return this->data.type == 1U; }
174  inline unsigned long get_time_in_millisecs() const { return static_cast<unsigned long>(this->data.time); }
175  inline Succeeded set_time_in_millisecs(const unsigned long time_in_millisecs)
176  {
177  this->data.time = ((1U << 28) - 1) & static_cast<unsigned>(time_in_millisecs);
178  // TODO return more useful value
179  return Succeeded::yes;
180  }
181  inline unsigned int get_gating() const { return this->data.gating; }
182  inline Succeeded set_gating(unsigned int g)
183  {
184  this->data.gating = g & 0xf;
185  return this->data.gating == g ? Succeeded::yes : Succeeded::no;
186  }
187 
188 private:
189  BOOST_STATIC_ASSERT(sizeof(CListTimeDataECAT966) == 4);
190  union
191  {
193  boost::int32_t raw;
194  };
195 };
196 
198 
200 class CListRecordECAT966 : public CListRecordWithGatingInput
201 {
202 
203  // public:
204 
205  bool is_time() const { return this->time_data.is_time(); }
206  bool is_gating_input() const { return this->is_time(); }
207  bool is_event() const { return !this->is_time(); }
208  virtual CListEventECAT966& event() { return this->event_data; }
209  virtual const CListEventECAT966& event() const { return this->event_data; }
210  virtual CListTimeECAT966& time() { return this->time_data; }
211  virtual const CListTimeECAT966& time() const { return this->time_data; }
212  virtual CListTimeECAT966& gating_input() { return this->time_data; }
213  virtual const CListTimeECAT966& gating_input() const { return this->time_data; }
214 
215  bool operator==(const CListRecord& e2) const
216  {
217  return dynamic_cast<CListRecordECAT966 const*>(&e2) != 0 && raw == dynamic_cast<CListRecordECAT966 const&>(e2).raw;
218  }
219 
220 public:
221  virtual Succeeded init_from_data_ptr(const char* const data_ptr,
222  const std::size_t
223 #ifndef NDEBUG
224  size // only use within assert
225 #endif
226  ,
227  const bool do_byte_swap)
228  {
229  assert(size >= 4);
230  std::copy(data_ptr, data_ptr + 4, reinterpret_cast<char*>(&raw)); // TODO necessary for operator==
231  if (do_byte_swap)
232  ByteOrder::swap_order(raw);
233  this->time_data.init_from_data_ptr(&raw);
234  // should in principle check return value, but it's always Succeeded::yes anyway
235  if (!this->is_time())
236  return this->event_data.init_from_data_ptr(&raw);
237  else
238  return Succeeded::yes;
239  }
240 
241  virtual std::size_t
242  size_of_record_at_ptr(const char* const /*data_ptr*/, const std::size_t /*size*/, const bool /*do_byte_swap*/) const
243  {
244  return 4;
245  }
246 
247 private:
248  CListEventECAT966 event_data;
249  CListTimeECAT966 time_data;
250  boost::int32_t raw;
251 };
252 
253 END_NAMESPACE_ECAT7
254 END_NAMESPACE_ECAT
255 END_NAMESPACE_STIR
256 
257 #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.
A class for decoding a raw timing &#39;event&#39; from a listmode file from the ECAT 966 scanner.
Definition: CListRecordECAT966.h:146
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 decoding storing and using a raw coincidence event from a listmode file from the ECAT 966 s...
Definition: CListRecordECAT966.h:54
Declarations of class stir::ListGatingInput, which is used for list mode data.
Succeeded set_prompt(const bool prompt=true)
Changes the event from prompt to delayed or vice versa.
Definition: CListRecordECAT966.h:123
unsigned int get_gating() const
get gating-related info
Definition: CListRecordECAT966.h:181
Declaration of the stir::round functions.
Definition of class stir::CListEventCylindricalScannerWithViewTangRingRingEncoding.
A class for storing and using a timing &#39;event&#39; from a listmode file from the ECAT 966 scanner...
Definition: CListRecordECAT966.h:164
Definition of STIRIsNativeByteOrderBigEndian and STIRIsNativeByteOrderLittleEndian preprocessor symbo...
Class for storing and using a coincidence event from a listmode file from the ECAT 966 scanner...
Definition: CListRecordECAT966.h:103
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
A class for a general element of a listmode file.
Definition: CListRecordECAT966.h:200
Declaration of routines which convert ECAT things into our building blocks and vice versa...
Declaration of class stir::DetectionPositionPair.