/*=========================================================================
*
*  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 sitkProjectedLandweberDeconvolutionImageFilter_h
#define sitkProjectedLandweberDeconvolutionImageFilter_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 ProjectedLandweberDeconvolutionImageFilter
\brief Deconvolve an image using the projected Landweber deconvolution algorithm.

This filter performs the same calculation per iteration as the LandweberDeconvolutionImageFilter . However, at each iteration, negative pixels in the intermediate result are projected (set) to zero. This is useful if the solution is assumed to always be non-negative, which is the case when dealing with images formed by counting photons, for example.

This code was adapted from the Insight Journal contribution:

"Deconvolution: infrastructure and reference algorithms" by Gaetan Lehmann https://doi.org/10.54294/tvgfv1 

\author Gaetan Lehmann, Biologie du Developpement et de la Reproduction, INRA de Jouy-en-Josas, France 


\author Cory Quammen, The University of North Carolina at Chapel Hill


\see IterativeDeconvolutionImageFilter 


\see RichardsonLucyDeconvolutionImageFilter 


\see LandweberDeconvolutionImageFilter
\sa itk::simple::ProjectedLandweberDeconvolution for the procedural interface
\sa itk::ProjectedLandweberDeconvolutionImageFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT ProjectedLandweberDeconvolutionImageFilter : public ImageFilter {
    public:
      using Self = ProjectedLandweberDeconvolutionImageFilter;

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

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

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

      /**
       * Set the relaxation factor.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetAlpha ( double Alpha ) { this->m_Alpha = Alpha; return *this; }

      /**
       * Get the relaxation factor.
       */
      double GetAlpha() const { return this->m_Alpha; }\

      /**
       * Set the number of iterations.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetNumberOfIterations ( int NumberOfIterations ) { this->m_NumberOfIterations = NumberOfIterations; return *this; }

      /**
       * Get the number of iterations.
       */
      int GetNumberOfIterations() const { return this->m_NumberOfIterations; }\

      /**
       * Normalize the output image by the sum of the kernel components

       */
      SITK_RETURN_SELF_TYPE_HEADER SetNormalize ( bool Normalize ) { this->m_Normalize = Normalize; return *this; }

      /** Set the value of Normalize to true or false respectfully. */
      SITK_RETURN_SELF_TYPE_HEADER NormalizeOn() { return this->SetNormalize(true); }
      SITK_RETURN_SELF_TYPE_HEADER NormalizeOff() { return this->SetNormalize(false); }

      /**
       */
      bool GetNormalize() const { return this->m_Normalize; }

      typedef enum {ZERO_PAD,ZERO_FLUX_NEUMANN_PAD,PERIODIC_PAD} BoundaryConditionType;\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetBoundaryCondition ( BoundaryConditionType BoundaryCondition ) { this->m_BoundaryCondition = BoundaryCondition; return *this; }

      /**
       */
      BoundaryConditionType GetBoundaryCondition() const { return this->m_BoundaryCondition; }

      typedef enum {SAME,VALID} OutputRegionModeType;\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetOutputRegionMode ( OutputRegionModeType OutputRegionMode ) { this->m_OutputRegionMode = OutputRegionMode; return *this; }

      /**
       */
      OutputRegionModeType GetOutputRegionMode() const { return this->m_OutputRegionMode; }

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

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


      /** Execute the filter on the input images */

      Image Execute ( const Image& image1, const Image& image2 );

    private:

      /** Setup for member function dispatching */

      using MemberFunctionType = Image (Self::*)( const Image& image1, const Image& image2 );
      template <class TImageType> Image ExecuteInternal ( const Image& image1, const Image& image2 );


      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;

      std::unique_ptr<detail::MemberFunctionFactory<MemberFunctionType> > m_MemberFactory;


      double  m_Alpha{0.1};

      int  m_NumberOfIterations{1};

      /*  */
      bool  m_Normalize{false};

      BoundaryConditionType  m_BoundaryCondition{itk::simple::ProjectedLandweberDeconvolutionImageFilter::ZERO_FLUX_NEUMANN_PAD};

      OutputRegionModeType  m_OutputRegionMode{itk::simple::ProjectedLandweberDeconvolutionImageFilter::SAME};


    };

    /**\
     * \brief Deconvolve an image using the projected Landweber deconvolution algorithm.
     *
     * This function directly calls the execute method of ProjectedLandweberDeconvolutionImageFilter
     * in order to support a procedural API
     *
     * \sa itk::simple::ProjectedLandweberDeconvolutionImageFilter for the object oriented interface
     * @{
     */

     SITKBasicFilters_EXPORT Image ProjectedLandweberDeconvolution ( const Image& image1, const Image& image2, double alpha = 0.1, int numberOfIterations = 1, bool normalize = false, ProjectedLandweberDeconvolutionImageFilter::BoundaryConditionType boundaryCondition = itk::simple::ProjectedLandweberDeconvolutionImageFilter::ZERO_FLUX_NEUMANN_PAD, ProjectedLandweberDeconvolutionImageFilter::OutputRegionModeType outputRegionMode = itk::simple::ProjectedLandweberDeconvolutionImageFilter::SAME );

     /** @} */
}
#endif
