Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabling PET reconstruction from list mode data #1103

Merged
merged 52 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
51fed6c
implemented basic-functionality listmode data class in C++ and Python
evgueni-ovtchinnikov May 10, 2022
c4be9dd
added objective function type for lismode reconstruction
evgueni-ovtchinnikov May 11, 2022
0063f78
introduced abstract base class PETScanData for all raw data objects
evgueni-ovtchinnikov May 12, 2022
b143cfc
[ci skip] interfaced PETScanData into Python
evgueni-ovtchinnikov May 12, 2022
b209f33
Minimal backbone for LM recons
NikEfth May 17, 2022
31ef16c
New test for LM data (test6)
NikEfth May 19, 2022
b38b35b
fix
NikEfth May 19, 2022
036c7c2
Merge branch 'HEAD' into lm-recon
NikEfth May 19, 2022
65f9fe0
Working test6
NikEfth May 19, 2022
97f76cd
Generalize the paths in test6
NikEfth May 19, 2022
26d36fc
Minor renaming
NikEfth May 19, 2022
db4479d
simplify link library to Boost
paskino Feb 1, 2022
debcd5b
Merge branch 'master' into HEAD
paskino May 21, 2022
b59524c
remove dangling endif
paskino May 21, 2022
f65e1de
Merge pull request #1 from paskino/edo_lm-recon
NikEfth May 21, 2022
e4632db
[ci skip] moved data folder TBPET out of SIRF repo
evgueni-ovtchinnikov May 23, 2022
ea18b8d
removed unused stuff from cstir_test6.cpp
evgueni-ovtchinnikov May 23, 2022
7a33289
restored backward compatibility of run_test6.cpp
evgueni-ovtchinnikov May 23, 2022
7e0e299
implemented C interface for list mode reconstruction objective function
evgueni-ovtchinnikov May 23, 2022
47eb909
started interfacing reconstruction from listmode into Python
evgueni-ovtchinnikov May 23, 2022
08f0425
implemented minimal Python interface for reconstruction from listmode…
evgueni-ovtchinnikov May 24, 2022
4dd2de7
resolved some issues raised by Kris
evgueni-ovtchinnikov May 25, 2022
50ef6d4
small amendments in STIR.py
evgueni-ovtchinnikov May 25, 2022
eb2ae63
removed cstir_test6 from ctest tests
evgueni-ovtchinnikov May 25, 2022
27e5d15
minor fixes to listmode classes
KrisThielemans May 26, 2022
ef4c9eb
removed some unneeded data_sptr() methods
evgueni-ovtchinnikov May 26, 2022
608f39a
replaced cache_path quick fix with a more proper handling
evgueni-ovtchinnikov May 26, 2022
8b96919
Merge remote-tracking branch 'origin/master' into lm-recon
KrisThielemans May 27, 2022
05083e8
[ci skip] corrected copyrights in cSTIR/tests/test6.cpp
evgueni-ovtchinnikov May 30, 2022
ed30e6b
make listmode recon compatible with STIR 5.1.0
KrisThielemans Jan 15, 2023
4fa6220
Merge branch 'master' into lm-recon
KrisThielemans Mar 2, 2023
cd0c423
rename PETScanData to ScanData(Python) or STIRScanData (C++)
KrisThielemans Mar 2, 2023
ab26634
Merge remote-tracking branch 'origin/master' into lm-recon
KrisThielemans Jan 15, 2024
dd4e33e
No longer derive ListmodeData from DataContainer
KrisThielemans Jan 17, 2024
a66667b
update listmode test (WIP)
KrisThielemans Jan 17, 2024
5698103
Derive DataContainer from ContainerBase
KrisThielemans Jan 18, 2024
61e692d
speed-up listmode recon test and use SIRF example data
KrisThielemans Jan 18, 2024
27eec3d
attended to Codacy issues
evgueni-ovtchinnikov Jan 19, 2024
81f1389
attended to further Codacy issues
evgueni-ovtchinnikov Jan 19, 2024
6ed55d8
fix ListmodeData hierarchy and add get_info to STIR containers
KrisThielemans Jan 21, 2024
b98c6d0
renamed ListmodeData to STIRListmodeData for consistency
KrisThielemans Jan 21, 2024
713ad10
add set_acquisition_model to listmode obj-fun
KrisThielemans Jan 21, 2024
835b499
minor doc corrections
KrisThielemans Mar 28, 2024
9ce3b51
listmode recon improvements
KrisThielemans Mar 28, 2024
f009fbf
Merge remote-tracking branch 'origin/master' into lm-recon
KrisThielemans Mar 28, 2024
bb42564
minor fix in demo
KrisThielemans Mar 28, 2024
56fbace
fix storing filename of listmode file
KrisThielemans Mar 28, 2024
b384409
add SIRF_DATA_PATH to STIR C++ test
KrisThielemans Apr 3, 2024
95b3a24
fixed bugs and issues found in lmrecontest2
evgueni-ovtchinnikov Apr 4, 2024
bf361ff
[ci skip] got rid of gpu stuff in reconstruct_from_listmode.py
evgueni-ovtchinnikov Apr 5, 2024
752c077
[ci skip] removed osem_lm_reconstruction.py, superseded by listmode_r…
evgueni-ovtchinnikov Apr 5, 2024
e4ac001
[ci skip] updated CHANGES.md
evgueni-ovtchinnikov Apr 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions examples/Python/PET/osem_lm_reconstruction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'''OSEM reconstruction from listmode demo.


Usage:
osem_lm_reconstruction [--help | options] <data_path>

Options:
-e <engn>, --engine=<engn> reconstruction engine [default: STIR]
'''


