36 #include <type_traits>
38 #include <Eigen/Dense>
42 #include "../mxError.hpp"
44 #include "../math/fft/fft.hpp"
45 #include "../math/vectorUtils.hpp"
66 template<
typename realT>
77 for(
size_t i=1; i<sz-1;++i) var += PSD[i];
79 var += half*PSD[sz-1];
97 template<
typename realT>
132 template<
typename realT>
133 realT
psdVar(
const std::vector<realT> & f,
134 const std::vector<realT> & PSD,
138 if(f.back() < 0)
return psdVar2sided(f[1]-f[0], PSD.data(), PSD.size(), half);
139 else return psdVar1sided(f[1]-f[0], PSD.data(), PSD.size(), half);
151 template<
typename eigenArrT>
157 typename eigenArrT::Scalar half = 0.5;
158 if(!trap) half = 1.0;
160 typename eigenArrT::Scalar var = 0;
164 for(
int i=1; i<freq.rows()-1;++i) var += PSD(i,0);
166 var += half*PSD(freq.rows()-1,0);
168 var *= (freq(1,0)-freq(0,0));
186 template<
class realT>
190 return (f_max/(0.5*dim));
202 template<
typename eigenArr>
204 typename eigenArr::Scalar dt,
205 bool inverse =
false )
207 typename eigenArr::Index dim, dim_1, dim_2;
208 typename eigenArr::Scalar df;
213 dim = std::max(dim_1, dim_2);
219 for(
int ii=0; ii < ceil(0.5*(dim-1) + 1); ++ii)
224 for(
int ii=ceil(0.5*(dim-1)+1); ii < dim_1; ++ii)
226 vec(ii) = (ii-dim)*df;
231 for(
int ii=0; ii < dim; ++ii)
233 vec(ii) = df * ii / dim;
248 template<
typename realT,
typename realParamT>
258 if(vec.size() % 2 == 1)
260 mxError(
"frequencyGrid", MXE_INVALIDARG,
"Frequency scale can't be odd-sized for FFT order");
264 realT df = (1.0/dtTT)/((realT) vec.size());
266 for(ssize_t ii=0; ii < ceil(0.5*(vec.size()-1) + 1); ++ii)
271 for(ssize_t ii=ceil(0.5*(vec.size()-1)+1); ii < vec.size(); ++ii)
273 vec[ii] = (ii-(ssize_t)vec.size())*df;
280 if(vec.size() % 2 == 0)
282 realT df = (0.5/dtTT)/((realT) vec.size() - 1);
283 for(
int ii=0; ii < vec.size(); ++ii)
292 realT df = (0.5/dt)/((realT) vec.size());
293 for(
int ii=0; ii < vec.size(); ++ii)
295 vec[ii] = df * (ii+1);
304 template<
typename eigenArr,
typename realParamT>
311 typename eigenArr::Scalar dr = drT;
313 typename eigenArr::Index dim_1, dim_2;
314 typename eigenArr::Scalar k_1, k_2, df;
319 if(k_x) k_x->resize(dim_1, dim_2);
320 if(k_y) k_y->resize(dim_1, dim_2);
324 for(
int ii=0; ii < 0.5*(dim_1-1) + 1; ++ii)
327 for(
int jj=0; jj < 0.5*(dim_2-1)+1; ++jj)
331 arr(ii, jj) = sqrt(k_1*k_1 + k_2*k_2);
333 if(k_x) (*k_x)(ii,jj) = k_1;
334 if(k_x) (*k_y)(ii,jj) = k_2;
337 for(
int jj=0.5*(dim_2-1)+1; jj < dim_2; ++jj)
339 k_2 = (jj-dim_2) * df;
341 arr(ii, jj) = sqrt(k_1*k_1 + k_2*k_2);
343 if(k_x) (*k_x)(ii,jj) = k_1;
344 if(k_x) (*k_y)(ii,jj) = k_2;
348 for(
int ii=0.5*(dim_1-1)+1; ii < dim_1; ++ii)
351 for(
int jj=0; jj < 0.5*(dim_2-1) + 1; ++jj)
355 arr(ii, jj) = sqrt(k_1*k_1 + k_2*k_2);
357 if(k_x) (*k_x)(ii,jj) = k_1;
358 if(k_x) (*k_y)(ii,jj) = k_2;
361 for(
int jj=0.5*(dim_2-1)+1; jj < dim_2; ++jj)
363 k_2 = (jj-dim_2) * df;
365 arr(ii, jj) = sqrt(k_1*k_1 + k_2*k_2);
367 if(k_x) (*k_x)(ii,jj) = k_1;
368 if(k_x) (*k_y)(ii,jj) = k_2;
374 template<
typename eigenArr>
376 typename eigenArr::Scalar dt
384 template<
typename eigenArr>
386 typename eigenArr::Scalar dt,
406 template<
typename realT>
409 realT integ = 2*(pow(fmax, -1.0*alpha + 1.0) - pow(fmin, -1.0*alpha + 1.0))/(-1.0*alpha + 1.0);
424 template<
typename realT>
427 realT integ = 2*(pow(kmax, -1*alpha + 2.0) - pow(kmin, -1.0*alpha + 2.0))/(-1*alpha + 2.0);
440 template<
typename floatT,
typename floatParamT>
442 std::vector<floatT> & f,
444 floatT fmin = std::numeric_limits<floatT>::min(),
445 floatT fmax = std::numeric_limits<floatT>::max()
453 if(fmin != std::numeric_limits<floatT>::min() || fmax != std::numeric_limits<floatT>::max())
455 for(
size_t i = 0; i < psd.size(); ++i)
457 if(fabs(f[i]) < fmin || fabs(f[i]) > fmax)
continue;
463 for(
size_t i = 0; i < psd.size(); ++i)
471 for(
size_t i = 0; i < psd.size(); ++i) psd[i] *= norm/s;
484 template<
typename floatT,
typename floatParamT>
485 floatT
normPSD( Eigen::Array<floatT, Eigen::Dynamic, Eigen::Dynamic> & psd,
486 Eigen::Array<floatT, Eigen::Dynamic, Eigen::Dynamic> &
k,
488 floatT kmin = std::numeric_limits<floatT>::min(),
489 floatT kmax = std::numeric_limits<floatT>::max()
496 if(
k.rows() > 1) dk1 =
k(1,0) -
k(0,0);
499 if(
k.cols() > 1) dk2 =
k(0,1) -
k(0,0);
505 if(kmin != std::numeric_limits<floatT>::min() || kmax != std::numeric_limits<floatT>::max())
507 for(
int c = 0;
c < psd.cols(); ++
c)
509 for(
int r = 0; r < psd.rows(); ++r)
511 if(fabs(
k(r,
c)) < kmin || fabs(
k(r,
c)) > kmax)
continue;
518 for(
int c = 0;
c < psd.cols(); ++
c)
520 for(
int r = 0; r < psd.rows(); ++r)
529 for(
int c = 0;
c < psd.cols(); ++
c)
531 for(
int r = 0; r < psd.rows(); ++r)
560 template<
typename eigenArrp,
typename eigenArrf>
563 typename eigenArrp::Scalar alpha,
564 typename eigenArrp::Scalar beta = -1 )
566 typedef typename eigenArrp::Scalar Scalar;
568 typename eigenArrp::Index dim_1, dim_2;
581 fmax = freq.abs().maxCoeff();
584 fmin = (freq.abs()>0).select(freq.abs(), freq.abs()+fmax).minCoeff();
589 for(
int ii =0; ii < dim_1; ++ii)
591 for(
int jj=0; jj < dim_2; ++jj)
599 p = beta / std::pow(std::abs(freq(ii,jj)), alpha);
620 template<
typename floatT,
typename floatfT,
typename alphaT,
typename T0T,
typename t0T,
typename betaT>
622 std::vector<floatfT> & f,
630 #ifndef MX_VKPSD_REFACT
631 static_assert( 0*std::is_floating_point<floatT>::value,
"the 1D vonKarmanPSD has been refactored. After modifying your code to match, you must define MX_VKPSD_REFACT before including psdUtils.hpp to avoid this error.");
635 if(T0 > 0) T02 = 1.0/(T0*T0);
638 floatT sqrt_alpha = 0.5*alpha;
641 if(beta <= 0) _beta = 1;
644 psd.resize(f.size());
646 for(
size_t i=0; i< f.size(); ++i)
648 floatT p = _beta / pow( pow(f[i],2) + T02, sqrt_alpha);
649 if(t0 > 0 ) p *= exp(-1*pow( f[i]*
static_cast<floatT
>(t0), 2));
669 template<
typename floatT>
671 std::vector<floatT> & f,
681 psd.resize(f.size());
683 for(
int i=0; i< f.size(); ++i)
685 floatT p = beta / (1 + pow(f[i]/fn, alpha));
714 template<
typename eigenArrp,
typename eigenArrf,
typename alphaT,
typename L0T,
typename l0T,
typename betaT>
722 typedef typename eigenArrp::Scalar Scalar;
724 typename eigenArrp::Index dim_1, dim_2;
737 fmax = freq.abs().maxCoeff();
740 fmin = (freq.abs()>0).select(freq.abs(), freq.abs()+fmax).minCoeff();
742 _beta = beta =
oneoverf_norm(fmin, fmax,
static_cast<Scalar
>(alpha));
744 else _beta =
static_cast<Scalar
>(beta);
748 if(L0 > 0) L02 = 1.0/(L0*L0);
751 Scalar sqrt_alpha = 0.5*alpha;
753 for(
int ii =0; ii < dim_1; ++ii)
755 for(
int jj=0; jj < dim_2; ++jj)
757 if(freq(ii,jj) == 0 && L02 == 0)
763 p = _beta / pow( pow(freq(ii,jj),2) + L02, sqrt_alpha);
764 if(l0 > 0 ) p *= exp(-1*pow( freq(ii,jj)*
static_cast<Scalar
>(l0), 2));
793 template<
typename vectorTout,
typename vectorTin>
795 vectorTin & psdOneSided,
796 bool addZeroFreq =
false,
797 typename vectorTin::value_type scale = 0.5
800 typedef typename vectorTout::value_type outT;
806 if( addZeroFreq == 0 )
809 N = 2*psdOneSided.size()-2;
813 N = 2*psdOneSided.size();
816 psdTwoSided.resize(N);
821 psdTwoSided[0] = outT(0.0);
825 psdTwoSided[0] = outT(psdOneSided[0]);
830 for(i=0; i < psdOneSided.size() - 1 - (1-needZero); ++i)
832 psdTwoSided[i + 1] = outT(psdOneSided[i + (1-needZero)] * scale);
833 psdTwoSided[i + psdOneSided.size()+ needZero] = outT(psdOneSided[ psdOneSided.size() - 2 - i] * scale);
835 psdTwoSided[i + 1] = outT(psdOneSided[i + (1-needZero) ]);
852 std::vector<T> & freqOneSided
859 if(freqOneSided[0] != 0)
861 N = 2*freqOneSided.size();
866 N = 2*freqOneSided.size()-2;
869 freqTwoSided.resize(N);
873 freqTwoSided[0] = 0.0;
877 freqTwoSided[0] = freqOneSided[0];
881 for(i=0; i < freqOneSided.size() - 1 - (1-needZero); ++i)
883 freqTwoSided[i + 1] = freqOneSided[i + (1-needZero) ];
884 freqTwoSided[i + freqOneSided.size()+ needZero] = -freqOneSided[ freqOneSided.size() - 2 - i];
886 freqTwoSided[i + 1] = freqOneSided[i + (1-needZero) ];
907 template<
typename realT>
909 std::vector<realT> & binPSD,
910 std::vector<realT> & freq,
911 std::vector<realT> & PSD,
913 bool binAtZero =
true
926 realT df = freq[1]-freq[0];
930 while(freq[i] <= 0.5*binSize + 0.5*df)
935 if(i >= freq.size())
break;
940 binFreq.push_back(0);
941 binPSD.push_back(PSD[0]);
945 binFreq.push_back(0);
946 binPSD.push_back(sumPSD/nSum);
956 while(i < freq.size())
959 while( freq[i] - startFreq + 0.5*df < binSize )
967 if(i >= freq.size()-1)
break;
973 sumPSD += 0.5*PSD[i];
981 binFreq.push_back(sumFreq/nSum);
986 binFreq.push_back( freq[freq.size()-1]);
989 binPSD.push_back(sumPSD/(nSum-1));
994 if(i >= freq.size())
break;
1003 realT var =
psdVar(freq[1]-freq[0],PSD);
1004 realT binv =
psdVar(binFreq[1]-binFreq[0], binPSD);
1006 for(
int i=0; i<binFreq.size();++i) binPSD[i] *= var/binv;
constexpr units::realT c()
The speed of light.
constexpr units::realT k()
Boltzmann Constant.
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.
void vonKarmanPSD(eigenArrp &psd, eigenArrf &freq, alphaT alpha, L0T L0=0, l0T l0=0, betaT beta=-1)
Generates a von Karman power spectrum.
void frequencyGrid(eigenArr &arr, typename eigenArr::Scalar dt, eigenArr &k_x, eigenArr &k_y)
Create a frequency grid.
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.
void frequency_grid1D(eigenArr &vec, typename eigenArr::Scalar dt, bool inverse=false)
Create a 1-D frequency grid.
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.
floatT normPSD(Eigen::Array< floatT, Eigen::Dynamic, Eigen::Dynamic > &psd, Eigen::Array< floatT, Eigen::Dynamic, Eigen::Dynamic > &k, floatParamT normT, floatT kmin=std::numeric_limits< floatT >::min(), floatT kmax=std::numeric_limits< floatT >::max())
Normalize a 2-D PSD to have a given variance.
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)