-
Notifications
You must be signed in to change notification settings - Fork 95
/
Copy pathstir_ecat_common.cxx
217 lines (194 loc) · 5.71 KB
/
stir_ecat_common.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//
//
/*!
\file
\ingroup ECAT
\brief Implementation of routines which convert ECAT6, ECAT7 and ECAT8 things into our building blocks and vice versa.
\author Kris Thielemans
\author PARAPET project
*/
/*
Copyright (C) 2000 PARAPET partners
Copyright (C) 2000- 2009, Hammersmith Imanet Ltd
Copyright (C) 2020, 2023 University College London
This file is part of STIR.
SPDX-License-Identifier: Apache-2.0 AND License-ref-PARAPET-license
See STIR/LICENSE.txt for details
*/
#include "stir/ByteOrder.h"
#include "stir/NumericType.h"
#include "stir/Scanner.h"
#include "stir/ProjDataInfo.h"
#include "stir/IO/stir_ecat_common.h"
#include "stir/warning.h"
#include "stir/error.h"
START_NAMESPACE_STIR
START_NAMESPACE_ECAT
void
find_type_from_ECAT_data_type(NumericType& type, ByteOrder& byte_order, const short data_type)
{
switch (data_type)
{
case ECAT_Byte_data_type:
type = NumericType("signed integer", 1);
byte_order = ByteOrder::little_endian;
return;
case ECAT_I2_little_endian_data_type:
type = NumericType("signed integer", 2);
byte_order = ByteOrder::little_endian;
return;
case ECAT_I2_big_endian_data_type:
type = NumericType("signed integer", 2);
byte_order = ByteOrder::big_endian;
return;
case ECAT_R4_VAX_data_type:
type = NumericType("float", 4);
byte_order = ByteOrder::little_endian;
return;
case ECAT_R4_IEEE_big_endian_data_type:
type = NumericType("float", 4);
byte_order = ByteOrder::big_endian;
return;
case ECAT_I4_little_endian_data_type:
type = NumericType("signed integer", 4);
byte_order = ByteOrder::little_endian;
return;
case ECAT_I4_big_endian_data_type:
type = NumericType("signed integer", 4);
byte_order = ByteOrder::big_endian;
return;
default:
error("find_type_from_ecat_data_type: unsupported data_type: %d", data_type);
// just to avoid compiler warnings
return;
}
}
short
find_ECAT_data_type(const NumericType& type, const ByteOrder& byte_order)
{
if (!type.signed_type())
warning("find_ecat_data_type: ecat data support only signed types. Using the signed equivalent\n");
if (type.integer_type())
{
switch (type.size_in_bytes())
{
case 1:
return ECAT_Byte_data_type;
case 2:
return byte_order == ByteOrder::big_endian ? ECAT_I2_big_endian_data_type : ECAT_I2_little_endian_data_type;
case 4:
return byte_order == ByteOrder::big_endian ? ECAT_I4_big_endian_data_type : ECAT_I4_little_endian_data_type;
default: {
// write error message below
}
}
}
else
{
switch (type.size_in_bytes())
{
case 4:
return byte_order == ByteOrder::big_endian ? ECAT_R4_IEEE_big_endian_data_type : ECAT_R4_VAX_data_type;
default: {
// write error message below
}
}
}
std::string number_format;
std::size_t size_in_bytes;
type.get_Interfile_info(number_format, size_in_bytes);
error("find_ecat_data_type: ecat does not support data type '%s' of %d bytes.\n", number_format.c_str(), size_in_bytes);
// just to satisfy compilers
return short(0);
}
short
find_ECAT_system_type(const Scanner& scanner)
{
switch (scanner.get_type())
{
case Scanner::E921:
return 921;
case Scanner::E925:
return 925;
case Scanner::E931:
return 931;
case Scanner::E951:
return 951;
case Scanner::E953:
return 953;
case Scanner::E961:
return 961;
case Scanner::E962:
return 962;
case Scanner::E966:
return 966;
case Scanner::RPT:
return 128;
case Scanner::RATPET:
return 42;
default:
warning("\nfind_ecat_system_type: scanner \"%s\" currently unsupported. Returning 0.\n", scanner.get_name().c_str());
return 0;
}
}
Scanner*
find_scanner_from_ECAT_system_type(const short system_type)
{
switch (system_type)
{
case 128:
return new Scanner(Scanner::RPT);
case 921:
return new Scanner(Scanner::E921);
case 925:
return new Scanner(Scanner::E925);
case 931:
case 12:
return new Scanner(Scanner::E931);
case 951:
return new Scanner(Scanner::E951);
case 953:
return new Scanner(Scanner::E953);
case 961:
return new Scanner(Scanner::E961);
case 962:
return new Scanner(Scanner::E962);
case 966:
return new Scanner(Scanner::E966);
case 42:
return new Scanner(Scanner::RATPET);
default:
return new Scanner(Scanner::Unknown_scanner);
}
}
std::vector<int>
find_segment_sequence(const ProjDataInfo& pdi)
{
const int max_segment_num = pdi.get_max_segment_num();
std::vector<int> segment_sequence(2 * max_segment_num + 1);
// KT 25/10/2000 swapped segment order
// ECAT 7 always stores segments as 0, -1, +1, ...
segment_sequence[0] = 0;
for (int segment_num = 1; segment_num <= max_segment_num; ++segment_num)
{
segment_sequence[2 * segment_num - 1] = -segment_num;
segment_sequence[2 * segment_num] = segment_num;
}
return segment_sequence;
}
std::vector<int>
find_timing_poss_sequence(const ProjDataInfo& pdi)
{
const int max_timing_pos_num = pdi.get_num_tof_poss() / 2;
std::vector<int> timing_pos_sequence(2 * max_timing_pos_num + 1);
// Siemens always stores timing_poss as 0, -1, +1, ...
timing_pos_sequence[0] = 0;
for (int timing_pos_num = 1; timing_pos_num <= max_timing_pos_num; ++timing_pos_num)
{
timing_pos_sequence[2 * timing_pos_num - 1] = timing_pos_num;
timing_pos_sequence[2 * timing_pos_num] = -timing_pos_num;
}
return timing_pos_sequence;
}
END_NAMESPACE_ECAT
END_NAMESPACE_STIR