__version__ = '0.1.0'
from docopt import docopt
args = docopt(__doc__, version=__version__)


# import engine module
exec('from sirf.' + args['--engine'] + ' import *')


data_path = args['<data_path>'] + '/'


def main():

# direct all engine's information and warnings printing to files
msg_red = MessageRedirector('info.txt', 'warn.txt')

cache_path = data_path;
sens_filename = cache_path + "sens_0.hv";
#print(sens_filename)
tmpl_projdata_filename = data_path + "tmpl_scanner.hs";
#print(tmpl_projdata_filename)

acq_tmpl = AcquisitionData(tmpl_projdata_filename)
#print(acq_tmpl.dimensions())

img_data = ImageData(sens_filename)
#print(img_data.dimensions())

#obj_fun = PoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBin()
obj_fun = make_Poisson_loglikelihood( \
likelihood_type='LinearModelForMeanAndListModeDataWithProjMatrixByBin')
obj_fun.set_cache_path(cache_path, True)
obj_fun.set_skip_lm_input_file(True);
obj_fun.set_skip_balanced_subsets(True);
obj_fun.set_acquisition_data(acq_tmpl);
obj_fun.set_skip_balanced_subsets(True);
obj_fun.set_max_ring_difference(60);
obj_fun.set_cache_max_size(1500000000);

#print(obj_fun.get_cache_path())
#print(obj_fun.get_cache_max_size())
#print(obj_fun.get_subsensitivity_filenames())

num_subiterations = 11
recon = OSMAPOSLReconstructor()
recon.set_objective_function(obj_fun)
recon.set_num_subiterations(num_subiterations)
recon.set_output_filename_prefix(data_path + "/my_output");
recon.set_save_interval(1);

print('setting up, please wait...')
recon.set_up(img_data)

print('reconstructing, please wait...')
recon.reconstruct(img_data)

img_out = recon.get_output()
print(img_out.dimensions())

# if anything goes wrong, an exception will be thrown
# (cf. Error Handling section in the spec)
try:
main()
print('\n=== done with %s' % __file__)

except error as err:
# display error information
print('%s' % err.value)
12 changes: 1 addition & 11 deletions src/Registration/cReg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,7 @@ if (NIFTYREG_BUILT_WITH_OPENCL)
endif()

