LCOV - code coverage report
Current view: top level - include/sigproc - psdVarMean.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 0.0 % 53 0
Test Date: 2026-08-30 22:23:37 Functions: 0.0 % 7 0

            Line data    Source code
       1              : /** \file psdVarMean.hpp
       2              :  * \brief Tools for calculating the variance of the mean of a PSD
       3              :  *
       4              :  * \author Jared R. Males (jaredmales@gmail.com)
       5              :  *
       6              :  * \ingroup signal_processing_files
       7              :  *
       8              :  */
       9              : 
      10              : //***********************************************************************//
      11              : // Copyright 2018,2019,2020 Jared R. Males (jaredmales@gmail.com)
      12              : //
      13              : // This file is part of mxlib.
      14              : //
      15              : // mxlib is free software: you can redistribute it and/or modify
      16              : // it under the terms of the GNU General Public License as published by
      17              : // the Free Software Foundation, either version 3 of the License, or
      18              : // (at your option) any later version.
      19              : //
      20              : // mxlib is distributed in the hope that it will be useful,
      21              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      22              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      23              : // GNU General Public License for more details.
      24              : //
      25              : // You should have received a copy of the GNU General Public License
      26              : // along with mxlib.  If not, see <http://www.gnu.org/licenses/>.
      27              : //***********************************************************************//
      28              : 
      29              : #ifndef psdVarMean_hpp
      30              : #define psdVarMean_hpp
      31              : 
      32              : #include <vector>
      33              : 
      34              : #include <gsl/gsl_integration.h>
      35              : #include <gsl/gsl_errno.h>
      36              : 
      37              : #include "../math/func/bessel.hpp"
      38              : #include "../math/constants.hpp"
      39              : #include "../math/gslInterpolator.hpp"
      40              : 
      41              : #include "psdFilter.hpp"
      42              : 
      43              : namespace mx
      44              : {
      45              : namespace sigproc
      46              : {
      47              : 
      48              : /// Parameters for calculating the variance of the mean from a numerical PSD.
      49              : /** Interpolates on the PSD for the integration.
      50              :  *
      51              :  *  \tparam realT the real floating point type of the frequency and PSD vectors. [Must be double due to GSL]
      52              :  */
      53              : template <typename _realT>
      54              : struct psdVarMeanParams
      55              : {
      56              :     typedef _realT realT;
      57              : 
      58              :     std::vector<realT> *freq{ nullptr }; ///< Pointer to the frequency vector
      59              :     std::vector<realT> *psd{ nullptr };  ///< Pointer to the psd vector
      60              :     realT T{ 0 };                        ///< The sample length (units appropriate for freq)
      61              : 
      62              :     realT minf{ 0 }; ///< The minimum frequency
      63              :     realT maxf{ 0 }; ///< The maximum frequency
      64              : 
      65              :     realT extrapAlpha{ 0 };
      66              : 
      67              :     bool initialized{ false }; ///< Flag controlling whether the interpolator is initialized
      68              : 
      69              : #ifdef MX_OLD_GSL
      70              :     math::gslInterpolator<math::gsl_interp_linear<realT>> terp; ///< Interpolator for the PSD
      71              : #else
      72              :     math::gslInterpolator<math::gsl_interp_steffen<realT>> terp; ///< Interpolator for the PSD
      73              : #endif
      74              : 
      75              :     /// Get the value of the PSD at k using interpolation
      76              :     /** Extrapolates outside the range of frequencies in freq.
      77              :      * Right now this is just constant.
      78              :      *
      79              :      * \todo implement better extrapolation past max-freq.
      80              :      */
      81            0 :     realT psdVal( realT k /**< [in] The transformed frequency coordinate */ )
      82              :     {
      83            0 :         if( !initialized )
      84              :         {
      85            0 :             if( freq == nullptr || psd == nullptr )
      86              :             {
      87            0 :                 std::cerr << "Vectors not set.\n";
      88            0 :                 exit( -1 );
      89              :             }
      90            0 :             if( T == 0 )
      91              :             {
      92            0 :                 std::cerr << "T not set.\n";
      93            0 :                 exit( -1 );
      94              :             }
      95              : 
      96            0 :             terp.setup( *freq, *psd );
      97              :             // #ifdef MX_OLD_GSL
      98              :             // terp.setup(gsl_interp_linear, *freq, *psd);
      99              :             // #else
     100              :             // terp.setup(gsl_interp_steffen, *freq, *psd);
     101              :             // #endif
     102              : 
     103            0 :             minf = ( *freq )[0];
     104            0 :             maxf = ( *freq )[freq->size() - 1];
     105              : 
     106            0 :             initialized = true;
     107              :         }
     108              : 
     109            0 :         realT f = ( 2.0 / T ) * k;
     110              : 
     111            0 :         if( f < minf )
     112            0 :             return ( *psd )[0];
     113              : 
     114            0 :         if( f > maxf )
     115              :         {
     116              :             // Enter extrapolation here
     117              :             // return 0;//(*psd)[psd->size()-1];
     118            0 :             if( extrapAlpha == 0 )
     119            0 :                 return 0;
     120              : 
     121            0 :             return ( *psd )[psd->size() - 1] * pow( f / maxf, -1 * extrapAlpha );
     122              :         }
     123              : 
     124            0 :         return terp( f );
     125              :     }
     126              : };
     127              : 
     128              : /// Integration worker function for psdVarMean::operator()
     129              : /**
     130              :  * \tparam paramsT the type of the parameter structure. See psdVarMean.
     131              :  *
     132              :  * \returns the value of the integrand at k
     133              :  *
     134              :  *
     135              :  */
     136              : template <typename paramsT>
     137            0 : typename paramsT::realT psdVarMeanFunc( typename paramsT::realT k, ///< [in] the scaled frequency coordinate
     138              :                                         void *params               ///< [in] pointer to the parameter structure
     139              : )
     140              : {
     141              :     typedef typename paramsT::realT realT;
     142              : 
     143            0 :     paramsT *pvar = (paramsT *)params;
     144              : 
     145            0 :     realT J = math::func::bessel_j<realT, realT>( 0.5, math::two_pi<realT>() * k );
     146              : 
     147            0 :     return J * J / k * pvar->psdVal( k );
     148              : }
     149              : 
     150              : /// Calculate the variance of the mean for a process given its PSD
     151              : /** Functor which manages the GSL integration workspace memory.
     152              :  *
     153              :  * \todo document the paramsT interface
     154              :  *
     155              :  * \tparam paramsT is a parameter structure with the correct interface.
     156              :  *
     157              :  *  \ingroup psds
     158              :  */
     159              : template <typename paramsT>
     160              : struct psdVarMean
     161              : {
     162              :     typedef typename paramsT::realT realT;
     163              : 
     164              :     realT extrapAlpha{ 0 }; ///< The extrapolation exponent.  No extrapolation if 0.
     165              : 
     166              :   protected:
     167              :     gsl_integration_workspace *w{ nullptr }; ///< The GSL integration workspace memory
     168              : 
     169              :     size_t wSize{ 10000 }; ///< The size of the GSL workspace
     170              : 
     171              :     /// Initializes the gsl library.
     172            0 :     void init()
     173              :     {
     174              :         ///\todo We'll get the occasional failure to reach tolerance error, just ignore them all for now.
     175            0 :         gsl_set_error_handler_off();
     176            0 :     }
     177              : 
     178              :   public:
     179              :     /// Default c'tor
     180            0 :     psdVarMean()
     181            0 :     {
     182            0 :         init();
     183            0 :     }
     184              : 
     185              :     /// Constructor which initializes workspace size
     186            0 :     psdVarMean( size_t wm /**< [in] Size of the GSL integration workspace*/ )
     187            0 :     {
     188            0 :         init();
     189            0 :         wSize = wm;
     190            0 :     }
     191              : 
     192              :     /// d'tor cleans up the workspace memory
     193            0 :     ~psdVarMean()
     194              :     {
     195            0 :         if( w != nullptr )
     196              :         {
     197            0 :             gsl_integration_workspace_free( w );
     198              :         }
     199            0 :     }
     200              : 
     201              :     /// Calculate the variance of the mean for a psd over a sample length
     202              :     /**
     203              :      * \returns the variance of the mean for the process governed by the PSD.
     204              :      */
     205            0 :     realT operator()( realT &error,             ///< [out] The error estimate returned by gsl_integration_qagiu
     206              :                       std::vector<realT> &freq, ///< [in] The frequency vector
     207              :                       std::vector<realT> &psd,  ///< [in] The psd vector
     208              :                       realT T                   ///< [in] The sample length (units approprate for freq)
     209              :     )
     210              :     {
     211            0 :         if( w == nullptr )
     212              :         {
     213            0 :             w = gsl_integration_workspace_alloc( wSize );
     214              :         }
     215              : 
     216              :         // Setup the integration parameters structure
     217            0 :         paramsT pvar;
     218              : 
     219            0 :         pvar.freq = &freq;
     220            0 :         pvar.psd = &psd;
     221            0 :         pvar.T = T;
     222              : 
     223            0 :         pvar.extrapAlpha = extrapAlpha;
     224              : 
     225              :         // Setup the function
     226              :         gsl_function func;
     227              : 
     228            0 :         func.function = &psdVarMeanFunc<paramsT>;
     229            0 :         func.params = &pvar;
     230              : 
     231              :         realT result;
     232              : 
     233            0 :         int ec = gsl_integration_qagiu( &func, 0.0, 1e-14, 1e-8, wSize, w, &result, &error );
     234              :         static_cast<void>( ec );
     235              : 
     236            0 :         return result / ( 2 * T );
     237            0 :     }
     238              : };
     239              : 
     240              : } // namespace sigproc
     241              : } // namespace mx
     242              : 
     243              : #endif // psdVarMean_hpp
        

Generated by: LCOV version 2.0-1