LCOV - code coverage report
Current view: top level - include/math/fit - fitGammaDistribution.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 0.0 % 4 0
Test Date: 2026-08-30 22:23:37 Functions: 0.0 % 1 0

            Line data    Source code
       1              : /** \file fitGammaDistribution.hpp
       2              :  * \author Jared R. Males
       3              :  * \brief Tools for fitting the GammaDistribution distribution to data.
       4              :  * \ingroup fitting_files
       5              :  *
       6              :  */
       7              : 
       8              : //***********************************************************************//
       9              : // Copyright 2023 Jared R. Males (jaredmales@gmail.com)
      10              : //
      11              : // This file is part of mxlib.
      12              : //
      13              : // mxlib is free software: you can redistribute it and/or modify
      14              : // it under the terms of the GNU General Public License as published by
      15              : // the Free Software Foundation, either version 3 of the License, or
      16              : // (at your option) any later version.
      17              : //
      18              : // mxlib is distributed in the hope that it will be useful,
      19              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      20              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      21              : // GNU General Public License for more details.
      22              : //
      23              : // You should have received a copy of the GNU General Public License
      24              : // along with mxlib.  If not, see <http://www.gnu.org/licenses/>.
      25              : //***********************************************************************//
      26              : 
      27              : #ifndef fitGammaDistribution_hpp
      28              : #define fitGammaDistribution_hpp
      29              : 
      30              : #include "levmarInterface.hpp"
      31              : #include "../func/gammaDistribution.hpp"
      32              : 
      33              : namespace mx
      34              : {
      35              : namespace math
      36              : {
      37              : namespace fit
      38              : {
      39              : 
      40              : template <typename realT>
      41              : struct array2FitGammaDistribution;
      42              : 
      43              : /** \defgroup gammaDist_peak_fit Gamma Distribution
      44              :  * \brief Fitting the Gamma Distribution to data.
      45              :  *
      46              :  * The Gamma Distribution is fit to data.
      47              :  *
      48              :  * \ingroup peak_fit
      49              :  */
      50              : 
      51              : /// Class to manage fitting the GammaDistribution Distribution to data via the \ref levmarInterface
      52              : /** In addition to the requirements on fitterT specified by \ref levmarInterface
      53              :  * this class also requires this definition in fitterT
      54              :  * \code
      55              :  * static const int nparams = 3;
      56              :  * \endcode
      57              :  * where the number 3 is replaced by the number of parameters that fitterT expects to fit.
      58              :  *
      59              :  * \tparam fitterT a type meeting the above requirements.
      60              :  *
      61              :  * \ingroup gammaDist_peak_fit
      62              :  *
      63              :  */
      64              : template <typename fitterT>
      65              : class fitGammaDistribution : public levmarInterface<fitterT>
      66              : {
      67              : 
      68              :   public:
      69              :     typedef typename fitterT::realT realT;
      70              : 
      71              :     static const int nparams = fitterT::nparams;
      72              : 
      73              :     array2FitGammaDistribution<realT> arr;
      74              : 
      75              :     void initialize()
      76              :     {
      77              :         this->allocate_params( nparams );
      78              :         this->adata = &arr;
      79              :     }
      80              : 
      81              :     fitGammaDistribution()
      82              :     {
      83              :         initialize();
      84              :     }
      85              : 
      86              :     ~fitGammaDistribution()
      87              :     {
      88              :     }
      89              : 
      90              :     /// Set the initial guess.
      91              :     void setGuess( realT x0,    ///< [in] the location parameter
      92              :                    realT k,     ///< [in] the shape parameter
      93              :                    realT theta, ///< [in] the scale parameter
      94              :                    realT denom  ///< [in] the denominator or 1/peak-scale
      95              :     )
      96              :     {
      97              :         static_assert( nparams == 4, "fitGammaDistribution: Wrong setGuess called for no location parameter." );
      98              : 
      99              :         this->p[2] = x0; // this is p[2] to make it easy to leave out
     100              :         this->p[0] = k;
     101              :         this->p[1] = theta;
     102              :         this->p[3] = denom;
     103              :     }
     104              : 
     105              :     /// Set the initial guess.
     106              :     void setGuess( realT x0,   ///< [in] the location parameter
     107              :                    realT k,    ///< [in] the shape parameter
     108              :                    realT theta ///< [in] the scale parameter
     109              :     )
     110              :     {
     111              :         static_assert( nparams == 3, "fitGammaDistribution: Wrong setGuess called for no location parameter." );
     112              : 
     113              :         this->p[2] = x0; // this is p[2] to make it easy to leave out
     114              :         this->p[0] = k;
     115              :         this->p[1] = theta;
     116              :     }
     117              : 
     118              :     /// Set the initial guess when no location parameter is used.
     119              :     void setGuess( realT k,    ///< [in] the shape parameter
     120              :                    realT theta ///< [in] the scale parameter
     121              :     )
     122              :     {
     123              :         static_assert( nparams == 2, "fitGammaDistribution: Wrong setGuess called for location parameter." );
     124              : 
     125              :         this->p[0] = k;
     126              :         this->p[1] = theta;
     127              :     }
     128              : 
     129              :     void setArray( realT *data, int n )
     130              :     {
     131              :         arr.data = data;
     132              :         arr.n = n;
     133              : 
     134              :         this->n = n;
     135              :     }
     136              : 
     137              :     void x0( realT nx0 )
     138              :     {
     139              :         arr.x0 = nx0;
     140              :         if( nparams == 3 )
     141              :         {
     142              :             this->p[2] = nx0; // this is p[2] to make it easy to leave out
     143              :         }
     144              :     }
     145              : 
     146              :     void k( realT nk )
     147              :     {
     148              :         arr.k = nk;
     149              :         this->p[0] = nk;
     150              :     }
     151              : 
     152            0 :     void theta( realT na )
     153              :     {
     154            0 :         arr.theta = na;
     155            0 :         this->p[1] = na;
     156            0 :     }
     157              : 
     158              :     void denom( realT nd )
     159              :     {
     160              :         arr.denom = nd;
     161              :         if( nparams == 4 )
     162              :         {
     163              :             this->p[3] = nd;
     164              :         }
     165              :     }
     166              : 
     167              :     int fit()
     168              :     {
     169              :         return levmarInterface<fitterT>::fit();
     170              :     }
     171              : 
     172              :     realT x0()
     173              :     {
     174              :         if( nparams == 3 )
     175              :         {
     176              :             return this->p[2];
     177              :         }
     178              :         else
     179              :         {
     180              :             return 0;
     181              :         }
     182              :     }
     183              : 
     184              :     realT k()
     185              :     {
     186              :         return this->p[0];
     187              :     }
     188              : 
     189              :     realT theta()
     190              :     {
     191              :         return this->p[1];
     192              :     }
     193              : 
     194              :     realT denom()
     195              :     {
     196              :         if( nparams == 4 )
     197              :         {
     198              :             return this->p[3];
     199              :         }
     200              :         else
     201              :         {
     202              :             return func::gammaDistributionDenom<realT>( this->p[0], this->p[1] );
     203              :         }
     204              :     }
     205              : };
     206              : 
     207              : /// Wrapper for a native array to pass to \ref levmarInterface, with GammaDistribution details.
     208              : /** \ingroup gammaDist_peak_fit
     209              :  */
     210              : template <typename realT>
     211              : struct array2FitGammaDistribution
     212              : {
     213              :     realT *data{ nullptr }; ///< Pointer to the array
     214              :     size_t n{ 0 };          ///< dimension of the array
     215              : 
     216              :     realT x0{ 0 };    ///< the location parameter.
     217              :     realT k{ 0 };     ///< the shape parameter
     218              :     realT theta{ 0 }; ///< the scale parameter
     219              :     realT denom{ 0 }; ///< the denominator or 1/peak-scale
     220              : };
     221              : 
     222              : ///\ref levmarInterface fitter structure for the shifted Gamma Distribution with arbitrary peak scaling
     223              : /**
     224              :  *
     225              :  * \ingroup gammaDist_peak_fit
     226              :  *
     227              :  */
     228              : template <typename _realT>
     229              : struct gammaDistribution_4param_fitter
     230              : {
     231              :     typedef _realT realT;
     232              : 
     233              :     static const int nparams = 4;
     234              : 
     235              :     static void func( realT *p, realT *hx, int m, int n, void *adata )
     236              :     {
     237              :         array2FitGammaDistribution<realT> *arr = (array2FitGammaDistribution<realT> *)adata;
     238              : 
     239              :         for( int i = 0; i < arr->n; i++ )
     240              :         {
     241              :             hx[i] = func::gammaDistribution<realT>( i, p[2], p[0], p[1], p[3] ) - arr->data[i];
     242              :         }
     243              :     }
     244              : };
     245              : 
     246              : ///\ref levmarInterface fitter structure for the shifted Gamma Distribution
     247              : /**
     248              :  *
     249              :  * \ingroup gammaDist_peak_fit
     250              :  *
     251              :  */
     252              : template <typename _realT>
     253              : struct gammaDistribution_3param_fitter
     254              : {
     255              :     typedef _realT realT;
     256              : 
     257              :     static const int nparams = 3;
     258              : 
     259              :     static void func( realT *p, realT *hx, int m, int n, void *adata )
     260              :     {
     261              :         array2FitGammaDistribution<realT> *arr = (array2FitGammaDistribution<realT> *)adata;
     262              : 
     263              :         realT denom = func::gammaDistributionDenom<realT>( p[0], p[1] );
     264              : 
     265              :         for( int i = 0; i < arr->n; i++ )
     266              :         {
     267              :             hx[i] = func::gammaDistribution<realT>( i, p[2], p[0], p[1], denom ) - arr->data[i];
     268              :         }
     269              :     }
     270              : };
     271              : 
     272              : ///\ref levmarInterface fitter structure for the Gamma Distribution
     273              : /**
     274              :  *
     275              :  * \ingroup gammaDist_peak_fit
     276              :  *
     277              :  */
     278              : template <typename _realT>
     279              : struct gammaDistribution_2param_fitter
     280              : {
     281              :     typedef _realT realT;
     282              : 
     283              :     static const int nparams = 2;
     284              : 
     285              :     static void func( realT *p, realT *hx, int m, int n, void *adata )
     286              :     {
     287              :         array2FitGammaDistribution<realT> *arr = (array2FitGammaDistribution<realT> *)adata;
     288              : 
     289              :         realT denom = func::gammaDistributionDenom<realT>( p[0], p[1] );
     290              : 
     291              :         for( int i = 0; i < arr->n; i++ )
     292              :         {
     293              :             hx[i] = func::gammaDistribution<realT>( i, 0.0, p[0], p[1], denom ) - arr->data[i];
     294              :         }
     295              :     }
     296              : };
     297              : 
     298              : } // namespace fit
     299              : } // namespace math
     300              : } // namespace mx
     301              : 
     302              : #endif // fitGammaDistribution_hpp
        

Generated by: LCOV version 2.0-1