# Add boost library dependencies
if((CMAKE_VERSION VERSION_LESS 3.5.0) OR (NOT _Boost_IMPORTED_TARGETS))
# This is harder than it should be on older CMake versions to be able to cope with
# spaces in filenames.
foreach(C SYSTEM FILESYSTEM)
target_link_libraries(Reg PUBLIC optimized "${Boost_${C}_LIBRARY_RELEASE}")
target_link_libraries(Reg PUBLIC debug "${Boost_${C}_LIBRARY_DEBUG}")
endforeach()
else()
# Nice and simple for recent CMake (which knows about your Boost version)
target_link_libraries(Reg PUBLIC Boost::system Boost::filesystem)
endif()
target_link_libraries(Reg PUBLIC Boost::system Boost::filesystem)

# Link Matlab for SPM
IF(SPM_FOUND)
Expand Down
12 changes: 1 addition & 11 deletions src/xGadgetron/cGadgetron/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,7 @@ target_include_directories(cgadgetron PUBLIC "${ISMRMRD_INCLUDE_DIR}")

target_link_libraries(cgadgetron PUBLIC iutilities csirf)
# Add boost library dependencies
if((CMAKE_VERSION VERSION_LESS 3.5.0) OR (NOT _Boost_IMPORTED_TARGETS))
# This is harder than it should be on older CMake versions to be able to cope with
# spaces in filenames.
foreach(C SYSTEM FILESYSTEM THREAD DATE_TIME CHRONO)
target_link_libraries(cgadgetron PUBLIC optimized "${Boost_${C}_LIBRARY_RELEASE}")
target_link_libraries(cgadgetron PUBLIC debug "${Boost_${C}_LIBRARY_DEBUG}")
endforeach()
else()
# Nice and simple for recent CMake (which knows about your Boost version)
target_link_libraries(cgadgetron PUBLIC Boost::system Boost::filesystem Boost::thread Boost::date_time Boost::chrono)
endif()
target_link_libraries(cgadgetron PUBLIC Boost::system Boost::filesystem Boost::thread Boost::date_time Boost::chrono)

target_link_libraries(cgadgetron PUBLIC ISMRMRD::ISMRMRD)
target_link_libraries(cgadgetron PUBLIC "${FFTW3_LIBRARIES}")
Expand Down
12 changes: 1 addition & 11 deletions src/xSTIR/cSTIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,7 @@ target_include_directories(cstir PUBLIC "${STIR_INCLUDE_DIRS}")
target_link_libraries(cstir csirf iutilities)
target_link_libraries(cstir "${STIR_LIBRARIES}")
# Add boost library dependencies
if((CMAKE_VERSION VERSION_LESS 3.5.0) OR (NOT _Boost_IMPORTED_TARGETS))
# This is harder than it should be on older CMake versions to be able to cope with
# spaces in filenames.
foreach(C SYSTEM FILESYSTEM THREAD DATE_TIME CHRONO)
target_link_libraries(cstir optimized "${Boost_${C}_LIBRARY_RELEASE}")
target_link_libraries(cstir debug "${Boost_${C}_LIBRARY_DEBUG}")
endforeach()
else()
# Nice and simple for recent CMake (which knows about your Boost version)
target_link_libraries(cstir Boost::system Boost::filesystem Boost::thread Boost::date_time Boost::chrono)
endif()
target_link_libraries(cstir Boost::system Boost::filesystem Boost::thread Boost::date_time Boost::chrono)

