Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:04:22

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 //
0005 // This code is originally written by Sampo Niskanen in java.
0006 // Translated to C++ by M.Frank
0007 //
0008 // See original copyright notice below
0009 //==========================================================================
0010 //
0011 // PinkNoise.java  -  a pink noise generator
0012 //
0013 // Copyright (c) 2008, Sampo Niskanen <sampo.niskanen@iki.fi>
0014 // All rights reserved.
0015 // Source:  http://www.iki.fi/sampo.niskanen/PinkNoise/
0016 //
0017 // Distrubuted under the BSD license:
0018 //
0019 // Redistribution and use in source and binary forms, with or without
0020 // modification, are permitted provided that the following conditions
0021 // are met:
0022 //
0023 //  - Redistributions of source code must retain the above copyright
0024 // notice, this list of conditions and the following disclaimer.
0025 // 
0026 //  - Redistributions in binary form must reproduce the above
0027 // copyright notice, this list of conditions and the following
0028 // disclaimer in the documentation and/or other materials provided
0029 // with the distribution.
0030 //
0031 //  - Neither the name of the copyright owners nor contributors may be
0032 // used to endorse or promote products derived from this software
0033 // without specific prior written permission.
0034 //
0035 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0036 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0037 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
0038 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
0039 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
0040 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
0041 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0042 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
0043 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0044 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
0045 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0046 // POSSIBILITY OF SUCH DAMAGE.
0047 //
0048 //==========================================================================
0049 
0050 #ifndef DDDIGI_NOISE_FALPHANOISE_H
0051 #define DDDIGI_NOISE_FALPHANOISE_H
0052 
0053 /// C/C++ include files
0054 #include <vector>
0055 #include <random>
0056 
0057 /// Namespace for the AIDA detector description toolkit
0058 namespace dd4hep {
0059 
0060   /// Namespace for the Digitization part of the AIDA detector description toolkit
0061   namespace detail {
0062 
0063     /// Source of pink noise with a power spectrum proportional to 1/f^alpha.
0064     /**
0065      * A class that provides a source of pink noise with a power spectrum
0066      * density (PSD) proportional to 1/f^alpha.  "Regular" pink noise has a
0067      * PSD proportional to 1/f, i.e. alpha=1.  However, many natural
0068      * systems may require a different PSD proportionality.  The value of
0069      * alpha may be from 0 to 2, inclusive.  The special case alpha=0
0070      * results in white noise (directly generated random numbers) and
0071      * alpha=2 results in brown noise (integrated white noise).
0072      * <p>
0073      * The values are computed by applying an IIR filter to generated
0074      * Gaussian random numbers.  The number of poles used in the filter
0075      * may be specified.  For each number of poles there is a limiting
0076      * frequency below which the PSD becomes constant.  Values as low as
0077      * 1-3 poles produce relatively good results, however these values
0078      * will be concentrated near zero.  Using a larger number of poles
0079      * will allow more low frequency components to be included, leading to
0080      * more variation from zero.  However, the sequence is stationary,
0081      * that is, it will always return to zero even with a large number of
0082      * poles.
0083      * <p>
0084      * The distribution of values is very close to Gaussian with mean
0085      * zero, but the variance depends on the number of poles used.
0086      * The resulting distribution is almost Gaussian, but has a relatively 
0087      * larger amount of large values. To re-normalize the variance a
0088      * calibration method normalize() is provided.
0089      * <p>
0090      * The IIR filter used by this class is presented by N. Jeremy Kasdin,
0091      * Proceedings of the IEEE, Vol. 83, No. 5, May 1995, p. 822.
0092      * 
0093      *  \author  Sampo Niskanen <sampo.niskanen@iki.fi>
0094      *  \author  M.Frank
0095      *  \version 1.0
0096      *  \ingroup DD4HEP_DIGITIZATION
0097      */
0098     class FalphaNoise    {
0099     public:
0100       /// Minimal class to mimic a std::random_engine
0101       struct random_engine_wrapper  {
0102         typedef unsigned int result_type;
0103         static constexpr result_type min()      { return std::default_random_engine::min(); }
0104         static constexpr result_type max()      { return std::default_random_engine::max(); }
0105         static constexpr double      range()    { return double(max()) - double(min());     }
0106         virtual result_type operator()()  const = 0;
0107       };
0108       /// Concrete wrapper of a user defined random engine
0109       template <typename ENGINE> struct random_engine : public random_engine_wrapper {
0110         ENGINE& engine;
0111         random_engine(ENGINE& e) : engine(e) {}
0112         virtual result_type operator()()   const  {
0113           static constexpr double norm = random_engine_wrapper::range() / (double(ENGINE::max() - ENGINE::min()));
0114           return result_type(double(engine()) * norm);
0115         }
0116       };
0117 
0118     protected:
0119 #ifdef  __GSL_FALPHA_NOISE
0120       long ptr = -1;
0121       double * arr = nullptr;
0122 #endif
0123       /// Number of poles used for the approximation
0124       size_t                  m_poles    = 0;
0125       /// The variance of the pink noise distribution
0126       double                  m_variance = -1e0;
0127       /// The alpha coefficient for the 1/f**alpha generated noise
0128       double                  m_alpha    = -1e0;
0129       /// Array of multipliers
0130       std::vector<double>     m_multipliers {};
0131       /// Array of buffered values
0132       std::vector<double>     m_values {};
0133       /// Normal distribution with variance for the white noise generation
0134       std::normal_distribution<double> m_distribution;
0135 
0136       /// Internal usage for the transformation from the normal distruted white noise to pink noise
0137       double compute(double gaussian);
0138       /// Internal implementation of the normalization of the variance
0139       void normalizeVariance(const random_engine_wrapper& engine, size_t shots);
0140 
0141     public:
0142       /// Default constructor. Requires a later call to init(...)
0143       FalphaNoise() = default;
0144       /// Initializing constructor. Leaves the enerator full functional
0145       FalphaNoise(size_t poles, double alpha, double variance);
0146       /// Initializing constructor with 5 poles. Leaves the enerator full functional
0147       FalphaNoise(double alpha, double variance);
0148       /// Default destructor
0149       virtual ~FalphaNoise() = default;
0150       /// Access variance value
0151       double variance()   const   {  return m_variance;  }
0152       /// Access alpha value
0153       double alpha()      const   {  return m_alpha;     }
0154       /// Initialize the 1/f**alpha random generator. If already called reconfigures.
0155       void init(size_t poles, double alpha, double variance);
0156       /// Approximatively compute proper variance and apply computed value
0157       void normalize(size_t shots=10000);
0158       /// Approximatively compute proper variance using external ranfom engine and apply computed value
0159       template <typename ENGINE> void normalize(ENGINE& engine, size_t shots=10000);
0160       /// Retrieve the next random number of the sequence
0161       template <typename ENGINE> double operator()(ENGINE& engine);
0162     };
0163 
0164     /// Retrieve the next random number of the sequence
0165     template <typename ENGINE> inline double FalphaNoise::operator()(ENGINE& engine)   {
0166       return compute(m_distribution(engine));
0167     }
0168     /// Approximatively compute proper variance using external ranfom engine and apply computed value
0169     template <typename ENGINE> void FalphaNoise::normalize(ENGINE& engine, size_t shots)   {
0170       normalizeVariance(random_engine<ENGINE>(engine), shots);
0171     }
0172   }    // End namespace detail
0173 }      // End namespace dd4hep
0174 #endif // DDDIGI_NOISE_FALPHANOISE_H