/*=========================================================================
*
*  Copyright NumFOCUS
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0.txt
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*=========================================================================*/
#ifndef sitkShotNoiseImageFilter_h
#define sitkShotNoiseImageFilter_h

/*
 * WARNING: DO NOT EDIT THIS FILE!
 * THIS FILE IS AUTOMATICALLY GENERATED BY THE SIMPLEITK BUILD PROCESS.
 * Please look at sitkImageFilterTemplate.h.in to make changes.
 */

#include <memory>

#include "sitkBasicFilters.h"
#include "sitkImageFilter.h"

namespace itk::simple {

    /**\class ShotNoiseImageFilter
\brief Alter an image with shot noise.

The shot noise follows a Poisson distribution:

\par 
\f$ I = N(I_0) \f$ 


\par 
where \f$ N(I_0) \f$ is a Poisson-distributed random variable of mean \f$ I_0 \f$ . The noise is thus dependent on the pixel intensities in the image.


The intensities in the image can be scaled by a user provided value to map pixel values to the actual number of particles. The scaling can be seen as the inverse of the gain used during the acquisition. The noisy signal is then scaled back to its input intensity range:

\par 
\f$ I = \frac{N(I_0 \times s)}{s} \f$ 


\par 
where \f$ s \f$ is the scale factor.


The Poisson-distributed variable \f$ \lambda \f$ is computed by using the algorithm:

\par 
\f$ \begin{array}{l} k \leftarrow 0 \\ p \leftarrow 1 \\ \textbf{repeat} \\ \left\{ \begin{array}{l} k \leftarrow k+1 \\ p \leftarrow p \ast U() \end{array} \right. \\ \textbf{until } p > e^{\lambda} \\ \textbf{return} (k) \end{array} \f$ 


\par 
where \f$ U() \f$ provides a uniformly distributed random variable in the interval \f$ [0,1] \f$ .


This algorithm is very inefficient for large values of \f$ \lambda \f$ , though. Fortunately, the Poisson distribution can be accurately approximated by a Gaussian distribution of mean and variance \f$ \lambda \f$ when \f$ \lambda \f$ is large enough. In this implementation, this value is considered to be 50. This leads to the faster algorithm:

\par 
\f$ \lambda + \sqrt{\lambda} \times N()\f$ 


\par 
where \f$ N() \f$ is a normally distributed random variable of mean 0 and variance 1.


\author Gaetan Lehmann


This code was contributed in the Insight Journal paper "Noise
Simulation". https://doi.org/10.54294/vh6vbw
\sa itk::simple::ShotNoise for the procedural interface
\sa itk::ShotNoiseImageFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT ShotNoiseImageFilter : public ImageFilter {
    public:
      using Self = ShotNoiseImageFilter;

      /** Destructor */
      virtual ~ShotNoiseImageFilter();

      /** Default Constructor that takes no arguments and initializes
       * default parameters */
      ShotNoiseImageFilter();

      /** Define the pixels types supported by this filter */
      using PixelIDTypeList = BasicPixelIDTypeList;
\

      /**
       * Set/Get the value to map the pixel value to the actual particle counting. The scaling can be seen as the inverse of the gain used during the acquisition. The noisy signal is then scaled back to its input intensity range. Defaults to 1.0.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetScale ( double Scale ) { this->m_Scale = Scale; return *this; }

      /**
       * Set/Get the value to map the pixel value to the actual particle counting. The scaling can be seen as the inverse of the gain used during the acquisition. The noisy signal is then scaled back to its input intensity range. Defaults to 1.0.
       */
      double GetScale() const { return this->m_Scale; }\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetSeed ( uint32_t Seed ) { this->m_Seed = Seed; return *this; }

      /**
       */
      uint32_t GetSeed() const { return this->m_Seed; }

      /** Name of this class */
      std::string GetName() const { return std::string ("ShotNoiseImageFilter"); }

      /** Print ourselves out */
      std::string ToString() const;


      /** Execute the filter on the input image */
#ifndef SWIG
      Image Execute ( Image&& image1 );
#endif
      Image Execute ( const Image& image1 );

    private:

      /** Setup for member function dispatching */

      using MemberFunctionType = Image (Self::*)( const Image& image1 );
      template <class TImageType> Image ExecuteInternal ( const Image& image1 );
      /** Dispatched methods which calls ExecuteInternal on each component */
      template <class TImageType> Image ExecuteInternalVectorImage ( const Image& image );

      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;
      friend struct detail::ExecuteInternalVectorImageAddressor<MemberFunctionType>;
      std::unique_ptr<detail::MemberFunctionFactory<MemberFunctionType> > m_MemberFactory;


      double  m_Scale{1.0};

      uint32_t  m_Seed{(uint32_t) itk::simple::sitkWallClock};


      bool m_InPlace{false};
    };

    /**\
     * \brief Alter an image with shot noise.
     *
     * This function directly calls the execute method of ShotNoiseImageFilter
     * in order to support a procedural API
     *
     * \sa itk::simple::ShotNoiseImageFilter for the object oriented interface
     * @{
     */
#ifndef SWIG
     SITKBasicFilters_EXPORT Image ShotNoise ( Image&& image1, double scale = 1.0, uint32_t seed = (uint32_t) itk::simple::sitkWallClock );
#endif
     SITKBasicFilters_EXPORT Image ShotNoise ( const Image& image1, double scale = 1.0, uint32_t seed = (uint32_t) itk::simple::sitkWallClock );

     /** @} */
}
#endif
