148 const int n =
static_cast<int>(
X.rows());
149 SelfAdjointEigenSolver<MatrixXd> eig(
X);
150 VectorXd eigVals = eig.eigenvalues();
151 MatrixXd eigVecs = eig.eigenvectors();
154 const double limit = eigVals(n - 1) * 1e-7;
155 const int startIdx = reduceRank ? 1 : 0;
157 VectorXd eigPow = VectorXd::Zero(n);
158 for (
int i = startIdx; i < n; ++i) {
159 if (eigVals(i) > limit) {
160 eigPow(i) = std::pow(eigVals(i), p);
164 return eigVecs * eigPow.asDiagonal() * eigVecs.transpose();
179 MatrixX3d& maxPowerOri)
181 const int nChannels =
static_cast<int>(G.rows());
182 const int nDipoles =
static_cast<int>(G.cols());
183 const int nSources = nDipoles / nOrient;
185 if (nSources * nOrient != nDipoles) {
186 qWarning(
"InvBeamformerCompute::computeBeamformer - G.cols() not divisible by nOrient!");
189 if (Cm.rows() != nChannels || Cm.cols() != nChannels) {
190 qWarning(
"InvBeamformerCompute::computeBeamformer - Cm dimension mismatch with leadfield!");
198 double loadingFactor = 0.0;
200 regPinv(Cm, reg, CmInv, loadingFactor, cmRank);
203 double noiseLevel = loadingFactor;
205 const VectorXd cmEig = SelfAdjointEigenSolver<MatrixXd>(Cm, EigenvaluesOnly).eigenvalues();
206 noiseLevel = std::max(cmEig(nChannels - cmRank), loadingFactor);
213 int nOrientOut = nOrient;
219 nOrientOut = nOrient;
222 W.resize(
static_cast<Eigen::Index
>(nSources) * nOrientOut, nChannels);
226 maxPowerOri.resize(nSources, 3);
227 maxPowerOri.setZero();
229 maxPowerOri.resize(0, 3);
232 for (
int s = 0; s < nSources; ++s) {
234 MatrixXd Gk = G.middleCols(
static_cast<Eigen::Index
>(s) * nOrient, nOrient);
237 if (reduceRank && nOrient > 1) {
238 reduceLeadfieldRank(Gk);
244 int orientForFilter = nOrient;
250 MatrixXd bfNumer = Gk.transpose() * CmInv;
251 MatrixXd bfDenom = bfNumer * Gk;
253 MatrixXd oriNumer, oriDenom;
255 oriNumer = MatrixXd::Identity(nOrient, nOrient);
260 oriDenom = Gk.transpose() * (CmInv * CmInv) * Gk;
264 MatrixXd oriDenomInv = invertSmallSym(oriDenom, reduceRank);
265 MatrixXd oriPick = oriDenomInv * oriNumer;
269 EigenSolver<MatrixXd> eigSolve(oriPick);
270 VectorXcd eigVals = eigSolve.eigenvalues();
271 MatrixXcd eigVecs = eigSolve.eigenvectors();
275 for (
int i = 0; i < eigVals.size(); ++i) {
276 double absVal = std::abs(eigVals(i));
277 if (absVal > maxVal) {
284 Vector3d ori = eigVecs.col(maxIdx).real().head(3).normalized();
288 double dot = ori.dot(nn.row(s).transpose());
293 maxPowerOri.row(s) = ori.transpose();
301 Gk = Gk.col(2).eval();
311 MatrixXd bfNumer = Gk.transpose() * CmInv;
312 MatrixXd bfDenom = bfNumer * Gk;
317 bfDenomInv = MatrixXd::Zero(orientForFilter, orientForFilter);
318 for (
int d = 0; d < orientForFilter; ++d) {
319 double val = bfDenom(d, d);
320 bfDenomInv(d, d) = (std::abs(val) > 1e-30) ? 1.0 / val : 0.0;
323 bfDenomInv = invertSmallSym(bfDenom, reduceRank);
326 MatrixXd Wug = bfDenomInv * bfNumer;
333 MatrixXd noiseNorm = Wug * Wug.transpose();
335 for (
int d = 0; d < orientForFilter; ++d) {
336 double normVal = std::sqrt(std::abs(noiseNorm(d, d)));
337 if (normVal > 1e-30) {
338 Wug.row(d) /= normVal;
343 Wug /= std::sqrt(noiseLevel);
348 MatrixXd inner = bfNumer * bfNumer.transpose();
349 MatrixXd innerPow =
symMatPow(inner, -0.5,
false);
350 Wug = innerPow * bfNumer;
354 W.middleRows(
static_cast<Eigen::Index
>(s) * nOrientOut, nOrientOut) = Wug;
static bool computeBeamformer(const Eigen::MatrixXd &G, const Eigen::MatrixXd &Cm, double reg, int nOrient, BeamformerWeightNorm weightNorm, BeamformerPickOri pickOri, bool reduceRank, BeamformerInversion invMethod, const Eigen::MatrixX3d &nn, Eigen::MatrixXd &W, Eigen::MatrixX3d &maxPowerOri)