Skip to content

Commit e168b07

Browse files
authoredSep 4, 2024··
Merge pull request #1503 from KrisThielemans/GERDF9_DMI
GE Discovery MI updates
2 parents 5d12267 + 66c60da commit e168b07

File tree

4 files changed

+81
-35
lines changed

4 files changed

+81
-35
lines changed
 

‎documentation/release_6.3.htm

+5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ <h3>New functionality</h3>
2525
is disabled for backwards compatibility.<br>
2626
<a href=https://github.com/UCL/STIR/pull/1291>PR #1291</a>
2727
</li>
28+
<li>
29+
Data from GE Discovery MI systems in RDF9 should now be readable. TOF information on these scanners has also been added.
30+
However, projection data is currently still always returned as non-TOF (but list-mode data is read as TOF).<br>
31+
<a href=https://github.com/UCL/STIR/pull/1503>PR #1503</a>
32+
</li>
2833
</ul>
2934

3035

‎src/IO/GEHDF5Wrapper.cxx

+31-26
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ read_float(const H5::H5File& file, const std::string& dataset)
6565
return tmp;
6666
}
6767

68+
static std::string
69+
read_string(const H5::H5File& file, const std::string& dataset)
70+
{
71+
H5::DataSet ds = file.openDataSet(dataset.c_str());
72+
H5::StrType datatype = ds.getStrType();
73+
74+
std::string value;
75+
ds.read(value, datatype);
76+
return value;
77+
}
78+
6879
bool
6980
GEHDF5Wrapper::check_GE_signature(const std::string& filename)
7081
{
@@ -90,13 +101,7 @@ GEHDF5Wrapper::check_GE_signature(H5::H5File& file)
90101
if (file.getId() == -1)
91102
error("File is not open. Aborting");
92103

93-
H5::StrType vlst(
94-
0,
95-
37); // 37 here is the length of the string (PW got it from the text file generated by list2txt with the LIST000_decomp.BLF
96-
std::string read_str_manufacturer;
97-
98-
H5::DataSet dataset2 = file.openDataSet("/HeaderData/ExamData/manufacturer");
99-
dataset2.read(read_str_manufacturer, vlst);
104+
std::string read_str_manufacturer = read_string(file, "/HeaderData/ExamData/manufacturer");
100105

101106
if (read_str_manufacturer == "GE MEDICAL SYSTEMS")
102107
{
@@ -277,14 +282,7 @@ GEHDF5Wrapper::open(const std::string& filename)
277282
shared_ptr<Scanner>
278283
GEHDF5Wrapper::get_scanner_from_HDF5()
279284
{
280-
std::string read_str_scanner;
281-
H5::StrType vlst(
282-
0,
283-
37); // 37 here is the length of the string (PW got it from the text file generated by list2txt with the LIST000_decomp.BLF
284-
285-
H5::DataSet dataset = file.openDataSet("/HeaderData/ExamData/scannerDesc");
286-
dataset.read(read_str_scanner, vlst);
287-
285+
std::string read_str_scanner = read_string(this->file, "/HeaderData/ExamData/scannerDesc");
288286
float effective_ring_diameter;
289287
int num_transaxial_blocks_per_bucket = 0;
290288
int num_axial_blocks_per_bucket = 0;
@@ -425,6 +423,11 @@ GEHDF5Wrapper::initialise_proj_data_info_from_HDF5()
425423
{
426424
shared_ptr<Scanner> scanner_sptr = get_scanner_from_HDF5();
427425

426+
// TODO get TOF mashing when reading sinos as TOF
427+
const auto num_tof_bins = read_dataset_uint32("/HeaderData/Sorter/numTOF_bins");
428+
if (num_tof_bins > 1)
429+
warning("GE RDF data currently still read as non-TOF");
430+
428431
this->proj_data_info_sptr
429432
= ProjDataInfo::construct_proj_data_info(scanner_sptr,
430433
/*span*/ 2,
@@ -654,11 +657,20 @@ GEHDF5Wrapper::initialise_proj_data(const unsigned int view_num)
654657
if (view_num == 0 || view_num > static_cast<unsigned>(this->get_scanner_sptr()->get_num_detectors_per_ring() / 2))
655658
error("internal error in GE HDF5 code: view number " + std::to_string(view_num) + " is incorrect");
656659

660+
const auto num_tof_bins = read_dataset_uint32("/HeaderData/Sorter/numTOF_bins");
661+
657662
if (rdf_ver == 9)
658663
{
659-
m_address = "/SegmentData/Segment2/3D_TOF_Sinogram/view" + std::to_string(view_num);
660-
661-
m_dataset_sptr.reset(new H5::DataSet(file.openDataSet(m_address)));
664+
if (num_tof_bins > 1)
665+
{
666+
m_address = "/SegmentData/Segment2/3D_TOF_Sinogram/view" + std::to_string(view_num);
667+
m_dataset_sptr.reset(new H5::DataSet(file.openDataSet(m_address)));
668+
}
669+
else
670+
{
671+
m_address = "/SegmentData/Segment2/3D_Sinogram/view" + std::to_string(view_num);
672+
m_dataset_sptr.reset(new H5::DataSet(file.openDataSet(m_address)));
673+
}
662674
m_dataspace = m_dataset_sptr->getSpace();
663675
// Create an array to host the size of the dimensions
664676
const int rank = m_dataspace.getSimpleExtentNdims();
@@ -673,13 +685,7 @@ GEHDF5Wrapper::initialise_proj_data(const unsigned int view_num)
673685
// AB for signa, these where [1981,27,357] and [45,448,357]
674686
m_NX_SUB = dims[0]; // hyperslab dimensions
675687
m_NY_SUB = dims[1];
676-
m_NZ_SUB = dims[2];
677-
#if 0
678-
// AB todo: ??? why are these different?
679-
m_NX = 45; // output buffer dimensions
680-
m_NY = 448;
681-
m_NZ = 357;
682-
#endif
688+
m_NZ_SUB = rank > 2 ? dims[2] : 1;
683689
}
684690
else
685691
return Succeeded::no;
@@ -831,7 +837,6 @@ GEHDF5Wrapper::read_sinogram(Array<3, unsigned char>& output,
831837
}
832838
}
833839
}
834-
output.release_data_ptr();
835840
}
836841

837842
return Succeeded::yes;

‎src/buildblock/Scanner.cxx

+44-9
Original file line numberDiff line numberDiff line change
@@ -864,9 +864,10 @@ Scanner::Scanner(Type scanner_type)
864864
1,
865865
0.0944F, // energy resolution from Hsu et al. 2017
866866
511.F,
867-
(short int)(0),
868-
(float)(0), // TODO
869-
(float)(0));
867+
(short int)(2 * 188 + 1), // from RDF file
868+
(float)(13), // from RDF file
869+
(float)(375.4) // Hsu et al.
870+
);
870871
break;
871872