install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/"
COMPONENT Development
Expand Down
31 changes: 25 additions & 6 deletions src/xSTIR/cSTIR/cstir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ void* cSTIR_newObject(const char* name)
"PoissonLogLikelihoodWithLinearModelForMeanAndProjData"))
return NEW_OBJECT_HANDLE
(xSTIR_PoissonLogLikelihoodWithLinearModelForMeanAndProjData3DF);
if (sirf::iequals(name,
"PoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBin"))
return NEW_OBJECT_HANDLE
(xSTIR_PoissonLLhLinModMeanListDataProjMatBin3DF);
if (sirf::iequals(name, "AcqModUsingMatrix"))
return NEW_OBJECT_HANDLE(AcqModUsingMatrix3DF);
#ifdef STIR_WITH_NiftyPET_PROJECTOR
Expand Down Expand Up @@ -206,6 +210,11 @@ void* cSTIR_setParameter
return
cSTIR_setPoissonLogLikelihoodWithLinearModelForMeanAndProjDataParameter
(hs, name, hv);
else if (sirf::iequals(obj,
"PoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBin"))
return
cSTIR_setPoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBinParameter
(hs, name, hv);
else if (sirf::iequals(obj, "Reconstruction"))
return cSTIR_setReconstructionParameter(hs, name, hv);
else if (sirf::iequals(obj, "IterativeReconstruction"))
Expand Down Expand Up @@ -256,11 +265,16 @@ void* cSTIR_parameter(const void* ptr, const char* obj, const char* name)
return cSTIR_PLSPriorParameter(handle, name);
else if (sirf::iequals(obj, "GeneralisedObjectiveFunction"))
return cSTIR_generalisedObjectiveFunctionParameter(handle, name);
else if (sirf::iequals(obj,
"PoissonLogLikelihoodWithLinearModelForMeanAndProjData"))
return
cSTIR_PoissonLogLikelihoodWithLinearModelForMeanAndProjDataParameter
(handle, name);
else if (sirf::iequals(obj,
"PoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBin"))
return
cSTIR_PoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBinParameter
(handle, name);
else if (sirf::iequals(obj,
"PoissonLogLikelihoodWithLinearModelForMeanAndProjData"))
return
cSTIR_PoissonLogLikelihoodWithLinearModelForMeanAndProjDataParameter
(handle, name);
else if (sirf::iequals(obj, "IterativeReconstruction"))
return cSTIR_iterativeReconstructionParameter(handle, name);
else if (sirf::iequals(obj, "OSMAPOSL"))
Expand Down Expand Up @@ -307,8 +321,13 @@ void* cSTIR_objectFromFile(const char* name, const char* filename)
sptr.reset(new PETAcquisitionDataInMemory(filename));
return newObjectHandle(sptr);
}
if (sirf::iequals(name, "ListmodeData")) {
std::shared_ptr<ListmodeData>
sptr(new ListmodeData(filename));
return newObjectHandle(sptr);
}
if (sirf::iequals(name, "ListmodeToSinograms")) {
std::shared_ptr<ListmodeToSinograms>
std::shared_ptr<ListmodeToSinograms>
sptr(new ListmodeToSinograms(filename));
return newObjectHandle(sptr);
}
Expand Down
71 changes: 69 additions & 2 deletions src/xSTIR/cSTIR/cstir_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ using namespace sirf;
extern "C"
char* charDataFromHandle(const void* ptr);

extern "C"
void* charDataHandle(const char* ptr);

static void*
handle_error(const std::string& error_string, const char* file, int line)
{
Expand Down Expand Up @@ -660,6 +663,50 @@ sirf::cSTIR_setPoissonLogLikelihoodWithLinearModelForMeanAndProjDataParameter
return new DataHandle;
}

