diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f416e29aca..5c8788e9f0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -270,6 +270,11 @@ target_link_libraries(stir_registries) # TODO, really should use stir_libs.cmake target_include_directories(stir_registries PRIVATE ${STIR_INCLUDE_DIR}) target_include_directories(stir_registries PRIVATE ${Boost_INCLUDE_DIR}) +if (FMT_INCLUDE_DIRS) # used by stir::format if std::format doesn't work + target_include_directories(stir_registries PUBLIC + $ + $) +endif() target_include_directories(stir_registries PUBLIC $ $) diff --git a/src/include/stir/listmode/CListEventScannerWithDiscreteDetectors.h b/src/include/stir/listmode/CListEventScannerWithDiscreteDetectors.h index 1e170ee952..7b48ecd6f3 100644 --- a/src/include/stir/listmode/CListEventScannerWithDiscreteDetectors.h +++ b/src/include/stir/listmode/CListEventScannerWithDiscreteDetectors.h @@ -10,6 +10,7 @@ */ /* Copyright (C) 2003- 2011, Hammersmith Imanet Ltd + Copyright (C) University College London, 2017, 2023, 2026 This file is part of STIR. SPDX-License-Identifier: Apache-2.0 @@ -26,25 +27,36 @@ START_NAMESPACE_STIR -//! Class for storing and using a coincidence event from a list mode file for a cylindrical single layer scanner +//! Base-class for storing and using a coincidence event for a list-mode file that uses detector indices /*! \ingroup listmode For scanners with discrete detectors, the list mode events usually store detector indices - in some way. This class provides access mechanisms to those detection positions, and - also provides more efficient implementations of some virtual members of CListEvent. + in some way. This class provides virtual members to to set/get those detection indices + via DetectionPositionPair. + + \see CListEventScannerWithDiscreteDetectors. This base-class exists for cases where we don't + want/need to know the ProjDataInfo type. */ -template -class CListEventScannerWithDiscreteDetectors : public CListEvent +class CListEventScannerWithDiscreteDetectorsBase : public CListEvent { public: - explicit CListEventScannerWithDiscreteDetectors(const shared_ptr& proj_data_info); - - const Scanner* get_scanner_ptr() const { return this->uncompressed_proj_data_info_sptr->get_scanner_ptr(); } - //! This routine returns the corresponding detector pair virtual void get_detection_position(DetectionPositionPair<>&) const = 0; //! This routine sets in a coincidence event from detector "indices" virtual void set_detection_position(const DetectionPositionPair<>&) = 0; +}; + +//! Class for coincidence events from a list-mode file that uses detector indices and a specific type of ProjDataInfo +/*! \ingroup listmode + This class provides more efficient implementations of some virtual members of CListEvent. +*/ +template +class CListEventScannerWithDiscreteDetectors : public CListEventScannerWithDiscreteDetectorsBase +{ +public: + explicit CListEventScannerWithDiscreteDetectors(const shared_ptr& proj_data_info); + + const Scanner* get_scanner_ptr() const { return this->uncompressed_proj_data_info_sptr->get_scanner_ptr(); } //! find LOR between detector pairs /*! Overrides the default implementation to use get_detection_position() @@ -72,8 +84,6 @@ class CListEventScannerWithDiscreteDetectors : public CListEvent protected: shared_ptr get_uncompressed_proj_data_info_sptr() const { return uncompressed_proj_data_info_sptr; } - // shared_ptr scanner_sptr; - private: shared_ptr uncompressed_proj_data_info_sptr; }; diff --git a/src/include/stir/listmode/CListRecordPETSIRD.h b/src/include/stir/listmode/CListRecordPETSIRD.h index 2ea0ef4bbb..ba934365c7 100644 --- a/src/include/stir/listmode/CListRecordPETSIRD.h +++ b/src/include/stir/listmode/CListRecordPETSIRD.h @@ -22,11 +22,9 @@ #include "stir/listmode/CListEventScannerWithDiscreteDetectors.h" #include "stir/listmode/CListRecord.h" #include "stir/DetectionPositionPair.h" -#include "stir/Succeeded.h" -#include "stir/ByteOrderDefine.h" - -#include "stir/DetectorCoordinateMap.h" #include "stir/PETSIRDInfo.h" +#include "stir/Succeeded.h" +#include "stir/format.h" START_NAMESPACE_STIR @@ -34,17 +32,20 @@ template class CListEventPETSIRD : public CListEventScannerWithDiscreteDetectors { public: + //! Constructor which leaves \c det_pos_pair and \c is_prompts undefined. + inline CListEventPETSIRD(shared_ptr proj_data_info_sptr) + : CListEventScannerWithDiscreteDetectors(proj_data_info_sptr) + {} + inline CListEventPETSIRD(shared_ptr proj_data_info_sptr, - DetectionPositionPair<>* det_pos_pair, - bool* is_prompt) + const DetectionPositionPair<>& det_pos_pair, + bool is_prompt_v) : CListEventScannerWithDiscreteDetectors(proj_data_info_sptr), - det_pos_pair_ptr(det_pos_pair), - is_prompt_ptr(is_prompt) + _det_pos_pair(det_pos_pair), + _is_prompt(is_prompt_v) {} - // inline void get_bin(Bin& bin, const ProjDataInfo& proj_data_info) const override; - - inline bool is_prompt() const override { return *this->is_prompt_ptr; } + inline bool is_prompt() const override { return this->_is_prompt; } bool operator==(const CListEventPETSIRD& other) const { @@ -56,23 +57,23 @@ class CListEventPETSIRD : public CListEventScannerWithDiscreteDetectorsis_prompt_ptr = prompt; + this->_is_prompt = prompt; return Succeeded::yes; } - virtual void get_detection_position(DetectionPositionPair<>& det_pos_pair) const override + virtual void get_detection_position(DetectionPositionPair<>& det_pos_pair_arg) const override { - det_pos_pair = *this->det_pos_pair_ptr; + det_pos_pair_arg = this->_det_pos_pair; } - virtual void set_detection_position(const DetectionPositionPair<>& det_pos_pair) override + virtual void set_detection_position(const DetectionPositionPair<>& det_pos_pair_arg) override { - *this->det_pos_pair_ptr = det_pos_pair; + this->_det_pos_pair = det_pos_pair_arg; } private: - DetectionPositionPair<>* det_pos_pair_ptr = nullptr; - bool* is_prompt_ptr = nullptr; + DetectionPositionPair<> _det_pos_pair; + bool _is_prompt; }; class CListTimePETSIRD : public ListTime @@ -96,21 +97,18 @@ class CListTimePETSIRD : public ListTime The time associated with a PETSIRD event is therefore obtained from the enclosing EventTimeBlock, rather than from a separate time marker record. - \par CListModeDataPETSIRD assigns this time to the record before returning it. Consequently, a CListRecordPETSIRD represents a coincidence event and also carries valid timing information. - \par - This follows the STIR convention, similar to CListRecordROOT, - that a listmode record can be both an event record and a time record. - + In this implementation, a record is both an event record and a time record, + similar to CListRecordROOT. */ class CListRecordPETSIRD : public CListRecord { public: CListRecordPETSIRD(shared_ptr petsird_info_sptr, shared_ptr proj_data_info_sptr) - : event_data(make_event_data(proj_data_info_sptr, this->det_pos_pair, this->is_prompt_event)), + : event_data(make_event_data(proj_data_info_sptr)), petsird_info_sptr(std::move(petsird_info_sptr)), proj_data_info_sptr(std::move(proj_data_info_sptr)) {} @@ -128,7 +126,7 @@ class CListRecordPETSIRD : public CListRecord bool operator==(const CListRecordPETSIRD& e2) const { return event_data == e2.event_data && time_data == e2.time_data; } - Succeeded init_from_data(petsird::CoincidenceEvent& event, const bool is_prompt = true) + Succeeded init_from_data(const petsird::CoincidenceEvent& event, const bool is_prompt) { const auto scanner_info_sptr = petsird_info_sptr->get_petsird_scanner_info_sptr(); @@ -144,35 +142,34 @@ class CListRecordPETSIRD : public CListRecord auto it1 = petsird_info_sptr->get_petsird_to_stir_map()->find(exp_det_0); if (it0 == petsird_info_sptr->get_petsird_to_stir_map()->end() || it1 == petsird_info_sptr->get_petsird_to_stir_map()->end()) { - error("get_stir_det_pos_from_PETSIRD_id: one or both PETSIRD ids not found", - exp_det_0.module_index, - exp_det_0.element_index, - exp_det_0.energy_index); + error(format("get_stir_det_pos_from_PETSIRD_id: one or both PETSIRD ids (mod {}, elem {}, energy {}) not found", + exp_det_0.module_index, + exp_det_0.element_index, + exp_det_0.energy_index)); } // Warning: this assumes that the PETSIRD TOF bins and the STIR ProjDataInfo // timing positions have the same binning/mashing and number of TOF bins. // If the STIR proj_data_info uses a different TOF mashing factor or TOF range, // this simple offset conversion is not valid. - this->det_pos_pair = DetectionPositionPair<>( + const DetectionPositionPair<> det_pos_pair( it0->second, it1->second, static_cast(event.tof_idx) + this->proj_data_info_sptr->get_min_tof_pos_num()); - - is_prompt_event = is_prompt; + this->event_data->set_detection_position(det_pos_pair); + this->event_data->set_prompt(is_prompt); return Succeeded::yes; } private: - static std::unique_ptr - make_event_data(shared_ptr proj_data_info, DetectionPositionPair<>& det_pos_pair, bool& is_prompt_event); + static std::unique_ptr + make_event_data(shared_ptr proj_data_info); - std::unique_ptr event_data; + std::unique_ptr event_data; CListTimePETSIRD time_data; shared_ptr petsird_info_sptr; shared_ptr proj_data_info_sptr; bool is_prompt_event = true; - DetectionPositionPair<> det_pos_pair; }; END_NAMESPACE_STIR diff --git a/src/listmode_buildblock/CListRecordPETSIRD.cxx b/src/listmode_buildblock/CListRecordPETSIRD.cxx index cb1c33f479..8a8e776a58 100644 --- a/src/listmode_buildblock/CListRecordPETSIRD.cxx +++ b/src/listmode_buildblock/CListRecordPETSIRD.cxx @@ -23,10 +23,8 @@ START_NAMESPACE_STIR -std::unique_ptr -CListRecordPETSIRD::make_event_data(shared_ptr proj_data_info_sptr, - DetectionPositionPair<>& det_pos_pair, - bool& is_prompt_event) +std::unique_ptr +CListRecordPETSIRD::make_event_data(shared_ptr proj_data_info_sptr) { // construct event of type of current ProjDataInfo // Note: currently cumbersome due to change ProjDataInfo hierarchy. @@ -35,22 +33,19 @@ CListRecordPETSIRD::make_event_data(shared_ptr proj_data_inf if ((proj_data_info_sptr->get_scanner_ptr()->get_scanner_geometry() == "Cylindrical") && (dynamic_cast(proj_data_info_sptr.get()) != nullptr)) { - return std::make_unique>( - proj_data_info_sptr, &det_pos_pair, &is_prompt_event); + return std::make_unique>(proj_data_info_sptr); } if ((proj_data_info_sptr->get_scanner_ptr()->get_scanner_geometry() == "BlocksOnCylindrical") && (dynamic_cast(proj_data_info_sptr.get()) != nullptr)) { - return std::make_unique>( - proj_data_info_sptr, &det_pos_pair, &is_prompt_event); + return std::make_unique>(proj_data_info_sptr); } if ((proj_data_info_sptr->get_scanner_ptr()->get_scanner_geometry() == "Generic") && (dynamic_cast(proj_data_info_sptr.get()) != nullptr)) { - return std::make_unique>( - proj_data_info_sptr, &det_pos_pair, &is_prompt_event); + return std::make_unique>(proj_data_info_sptr); } error("Unsupported ProjDataInfo type in CListRecordPETSIRD::make_event_data");