Skip to content

Commit

Permalink
Merge branch 'develop' into IRnewOption
Browse files Browse the repository at this point in the history
  • Loading branch information
kochebina authored Dec 7, 2023
2 parents 64b6660 + 1b9f024 commit 92198d0
Show file tree
Hide file tree
Showing 11 changed files with 550 additions and 347 deletions.
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,6 @@ MESSAGE("- Coincidence digitizer modules (combining of several Coincidence Sorte
MESSAGE("- Compton Camera digitizer modules and output")
MESSAGE("- Output: Sinogram, Ecat7, LMF")
MESSAGE("- ARF may work not properly yet")
MESSAGE("- Digitizer Modules to be added soon: Buffer, intrinsicResolutionBlurring, lightYield, transferEfficiency, quantumEfficiency, crosstalk, calibration")
MESSAGE("We apologize for this inconvenience and kindly ask for your patience.")
MESSAGE("This functionalities will be added during 2023.")
MESSAGE("Meanwhile, please, use Gate 9.2")
Expand Down
32 changes: 17 additions & 15 deletions docs/digitizer_and_detector_modeling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -875,12 +875,28 @@ With the previous commands, the same quantum efficiency will be applied to all t

To set multiple quantum efficiencies using files (*fileName1*, *fileName2*, ... for each of the different modules), the following commands can be used::

/gate/digitizer/Singles/insert quantumEfficiency
/gate/digitizerMgr/crystal/SinglesDigitizer/Singles/insert quantumEfficiency
/gate/digitizerMgr/crystal/SinglesDigitizer/Singles/intrinsicResolution/useFileDataForQE fileName1
/gate/digitizerMgr/crystal/SinglesDigitizer/Singles/intrinsicResolution/useFileDataForQE fileName2

If the *crystal* volume is a daughter of a *module* volume which is an array of 8 x 8 crystals, the file *fileName1* will contain 64 values of quantum efficiency. If several files are given (in this example two files), the program will choose randomly between theses files for each *module*.


Memory buffers and bandwidth
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To mimic the effect of limited transfer rate, a module models the data loss due to an overflow of a memory buffer, read periodically, following a given reading frequency. This module uses two parameters, the reading frequency :math:`\nu ` and the memory depth :math:`D` . Moreover, two reading methods can be modelled, that is, in an event per event basis (an event is read at each reading clock tick), or in a full buffer reading basic (at each reading clock tick, the whole buffer is emptied out). In the first reading method, the data rate is then limited to :math:`\nu` , while in the second method, the data rate is limited to :math:`D\cdot\nu`. When the size limit is reached, any new pulse is rejected, until the next reading clock tick arrival which frees a part of the buffer. In such a case, a non null buffer depth allows to manage a local rise of the input data flow. To specify a buffer, read at 10 MHz, with a buffer depth of 64 events, in a mode where the whole buffer is read in one clock tick, one can use::

/gate/digitizerMgr/crystal/SinglesDigitizer/Singles/insert buffer
/gate/digitizerMgr/crystal/SinglesDigitizer/Singles/buffer/setBufferSize 64 B
/gate/digitizerMgr/crystal/SinglesDigitizer/Singles/buffer/setReadFrequency 10 MHz
/gate/digitizerMgr/crystal/SinglesDigitizer/Singles/buffer/setMode 1

The size of the buffer represents the number of elements, 64 Singles in this example, that the user can store in a buffer. To read the buffer in an event by event basis, one should replace the last line by **setMode = 0.**




Modules to be addapted (NOT YET INCLUDED IN GATE NEW DIGITIZER)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -915,20 +931,6 @@ In PET analysis, coincidence events provide the lines of response (LOR) needed f



Memory buffers and bandwidth
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To mimic the effect of limited transfer rate, a module models the data loss due to an overflow of a memory buffer, read periodically, following a given reading frequency. This module uses two parameters, the reading frequency :math:`\nu ` and the memory depth :math:`D` . Moreover, two reading methods can be modelled, that is, in an event per event basis (an event is read at each reading clock tick), or in a full buffer reading basic (at each reading clock tick, the whole buffer is emptied out). In the first reading method, the data rate is then limited to :math:`\nu` , while in the second method, the data rate is limited to :math:`D\cdot\nu`. When the size limit is reached, any new pulse is rejected, until the next reading clock tick arrival which frees a part of the buffer. In such a case, a non null buffer depth allows to manage a local rise of the input data flow. To specify a buffer, read at 10 MHz, with a buffer depth of 64 events, in a mode where the whole buffer is read in one clock tick, one can use::

/gate/digitizer/Your_Single_chain/insert buffer
/gate/digitizer/Your_Single_chain/buffer/setBufferSize 64 B
/gate/digitizer/Your_Single_chain/buffer/setReadFrequency 10 MHz
/gate/digitizer/Your_Single_chain/buffer/setMode 1

The chain *Your_Single_chain* can be the default chain *Singles* or any of single chain that the user has defined. The size of the buffer represents the number of elements, 64 Singles in this example, that the user can store in a buffer. To read the buffer in an event by event basis, one should replace the last line by **setMode = 0.**




.. _digitizer_multiple_processor_chains-label:

Expand Down
197 changes: 103 additions & 94 deletions source/digits_hits/include/GateCrosstalk.hh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,91 +6,80 @@ of the GNU Lesser General Public Licence (LGPL)
See LICENSE.md for further details
----------------------*/

// OK GND 2022

/*! \class GateCrosstalk
\brief Digitizer Module for simulating an optical and/or an electronic Crosstalk
- GateCrosstalk - by [email protected] (dec 2002)
- Digitizer Module for simulating an optical and/or an electronic Crosstalk
of the scintillation light between the neighbor crystals:
if the input Digi arrives in a crystal array, Digis around
it are created (in the edge and corner neighbor crystals).
ATTENTION: this module functions only for a chosen volume which is an array repeater !!!
5/12/23 - added to GND by [email protected] but MAYBE NOT PROPERLY TESTED !!!!
\sa GateVDigitizerModule
*/
#ifndef GateCrosstalk_h
#define GateCrosstalk_h 1

#include "GateVDigitizerModule.hh"
#include "GateDigi.hh"
#include "GateClockDependent.hh"
#include "GateCrystalSD.hh"

#include "globals.hh"
#include <iostream>
#include <vector>

#include "GateVPulseProcessor.hh"
#include "GateCrosstalkMessenger.hh"
#include "GateSinglesDigitizer.hh"

class GateCrosstalkMessenger;
class GateArrayParamsFinder;
class GateOutputVolumeID;

/*! \class GateCrosstalk
\brief Pulse-processor for simulating an optical and/or an electronic crosstalk
- GateCrosstalk - by [email protected] (dec 2002)
class GateCrosstalk : public GateVDigitizerModule
{
public:
//! This function allows to retrieve the current instance of the GateCrosstalk singleton
/*!
If the GateCrosstalk already exists, GetInstance only returns a pointer to this singleton.
If this singleton does not exist yet, GetInstance creates it by calling the private
GateCrosstalk constructor
*/
static GateCrosstalk* GetInstance(GateSinglesDigitizer* itsChain,
const G4String& itsName,
G4double itsEdgesFraction, G4double itsCornersFraction);

- Pulse-processor for simulating an optical and/or an electronic crosstalk
of the scintillation light between the neighbor crystals:
if the input pulse arrives in a crystal array, pulses around
it are created (in the edge and corner neighbor crystals).
ATTENTION: this module functions only for a chosen volume which is an array repeater !!!

GateCrosstalk(GateSinglesDigitizer *digitizer, G4String name, G4double itsEdgesFraction, G4double itsCornersFraction);
~GateCrosstalk();

void Digitize() override;

\sa GateVPulseProcessor
*/
class GateCrosstalk : public GateVPulseProcessor
{
public:
//! This function allows to retrieve the current instance of the GateCrosstalk singleton
/*!
If the GateCrosstalk already exists, GetInstance only returns a pointer to this singleton.
If this singleton does not exist yet, GetInstance creates it by calling the private
GateCrosstalk constructor
*/
static GateCrosstalk* GetInstance(GatePulseProcessorChain* itsChain,
const G4String& itsName,
G4double itsEdgesFraction, G4double itsCornersFraction);

//! Public Destructor
virtual ~GateCrosstalk() ;

private:
//!< Private constructor which Constructs a new crosstalk module attached to a GateDigitizer:
//! this function should only be called from GetInstance()
GateCrosstalk(GatePulseProcessorChain* itsChain,
const G4String& itsName,
G4double itsEdgesFraction, G4double itsCornersFraction) ;

public:


void CheckVolumeName(G4String val);

//! \name getters and setters
//@{
//! This function returns the fraction of the part of energy which goes in the edge crystals.
G4double GetEdgesFraction() { return m_edgesCrosstalkFraction; }

//! This function sets the fraction of the part of energy which goes in the edge crystals.
void SetEdgesFraction (G4double val) { m_edgesCrosstalkFraction = val; }

//! This function returns the fraction of the part of energy which goes in the corner crystals.
G4double GetCornersFraction() { return m_cornersCrosstalkFraction; }

//! This function sets the fraction of the part of energy which goes in the corner crystals.
void SetCornersFraction (G4double val) { m_cornersCrosstalkFraction = val; }

//! Return the rest crosstalk per cent
G4double GetXTPerCent() { return m_XtalkpCent; };
//@}

//! Implementation of the pure virtual method declared by the base class GateDigitizerComponent
//! print-out the attributes specific of the crosstalk
virtual void DescribeMyself(size_t indent);

protected:
//! Implementation of the pure virtual method declared by the base class GateVPulseProcessor
//! This methods processes one input-pulse
//! It is is called by ProcessPulseList() for each of the input pulses
//! The result of the pulse-processing is incorporated into the output pulse-list
void ProcessOnePulse(const GatePulse* inputPulse,GatePulseList& outputPulseList);

private:

void CheckVolumeName(G4String val);

//! \name getters and setters
//@{
//! This function returns the fraction of the part of energy which goes in the edge crystals.
G4double GetEdgesFraction() { return m_edgesCrosstalkFraction; }

//! This function sets the fraction of the part of energy which goes in the edge crystals.
void SetEdgesFraction (G4double val) { m_edgesCrosstalkFraction = val; }

//! This function returns the fraction of the part of energy which goes in the corner crystals.
G4double GetCornersFraction() { return m_cornersCrosstalkFraction; }

//! This function sets the fraction of the part of energy which goes in the corner crystals.
void SetCornersFraction (G4double val) { m_cornersCrosstalkFraction = val; }

//! Return the rest Crosstalk per cent
G4double GetXTPerCent() { return m_XtalkpCent; };
//@}

void DescribeMyself(size_t );

private:
// //! Find the different parameters of the array of detection :
// //! The numbers of rows in x, y and z
// //! The position in this matrix of the hit
Expand All @@ -102,34 +91,54 @@ class GateCrosstalk : public GateVPulseProcessor
// //! Get the ArrayRepeater from an VObjectReapeater (if it isn't an ArrayRepeater return 0)
// GateArrayRepeater* GetArrayRepeater(GateVGlobalPlacement* aRepeater);

// //! Find the different parameters of the input Pulse :
// //! Find the different parameters of the input Digi :
// //! e.g. the position in this array of the hit
// void FindInputPulseParams(const GateVolumeID* m_volumeID);
// void FindInputDigiParams(const GateVolumeID* m_volumeID);

//! Create a new VolumeID for the volume of in the matrix with position \i,\j,\k
GateVolumeID CreateVolumeID(const GateVolumeID* m_volumeID, G4int i, G4int j, G4int k);
//! Create a new VolumeID for the volume of in the matrix with position \i,\j,\k
GateVolumeID CreateVolumeID(const GateVolumeID* m_volumeID, G4int i, G4int j, G4int k);

//! Create a new OutputVolumeID for the volume of in the matrix with position \i,\j,\k
GateOutputVolumeID CreateOutputVolumeID(const GateVolumeID m_volumeID);
//! Create a new OutputVolumeID for the volume of in the matrix with position \i,\j,\k
GateOutputVolumeID CreateOutputVolumeID(const GateVolumeID m_volumeID);

//! Create a new Pulse of an energy of \val * ENERGY of \pulse in the volume in position \i,\j,\k
GatePulse* CreatePulse(G4double val, const GatePulse* pulse, G4int i, G4int j, G4int k);
//! Create a new Digi of an energy of \val * ENERGY of \Digi in the volume in position \i,\j,\k
GateDigi* CreateDigi(G4double val, const GateDigi* Digi, G4int i, G4int j, G4int k);

private:
//! Static pointer to the GateCrosstalk singleton
static GateCrosstalk* theGateCrosstalk;

G4double m_XtalkpCent; //!< Actual crosstalk per cent of energy
G4double m_edgesCrosstalkFraction, m_cornersCrosstalkFraction; //!< Coefficient which connects energy to the resolution
GateCrosstalkMessenger *m_messenger; //!< Messenger
G4String m_volume; //!< Name of the crosstalk volume
G4int m_testVolume; //!< Equal to 1 if m_volume is a valid volume name, else 0
protected:
G4double m_XtalkpCent; //!< Actual Crosstalk per cent of energy
G4double m_edgesCrosstalkFraction, m_cornersCrosstalkFraction; //!< Coefficient which connects energy to the resolution
GateCrosstalkMessenger *m_messenger; //!< Messenger
G4String m_volume; //!< Name of the Crosstalk volume
G4int m_testVolume; //!< Equal to 1 if m_volume is a valid volume name, else 0

GateArrayParamsFinder* ArrayFinder;
size_t m_nbX, m_nbY, m_nbZ; //!< Parameters of the matrix of detection
size_t m_i, m_j, m_k; //!< position \i,\j,\k in the matrix
size_t m_depth; //!< Depth of the selected volume in the Inserter
};
GateArrayParamsFinder* ArrayFinder;
size_t m_nbX, m_nbY, m_nbZ; //!< Parameters of the matrix of detection
size_t m_i, m_j, m_k; //!< position \i,\j,\k in the matrix
size_t m_depth;

private:

//! Static pointer to the GateCrosstalk singleton
static GateCrosstalk* theGateCrosstalk;

GateDigi* m_outputDigi;

GateCrosstalkMessenger *m_Messenger;

GateDigiCollection* m_OutputDigiCollection;

GateSinglesDigitizer *m_digitizer;


};