void*
sirf::cSTIR_setPoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBinParameter
(DataHandle* hp, const char* name, const DataHandle* hv)
{
xSTIR_PoissonLLhLinModMeanListDataProjMatBin3DF&
obj_fun = objectFromHandle
<xSTIR_PoissonLLhLinModMeanListDataProjMatBin3DF>
(hp);
std::string arg(name);
const char* prefix = arg.substr(0, 10).c_str();
evgueni-ovtchinnikov marked this conversation as resolved.
Show resolved Hide resolved
std::string cp("cache_path");
if (sirf::iequals(prefix, cp)) {
std::string s(charDataFromDataHandle(hv));
auto found = s.find(",");
evgueni-ovtchinnikov marked this conversation as resolved.
Show resolved Hide resolved
if (found == std::string::npos)
obj_fun.set_cache_path(s, false);
else
obj_fun.set_cache_path(s.substr(0, found), true);
}
else if (sirf::iequals(name, "acquisition_data")) {
SPTR_FROM_HANDLE(PETAcquisitionData, sptr_ad, hv);
obj_fun.set_acquisition_data(sptr_ad);
}
// else if (sirf::iequals(name, "acquisition_model")) {
// SPTR_FROM_HANDLE(PETAcquisitionModelUsingMatrix, sptr_pm, hv);
// obj_fun.set_acquisition_model(sptr_pm);
// }
else if (sirf::iequals(name, "skip_lm_input_file")) {
obj_fun.set_skip_lm_input_file(dataFromHandle<int>(hv));
}
else if (sirf::iequals(name, "skip_balanced_subsets")) {
obj_fun.set_skip_balanced_subsets(dataFromHandle<int>(hv));
}
else if (sirf::iequals(name, "max_ring_difference")) {
obj_fun.set_max_ring_difference(dataFromHandle<int>(hv));
}
else if (sirf::iequals(name, "cache_max_size")) {
obj_fun.set_cache_max_size(dataFromHandle<int>(hv));
}
else
return parameterNotFound(name, __FILE__, __LINE__);
return new DataHandle;
}

void*
sirf::cSTIR_PoissonLogLikelihoodWithLinearModelForMeanAndProjDataParameter
(const DataHandle* handle, const char* name)
Expand All @@ -675,6 +722,24 @@ sirf::cSTIR_PoissonLogLikelihoodWithLinearModelForMeanAndProjDataParameter
return parameterNotFound(name, __FILE__, __LINE__);
}

void*
sirf::cSTIR_PoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBinParameter
(DataHandle* handle, const char* name)
{
xSTIR_PoissonLLhLinModMeanListDataProjMatBin3DF&
obj_fun = objectFromHandle
<xSTIR_PoissonLLhLinModMeanListDataProjMatBin3DF>
(handle);
if (sirf::iequals(name, "cache_path")) {
return charDataHandle(obj_fun.get_cache_path().c_str());
}
if (sirf::iequals(name, "cache_max_size"))
return dataHandle<int>(obj_fun.get_cache_max_size());
if (sirf::iequals(name, "subsensitivity_filenames"))
return charDataHandle(obj_fun.get_subsensitivity_filenames().c_str());
return parameterNotFound(name, __FILE__, __LINE__);
}

void*
sirf::cSTIR_setReconstructionParameter
(DataHandle* hp, const char* name, const DataHandle* hv)
Expand All @@ -684,8 +749,10 @@ sirf::cSTIR_setReconstructionParameter
if (sirf::iequals(name, "output_filename_prefix"))
recon.set_output_filename_prefix(charDataFromDataHandle(hv));
else if (sirf::iequals(name, "input_data")) {
SPTR_FROM_HANDLE(PETAcquisitionData, sptr_ad, hv);
recon.set_input_data(sptr_ad->data());
//SPTR_FROM_HANDLE(PETAcquisitionData, sptr_ad, hv);
//recon.set_input_data(sptr_ad->data());
SPTR_FROM_HANDLE(PETScanData, sptr_ad, hv);
recon.set_input_data(sptr_ad->data_sptr());
}
else if (sirf::iequals(name, "disable_output")) {
recon.set_disable_output(true);
Expand Down
8 changes: 8 additions & 0 deletions src/xSTIR/cSTIR/include/sirf/STIR/cstir_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ namespace sirf {
cSTIR_setPoissonLogLikelihoodWithLinearModelForMeanAndProjDataParameter
(DataHandle* hp, const char* name, const DataHandle* hv);

void*
cSTIR_setPoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBinParameter
(DataHandle* hp, const char* name, const DataHandle* hv);

void*
cSTIR_PoissonLogLikelihoodWithLinearModelForMeanAndListModeDataWithProjMatrixByBinParameter
(DataHandle* handle, const char* name);

void*
cSTIR_PoissonLogLikelihoodWithLinearModelForMeanAndProjDataParameter
(const DataHandle* handle, const char* name);
Expand Down
Loading