65 const MatrixXd& matData,
66 const MatrixXd& matSourcePos,
69 QList<TrapMusicDipole> dipoles;
71 const int nCh =
static_cast<int>(matLeadField.rows());
72 const int nSrc =
static_cast<int>(matSourcePos.rows());
74 if (nCh == 0 || matData.rows() != nCh || matLeadField.cols() !=
static_cast<Eigen::Index
>(nSrc) * iNOrient) {
75 qWarning() <<
"[InvTrapMusic::compute] Dimension mismatch.";
80 JacobiSVD<MatrixXd> dataSvd(matData, ComputeThinU);
81 const VectorXd& singVals = dataSvd.singularValues();
85 for (
int i = 1; i < singVals.size(); ++i) {
86 if (singVals[i] < singVals[0] * 0.05)
90 nSignal = std::max(nSignal, m_iMaxSources);
91 nSignal = std::min(nSignal,
static_cast<int>(std::min(dataSvd.matrixU().cols(),
92 static_cast<Index
>(nCh / 2))));
95 MatrixXd signalSubspace = dataSvd.matrixU().leftCols(nSignal);
98 MatrixXd projector = MatrixXd::Identity(nCh, nCh);
100 for (
int iter = 0; iter < m_iMaxSources; ++iter) {
102 MatrixXd projLF = projector * matLeadField;
103 MatrixXd projSS = projector * signalSubspace;
106 int ssDim =
static_cast<int>(projSS.cols()) - iter;
109 ssDim = std::min(ssDim,
static_cast<int>(projSS.cols()));
111 JacobiSVD<MatrixXd> ssSvd(projSS, ComputeThinU);
112 MatrixXd truncSS = ssSvd.matrixU().leftCols(ssDim);
119 double bestCorr = correlations.maxCoeff(&bestIdx);
121 if (bestCorr < m_dThreshold)
126 dipole.
sourceIdx =
static_cast<int>(bestIdx);
128 dipole.
position = matSourcePos.row(bestIdx).transpose();
131 int colStart =
static_cast<int>(bestIdx) * iNOrient;
136 MatrixXd lfSrc = matLeadField.block(0, colStart, nCh, iNOrient);
137 MatrixXd proj = truncSS * truncSS.transpose() * lfSrc;
138 JacobiSVD<MatrixXd> orientSvd(proj, ComputeThinV);
139 Vector3d orient = orientSvd.matrixV().col(0);
144 dipoles.append(dipole);
147 MatrixXd lfSrc = matLeadField.block(0, colStart, nCh, iNOrient);
148 MatrixXd lfOrth = lfSrc.householderQr().householderQ() *
149 MatrixXd::Identity(nCh, iNOrient);
150 projector = projector - lfOrth * lfOrth.transpose() * projector;
159 const MatrixXd& matSignalSubspace,
162 const int nSrcTotal =
static_cast<int>(matLeadField.cols()) / iNOrient;
163 VectorXd correlations(nSrcTotal);
166 MatrixXd P_s = matSignalSubspace * matSignalSubspace.transpose();
168 for (
int s = 0; s < nSrcTotal; ++s) {
169 int colStart = s * iNOrient;
170 MatrixXd G_s = matLeadField.block(0, colStart, matLeadField.rows(), iNOrient);
173 MatrixXd projG = P_s * G_s;
174 double normProjG = projG.norm();
175 double normG = G_s.norm();
177 correlations[s] = (normG > 1e-15) ? (normProjG / normG) : 0.0;
static Eigen::VectorXd scanCorrelations(const Eigen::MatrixXd &matLeadField, const Eigen::MatrixXd &matSignalSubspace, int iNOrient)
Compute the MUSIC-type subspace correlation for all source locations.
QList< TrapMusicDipole > compute(const Eigen::MatrixXd &matLeadField, const Eigen::MatrixXd &matData, const Eigen::MatrixXd &matSourcePos, int iNOrient=3) const
Compute TRAP-MUSIC source localization.