Skip to content

Commit

Permalink
prepare CListEventCylindricalScannerWithDiscreteDetectors for non-cyl…
Browse files Browse the repository at this point in the history
…indrical

- move all functionality to template class CListEventScannerWithDiscreteDetectors<ProjDataInfoT>
- keep CListEventCylindricalScannerWithDiscreteDetectors as derived class such that this change
is backwards compatible
  • Loading branch information
KrisThielemans committed Jul 9, 2023
1 parent d04922d commit 4bd016d
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 73 deletions.
9 changes: 9 additions & 0 deletions documentation/release_5.2.htm
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ <h3>Build system and dependencies</h3>
</li>
</ul>

<h3>Changes for developers</h3>
<ul>
<li>moved all functionality in <code>CListEventCylindricalScannerWithDiscreteDetectors</code> to template class
<code>CListEventScannerWithDiscreteDetectors</code> (templated in <code>ProjDataInfoT</code>). This enables
re-use for generic/blocksoncylindrical scanners.
<br /><a href="https://github.com/UCL/STIR/pull/1222/">PR #1222</a>.
</li>
</ul>


<h3>Known problems</h3>
<ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
/*
Copyright (C) 2003- 2011, Hammersmith Imanet Ltd
Copyright (C) 2023, University College London
This file is part of STIR.
SPDX-License-Identifier: Apache-2.0
Expand All @@ -19,73 +19,25 @@
#ifndef __stir_listmode_CListEventCylindricalScannerWithDiscreteDetectors_H__
#define __stir_listmode_CListEventCylindricalScannerWithDiscreteDetectors_H__

#include "stir/Succeeded.h"
#include "stir/DetectionPositionPair.h"
#include "stir/listmode/CListEventScannerWithDiscreteDetectors.h"
#include "stir/ProjDataInfoCylindricalNoArcCorr.h"
#include "stir/listmode/CListRecord.h"

START_NAMESPACE_STIR

//! Class for storing and using a coincidence event from a list mode file for a cylindrical single layer scanner
//! Class for storing and using a coincidence event from a list mode file for a cylindrical scanner
/*! \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.
At present, could just as well be a `typedef`.
*/
class CListEventCylindricalScannerWithDiscreteDetectors : public CListEvent
class CListEventCylindricalScannerWithDiscreteDetectors : public CListEventScannerWithDiscreteDetectors<ProjDataInfoCylindricalNoArcCorr>
{
public:
inline explicit
CListEventCylindricalScannerWithDiscreteDetectors(const shared_ptr<Scanner>& scanner_sptr);

const Scanner * get_scanner_ptr() const
{ return this->scanner_sptr.get(); }

//! 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;

//! find LOR between detector pairs
/*! Overrides the default implementation to use get_detection_position()
which should be faster.
*/
inline virtual LORAs2Points<float> get_LOR() const;

//! find bin for this event
/*! Overrides the default implementation to use get_detection_position()
which should be faster.
\warning This implementation is only valid for \c proj_data_info of
type ProjDataInfoCylindricalNoArcCorr. However, because of efficiency reasons
this is only checked in debug mode (NDEBUG not defined).
*/
inline virtual void get_bin(Bin& bin, const ProjDataInfo& proj_data_info) const;

//! This method checks if the template is valid for LmToProjData
/*! Used before the actual processing of the data (see issue #61), before calling get_bin()
* Most scanners have listmode data that correspond to non arc-corrected data and
* this check avoids a crash when an unsupported template is used as input.
*/
inline virtual bool is_valid_template(const ProjDataInfo&) const;

protected:
shared_ptr<const ProjDataInfoCylindricalNoArcCorr>
get_uncompressed_proj_data_info_sptr() const
{
return uncompressed_proj_data_info_sptr;
}

shared_ptr<Scanner> scanner_sptr;
private:
shared_ptr<const ProjDataInfoCylindricalNoArcCorr>
uncompressed_proj_data_info_sptr;

typedef CListEventScannerWithDiscreteDetectors<ProjDataInfoCylindricalNoArcCorr> base_type;
public:
using base_type::base_type;
};

END_NAMESPACE_STIR

#include "stir/listmode/CListEventCylindricalScannerWithDiscreteDetectors.inl"
//#include "stir/listmode/CListEventCylindricalScannerWithDiscreteDetectors.inl"

#endif
93 changes: 93 additions & 0 deletions src/include/stir/listmode/CListEventScannerWithDiscreteDetectors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//
//
/*!
\file
\ingroup listmode
\brief Declarations of class stir::CListEventScannerWithDiscreteDetectors
\author Kris Thielemans
*/
/*
Copyright (C) 2003- 2011, Hammersmith Imanet Ltd
This file is part of STIR.
SPDX-License-Identifier: Apache-2.0
See STIR/LICENSE.txt for details
*/
#ifndef __stir_listmode_CListEventScannerWithDiscreteDetectors_H__
#define __stir_listmode_CListEventScannerWithDiscreteDetectors_H__

#include "stir/Succeeded.h"
#include "stir/DetectionPositionPair.h"
#include "stir/ProjDataInfo.h"
#include "stir/listmode/CListRecord.h"

START_NAMESPACE_STIR

