Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
$<BUILD_INTERFACE:${FMT_INCLUDE_DIRS}>
$<INSTALL_INTERFACE:include>)
endif()
target_include_directories(stir_registries PUBLIC
$<BUILD_INTERFACE:${CUVEC_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>)
Expand Down
32 changes: 21 additions & 11 deletions src/include/stir/listmode/CListEventScannerWithDiscreteDetectors.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 ProjDataInfoT>
class CListEventScannerWithDiscreteDetectors : public CListEvent
class CListEventScannerWithDiscreteDetectorsBase : public CListEvent
{
public:
explicit CListEventScannerWithDiscreteDetectors(const shared_ptr<const ProjDataInfo>& 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 ProjDataInfoT>
class CListEventScannerWithDiscreteDetectors : public CListEventScannerWithDiscreteDetectorsBase
{
public:
explicit CListEventScannerWithDiscreteDetectors(const shared_ptr<const ProjDataInfo>& 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()
Expand Down Expand Up @@ -72,8 +84,6 @@ class CListEventScannerWithDiscreteDetectors : public CListEvent
protected:
shared_ptr<const ProjDataInfoT> get_uncompressed_proj_data_info_sptr() const { return uncompressed_proj_data_info_sptr; }

// shared_ptr<Scanner> scanner_sptr;

private:
shared_ptr<const ProjDataInfoT> uncompressed_proj_data_info_sptr;
};
Expand Down
69 changes: 33 additions & 36 deletions src/include/stir/listmode/CListRecordPETSIRD.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,30 @@
#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

template <class ProjDataInfoT>
class CListEventPETSIRD : public CListEventScannerWithDiscreteDetectors<ProjDataInfoT>
{
public:
//! Constructor which leaves \c det_pos_pair and \c is_prompts undefined.
inline CListEventPETSIRD(shared_ptr<const ProjDataInfo> proj_data_info_sptr)
: CListEventScannerWithDiscreteDetectors<ProjDataInfoT>(proj_data_info_sptr)
{}

inline CListEventPETSIRD(shared_ptr<const ProjDataInfo> proj_data_info_sptr,
DetectionPositionPair<>* det_pos_pair,
bool* is_prompt)
const DetectionPositionPair<>& det_pos_pair,
bool is_prompt_v)
: CListEventScannerWithDiscreteDetectors<ProjDataInfoT>(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
{
Expand All @@ -56,23 +57,23 @@ class CListEventPETSIRD : public CListEventScannerWithDiscreteDetectors<ProjData

inline Succeeded set_prompt(const bool prompt) override
{
*this->is_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
Expand All @@ -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<const PETSIRDInfo> petsird_info_sptr, shared_ptr<const ProjDataInfo> 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))
{}
Expand All @@ -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();

Expand All @@ -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<int>(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<CListEvent>
make_event_data(shared_ptr<const ProjDataInfo> proj_data_info, DetectionPositionPair<>& det_pos_pair, bool& is_prompt_event);
static std::unique_ptr<CListEventScannerWithDiscreteDetectorsBase>
make_event_data(shared_ptr<const ProjDataInfo> proj_data_info);

std::unique_ptr<CListEvent> event_data;
std::unique_ptr<CListEventScannerWithDiscreteDetectorsBase> event_data;
CListTimePETSIRD time_data;

shared_ptr<const PETSIRDInfo> petsird_info_sptr;
shared_ptr<const ProjDataInfo> proj_data_info_sptr;

bool is_prompt_event = true;
DetectionPositionPair<> det_pos_pair;
};

END_NAMESPACE_STIR
Expand Down
15 changes: 5 additions & 10 deletions src/listmode_buildblock/CListRecordPETSIRD.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@

START_NAMESPACE_STIR

std::unique_ptr<CListEvent>
CListRecordPETSIRD::make_event_data(shared_ptr<const ProjDataInfo> proj_data_info_sptr,
DetectionPositionPair<>& det_pos_pair,
bool& is_prompt_event)
std::unique_ptr<CListEventScannerWithDiscreteDetectorsBase>
CListRecordPETSIRD::make_event_data(shared_ptr<const ProjDataInfo> proj_data_info_sptr)
{
// construct event of type of current ProjDataInfo
// Note: currently cumbersome due to change ProjDataInfo hierarchy.
Expand All @@ -35,22 +33,19 @@ CListRecordPETSIRD::make_event_data(shared_ptr<const ProjDataInfo> proj_data_inf
if ((proj_data_info_sptr->get_scanner_ptr()->get_scanner_geometry() == "Cylindrical")
&& (dynamic_cast<const ProjDataInfoCylindricalNoArcCorr*>(proj_data_info_sptr.get()) != nullptr))
{
return std::make_unique<CListEventPETSIRD<ProjDataInfoCylindricalNoArcCorr>>(
proj_data_info_sptr, &det_pos_pair, &is_prompt_event);
return std::make_unique<CListEventPETSIRD<ProjDataInfoCylindricalNoArcCorr>>(proj_data_info_sptr);
}

if ((proj_data_info_sptr->get_scanner_ptr()->get_scanner_geometry() == "BlocksOnCylindrical")
&& (dynamic_cast<const ProjDataInfoBlocksOnCylindricalNoArcCorr*>(proj_data_info_sptr.get()) != nullptr))
{
return std::make_unique<CListEventPETSIRD<ProjDataInfoBlocksOnCylindricalNoArcCorr>>(
proj_data_info_sptr, &det_pos_pair, &is_prompt_event);
return std::make_unique<CListEventPETSIRD<ProjDataInfoBlocksOnCylindricalNoArcCorr>>(proj_data_info_sptr);
}

if ((proj_data_info_sptr->get_scanner_ptr()->get_scanner_geometry() == "Generic")
&& (dynamic_cast<const ProjDataInfoGenericNoArcCorr*>(proj_data_info_sptr.get()) != nullptr))
{
return std::make_unique<CListEventPETSIRD<ProjDataInfoGenericNoArcCorr>>(
proj_data_info_sptr, &det_pos_pair, &is_prompt_event);
return std::make_unique<CListEventPETSIRD<ProjDataInfoGenericNoArcCorr>>(proj_data_info_sptr);
}

error("Unsupported ProjDataInfo type in CListRecordPETSIRD::make_event_data");
Expand Down
Loading