86 if(!forward.
sol || forward.
sol->data.size() == 0) {
87 qWarning(
"InvLCMV::makeLCMV - Forward solution has no gain matrix!");
91 MatrixXd G = forward.
sol->data;
92 const int nChannels =
static_cast<int>(G.rows());
94 const int nSources =
static_cast<int>(G.cols()) / nOrient;
96 qInfo(
"InvLCMV::makeLCMV - Leadfield: %d channels x %d sources (n_orient=%d)",
97 nChannels, nSources, nOrient);
103 if(noiseCov.
data.size() > 0) {
106 if(noiseCov.
eig.size() > 0 && noiseCov.
eigvec.size() > 0) {
107 VectorXd invSqrtEig(noiseCov.
eig.size());
108 for(
int i = 0; i < noiseCov.
eig.size(); ++i) {
109 invSqrtEig(i) = (noiseCov.
eig(i) > 1e-30)
110 ? 1.0 / std::sqrt(noiseCov.
eig(i))
113 whitener = invSqrtEig.asDiagonal() * noiseCov.
eigvec.transpose();
116 whitener = MatrixXd::Identity(nChannels, nChannels);
119 whitener = MatrixXd::Identity(nChannels, nChannels);
125 MatrixXd projMat = MatrixXd::Identity(nChannels, nChannels);
134 MatrixXd Gw = whitener * G;
136 MatrixXd CmData = dataCov.
data;
137 if(CmData.rows() != nChannels || CmData.cols() != nChannels) {
138 qWarning(
"InvLCMV::makeLCMV - Data covariance dimension (%d x %d) "
139 "does not match leadfield channels (%d)!",
140 static_cast<int>(CmData.rows()),
static_cast<int>(CmData.cols()), nChannels);
144 MatrixXd CmW = whitener * CmData * whitener.transpose();
146 CmW = (CmW + CmW.transpose()) * 0.5;
151 MatrixX3d nn = forward.
source_nn.cast<
double>();
160 Gw, CmW, reg, nOrient,
161 weightNorm, pickOri, reduceRank, invMethod,
165 qWarning(
"InvLCMV::makeLCMV - Beamformer computation failed!");
174 result.
proj = projMat;
184 result.
rank =
static_cast<int>(CmW.rows());
191 verts.resize(forward.
src[0].vertno.
size() + forward.
src[1].vertno.
size());
192 verts << forward.
src[0].vertno, forward.
src[1].vertno;
193 }
else if(forward.
src.
size() == 1) {
194 verts = forward.
src[0].vertno;
198 qInfo(
"InvLCMV::makeLCMV - Done. Filter: %d x %d (sources=%d, orient=%d)",
199 static_cast<int>(W.rows()),
static_cast<int>(W.cols()), nSources, result.
nOrient());
206MatrixXd InvLCMV::applyFilter(
const MatrixXd &data,
const InvBeamformer &filters)
209 MatrixXd processed = data;
212 if(filters.
proj.size() > 0 && filters.
proj.rows() == data.rows()) {
213 processed = filters.
proj * processed;
217 if(filters.
whitener.size() > 0 && filters.
whitener.rows() == processed.rows()) {
218 processed = filters.
whitener * processed;
222 return filters.
weights[0] * processed;
230 qWarning(
"InvLCMV::applyLCMV - Invalid or non-LCMV filters!");
234 MatrixXd sol = applyFilter(evoked.
data, filters);
237 const int nOrient = filters.
nOrient();
240 const int nSources =
static_cast<int>(sol.rows()) / 3;
241 const int nTimes =
static_cast<int>(sol.cols());
242 MatrixXd combined(nSources, nTimes);
243 for(
int s = 0; s < nSources; ++s) {
244 combined.row(s) = sol.middleRows(s * 3, 3).colwise().norm();
249 float tmin = evoked.
times.size() > 0 ? evoked.
times[0] : 0.0f;
268 qWarning(
"InvLCMV::applyLCMVRaw - Invalid or non-LCMV filters!");
272 MatrixXd sol = applyFilter(data, filters);
274 const int nOrient = filters.
nOrient();
276 const int nSources =
static_cast<int>(sol.rows()) / 3;
277 const int nTimes =
static_cast<int>(sol.cols());
278 MatrixXd combined(nSources, nTimes);
279 for(
int s = 0; s < nSources; ++s) {
280 combined.row(s) = sol.middleRows(s * 3, 3).colwise().norm();
299 qWarning(
"InvLCMV::applyLCMVCov - Invalid or non-LCMV filters!");
304 MatrixXd CmW = dataCov.
data;
309 const int nOrient = filters.
nOrient();
313 MatrixXd powerMat = power;
Shared beamformer computation routines for LCMV and DICS.
InvLCMV class declaration — Linearly Constrained Minimum Variance beamformer.
FiffInfo class declaration.
#define FIFFV_MNE_FREE_ORI
FiffEvoked class declaration.
FiffCov class declaration.
MNEForwardSolution class declaration.
Linalg class declaration.
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Inverse source estimation (MNE, dSPM, sLORETA, dipole fitting).
FIFF measurement file information.
Computed beamformer spatial filter container.
BeamformerPickOri pickOri
BeamformerWeightNorm weightNorm
Eigen::MatrixX3f sourceNn
BeamformerInversion inversion
Eigen::MatrixX3d maxPowerOri
std::vector< Eigen::MatrixXd > weights
static Eigen::VectorXd computePower(const Eigen::MatrixXd &Cm, const Eigen::MatrixXd &W, int nOrient)
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)
static InvSourceEstimate applyLCMVCov(const FIFFLIB::FiffCov &dataCov, const InvBeamformer &filters)
static InvBeamformer makeLCMV(const FIFFLIB::FiffInfo &info, const MNELIB::MNEForwardSolution &forward, const FIFFLIB::FiffCov &dataCov, double reg=0.05, const FIFFLIB::FiffCov &noiseCov=FIFFLIB::FiffCov(), BeamformerPickOri pickOri=BeamformerPickOri::None, BeamformerWeightNorm weightNorm=BeamformerWeightNorm::UnitNoiseGain, bool reduceRank=false, BeamformerInversion invMethod=BeamformerInversion::Matrix)
static InvSourceEstimate applyLCMV(const FIFFLIB::FiffEvoked &evoked, const InvBeamformer &filters)
static InvSourceEstimate applyLCMVRaw(const Eigen::MatrixXd &data, float tmin, float tstep, const InvBeamformer &filters)
InvSourceSpaceType sourceSpaceType
InvOrientationType orientationType
MNELIB::MNESourceSpaces src
FIFFLIB::fiff_int_t source_ori
Eigen::MatrixX3f source_nn
FIFFLIB::FiffNamedMatrix::SDPtr sol