STIR  6.2.0
CListRecordGEHDF5.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003-2011 Hammersmith Imanet Ltd (CListRecordECAT.h)
3  Copyright (C) 2013, 2016, 2020 University College London
4  Copyright (C) 2017-2018 University of Leeds
5 */
18 #ifndef __stir_listmode_CListRecordGEHDF5_H__
19 #define __stir_listmode_CListRecordGEHDF5_H__
20 
23 #include "stir/Succeeded.h"
24 #include "stir/ByteOrder.h"
25 #include "stir/ByteOrderDefine.h"
26 #include <boost/static_assert.hpp>
27 #include <boost/cstdint.hpp>
28 #include "stir/error.h"
29 #include <iostream>
30 
31 START_NAMESPACE_STIR
32 
33 namespace GE
34 {
35 namespace RDF_HDF5
36 {
37 
38 namespace detail
39 {
40 /***********************************
41  * Supported Event Length Modes
42  ***********************************/
43 enum EventLength
44 {
45  /* RESERVED = 0x0, */
46  LENGTH_6_EVT = 0x1,
47  LENGTH_8_EVT = 0x2,
48  LENGTH_16_EVT = 0x3
49 };
50 
51 /***********************************
52  * Supported Event Types
53  ***********************************/
54 enum EventType
55 {
56  EXTENDED_EVT = 0x0,
57  COINC_EVT = 0x1
58 };
59 
60 /***********************************
61  * Supported Extended Event Types
62  ***********************************/
63 enum ExtendedEvtType
64 {
65  TIME_MARKER_EVT = 0x0,
66  COINC_COUNT_EVT = 0x1,
67  EXTERN_TRIG_EVT = 0x2,
68  TABLE_POS_EVT = 0x3,
69  /* RESERVED = 0x4 to 0xE */
70  /* 0xE is temporary taken here to mark end of it. */
71  END_LIST_EVT = 0xE,
72  SINGLE_EVT = 0xF
73 };
74 
76 
80 {
81 public:
82 #if STIRIsNativeByteOrderBigEndian
83  // Do byteswapping first before using this bit field.
84  TODO;
85 #else
86  boost::uint16_t eventLength : 2; /* Event Length : Enum for the number of bytes in the event */
87  boost::uint16_t eventType : 1; /* Event Type : Coin or Extended types */
88  boost::uint16_t eventTypeExt : 4; /* If not a coincidence, Extended Event Type : Time Marker, Trigger, Single..etc */
89  boost::uint16_t dummy : 9;
90 #endif
91 }; /*any record */
92 
94 
99 {
100 public:
101  inline bool is_prompt() const { return true; } // TODO
102  inline Succeeded set_prompt(const bool prompt = true)
103  {
104  // if (prompt) random=1; else random=0; return Succeeded::yes;
105  return Succeeded::no;
106  }
107  inline bool is_event() const
108  {
109  return (eventType == COINC_EVT) /* && eventTypeExt==COINC_COUNT_EVT)*/;
110  } // TODO need to find out how to see if it's a coincidence event
111 
112  inline int get_tof_bin() const { return static_cast<int>(-deltaTime); }
113 #if STIRIsNativeByteOrderBigEndian
114  // Do byteswapping first before using this bit field.
115  TODO
116 #else
117  boost::uint16_t eventLength : 2; /* Event Length : Enum for the number of bytes in the event */
118  boost::uint16_t eventType : 1; /* Event Type : Coin or Extended types */
119  boost::uint16_t hiXtalShortInteg : 1; /* High Crystal Short Integration on / off */
120  boost::uint16_t loXtalShortInteg : 1; /* Low Crystal Short Integration on / off */
121  boost::uint16_t hiXtalScatterRec : 1; /* High Crystal Scatter Recovered on / off */
122  boost::uint16_t loXtalScatterRec : 1; /* Low Crystal Scatter Recovered on / off */
123  boost::int16_t deltaTime : 9; /* TOF 'signed' delta time (units defined by electronics */
124  boost::uint16_t hiXtalAxialID : 6; /* High Crystal Axial Id */
125  boost::uint16_t hiXtalTransAxID : 10; /* High Crystal Trans-Axial Id */
126  boost::uint16_t loXtalAxialID : 6; /* Low Crystal Axial Id */
127  boost::uint16_t loXtalTransAxID : 10; /* Low Crystal Trans-Axial Id */
128 #endif
129 }; /*-coincidence event*/
130 
132 
137 {
138 public:
139  inline unsigned long get_time_in_millisecs() const { return (time_hi() << 16) | time_lo(); }
140  inline Succeeded set_time_in_millisecs(const unsigned long time_in_millisecs)
141  {
142  data.timeMarkerLS = ((1UL << 16) - 1) & (time_in_millisecs);
143  data.timeMarkerMS = (time_in_millisecs) >> 16;
144  // TODO return more useful value
145  return Succeeded::yes;
146  }
147  inline bool is_time() const
148  { // TODO need to find out how to see if it's a timing event
149  return (data.eventType == EXTENDED_EVT) && (data.eventTypeExt == TIME_MARKER_EVT);
150  } // TODO
151 
152 private:
153  typedef union
154  {
155  struct
156  {
157 #if STIRIsNativeByteOrderBigEndian
158  TODO
159 #else
160  boost::uint16_t eventLength : 2; /* Event Length : Enum for the number of bytes in the event */
161  boost::uint16_t eventType : 1; /* Event Type : Coin or Extended types */
162  boost::uint16_t eventTypeExt : 4; /* Extended Event Type : Time Marker, Trigger, Single..etc */
163  boost::uint16_t unused1 : 5; /* Unused */
164  boost::uint16_t externEvt3 : 1; /* External Event Input 3 Level */
165  boost::uint16_t externEvt2 : 1; /* External Event Input 2 Level */
166  boost::uint16_t externEvt1 : 1; /* External Event Input 1 Level */
167  boost::uint16_t externEvt0 : 1; /* External Event Input 0 Level */
168  boost::uint16_t timeMarkerLS : 16; /* Least Significant 16 bits of 32-bit Time Marker */
169  boost::uint16_t timeMarkerMS : 16; /* Most Significant 16 bits of 32-bitTime Marker */
170 #endif
171  };
172  } data_t;
173  data_t data;
174 
175  unsigned long time_lo() const
176  {
177  return data.timeMarkerLS;
178  }
179  unsigned long time_hi() const
180  {
181  return data.timeMarkerMS;
182  }
183 };
184 
185 } // namespace detail
186 
188 
194  public ListTime, // public CListGatingInput,
196 {
199  // typedef CListGatingDataGEHDF5 GatingType;
200 
201 public:
203 
208  CListRecordGEHDF5(const shared_ptr<const ProjDataInfo>& proj_data_info_sptr, const unsigned long first_time_stamp)
210  first_time_stamp(first_time_stamp)
211  {}
212 
213  bool is_time() const override { return this->time_data.is_time(); }
214 #if 0
215  bool is_gating_input() const
216  {
217  return this->gating_data.is_gating_input();
218  }
219 #endif
220 
221  bool is_event() const override
222  {
223  return this->event_data.is_event();
224  }
225  CListEvent& event() override
226  {
227  return *this;
228  }
229  const CListEvent& event() const override
230  {
231  return *this;
232  }
233  ListTime& time() override
234  {
235  return *this;
236  }
237  const ListTime& time() const override
238  {
239  return *this;
240  }
241 #if 0
242  virtual CListGatingInput& gating_input()
243  { return *this; }
244  virtual const CListGatingInput& gating_input() const
245  { return *this; }
246 #endif
247  bool operator==(const CListRecord& e2) const
248  {
249  return false;
250 #if 0
251 // TODO
252 dynamic_cast<CListRecordGEHDF5 const *>(&e2) != 0 &&
253  raw[0] == static_cast<CListRecordGEHDF5 const &>(e2).raw[0] &&
254  (this->is_event() || (raw[1] == static_cast<CListRecordGEHDF5 const &>(e2).raw[1]));
255 #endif
256  }
257 
258  // time
259  inline unsigned long get_time_in_millisecs() const override
260  {
261  return time_data.get_time_in_millisecs() - first_time_stamp;
262  }
263 
264  inline Succeeded set_time_in_millisecs(const unsigned long time_in_millisecs) override
265  {
266  return time_data.set_time_in_millisecs(time_in_millisecs);
267  }
268 #if 0
269  inline unsigned int get_gating() const
270  { return gating_data.get_gating(); }
271  inline Succeeded set_gating(unsigned int g)
272  { return gating_data.set_gating(g); }
273 #endif
274  // event
275  inline bool is_prompt() const override
276  {
277  return event_data.is_prompt();
278  }
279  inline Succeeded set_prompt(const bool prompt = true) override
280  {
281  return event_data.set_prompt(prompt);
282  }
283 
284  void get_detection_position(DetectionPositionPair<>& det_pos) const override
285  {
286  det_pos.pos1().tangential_coord()
287  = this->get_uncompressed_proj_data_info_sptr()->get_scanner_sptr()->get_num_detectors_per_ring() - 1
288  - event_data.loXtalTransAxID;
289  det_pos.pos1().axial_coord() = event_data.loXtalAxialID;
290  det_pos.pos2().tangential_coord()
291  = this->get_uncompressed_proj_data_info_sptr()->get_scanner_sptr()->get_num_detectors_per_ring() - 1
292  - event_data.hiXtalTransAxID;
293  det_pos.pos2().axial_coord() = event_data.hiXtalAxialID;
294  det_pos.timing_pos() = event_data.get_tof_bin();
295  }
296 
299  {
300  error("TODO");
301  }
302 
303  virtual std::size_t size_of_record_at_ptr(const char* const data_ptr, const std::size_t, const bool do_byte_swap) const
304  {
305  // TODO don't know what to do with byteswap.
306  assert(do_byte_swap == false);
307 
308  // Figure out the actual size from the eventLength bits.
309  union
310  {
312  boost::uint16_t raw[4];
313  };
314  std::copy(data_ptr, data_ptr + 2, &raw[0]);
315  switch (rec.eventLength)
316  {
317  case detail::LENGTH_6_EVT:
318  return std::size_t(6);
319  case detail::LENGTH_8_EVT:
320  return std::size_t(8);
321  case detail::LENGTH_16_EVT:
322  return std::size_t(16);
323  default:
324  error("ClistRecordGEHDF5: error decoding event (eventLength bits are incorrect)");
325  return std::size_t(0); // avoid compiler warnings
326  }
327  }
328 
329  virtual Succeeded init_from_data_ptr(const char* const data_ptr, const std::size_t size, const bool do_byte_swap)
330  {
331  assert(size >= 6);
332  assert(size <= 16);
333  std::copy(data_ptr, data_ptr + size, reinterpret_cast<char*>(&this->raw[0]));
334 
335  if (do_byte_swap)
336  {
337  error("ClistRecordGEHDF5: byte-swapping not supported yet. sorry");
338  // ByteOrder::swap_order(this->raw[0]);
339  }
340 
341  return Succeeded::yes;
342  }
343 
344 private:
345  unsigned long first_time_stamp;
346  union
347  {
348  DataType event_data;
349  TimeType time_data;
350  // GatingType gating_data;
351  boost::int32_t raw[16 / 4];
352  };
353  BOOST_STATIC_ASSERT(sizeof(boost::int32_t) == 4);
354  BOOST_STATIC_ASSERT(sizeof(DataType) == 6);
355  BOOST_STATIC_ASSERT(sizeof(TimeType) == 6);
356  // BOOST_STATIC_ASSERT(sizeof(GatingType)==8);
357 };
358 
359 } // namespace RDF_HDF5
360 } // namespace GE
361 
362 END_NAMESPACE_STIR
363 
364 #endif
Class for storing and using a coincidence event from a list mode file for a cylindrical scanner...
Definition: CListEventCylindricalScannerWithDiscreteDetectors.h:31
CListRecordGEHDF5(const shared_ptr< const ProjDataInfo > &proj_data_info_sptr, const unsigned long first_time_stamp)
constructor
Definition: CListRecordGEHDF5.h:208
This file declares the stir::ByteOrder class.
Declaration of class stir::Succeeded.
Class for storing and using a coincidence event from a GE RDF9 listmode file.
Definition: CListRecordGEHDF5.h:98
Class for finding out what the event/size-type is in a GE RDF9 listmode file.
Definition: CListRecordGEHDF5.h:79
Declaration of stir::error()
Class for records in a PET list mode file.
Definition: CListRecord.h:66
void set_detection_position(const DetectionPositionPair<> &) override
This routine sets in a coincidence event from detector "indices".
Definition: CListRecordGEHDF5.h:298
Class for storing and using a coincidence event from a list mode file.
Definition: CListRecord.h:52
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition: error.cxx:42
void get_detection_position(DetectionPositionPair<> &det_pos) const override
This routine returns the corresponding detector pair.
Definition: CListRecordGEHDF5.h:284
Definition of STIRIsNativeByteOrderBigEndian and STIRIsNativeByteOrderLittleEndian preprocessor symbo...
A class for a general element (or "record") of a GE RDF9 listmode file.
Definition: CListRecordGEHDF5.h:193
Succeeded set_prompt(const bool prompt=true) override
Changes the event from prompt to delayed or vice versa.
Definition: CListRecordGEHDF5.h:279
Declarations of class stir::CListEventCylindricalScannerWithDiscreteDetectors.
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition: Succeeded.h:43
A class for storing and using a timing &#39;event&#39; from a GE RDF9 listmode file.
Definition: CListRecordGEHDF5.h:136
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
A class for storing 2 coordinates-sets of a detection, together with a timing-position index (for TOF...
Definition: DetectionPositionPair.h:40