#endif








57 changes: 41 additions & 16 deletions source/digits_hits/include/GateCrosstalkMessenger.hh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,59 @@ of the GNU Lesser General Public Licence (LGPL)
See LICENSE.md for further details
----------------------*/

// OK GND 2022
/*This class is not used by GATE !
The purpose of this class is to help to create new users digitizer module(DM).
Please, check GateCrosstalk.cc for more detals
*/


/*! \class GateCrosstalkMessenger
\brief Messenger for the GateCrosstalk
- GateCrosstalk - by [email protected]
\sa GateCrosstalk, GateCrosstalkMessenger
*/


#ifndef GateCrosstalkMessenger_h
#define GateCrosstalkMessenger_h 1

#include "GatePulseProcessorMessenger.hh"
#include <vector>
#include "G4UIdirectory.hh"
#include "G4UImessenger.hh"
#include "globals.hh"

#include "GateClockDependentMessenger.hh"
class GateCrosstalk;

class G4UIcmdWithAString;
class G4UIcmdWithADouble;

class GateCrosstalk;

class GateCrosstalkMessenger: public GatePulseProcessorMessenger
class GateCrosstalkMessenger : public GateClockDependentMessenger
{
public:
GateCrosstalkMessenger(GateCrosstalk* itsCrosstalk);
virtual ~GateCrosstalkMessenger();
public:

GateCrosstalkMessenger(GateCrosstalk*);
~GateCrosstalkMessenger();

void SetNewValue(G4UIcommand*, G4String);

inline void SetNewValue(G4UIcommand* aCommand, G4String aString);

private:
GateCrosstalk* m_Crosstalk;

G4UIcmdWithADouble *edgesFractionCmd;
G4UIcmdWithADouble *cornersFractionCmd;

inline GateCrosstalk* GetCrosstalk()
{ return (GateCrosstalk*) GetPulseProcessor(); }

private:
G4UIcmdWithAString *newVolCmd;
G4UIcmdWithADouble *edgesFractionCmd;
G4UIcmdWithADouble *cornersFractionCmd;
};

