64template <
typename realT>
76 for(
size_t i = 1; i < sz - 1; ++i )
81 var += half * PSD[sz - 1];
98template <
typename realT>
111 for( ; i < sz / 2; ++i )
116 var += half * PSD[i];
134template <
typename realT>
135realT
psdVar(
const std::vector<realT> &f,
136 const std::vector<realT> &PSD,
143 return psdVar2sided( f[1] - f[0], PSD.data(), PSD.size(), half );
147 return psdVar1sided( f[1] - f[0], PSD.data(), PSD.size(), half );
160template <
typename eigenArrT>
167 typename eigenArrT::Scalar half = 0.5;
171 typename eigenArrT::Scalar var = 0;
173 var = half * PSD( 0, 0 );
175 for(
int i = 1; i < freq.rows() - 1; ++i )
178 var += half * PSD( freq.rows() - 1, 0 );
180 var *= ( freq( 1, 0 ) - freq( 0, 0 ) );
198template <
class realT>
201 return ( f_max / ( 0.5 * dim ) );
213template<
typename eigenArr>
214void frequency_grid1D( eigenArr & vec,
215 typename eigenArr::Scalar dt,
216 bool inverse =
false )
218 typename eigenArr::Index dim, dim_1, dim_2;
219 typename eigenArr::Scalar df;
224 dim = std::max(dim_1, dim_2);
230 for(
int ii=0; ii < ceil(0.5*(dim-1) + 1); ++ii)
235 for(
int ii=ceil(0.5*(dim-1)+1); ii < dim_1; ++ii)
237 vec(ii) = (ii-dim)*df;
242 for(
int ii=0; ii < dim; ++ii)
244 vec(ii) = df * ii / dim;
257template <
typename realT,
typename realParamT>
259 std::vector<realT> &vec,
268 if( vec.size() % 2 == 1 )
274 realT df = ( 1.0 / dtTT ) / ( (realT)vec.size() );
276 for( ssize_t ii = 0; ii < ceil( 0.5 * ( vec.size() - 1 ) + 1 ); ++ii )
281 for( ssize_t ii = ceil( 0.5 * ( vec.size() - 1 ) + 1 ); ii < vec.size(); ++ii )
283 vec[ii] = ( ii - (ssize_t)vec.size() ) * df;
290 if( vec.size() % 2 == 0 )
292 realT df = ( 0.5 / dtTT ) / ( (realT)vec.size() - 1 );
293 for(
int ii = 0; ii < vec.size(); ++ii )
302 realT df = ( 0.5 / dt ) / ( (realT)vec.size() );
303 for(
int ii = 0; ii < vec.size(); ++ii )
305 vec[ii] = df * ( ii + 1 );
314template <
typename eigenArr,
typename realParamT>
315void frequencyGrid( eigenArr &arr, realParamT drT, eigenArr *k_x, eigenArr *k_y )
317 typename eigenArr::Scalar dr = drT;
319 typename eigenArr::Index dim_1, dim_2;
320 typename eigenArr::Scalar k_1, k_2, df;
326 k_x->resize( dim_1, dim_2 );
328 k_y->resize( dim_1, dim_2 );
332 for(
int ii = 0; ii < 0.5 * ( dim_1 - 1 ) + 1; ++ii )
335 for(
int jj = 0; jj < 0.5 * ( dim_2 - 1 ) + 1; ++jj )
339 arr( ii, jj ) = sqrt( k_1 * k_1 + k_2 * k_2 );
342 ( *k_x )( ii, jj ) = k_1;
344 ( *k_y )( ii, jj ) = k_2;
347 for(
int jj = 0.5 * ( dim_2 - 1 ) + 1; jj < dim_2; ++jj )
349 k_2 = ( jj - dim_2 ) * df;
351 arr( ii, jj ) = sqrt( k_1 * k_1 + k_2 * k_2 );
354 ( *k_x )( ii, jj ) = k_1;
356 ( *k_y )( ii, jj ) = k_2;
360 for(
int ii = 0.5 * ( dim_1 - 1 ) + 1; ii < dim_1; ++ii )
362 k_1 = ( ii - dim_1 ) * df;
363 for(
int jj = 0; jj < 0.5 * ( dim_2 - 1 ) + 1; ++jj )
367 arr( ii, jj ) = sqrt( k_1 * k_1 + k_2 * k_2 );
370 ( *k_x )( ii, jj ) = k_1;
372 ( *k_y )( ii, jj ) = k_2;
375 for(
int jj = 0.5 * ( dim_2 - 1 ) + 1; jj < dim_2; ++jj )
377 k_2 = ( jj - dim_2 ) * df;
379 arr( ii, jj ) = sqrt( k_1 * k_1 + k_2 * k_2 );
382 ( *k_x )( ii, jj ) = k_1;
384 ( *k_y )( ii, jj ) = k_2;
390template <
typename eigenArr>
397template <
typename eigenArr>
398void frequencyGrid( eigenArr &arr,
typename eigenArr::Scalar dt, eigenArr &k_x, eigenArr &k_y )
413template <
typename realT>
416 realT integ = 2 * ( pow( fmax, -1.0 * alpha + 1.0 ) - pow( fmin, -1.0 * alpha + 1.0 ) ) / ( -1.0 * alpha + 1.0 );
431template <
typename realT>
434 realT integ = 2 * ( pow( kmax, -1 * alpha + 2.0 ) - pow( kmin, -1.0 * alpha + 2.0 ) ) / ( -1 * alpha + 2.0 );
447template <
typename floatT,
typename floatParamT>
449 std::vector<floatT> &f,
451 floatT fmin = std::numeric_limits<floatT>::min(),
453 floatT fmax = std::numeric_limits<floatT>::max()
462 if( fmin != std::numeric_limits<floatT>::min() || fmax != std::numeric_limits<floatT>::max() )
464 for(
size_t i = 0; i < psd.size(); ++i )
466 if( fabs( f[i] ) < fmin || fabs( f[i] ) > fmax )
473 for(
size_t i = 0; i < psd.size(); ++i )
479 s *= ( f[1] - f[0] );
481 for(
size_t i = 0; i < psd.size(); ++i )
495template <
typename floatT,
typename floatParamT>
497normPSD( Eigen::Array<floatT, Eigen::Dynamic, Eigen::Dynamic> &psd,
498 Eigen::Array<floatT, Eigen::Dynamic, Eigen::Dynamic> &k,
500 floatT kmin = std::numeric_limits<floatT>::min(),
502 floatT kmax = std::numeric_limits<floatT>::max()
511 dk1 = k( 1, 0 ) - k( 0, 0 );
516 dk2 = k( 0, 1 ) - k( 0, 0 );
523 if( kmin != std::numeric_limits<floatT>::min() || kmax != std::numeric_limits<floatT>::max() )
525 for(
int c = 0; c < psd.cols(); ++c )
527 for(
int r = 0; r < psd.rows(); ++r )
529 if( fabs( k( r, c ) ) < kmin || fabs( k( r, c ) ) > kmax )
537 for(
int c = 0; c < psd.cols(); ++c )
539 for(
int r = 0; r < psd.rows(); ++r )
548 for(
int c = 0; c < psd.cols(); ++c )
550 for(
int r = 0; r < psd.rows(); ++r )
552 psd( r, c ) *= norm / s;
579template <
typename eigenArrp,
typename eigenArrf>
582 typename eigenArrp::Scalar alpha,
583 typename eigenArrp::Scalar beta = -1 )
585 typedef typename eigenArrp::Scalar Scalar;
587 typename eigenArrp::Index dim_1, dim_2;
598 fmax = freq.abs().maxCoeff();
601 fmin = ( freq.abs() > 0 ).select( freq.abs(), freq.abs() + fmax ).minCoeff();
606 for(
int ii = 0; ii < dim_1; ++ii )
608 for(
int jj = 0; jj < dim_2; ++jj )
610 if( freq( ii, jj ) == 0 )
616 p = beta / std::pow( std::abs( freq( ii, jj ) ), alpha );
638template <
typename floatT,
641 typename T0T = double,
642 typename t0T = double,
643 typename betaT =
double>
645 std::vector<floatfT> &f,
656 T02 = 1.0 / ( T0 * T0 );
663 floatT sqrt_alpha = 0.5 * alpha;
675 psd.resize( f.size() );
679 floatT _t0 =
static_cast<floatT
>( t0 );
680 for(
size_t i = 0; i < f.size(); ++i )
682 psd[i] = _beta / pow( pow( f[i], 2 ) + T02, sqrt_alpha ) * exp( -1 * pow( f[i] * _t0, 2 ) );
687 for(
size_t i = 0; i < f.size(); ++i )
689 psd[i] = _beta / pow( pow( f[i], 2 ) + T02, sqrt_alpha );
709template <
typename floatT>
711 std::vector<floatT> &f,
718 psd.resize( f.size() );
720 for(
int i = 0; i < f.size(); ++i )
722 floatT p = beta / ( 1 + pow( f[i] / fn, alpha ) );
751template <
typename eigenArrp,
typename eigenArrf,
typename alphaT,
typename L0T,
typename l0T,
typename betaT>
752void vonKarmanPSD( eigenArrp &psd, eigenArrf &freq, alphaT alpha, L0T L0 = 0, l0T l0 = 0, betaT beta = -1 )
754 typedef typename eigenArrp::Scalar Scalar;
756 typename eigenArrp::Index dim_1, dim_2;
769 fmax = freq.abs().maxCoeff();
772 fmin = ( freq.abs() > 0 ).select( freq.abs(), freq.abs() + fmax ).minCoeff();
774 _beta = beta =
oneoverf_norm( fmin, fmax,
static_cast<Scalar
>( alpha ) );
777 _beta =
static_cast<Scalar
>( beta );
781 L02 = 1.0 / ( L0 * L0 );
785 Scalar sqrt_alpha = 0.5 * alpha;
787 for(
int ii = 0; ii < dim_1; ++ii )
789 for(
int jj = 0; jj < dim_2; ++jj )
791 if( freq( ii, jj ) == 0 && L02 == 0 )
797 p = _beta / pow( pow( freq( ii, jj ), 2 ) + L02, sqrt_alpha );
799 p *= exp( -1 * pow( freq( ii, jj ) *
static_cast<Scalar
>( l0 ), 2 ) );
826template <
typename vectorTout,
typename vectorTin>
828 vectorTout &psdTwoSided,
829 vectorTin &psdOneSided,
832 typename vectorTin::value_type scale = 0.5
836 typedef typename vectorTout::value_type outT;
842 if( addZeroFreq == 0 )
845 N = 2 * psdOneSided.size() - 2;
849 N = 2 * psdOneSided.size();
852 psdTwoSided.resize( N );
857 psdTwoSided[0] = outT( 0.0 );
861 psdTwoSided[0] = outT( psdOneSided[0] );
866 for( i = 0; i < psdOneSided.size() - 1 - ( 1 - needZero ); ++i )
868 psdTwoSided[i + 1] = outT( psdOneSided[i + ( 1 - needZero )] * scale );
869 psdTwoSided[i + psdOneSided.size() + needZero] = outT( psdOneSided[psdOneSided.size() - 2 - i] * scale );
871 psdTwoSided[i + 1] = outT( psdOneSided[i + ( 1 - needZero )] );
886 std::vector<T> &freqTwoSided,
887 std::vector<T> &freqOneSided
894 if( freqOneSided[0] != 0 )
896 N = 2 * freqOneSided.size();
901 N = 2 * freqOneSided.size() - 2;
904 freqTwoSided.resize( N );
908 freqTwoSided[0] = 0.0;
912 freqTwoSided[0] = freqOneSided[0];
916 for( i = 0; i < freqOneSided.size() - 1 - ( 1 - needZero ); ++i )
918 freqTwoSided[i + 1] = freqOneSided[i + ( 1 - needZero )];
919 freqTwoSided[i + freqOneSided.size() + needZero] = -freqOneSided[freqOneSided.size() - 2 - i];
921 freqTwoSided[i + 1] = freqOneSided[i + ( 1 - needZero )];
941template <
typename realT>
943 std::vector<realT> &binPSD,
944 std::vector<realT> &freq,
945 std::vector<realT> &PSD,
947 bool binAtZero =
true
960 realT df = freq[1] - freq[0];
963 while( freq[i] <= 0.5 * binSize + 0.5 * df )
968 if( i >= freq.size() )
974 binFreq.push_back( 0 );
975 binPSD.push_back( PSD[0] );
979 binFreq.push_back( 0 );
980 binPSD.push_back( sumPSD / nSum );
989 while( i < freq.size() )
992 while( freq[i] - startFreq + 0.5 * df < binSize )
995 sumPSD += sc * PSD[i];
1000 if( i >= freq.size() - 1 )
1004 if( i < freq.size() )
1007 sumPSD += 0.5 * PSD[i];
1013 if( i < freq.size() )
1015 binFreq.push_back( sumFreq / nSum );
1020 binFreq.push_back( freq[freq.size() - 1] );
1023 binPSD.push_back( sumPSD / ( nSum - 1 ) );
1028 if( i >= freq.size() )
1033 startFreq = freq[i];
1037 realT var =
psdVar( freq, PSD );
1038 realT binv =
psdVar( binFreq, binPSD );
1040 for(
int i = 0; i < binFreq.size(); ++i )
1041 binPSD[i] *= var / binv;
The Fast Fourier Transform interface.
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).
Declarations of some libarary wide utilities.
Header for the std::vector utilities.