//! Class for storing and using a coincidence event from a list mode file for a cylindrical single layer scanner
/*! \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.
*/
template <class ProjDataInfoT>
class CListEventScannerWithDiscreteDetectors : public CListEvent
{
public:

explicit CListEventScannerWithDiscreteDetectors(const shared_ptr<Scanner>&);

const Scanner * get_scanner_ptr() const
{ return this->scanner_sptr.get(); }

//! 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;

//! find LOR between detector pairs
/*! Overrides the default implementation to use get_detection_position()
which should be faster.
*/
inline virtual LORAs2Points<float> get_LOR() const;

//! find bin for this event
/*! Overrides the default implementation to use get_detection_position()
which should be faster.
\warning This implementation is only valid for \c proj_data_info of
type ProjDataInfoT. However, because of efficiency reasons
this is only checked in debug mode (NDEBUG not defined).
*/
inline virtual void get_bin(Bin& bin, const ProjDataInfo& proj_data_info) const;

//! This method checks if the template is valid for LmToProjData
/*! Used before the actual processing of the data (see issue #61), before calling get_bin()
* Most scanners have listmode data that correspond to non arc-corrected data and
* this check avoids a crash when an unsupported template is used as input.
*/
inline virtual bool is_valid_template(const ProjDataInfo&) const;

protected:
shared_ptr<const ProjDataInfoT>
get_uncompressed_proj_data_info_sptr() const
{
return uncompressed_proj_data_info_sptr;
}

shared_ptr<const Scanner> scanner_sptr;

private:
shared_ptr<const ProjDataInfoT>
uncompressed_proj_data_info_sptr;

};

END_NAMESPACE_STIR

#include "stir/listmode/CListEventScannerWithDiscreteDetectors.inl"

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,53 @@
/*!
\file
\ingroup listmode
\brief Implementations of class stir::CListEventCylindricalScannerWithDiscreteDetectors
\brief Implementations of class stir::CListEventScannerWithDiscreteDetectors
\author Kris Thielemans
*/
/*
Copyright (C) 2003- 2011, Hammersmith Imanet Ltd
Copyright (C) 2023, University College London
This file is part of STIR.
SPDX-License-Identifier: Apache-2.0
See STIR/LICENSE.txt for details
*/

#include "stir/LORCoordinates.h"
#include "stir/error.h"

START_NAMESPACE_STIR

CListEventCylindricalScannerWithDiscreteDetectors::
CListEventCylindricalScannerWithDiscreteDetectors(const shared_ptr<Scanner>& scanner_sptr)
: scanner_sptr(scanner_sptr)
template <class ProjDataInfoT>
CListEventScannerWithDiscreteDetectors<ProjDataInfoT>::
CListEventScannerWithDiscreteDetectors(const shared_ptr<Scanner>& scanner_sptr_v)
{
this->uncompressed_proj_data_info_sptr.reset
(dynamic_cast<ProjDataInfoCylindricalNoArcCorr *>
(
ProjDataInfo::ProjDataInfoCTI(scanner_sptr,
if (!scanner_sptr_v)
error("CListEventScannerWithDiscreteDetectors constructor called with zero scanner pointer");
this->scanner_sptr = scanner_sptr_v;
auto pdi_ptr =
ProjDataInfo::ProjDataInfoCTI(scanner_sptr_v,
1, scanner_sptr->get_num_rings()-1,
scanner_sptr->get_num_detectors_per_ring()/2,
scanner_sptr->get_max_num_non_arccorrected_bins(),
false)));
scanner_sptr->get_max_num_non_arccorrected_bins(),
false);
auto pdi_ptr_cast =
dynamic_cast<ProjDataInfoT *>(pdi_ptr);
if (!pdi_ptr_cast)
{
delete pdi_ptr;
error("CListEventScannerWithDiscreteDetectors constructor called with scanner that gives wrong type of ProjDataInfo");
}
this->uncompressed_proj_data_info_sptr.reset(pdi_ptr_cast);
}

template <class ProjDataInfoT>
LORAs2Points<float>
CListEventCylindricalScannerWithDiscreteDetectors::
CListEventScannerWithDiscreteDetectors<ProjDataInfoT>::
get_LOR() const
{
LORAs2Points<float> lor;
Expand Down Expand Up @@ -65,25 +78,27 @@ get_LOR() const
return lor;
}

template <class ProjDataInfoT>
void
CListEventCylindricalScannerWithDiscreteDetectors::
CListEventScannerWithDiscreteDetectors<ProjDataInfoT>::
get_bin(Bin& bin, const ProjDataInfo& proj_data_info) const
{
assert(dynamic_cast<ProjDataInfoCylindricalNoArcCorr const*>(&proj_data_info) != 0);
assert(dynamic_cast<ProjDataInfoT const*>(&proj_data_info) != 0);
DetectionPositionPair<> det_pos;
this->get_detection_position(det_pos);
if (static_cast<ProjDataInfoCylindricalNoArcCorr const&>(proj_data_info).
if (static_cast<ProjDataInfoT const&>(proj_data_info).
get_bin_for_det_pos_pair(bin, det_pos) == Succeeded::no)
bin.set_bin_value(0);
else
bin.set_bin_value(1);
}

template <class ProjDataInfoT>
bool
CListEventCylindricalScannerWithDiscreteDetectors::
CListEventScannerWithDiscreteDetectors<ProjDataInfoT>::
is_valid_template(const ProjDataInfo& proj_data_info) const
{
if (dynamic_cast<ProjDataInfoCylindricalNoArcCorr const*>(&proj_data_info)!= 0)
if (dynamic_cast<ProjDataInfoT const*>(&proj_data_info)!= 0)
return true;

return false;
Expand Down

0 comments on commit 4bd016d

Please # to comment.