159 const int n =
static_cast<int>(
X.rows());
160 SelfAdjointEigenSolver<MatrixXd> eig(
X);
161 VectorXd eigVals = eig.eigenvalues();
162 MatrixXd eigVecs = eig.eigenvectors();
165 double maxEig = eigVals.cwiseAbs().maxCoeff();
166 double threshold = maxEig * 1e-10;
172 for(
int i = 0; i < n; ++i) {
173 if(std::abs(eigVals(i)) > threshold) {
181 VectorXd eigPow = VectorXd::Zero(n);
182 for(
int i = startIdx; i < n; ++i) {
183 if(std::abs(eigVals(i)) > threshold) {
184 eigPow(i) = std::pow(eigVals(i), p);
188 return eigVecs * eigPow.asDiagonal() * eigVecs.transpose();
203 MatrixX3d &maxPowerOri)
205 const int nChannels =
static_cast<int>(G.rows());
206 const int nDipoles =
static_cast<int>(G.cols());
207 const int nSources = nDipoles / nOrient;
209 if(nSources * nOrient != nDipoles) {
210 qWarning(
"InvBeamformerCompute::computeBeamformer - G.cols() not divisible by nOrient!");
213 if(Cm.rows() != nChannels || Cm.cols() != nChannels) {
214 qWarning(
"InvBeamformerCompute::computeBeamformer - Cm dimension mismatch with leadfield!");
222 double loadingFactor = 0.0;
224 regPinv(Cm, reg, CmInv, loadingFactor, cmRank);
230 int nOrientOut = nOrient;
236 nOrientOut = nOrient;
239 W.resize(nSources * nOrientOut, nChannels);
243 maxPowerOri.resize(nSources, 3);
244 maxPowerOri.setZero();
246 maxPowerOri.resize(0, 3);
249 for(
int s = 0; s < nSources; ++s) {
251 MatrixXd Gk = G.middleCols(s * nOrient, nOrient);
254 if(reduceRank && nOrient > 1) {
255 reduceLeadfieldRank(Gk);
261 int orientForFilter = nOrient;
267 MatrixXd bfNumer = Gk.transpose() * CmInv;
268 MatrixXd bfDenom = bfNumer * Gk;
270 MatrixXd oriNumer, oriDenom;
272 oriNumer = MatrixXd::Identity(nOrient, nOrient);
277 oriDenom = Gk.transpose() * (CmInv * CmInv) * Gk;
281 MatrixXd oriDenomInv = invertSmallSym(oriDenom, reduceRank);
282 MatrixXd oriPick = oriDenomInv * oriNumer;
286 EigenSolver<MatrixXd> eigSolve(oriPick);
287 VectorXcd eigVals = eigSolve.eigenvalues();
288 MatrixXcd eigVecs = eigSolve.eigenvectors();
292 for(
int i = 0; i < eigVals.size(); ++i) {
293 double absVal = std::abs(eigVals(i));
294 if(absVal > maxVal) {
301 Vector3d ori = eigVecs.col(maxIdx).real().head(3).normalized();
305 double dot = ori.dot(nn.row(s).transpose());
306 if(dot < 0.0) ori = -ori;
309 maxPowerOri.row(s) = ori.transpose();
327 MatrixXd bfNumer = Gk.transpose() * CmInv;
328 MatrixXd bfDenom = bfNumer * Gk;
333 bfDenomInv = MatrixXd::Zero(orientForFilter, orientForFilter);
334 for(
int d = 0; d < orientForFilter; ++d) {
335 double val = bfDenom(d, d);
336 bfDenomInv(d, d) = (std::abs(val) > 1e-30) ? 1.0 / val : 0.0;
339 bfDenomInv = invertSmallSym(bfDenom, reduceRank);
342 MatrixXd Wug = bfDenomInv * bfNumer;
349 MatrixXd noiseNorm = Wug * Wug.transpose();
351 for(
int d = 0; d < orientForFilter; ++d) {
352 double normVal = std::sqrt(std::abs(noiseNorm(d, d)));
353 if(normVal > 1e-30) {
354 Wug.row(d) /= normVal;
360 double noise = loadingFactor;
362 Wug /= std::sqrt(noise);
368 MatrixXd inner = bfNumer * bfNumer.transpose();
369 MatrixXd innerPow =
symMatPow(inner, -0.5, reduceRank);
370 Wug = innerPow * bfNumer;
374 W.middleRows(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)