#endif








6 changes: 6 additions & 0 deletions source/digits_hits/include/GateIntrinsicResolution.hh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ public:
void SetEref(const G4double& value ){ m_Eref=value;} ;
void SetLightOutput(const G4double& value ){ m_LY=value;} ;
void SetTransferEff(const G4double& value ){ m_TE=value;} ;
void SetEdgesFraction (G4double val) { m_edgesCrosstalkFraction = val; }
void SetCornersFraction (G4double val) { m_cornersCrosstalkFraction = val; }


//! Allow to use file(s) as lookout table for quantum efficiency
void UseFile(G4String aFile);
Expand All @@ -72,6 +75,7 @@ protected:
G4double m_LY; //Light Yield
G4double m_TE; //Transfer efficiency
G4double m_QE; //Quantum efficiency
G4double m_XtalkpCent;
G4bool isFirstEvent;

G4double m_variance;
Expand All @@ -97,6 +101,8 @@ protected:
G4double** m_table; //!< Lookout table for the quantum efficiency of all channels
G4String m_volumeName; //!< Name of the module
G4int m_testVolume; //!< equal to 1 if the volume name is valid, 0 else
G4double m_edgesCrosstalkFraction, m_cornersCrosstalkFraction; //!< Coefficient which connects energy to the resolution


private:
GateDigi* m_outputDigi;
Expand Down
Loading

0 comments on commit 92198d0

Please sign in to comment.