146 const int n =
static_cast<int>(
X.rows());
147 SelfAdjointEigenSolver<MatrixXd> eig(
X);
148 VectorXd eigVals = eig.eigenvalues();
149 MatrixXd eigVecs = eig.eigenvectors();
152 double maxEig = eigVals.cwiseAbs().maxCoeff();
153 double threshold = maxEig * 1e-10;
159 for(
int i = 0; i < n; ++i) {
160 if(std::abs(eigVals(i)) > threshold) {
168 VectorXd eigPow = VectorXd::Zero(n);
169 for(
int i = startIdx; i < n; ++i) {
170 if(std::abs(eigVals(i)) > threshold) {
171 eigPow(i) = std::pow(eigVals(i), p);
175 return eigVecs * eigPow.asDiagonal() * eigVecs.transpose();
190 MatrixX3d &maxPowerOri)
192 const int nChannels =
static_cast<int>(G.rows());
193 const int nDipoles =
static_cast<int>(G.cols());
194 const int nSources = nDipoles / nOrient;
196 if(nSources * nOrient != nDipoles) {
197 qWarning(
"InvBeamformerCompute::computeBeamformer - G.cols() not divisible by nOrient!");
200 if(Cm.rows() != nChannels || Cm.cols() != nChannels) {
201 qWarning(
"InvBeamformerCompute::computeBeamformer - Cm dimension mismatch with leadfield!");
209 double loadingFactor = 0.0;
211 regPinv(Cm, reg, CmInv, loadingFactor, cmRank);
217 int nOrientOut = nOrient;
223 nOrientOut = nOrient;
226 W.resize(
static_cast<Eigen::Index
>(nSources) * nOrientOut, nChannels);
230 maxPowerOri.resize(nSources, 3);
231 maxPowerOri.setZero();
233 maxPowerOri.resize(0, 3);
236 for(
int s = 0; s < nSources; ++s) {
238 MatrixXd Gk = G.middleCols(
static_cast<Eigen::Index
>(s) * nOrient, nOrient);
241 if(reduceRank && nOrient > 1) {
242 reduceLeadfieldRank(Gk);
248 int orientForFilter = nOrient;
254 MatrixXd bfNumer = Gk.transpose() * CmInv;
255 MatrixXd bfDenom = bfNumer * Gk;
257 MatrixXd oriNumer, oriDenom;
259 oriNumer = MatrixXd::Identity(nOrient, nOrient);
264 oriDenom = Gk.transpose() * (CmInv * CmInv) * Gk;
268 MatrixXd oriDenomInv = invertSmallSym(oriDenom, reduceRank);
269 MatrixXd oriPick = oriDenomInv * oriNumer;
273 EigenSolver<MatrixXd> eigSolve(oriPick);
274 VectorXcd eigVals = eigSolve.eigenvalues();
275 MatrixXcd eigVecs = eigSolve.eigenvectors();
279 for(
int i = 0; i < eigVals.size(); ++i) {
280 double absVal = std::abs(eigVals(i));
281 if(absVal > maxVal) {
288 Vector3d ori = eigVecs.col(maxIdx).real().head(3).normalized();
292 double dot = ori.dot(nn.row(s).transpose());
293 if(dot < 0.0) ori = -ori;
296 maxPowerOri.row(s) = ori.transpose();
314 MatrixXd bfNumer = Gk.transpose() * CmInv;
315 MatrixXd bfDenom = bfNumer * Gk;
320 bfDenomInv = MatrixXd::Zero(orientForFilter, orientForFilter);
321 for(
int d = 0; d < orientForFilter; ++d) {
322 double val = bfDenom(d, d);
323 bfDenomInv(d, d) = (std::abs(val) > 1e-30) ? 1.0 / val : 0.0;
326 bfDenomInv = invertSmallSym(bfDenom, reduceRank);
329 MatrixXd Wug = bfDenomInv * bfNumer;
336 MatrixXd noiseNorm = Wug * Wug.transpose();
338 for(
int d = 0; d < orientForFilter; ++d) {
339 double normVal = std::sqrt(std::abs(noiseNorm(d, d)));
340 if(normVal > 1e-30) {
341 Wug.row(d) /= normVal;
347 double noise = loadingFactor;
349 Wug /= std::sqrt(noise);
355 MatrixXd inner = bfNumer * bfNumer.transpose();
356 MatrixXd innerPow =
symMatPow(inner, -0.5, reduceRank);
357 Wug = innerPow * bfNumer;
361 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)