1515/*
1616 Copyright (C) 2017-2019, University of Leeds
1717 Copyright (C) 2018 University of Hull
18- Copyright (C) 2018-2020 , University College London
18+ Copyright (C) 2018-2021, 2024 , University College London
1919 This file is part of STIR.
2020
2121 SPDX-License-Identifier: Apache-2.0
2525
2626#include " stir/IO/GEHDF5Wrapper.h"
2727#include " stir/IndexRange3D.h"
28+ #include " stir/Radionuclide.h"
29+ #include " stir/RadionuclideDB.h"
2830#include " stir/is_null_ptr.h"
2931#include " stir/info.h"
3032#include " stir/error.h"
@@ -53,6 +55,15 @@ GEHDF5Wrapper::read_dataset_int32(const std::string& dataset_name)
5355 return tmp;
5456}
5557
58+
59+ static float read_float (const H5::H5File& file, const std::string& dataset)
60+ {
61+ float tmp = 0 .F ;
62+ H5::DataSet ds = file.openDataSet (dataset.c_str ());
63+ ds.read (&tmp, H5::PredType::NATIVE_FLOAT);
64+ return tmp;
65+ }
66+
5667bool GEHDF5Wrapper::check_GE_signature (const std::string& filename)
5768{
5869 try
@@ -89,34 +100,10 @@ bool GEHDF5Wrapper::check_GE_signature(H5::H5File& file)
89100 return false ;
90101}
91102
92- // // Checks if input file is listfile.
93- // AB: todo do we want this func? helps test from filename
94- /*
95- bool
96- GEHDF5Wrapper::is_list_file(const std::string& filename)
97- {
98-
99- H5::H5File file;
100-
101- if(!file.isHdf5(filename))
102- error("File is not HDF5. Aborting");
103-
104- file.openFile( filename, H5F_ACC_RDONLY );
105- // All RDF files shoudl have this DataSet
106- H5::DataSet dataset = file.openDataSet("/HeaderData/RDFConfiguration/isListFile");
107- unsigned int is_list;
108- dataset.read(&is_list, H5::PredType::STD_U32LE);
109- return is_list;
110-
111- }
112- */
113-
114-
115- // AB todo: only valid for RDF9 (until they tell us otherwise)
116103bool
117104GEHDF5Wrapper::is_list_file () const
118105{
119- // have we already checked this?
106+ // have we already checked this? (note: initially set to false in check_file())
120107 if (is_list)
121108 return true ;
122109
@@ -342,6 +329,13 @@ shared_ptr<Scanner> GEHDF5Wrapper::get_scanner_from_HDF5()
342329 str_radial_crystals_per_block.read (&num_transaxial_crystals_per_block, H5::PredType::NATIVE_UINT32);
343330 str_axial_crystals_per_block.read (&num_axial_crystals_per_block, H5::PredType::NATIVE_UINT32);
344331
332+ // TOF related
333+ const float timingResolutionInPico = read_float (file, " /HeaderData/SystemGeometry/timingResolutionInPico" );
334+ const int posCoincidenceWindow = read_dataset_int32 (" /HeaderData/AcqParameters/EDCATParameters/posCoincidenceWindow" );
335+ const int negCoincidenceWindow = read_dataset_int32 (" /HeaderData/AcqParameters/EDCATParameters/negCoincidenceWindow" );
336+ const float coincTimingPrecisionInPico = read_float (file, " /HeaderData/AcqParameters/EDCATParameters/coincTimingPrecision" ) * 1000 ; // in nanoSecs in file
337+ const int num_tof_bins = posCoincidenceWindow + negCoincidenceWindow + 1 ;
338+
345339 int num_rings = num_axial_blocks_per_bucket*num_axial_crystals_per_block*axial_modules_per_system;
346340 int num_detectors_per_ring = num_transaxial_blocks_per_bucket*num_transaxial_crystals_per_block*radial_modules_per_system;
347341 float ring_spacing = detector_axial_size/num_rings;
@@ -375,6 +369,31 @@ shared_ptr<Scanner> GEHDF5Wrapper::get_scanner_from_HDF5()
375369 scanner_sptr->set_inner_ring_radius ((effective_ring_diameter/2 ) - def_DOI);
376370 scanner_sptr->set_average_depth_of_interaction (def_DOI);
377371 }
372+ if (timingResolutionInPico > 0 // Signa files seem to have zero in this field
373+ && (fabs (scanner_sptr->get_timing_resolution () - timingResolutionInPico) > .1F ))
374+ {
375+ warning (" GEHDF5Wrapper: default STIR timing resolution is "
376+ + std::to_string (scanner_sptr->get_timing_resolution ())
377+ + " , while RDF says " + std::to_string (timingResolutionInPico)
378+ + " \n Will adjust scanner info to fit with the RDF file" );
379+ scanner_sptr->set_timing_resolution (timingResolutionInPico);
380+ }
381+ if (fabs (scanner_sptr->get_size_of_timing_pos () - coincTimingPrecisionInPico)> .1F )
382+ {
383+ warning (" GEHDF5Wrapper: default STIR size of (unmashed) TOF bins is "
384+ + std::to_string (scanner_sptr->get_size_of_timing_pos ())
385+ + " , while RDF says " + std::to_string (coincTimingPrecisionInPico)
386+ + " \n Will adjust scanner info to fit with the RDF file" );
387+ scanner_sptr->set_size_of_timing_poss (coincTimingPrecisionInPico);
388+ }
389+ if (std::abs (scanner_sptr->get_max_num_timing_poss () - num_tof_bins) > 0 )
390+ {
391+ warning (" GEHDF5Wrapper: default STIR number of (unmashed) TOF bins is "
392+ + std::to_string (scanner_sptr->get_max_num_timing_poss ())
393+ + " , while RDF says " + std::to_string (num_tof_bins)
394+ + " \n Will adjust scanner info to fit with the RDF file" );
395+ scanner_sptr->set_max_num_timing_poss (num_tof_bins);
396+ }
378397 if (scanner_sptr->get_default_bin_size () <= 0 .F )
379398 {
380399 warning (" GEHDF5Wrapper: default bin-size is not set. This will create trouble for FBP etc" );
@@ -401,7 +420,8 @@ void GEHDF5Wrapper::initialise_proj_data_info_from_HDF5()
401420 /* max_delta*/ scanner_sptr->get_num_rings ()-1 ,
402421 /* num_views */ scanner_sptr->get_num_detectors_per_ring ()/2 ,
403422 /* num_tangential_poss */ scanner_sptr->get_max_num_non_arccorrected_bins (),
404- /* arc_corrected */ false
423+ /* arc_corrected */ false ,
424+ this ->is_list_file () ? 1 : 0 // TODO change when reading sinos as TOF
405425 );
406426 this ->proj_data_info_sptr ->
407427 set_bed_position_horizontal (this ->read_dataset_int32 (" /HeaderData/AcqParameters/LandmarkParameters/absTableLongitude" )/10 .F ); /* units in RDF are 0.1 mm */
@@ -475,6 +495,22 @@ void GEHDF5Wrapper::initialise_exam_info()
475495
476496 TimeFrameDefinitions tm (tf);
477497 exam_info_sptr->set_time_frame_definitions (tm);
498+
499+ // radionuclide
500+ {
501+ auto rn_name_ds = file.openDataSet (" /HeaderData/ExamData/radionuclideName" );
502+ H5::StrType str_type (rn_name_ds);
503+ std::string rn_name;
504+ rn_name_ds.read (rn_name, str_type);
505+ RadionuclideDB radionuclide_db;
506+ Radionuclide radionuclide = radionuclide_db.get_radionuclide (exam_info_sptr->imaging_modality ,rn_name);
507+
508+ const float positron_fraction = read_float (file, " /HeaderData/ExamData/positronFraction" );
509+ const float half_life = read_float (file, " /HeaderData/ExamData/halfLife" );
510+ if (radionuclide.get_half_life (false ) < 0 )
511+ radionuclide = Radionuclide (rn_name, 511 .F , positron_fraction, half_life, exam_info_sptr->imaging_modality );
512+ exam_info_sptr->set_radionuclide (radionuclide);
513+ }
478514}
479515
480516Succeeded GEHDF5Wrapper::initialise_listmode_data ()
@@ -700,33 +736,6 @@ Succeeded GEHDF5Wrapper::initialise_efficiency_factors()
700736 return Succeeded::yes;
701737}
702738
703- float GEHDF5Wrapper::get_coincidence_time_window () const
704- {
705- if (!is_list_file () && !is_sino_file ())
706- error (" The file provided is not list or sino data. Aborting" );
707-
708- H5::DataSet ds_coincTimingPrecision = file.openDataSet (" /HeaderData/AcqParameters/EDCATParameters/coincTimingPrecision" );
709- H5::DataSet ds_posCoincidenceWindow = file.openDataSet (" /HeaderData/AcqParameters/EDCATParameters/posCoincidenceWindow" );
710- float coincTimingPrecision = 0 ;
711- int posCoincidenceWindow = 0 ;
712- ds_coincTimingPrecision.read (&coincTimingPrecision,H5::PredType::NATIVE_FLOAT);
713- ds_posCoincidenceWindow.read (&posCoincidenceWindow,H5::PredType::NATIVE_INT32);
714-
715- return (2 *posCoincidenceWindow+1 ) *coincTimingPrecision*1e-9 ;
716- }
717-
718- float GEHDF5Wrapper::get_halflife () const
719- {
720- if (!is_list_file () && !is_sino_file ())
721- error (" The file provided is not list or sino data. Aborting" );
722-
723- H5::DataSet ds_halflife = file.openDataSet (" /HeaderData/ExamData/halfLife" );
724- float halflife = 0 ;
725- ds_halflife.read (&halflife,H5::PredType::NATIVE_FLOAT);
726- return halflife;
727- }
728-
729-
730739// Developed for listmode access
731740Succeeded GEHDF5Wrapper::read_list_data ( char * output,
732741 const std::streampos offset, const hsize_t size) const
0 commit comments