Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-17 09:55:58

0001 /** @class sipm::SiPMSensor SimSiPM/SimSiPM/SiPMSensor.h SiPMSensor.h
0002  *
0003  *  @brief Main class used to simulate a SiPM
0004  *
0005  *  This class provides all the methods to simulate a SiPM sensor.
0006  *
0007  *  @author Edoardo Proserpio
0008  *  @date 2020
0009  */
0010 
0011 #ifndef SIPM_SIPMSENSOR_H
0012 #define SIPM_SIPMSENSOR_H
0013 
0014 #include <algorithm>
0015 #include <iomanip>
0016 #include <iostream>
0017 #include <memory>
0018 
0019 #include "SiPMAnalogSignal.h"
0020 #include "SiPMDebugInfo.h"
0021 #include "SiPMHit.h"
0022 #include "SiPMProperties.h"
0023 #include "SiPMRandom.h"
0024 
0025 namespace sipm {
0026 
0027 class SiPMSensor {
0028 public:
0029   /// @brief SiPMSensor constructor from a @ref SiPMProperties instance.
0030   /** Instantiates a SiPMSensor with parameter specified in the SiPMProperties.
0031    */
0032   SiPMSensor(const SiPMProperties&) noexcept;
0033 
0034   /// @brief Default SiPMSensor contructor.
0035   /** Instantiates a SiPMSensor with default settings.
0036    */
0037   SiPMSensor() noexcept;
0038 
0039   /// @brief Returns a const reference to the @ref SiPMProperties object
0040   /** used to setup ths SiPMSensor.
0041    * Used to access the SiPMSensor properties and settings
0042    */
0043   const SiPMProperties& properties() const { return m_Properties; }
0044 
0045   /// @brief Returns a reference to the @ref SiPMProperties object used to setup ths SiPMSensor.
0046   /**
0047    * Used to access and modify the SiPMSensor properties and settings
0048    */
0049   SiPMProperties& properties() { return m_Properties; }
0050 
0051   /// @brief Returns a reference to @ref SiPMAnalogSignal.
0052   /** Used to get the generated signal from the sensor. This method should be
0053    * run after @ref runEvent otherwise it will return only electronic noise.
0054    */
0055   const SiPMAnalogSignal& signal() const { return m_Signal; }
0056 
0057   /// @brief Returns vector containing all SiPMHits.
0058   /** Used for debug purposes only. In general SiPMHits should remain hidden
0059    * for the user of the library.
0060    */
0061   std::vector<SiPMHit> hits() const { return m_Hits; }
0062 
0063   /// @brief Returns a const reference to the @ref SiPMRandom.
0064   const SiPMRandom& rng() const { return m_rng; }
0065 
0066   /// @brief Returns a reference to the @ref SiPMRandom.
0067   /** Used to access and re-seed the underlying SiPMRandom object used for
0068    * pseudo-random numbers generation.
0069    */
0070   SiPMRandom& rng() { return m_rng; }
0071 
0072   /// @brief Returns a @ref SiPMDebugInfo
0073   /** @sa SiPMDebugInfo
0074    */
0075   SiPMDebugInfo debug() const { return SiPMDebugInfo(m_PhotonTimes.size(), m_nPe, m_nDcr, m_nXt, m_nDXt, m_nAp); }
0076 
0077   /// @brief Prints all informations about SiPMHits in SiPMSensor
0078   void dumpHits() const;
0079 
0080   /// @brief Sets a property from its name
0081   /** Sets a SiPM property using its name. For a list of available SiPM
0082    * properties names @sa SiPMProperties
0083    */
0084   void setProperty(const std::string&, const double);
0085 
0086   /// @brief Sets a different SiPMProperties for the SiPMSensor.
0087   /** Changes the underlying SiPMProperties object with a new one.
0088    */
0089   void setProperties(const SiPMProperties&);
0090 
0091   void addPhoton() {}
0092 
0093   /// @brief Adds a single photon to the list of photons to be simulated.
0094   void addPhoton(const double);
0095 
0096   /// @brief Adds a single photon to the list of photons to be simulated.
0097   void addPhoton(const double, const double);
0098 
0099   /// @brief Adds all photons to the list of photons to be simulated at once.
0100   void addPhotons(const std::vector<double>&);
0101 
0102   /// @brief Adds all photons to the list of photons to be simulated at once.
0103   void addPhotons(const std::vector<double>&, const std::vector<double>&);
0104 
0105   /// @brief Runs a complete SiPM event.
0106   void runEvent();
0107 
0108   /// @brief Resets internal state of the SiPMSensor.
0109   /** Resets the state of the SiPMSensor so it can be used again for a new
0110    * event.
0111    */
0112   void resetState();
0113 
0114   // Go virtual ?
0115   // virtual ~SiPMSensor() = default;
0116   // virtual std::vector<double> signalShape() const;
0117   friend std::ostream& operator<< (std::ostream&, const SiPMSensor&);
0118 
0119 private:
0120   /// @brief Returns the PDE value corresponding to the given wavelength.
0121   /** Uses the user defined spectral response to evaluate the PDE of photons
0122    * gien theyr wavelength. PDE values are calculated by linearly interpolating
0123    * the values stored in @ref SiPMProperties::m_PdeSpectrum.
0124    */
0125   double evaluatePde(const double) const;
0126   /// @brief Return wether the photon is detected given a PDE value.
0127   inline bool isDetected(const double aPde) const { return m_rng.Rand() < aPde; }
0128   /** @brief Return wether the generated SiPMHit coordinates are allowed on the
0129    * sensor's surface.
0130    */
0131   bool isInSensor(const int32_t, const int32_t) const;
0132   /// @brief Generates coordinates for a new hit.
0133   /** This metod associates a photoelectron with a sipm cell. The coordinates of
0134    * the hitted cell are generated randomly and  accordingly to
0135    * @ref SiPMProperties::HitDistribution.
0136    */
0137   math::pair<uint32_t> hitCell() const;
0138 
0139   /// @brief Returns the shape of the signal generated.
0140   /** Return the ideal signal shape intended as the signal generated by a single
0141    * photoelectron at time = 0. This signal will be used as a template to
0142    * generate all other signals.
0143    * Signal shape is based either on a two-exponential model or a
0144    * three-exponential model in case slow component is considered.
0145    * The two-exponential model is:
0146    * @f[ s(t) = e^{-\frac{t}{\tau_f}}-e^{-\frac{t}{\tau_r}}@f]
0147    * The three exponential model adds another falling exponential term with a
0148    * given weight.
0149    */
0150   std::vector<double> signalShape() const;
0151 
0152   /// @brief Generated DCR events.
0153   /** Dark counts events are generated as poisson processes and directly added
0154    * to the list of hitted cells.
0155    */
0156   void addDcrEvents();
0157 
0158   /// @brief Generates photoelectrons starting from the photons.
0159   /** Starting from the all the photons added to the sensor a list of
0160    * @ref SiPMHit is created considering the PDE type and values set by the user
0161    * and those hits are distributed on the SiPM surface considered the
0162    * @ref SiPMProperties::HitDistribution specified
0163    */
0164   void addPhotoelectrons();
0165 
0166   void addCorrelatedNoise();
0167 
0168   /// @brief Adds XT events.
0169   /** Adds optical crosstalk events to the already existing photoelectrons.
0170   * Each hitted cell may trigger a poissonian number of adjacent cells with
0171   * mean value given by the XT probability. XT events are added to the listo of
0172   * hits with the same time of the generating hit and theyr position is choosen
0173   * randomly between the 9 neighbouring cells.
0174   */
0175   SiPMHit generateXtHit(const SiPMHit&) const;
0176 
0177   /// @brief Add AP events.
0178   /** Adds afterpulse events. Each hit can produce a poissonian number of
0179   * afterpulses. Each afterpulse is delayed from the generating signal
0180   * following a slow/fast exponential distribution.
0181   */
0182   SiPMHit generateApHit(const SiPMHit&) const;
0183 
0184   /// @brief Calculates signal amplitudes for all hits
0185   /** Each hit has a starting amplitude of 1 but if the same cell has been
0186   * previously hitted the resulting amplitude will be calculated considering
0187   * the cell as an RC circuit, hence:
0188   * @f$ a = 1 - e^{-frac{\Delta_t}{\tau}} @f$
0189   */
0190   void calculateSignalAmplitudes();
0191 
0192   /// @brief Generates the SiPM signal
0193   /** The SiPM signal is generated considering the arriving time of each hit and
0194    * its amplitude. Signals are generated accorfingly to the signal produced by
0195    * @ref signalShape.
0196    */
0197   void generateSignal() __attribute__((hot));
0198 
0199   SiPMProperties m_Properties;
0200   mutable SiPMRandom m_rng;
0201 
0202   std::vector<double> m_SignalShape;
0203 
0204   uint32_t m_nTotalHits = 0;
0205   uint32_t m_nPe = 0;
0206   uint32_t m_nDcr = 0;
0207   uint32_t m_nXt = 0;
0208   uint32_t m_nDXt = 0;
0209   uint32_t m_nAp = 0;
0210 
0211   std::vector<double> m_PhotonTimes;
0212   std::vector<double> m_PhotonWavelengths;
0213   std::vector<SiPMHit> m_Hits;
0214 
0215   SiPMAnalogSignal m_Signal;
0216 };
0217 
0218 } // namespace sipm
0219 #endif /* SIPM_SIPMSENSOR_H */