STIR 6.4.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*/
17
18#ifndef __stir_listmode_CListRecordGEHDF5_H__
19#define __stir_listmode_CListRecordGEHDF5_H__
20
23#include "stir/Succeeded.h"
24#include "stir/ByteOrder.h"
26#include <boost/static_assert.hpp>
27#include <boost/cstdint.hpp>
28#include "stir/error.h"
29#include <iostream>
30
31START_NAMESPACE_STIR
32
33namespace GE
34{
35namespace RDF_HDF5
36{
37
38namespace detail
39{
40/***********************************
41 * Supported Event Length Modes
42 ***********************************/
43enum 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 ***********************************/
54enum EventType
55{
56 EXTENDED_EVT = 0x0,
57 COINC_EVT = 0x1
58};
59
60/***********************************
61 * Supported Extended Event Types
62 ***********************************/
63enum 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{
81public:
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{
100public:
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{
138public:
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
152private:
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{
197 typedef detail::CListEventDataGEHDF5 DataType;
198 typedef detail::ListTimeDataGEHDF5 TimeType;
199 // typedef CListGatingDataGEHDF5 GatingType;
200
201public:
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
252dynamic_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
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
344private:
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
362END_NAMESPACE_STIR
363
364#endif
Definition of STIRIsNativeByteOrderBigEndian and STIRIsNativeByteOrderLittleEndian preprocessor symbo...
This file declares the stir::ByteOrder class.
Declarations of class stir::CListEventCylindricalScannerWithDiscreteDetectors.
Declarations of classes stir::CListRecord, and stir::CListEvent which are used for list mode data.
Declaration of class stir::Succeeded.
Class for storing and using a coincidence event from a list mode file for a cylindrical scanner.
Definition CListEventCylindricalScannerWithDiscreteDetectors.h:33
Class for records in a PET list mode file.
Definition CListRecord.h:67
A class for storing 2 coordinates-sets of a detection, together with a timing-position index (for TOF...
Definition DetectionPositionPair.h:41
CListRecordGEHDF5(const shared_ptr< const ProjDataInfo > &proj_data_info_sptr, const unsigned long first_time_stamp)
constructor
Definition CListRecordGEHDF5.h:208
void set_detection_position(const DetectionPositionPair<> &) override
This routine sets in a coincidence event from detector "indices".
Definition CListRecordGEHDF5.h:298
void get_detection_position(DetectionPositionPair<> &det_pos) const override
This routine returns the corresponding detector pair.
Definition CListRecordGEHDF5.h:284
Succeeded set_prompt(const bool prompt=true) override
Changes the event from prompt to delayed or vice versa.
Definition CListRecordGEHDF5.h:279
Class for finding out what the event/size-type is in a GE RDF9 listmode file.
Definition CListRecordGEHDF5.h:80
Class for storing and using a coincidence event from a GE RDF9 listmode file.
Definition CListRecordGEHDF5.h:99
A class for storing and using a timing 'event' from a GE RDF9 listmode file.
Definition CListRecordGEHDF5.h:137
A class for storing and using a timing record from a listmode file.
Definition ListTime.h:47
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition Succeeded.h:44
Declaration of stir::error()
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition error.cxx:42