v2.0.0
Loading...
Searching...
No Matches
dpss.cpp
Go to the documentation of this file.
1//=============================================================================================================
12
13//=============================================================================================================
14// INCLUDES
15//=============================================================================================================
16
17#include "dpss.h"
18
19//=============================================================================================================
20// EIGEN INCLUDES
21//=============================================================================================================
22
23#include <Eigen/Core>
24#include <Eigen/Eigenvalues>
25
26//=============================================================================================================
27// STD INCLUDES
28//=============================================================================================================
29
30#include <cmath>
31
32//=============================================================================================================
33// USED NAMESPACES
34//=============================================================================================================
35
36using namespace UTILSLIB;
37using namespace Eigen;
38
39namespace
40{
41constexpr double DPSS_PI = 3.14159265358979323846;
42}
43
44//=============================================================================================================
45// DEFINE MEMBER METHODS
46//=============================================================================================================
47
48DpssResult Dpss::compute(int N, double halfBandwidth, int nTapers)
49{
50 if (nTapers < 0)
51 nTapers = static_cast<int>(std::floor(2.0 * halfBandwidth - 1.0));
52
53 const double W = halfBandwidth / static_cast<double>(N);
54
55 // Build the symmetric tridiagonal matrix T
56 // Diagonal: d(i) = ((N-1-2*i)/2)^2 * cos(2*pi*W)
57 // Off-diagonal: e(i) = (i+1)*(N-i-1)/2
58 VectorXd diag(N);
59 VectorXd offdiag(N > 1 ? N - 1 : 0);
60
61 const double cosW = std::cos(2.0 * DPSS_PI * W);
62
63 for (int i = 0; i < N; ++i) {
64 const double val = (static_cast<double>(N - 1) - 2.0 * static_cast<double>(i)) / 2.0;
65 diag[i] = val * val * cosW;
66 }
67
68 for (int i = 0; i < N - 1; ++i) {
69 offdiag[i] = static_cast<double>(i + 1) * static_cast<double>(N - i - 1) / 2.0;
70 }
71
72 // Construct tridiagonal matrix and solve eigenvalue problem
73 MatrixXd T = MatrixXd::Zero(N, N);
74 for (int i = 0; i < N; ++i)
75 T(i, i) = diag[i];
76 for (int i = 0; i < N - 1; ++i) {
77 T(i, i + 1) = offdiag[i];
78 T(i + 1, i) = offdiag[i];
79 }
80
81 SelfAdjointEigenSolver<MatrixXd> solver(T);
82
83 // Eigenvalues are sorted ascending; we want the largest nTapers
84 const VectorXd& allEigenvalues = solver.eigenvalues();
85 const MatrixXd& allEigenvectors = solver.eigenvectors();
86
87 DpssResult result;
88 result.matTapers.resize(nTapers, N);
89 result.vecEigenvalues.resize(nTapers);
90
91 for (int k = 0; k < nTapers; ++k) {
92 const int idx = N - 1 - k; // largest eigenvalue first
93 result.vecEigenvalues[k] = allEigenvalues[idx];
94
95 // Extract eigenvector as a row, normalize to unit L2 norm
96 VectorXd taper = allEigenvectors.col(idx);
97 const double norm = taper.norm();
98 if (norm > 0.0)
99 taper /= norm;
100
101 // Sign convention: first element should be positive
102 if (taper[0] < 0.0)
103 taper = -taper;
104
105 result.matTapers.row(k) = taper.transpose();
106 }
107
108 return result;
109}
Discrete Prolate Spheroidal Sequences (Slepian tapers) for multitaper spectral estimation.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Result of a DPSS taper computation.
Definition dpss.h:54
Eigen::MatrixXd matTapers
nTapers × N, each row is a unit-norm taper
Definition dpss.h:55
Eigen::VectorXd vecEigenvalues
Concentration ratios, length nTapers.
Definition dpss.h:56
static DpssResult compute(int N, double halfBandwidth, int nTapers=-1)
Definition dpss.cpp:48