42#include "../mxlib.hpp"
44#include "../math/ft/fftT.hpp"
45#include "../math/vectorUtils.hpp"
65template <
typename realT>
77 for(
size_t i = 1; i < sz - 1; ++i )
82 var += half * PSD[sz - 1];
100template <
typename realT>
113 for( ; i < sz / 2; ++i )
118 var += half * PSD[i];
137template <
typename realT>
138realT
psdVar(
const std::vector<realT> &f,
139 const std::vector<realT> &PSD,
146 return psdVar2sided( f[1] - f[0], PSD.data(), PSD.size(), half );
150 return psdVar1sided( f[1] - f[0], PSD.data(), PSD.size(), half );
163template <
typename eigenArrT>
170 typename eigenArrT::Scalar half = 0.5;
174 typename eigenArrT::Scalar var = 0;
176 var = half * PSD( 0, 0 );
178 for(
int i = 1; i < freq.rows() - 1; ++i )
181 var += half * PSD( freq.rows() - 1, 0 );
183 var *= ( freq( 1, 0 ) - freq( 0, 0 ) );
201template <
class realT>
204 return ( f_max / ( 0.5 * dim ) );
216template<
typename eigenArr>
217void frequency_grid1D( eigenArr & vec,
218 typename eigenArr::Scalar dt,
219 bool inverse =
false )
221 typename eigenArr::Index dim, dim_1, dim_2;
222 typename eigenArr::Scalar df;
227 dim = std::max(dim_1, dim_2);
233 for(
int ii=0; ii < ceil(0.5*(dim-1) + 1); ++ii)
238 for(
int ii=ceil(0.5*(dim-1)+1); ii < dim_1; ++ii)
240 vec(ii) = (ii-dim)*df;
245 for(
int ii=0; ii < dim; ++ii)
247 vec(ii) = df * ii / dim;
261template <
typename realT,
typename realParamT>
263 std::vector<realT> &vec,
272 if( vec.size() % 2 == 1 )
278 realT df = ( 1.0 / dtTT ) / ( (realT)vec.size() );
280 for( ssize_t ii = 0; ii < ceil( 0.5 * ( vec.size() - 1 ) + 1 ); ++ii )
285 for( ssize_t ii = ceil( 0.5 * ( vec.size() - 1 ) + 1 ); ii < vec.size(); ++ii )
287 vec[ii] = ( ii - (ssize_t)vec.size() ) * df;
294 if( vec.size() % 2 == 0 )
296 realT df = ( 0.5 / dtTT ) / ( (realT)vec.size() - 1 );
297 for(
int ii = 0; ii < vec.size(); ++ii )
306 realT df = ( 0.5 / dt ) / ( (realT)vec.size() );
307 for(
int ii = 0; ii < vec.size(); ++ii )
309 vec[ii] = df * ( ii + 1 );
318template <
typename eigenArr,
typename realParamT>
319void frequencyGrid( eigenArr &arr, realParamT drT, eigenArr *k_x, eigenArr *k_y )
321 typename eigenArr::Scalar dr = drT;
323 typename eigenArr::Index dim_1, dim_2;
324 typename eigenArr::Scalar k_1, k_2, df;
330 k_x->resize( dim_1, dim_2 );
332 k_y->resize( dim_1, dim_2 );
336 for(
int ii = 0; ii < 0.5 * ( dim_1 - 1 ) + 1; ++ii )
339 for(
int jj = 0; jj < 0.5 * ( dim_2 - 1 ) + 1; ++jj )
343 arr( ii, jj ) = sqrt( k_1 * k_1 + k_2 * k_2 );
346 ( *k_x )( ii, jj ) = k_1;
348 ( *k_y )( ii, jj ) = k_2;
351 for(
int jj = 0.5 * ( dim_2 - 1 ) + 1; jj < dim_2; ++jj )
353 k_2 = ( jj - dim_2 ) * df;
355 arr( ii, jj ) = sqrt( k_1 * k_1 + k_2 * k_2 );
358 ( *k_x )( ii, jj ) = k_1;
360 ( *k_y )( ii, jj ) = k_2;
364 for(
int ii = 0.5 * ( dim_1 - 1 ) + 1; ii < dim_1; ++ii )
366 k_1 = ( ii - dim_1 ) * df;
367 for(
int jj = 0; jj < 0.5 * ( dim_2 - 1 ) + 1; ++jj )
371 arr( ii, jj ) = sqrt( k_1 * k_1 + k_2 * k_2 );
374 ( *k_x )( ii, jj ) = k_1;
376 ( *k_y )( ii, jj ) = k_2;
379 for(
int jj = 0.5 * ( dim_2 - 1 ) + 1; jj < dim_2; ++jj )
381 k_2 = ( jj - dim_2 ) * df;
383 arr( ii, jj ) = sqrt( k_1 * k_1 + k_2 * k_2 );
386 ( *k_x )( ii, jj ) = k_1;
388 ( *k_y )( ii, jj ) = k_2;
394template <
typename eigenArr>
401template <
typename eigenArr>
402void frequencyGrid( eigenArr &arr,
typename eigenArr::Scalar dt, eigenArr &k_x, eigenArr &k_y )
417template <
typename realT>
420 realT integ = 2 * ( pow( fmax, -1.0 * alpha + 1.0 ) - pow( fmin, -1.0 * alpha + 1.0 ) ) / ( -1.0 * alpha + 1.0 );
435template <
typename realT>
438 realT integ = 2 * ( pow( kmax, -1 * alpha + 2.0 ) - pow( kmin, -1.0 * alpha + 2.0 ) ) / ( -1 * alpha + 2.0 );
452template <
typename floatT,
typename floatParamT>
454 std::vector<floatT> &f,
456 floatT fmin = std::numeric_limits<floatT>::min(),
458 floatT fmax = std::numeric_limits<floatT>::max()
467 if( fmin != std::numeric_limits<floatT>::min() || fmax != std::numeric_limits<floatT>::max() )
469 for(
size_t i = 0; i < psd.size(); ++i )
471 if( fabs( f[i] ) < fmin || fabs( f[i] ) > fmax )
478 for(
size_t i = 0; i < psd.size(); ++i )
484 s *= ( f[1] - f[0] );
486 for(
size_t i = 0; i < psd.size(); ++i )
501template <
typename floatT,
typename floatParamT>
503normPSD( Eigen::Array<floatT, Eigen::Dynamic, Eigen::Dynamic> &psd,
504 Eigen::Array<floatT, Eigen::Dynamic, Eigen::Dynamic> &k,
506 floatT kmin = std::numeric_limits<floatT>::min(),
508 floatT kmax = std::numeric_limits<floatT>::max()
517 dk1 = k( 1, 0 ) - k( 0, 0 );
522 dk2 = k( 0, 1 ) - k( 0, 0 );
529 if( kmin != std::numeric_limits<floatT>::min() || kmax != std::numeric_limits<floatT>::max() )
531 for(
int c = 0; c < psd.cols(); ++c )
533 for(
int r = 0; r < psd.rows(); ++r )
535 if( fabs( k( r, c ) ) < kmin || fabs( k( r, c ) ) > kmax )
543 for(
int c = 0; c < psd.cols(); ++c )
545 for(
int r = 0; r < psd.rows(); ++r )
554 for(
int c = 0; c < psd.cols(); ++c )
556 for(
int r = 0; r < psd.rows(); ++r )
558 psd( r, c ) *= norm / s;
585template <
typename eigenArrp,
typename eigenArrf>
588 typename eigenArrp::Scalar alpha,
589 typename eigenArrp::Scalar beta = -1 )
591 typedef typename eigenArrp::Scalar Scalar;
593 typename eigenArrp::Index dim_1, dim_2;
604 fmax = freq.abs().maxCoeff();
607 fmin = ( freq.abs() > 0 ).select( freq.abs(), freq.abs() + fmax ).minCoeff();
612 for(
int ii = 0; ii < dim_1; ++ii )
614 for(
int jj = 0; jj < dim_2; ++jj )
616 if( freq( ii, jj ) == 0 )
622 p = beta / std::pow( std::abs( freq( ii, jj ) ), alpha );
644template <
typename floatT,
647 typename T0T = double,
648 typename t0T = double,
649 typename betaT =
double>
651 std::vector<floatfT> &f,
662 T02 = 1.0 / ( T0 * T0 );
669 floatT sqrt_alpha = 0.5 * alpha;
681 psd.resize( f.size() );
685 floatT _t0 =
static_cast<floatT
>( t0 );
686 for(
size_t i = 0; i < f.size(); ++i )
688 psd[i] = _beta / pow( pow( f[i], 2 ) + T02, sqrt_alpha ) * exp( -1 * pow( f[i] * _t0, 2 ) );
693 for(
size_t i = 0; i < f.size(); ++i )
695 psd[i] = _beta / pow( pow( f[i], 2 ) + T02, sqrt_alpha );
715template <
typename floatT>
717 std::vector<floatT> &f,
724 psd.resize( f.size() );
726 for(
int i = 0; i < f.size(); ++i )
728 floatT p = beta / ( 1 + pow( f[i] / fn, alpha ) );
757template <
typename eigenArrp,
typename eigenArrf,
typename alphaT,
typename L0T,
typename l0T,
typename betaT>
758void vonKarmanPSD( eigenArrp &psd, eigenArrf &freq, alphaT alpha, L0T L0 = 0, l0T l0 = 0, betaT beta = -1 )
760 typedef typename eigenArrp::Scalar Scalar;
762 typename eigenArrp::Index dim_1, dim_2;
775 fmax = freq.abs().maxCoeff();
778 fmin = ( freq.abs() > 0 ).select( freq.abs(), freq.abs() + fmax ).minCoeff();
780 _beta = beta =
oneoverf_norm( fmin, fmax,
static_cast<Scalar
>( alpha ) );
783 _beta =
static_cast<Scalar
>( beta );
787 L02 = 1.0 / ( L0 * L0 );
791 Scalar sqrt_alpha = 0.5 * alpha;
793 for(
int ii = 0; ii < dim_1; ++ii )
795 for(
int jj = 0; jj < dim_2; ++jj )
797 if( freq( ii, jj ) == 0 && L02 == 0 )
803 p = _beta / pow( pow( freq( ii, jj ), 2 ) + L02, sqrt_alpha );
805 p *= exp( -1 * pow( freq( ii, jj ) *
static_cast<Scalar
>( l0 ), 2 ) );
833template <
typename vectorTout,
typename vectorTin>
835 vectorTout &psdTwoSided,
836 vectorTin &psdOneSided,
839 typename vectorTin::value_type scale = 0.5
843 typedef typename vectorTout::value_type outT;
849 if( addZeroFreq == 0 )
852 N = 2 * psdOneSided.size() - 2;
856 N = 2 * psdOneSided.size();
859 psdTwoSided.resize( N );
864 psdTwoSided[0] = outT( 0.0 );
868 psdTwoSided[0] = outT( psdOneSided[0] );
873 for( i = 0; i < psdOneSided.size() - 1 - ( 1 - needZero ); ++i )
875 psdTwoSided[i + 1] = outT( psdOneSided[i + ( 1 - needZero )] * scale );
876 psdTwoSided[i + psdOneSided.size() + needZero] = outT( psdOneSided[psdOneSided.size() - 2 - i] * scale );
878 psdTwoSided[i + 1] = outT( psdOneSided[i + ( 1 - needZero )] );
894 std::vector<T> &freqTwoSided,
895 std::vector<T> &freqOneSided
902 if( freqOneSided[0] != 0 )
904 N = 2 * freqOneSided.size();
909 N = 2 * freqOneSided.size() - 2;
912 freqTwoSided.resize( N );
916 freqTwoSided[0] = 0.0;
920 freqTwoSided[0] = freqOneSided[0];
924 for( i = 0; i < freqOneSided.size() - 1 - ( 1 - needZero ); ++i )
926 freqTwoSided[i + 1] = freqOneSided[i + ( 1 - needZero )];
927 freqTwoSided[i + freqOneSided.size() + needZero] = -freqOneSided[freqOneSided.size() - 2 - i];
929 freqTwoSided[i + 1] = freqOneSided[i + ( 1 - needZero )];
949template <
typename realT>
951 std::vector<realT> &binPSD,
952 std::vector<realT> &freq,
953 std::vector<realT> &PSD,
955 bool binAtZero =
true
968 realT df = freq[1] - freq[0];
971 while( freq[i] <= 0.5 * binSize + 0.5 * df )
976 if( i >= freq.size() )
982 binFreq.push_back( 0 );
983 binPSD.push_back( PSD[0] );
987 binFreq.push_back( 0 );
988 binPSD.push_back( sumPSD / nSum );
997 while( i < freq.size() )
1000 while( freq[i] - startFreq + 0.5 * df < binSize )
1003 sumPSD += sc * PSD[i];
1008 if( i >= freq.size() - 1 )
1012 if( i < freq.size() )
1015 sumPSD += 0.5 * PSD[i];
1021 if( i < freq.size() )
1023 binFreq.push_back( sumFreq / nSum );
1028 binFreq.push_back( freq[freq.size() - 1] );
1031 binPSD.push_back( sumPSD / ( nSum - 1 ) );
1036 if( i >= freq.size() )
1041 startFreq = freq[i];
1045 realT var =
psdVar( freq, PSD );
1046 realT binv =
psdVar( binFreq, binPSD );
1048 for(
int i = 0; i < binFreq.size(); ++i )
1049 binPSD[i] *= var / binv;
error_t
The mxlib error codes.
@ noerror
No error has occurred.
@ invalidarg
An argument was invalid.
error_t mxlib_error_report(const error_t &code, const std::string &expl, const std::source_location &loc=std::source_location::current())
Print a report to stderr given an mxlib error_t code and explanation and return the code.
void oneoverf_psd(eigenArrp &psd, eigenArrf &freq, typename eigenArrp::Scalar alpha, typename eigenArrp::Scalar beta=-1)
Generates a power spectrum.
realT oneoverf_norm(realT fmin, realT fmax, realT alpha)
Calculate the normalization for a 1-D PSD.
void augment1SidedPSD(vectorTout &psdTwoSided, vectorTin &psdOneSided, bool addZeroFreq=false, typename vectorTin::value_type scale=0.5)
Augment a 1-sided PSD to standard 2-sided FFT form.
eigenArrT::Scalar psdVarDisabled(eigenArrT &freq, eigenArrT &PSD, bool trap=true)
Calculate the variance of a PSD.
realT oneoverk_norm(realT kmin, realT kmax, realT alpha)
Calculate the normalization for a 2-D PSD.
realT psdVar1sided(realT df, const realT *PSD, size_t sz, realT half=0.5)
Calculate the variance of a 1-D, 1-sided PSD.
void augment1SidedPSDFreq(std::vector< T > &freqTwoSided, std::vector< T > &freqOneSided)
Augment a 1-sided frequency scale to standard FFT form.
realT psdVar(const std::vector< realT > &f, const std::vector< realT > &PSD, realT half=0.5)
Calculate the variance of a 1-D PSD.
realT psdVar2sided(realT df, const realT *PSD, size_t sz, realT half=0.5)
Calculate the variance of a 1-D, 2-sided PSD.
mx::error_t vonKarmanPSD(std::vector< floatT > &psd, std::vector< floatfT > &f, alphaT alpha, T0T T0=0, t0T t0=0, betaT beta=1)
Generate a 1-D von Karman power spectrum.
realT freq_sampling(size_t dim, realT f_max)
Calculates the frequency sampling for a grid given maximum dimension and maximum frequency.
int kneePSD(std::vector< floatT > &psd, std::vector< floatT > &f, floatT beta, floatT fn, floatT alpha)
Generate a 1-D "knee" PSD.
int normPSD(std::vector< floatT > &psd, std::vector< floatT > &f, floatParamT normT, floatT fmin=std::numeric_limits< floatT >::min(), floatT fmax=std::numeric_limits< floatT >::max())
Normalize a 1-D PSD to have a given variance.
int frequencyGrid(std::vector< realT > &vec, realParamT dt, bool fftOrder=true)
Create a 1-D frequency grid.
int rebin1SidedPSD(std::vector< realT > &binFreq, std::vector< realT > &binPSD, std::vector< realT > &freq, std::vector< realT > &PSD, realT binSize, bool binAtZero=true)
Rebin a PSD, including its frequency scale, to a larger frequency bin size (fewer bins)