49#include <unsupported/Eigen/FFT>
74 const int nChannels =
static_cast<int>(matData.rows());
75 const int nTimes =
static_cast<int>(matData.cols());
80 const int nFreqs = nFft / 2 + 1;
84 const int nTap =
static_cast<int>(dpss.
matTapers.rows());
87 double weightSum = 0.0;
88 for (
int t = 0; t < nTap; ++t)
92 result.
matPsd = MatrixXd::Zero(nChannels, nFreqs);
96 for (
int k = 0; k < nFreqs; ++k)
97 result.
vecFreqs[k] =
static_cast<double>(k) * sfreq /
static_cast<double>(nFft);
99 Eigen::FFT<double> fft;
102 for (
int ch = 0; ch < nChannels; ++ch) {
103 RowVectorXd psd = RowVectorXd::Zero(nFreqs);
105 for (
int t = 0; t < nTap; ++t) {
107 VectorXd tapered = matData.row(ch).transpose().array()
108 * dpss.
matTapers.row(t).transpose().array();
111 VectorXd padded = VectorXd::Zero(nFft);
112 const int copyLen = std::min(nTimes, nFft);
113 padded.head(copyLen) = tapered.head(copyLen);
117 fft.fwd(spec, padded);
121 for (
int k = 0; k < nFreqs; ++k)
122 psd[k] += w * std::norm(spec[k]);
126 const double dNorm = 1.0 / (weightSum * sfreq);
130 for (
int k = 1; k < nFreqs - 1; ++k)
133 result.
matPsd.row(ch) = psd;
MultitaperPsd class declaration — multitaper power spectral density estimator.
Dpss class declaration — Discrete Prolate Spheroidal Sequences (Slepian tapers).
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Result of a DPSS taper computation.
Eigen::MatrixXd matTapers
nTapers × N, each row is a unit-norm taper
Eigen::VectorXd vecEigenvalues
Concentration ratios, length nTapers.
static DpssResult compute(int N, double halfBandwidth, int nTapers=-1)
Result of a multitaper PSD computation.
Eigen::RowVectorXd vecFreqs
Frequency axis in Hz, length nFft/2+1.
Eigen::MatrixXd matPsd
n_channels × n_freqs; one-sided PSD in unit²/Hz
static MultitaperPsdResult compute(const Eigen::MatrixXd &matData, double sfreq, double halfBandwidth=4.0, int nTapers=-1, int nFft=-1)