872873
case DiscoveryMI4ring: // This is the 4-ring DMI
@@ -895,9 +896,10 @@ Scanner::Scanner(Type scanner_type)
895896
1,
896897
0.0944F, // energy resolution from Hsu et al. 2017
897898
511.F,
898-
(short int)(0),
899-
(float)(0), // TODO
900-
(float)(0));
899+
(short int)(2 * 188 + 1), // from RDF file
900+
(float)(13), // from RDF file
901+
(float)(375.4) // Hsu et al.
902+
);
901903
break;
902904

903905
case DiscoveryMI5ring: // This is the 5-ring DMI
@@ -926,9 +928,42 @@ Scanner::Scanner(Type scanner_type)
926928
1,
927929
0.0944F, // energy resolution from Hsu et al. 2017
928930
511.F,
929-
(short int)(0),
930-
(float)(0), // TODO
931-
(float)(0));
931+
(short int)(2 * 188 + 1), // from RDF file
932+
(float)(13), // from RDF file
933+
(float)(375.4) // Hsu et al.
934+
);
935+
break;
936+
937+
case DiscoveryMI6ring: // This is the 6-ring DMI
938+
// as above, but one extra block
939+
// Hsu et al. 2017 JNM
940+
// crystal size 3.95 x 5.3 x 25
941+
set_params(DiscoveryMI6ring,
942+
string_list("GE Discovery MI 6 rings",
943+
"Discovery MI6",
944+
"Discovery MI"), // needs to include last value as used by GE in RDF files
945+
54,
946+
415,
947+
401, // TODO should compute num_arccorrected_bins from effective_FOV/default_bin_size
948+
2 * 272,
949+
380.5F - 9.4F, // TODO inner_ring_radius and DOI, currently set such that effective ring-radius is correct
950+
9.4F, // TODO DOI
951+
5.52296F, // ring-spacing
952+
2.206F, // TODO currently using the central bin size default bin size. GE might be using something else
953+
static_cast<float>(-4.399 * _PI / 180), // TODO check sign
954+
6,
955+
4,
956+
9,
957+
4,
958+
1,
959+
1,
960+
1,
961+
0.0944F, // energy resolution from Hsu et al. 2017
962+
511.F,
963+
(short int)(2 * 188 + 1), // from RDF file
964+
(float)(13), // from RDF file
965+
(float)(375.4) // Hsu et al.
966+
);
932967
break;
933968
case HZLR:
934969

‎src/include/stir/Scanner.h

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ class Scanner
165165
DiscoveryMI3ring,
166166
DiscoveryMI4ring,
167167
DiscoveryMI5ring,
168+
DiscoveryMI6ring,
168169
HZLR,
169170
RATPET,
170171
PANDA,

0 commit comments

Comments
 (0)
Please sign in to comment.