69 const std::vector<MatrixXd> &csdMatrices,
70 const VectorXd &frequencies,
82 const int nFreqs =
static_cast<int>(csdMatrices.size());
84 qWarning(
"InvDICS::makeDICS - No CSD matrices provided!");
87 if(frequencies.size() != nFreqs) {
88 qWarning(
"InvDICS::makeDICS - Frequency vector size mismatch with CSD count!");
95 if(!forward.
sol || forward.
sol->data.size() == 0) {
96 qWarning(
"InvDICS::makeDICS - Forward solution has no gain matrix!");
100 MatrixXd G = forward.
sol->data;
101 const int nChannels =
static_cast<int>(G.rows());
103 const int nSources =
static_cast<int>(G.cols()) / nOrient;
105 qInfo(
"InvDICS::makeDICS - Leadfield: %d channels x %d sources (n_orient=%d), %d frequencies",
106 nChannels, nSources, nOrient, nFreqs);
112 if(noiseCov.
data.size() > 0 && noiseCov.
eig.size() > 0 && noiseCov.
eigvec.size() > 0) {
113 VectorXd invSqrtEig(noiseCov.
eig.size());
114 for(
int i = 0; i < noiseCov.
eig.size(); ++i) {
115 invSqrtEig(i) = (noiseCov.
eig(i) > 1e-30)
116 ? 1.0 / std::sqrt(noiseCov.
eig(i))
119 whitener = invSqrtEig.asDiagonal() * noiseCov.
eigvec.transpose();
121 whitener = MatrixXd::Identity(nChannels, nChannels);
124 MatrixXd projMat = MatrixXd::Identity(nChannels, nChannels);
127 MatrixXd Gw = whitener * G;
130 MatrixX3d nn = forward.
source_nn.cast<
double>();
135 for(
int fi = 0; fi < nFreqs; ++fi) {
136 MatrixXd Cm = csdMatrices[fi];
138 if(Cm.rows() != nChannels || Cm.cols() != nChannels) {
139 qWarning(
"InvDICS::makeDICS - CSD[%d] dimension mismatch!", fi);
151 MatrixXd CmW = whitener * Cm * whitener.transpose();
152 CmW = (CmW + CmW.transpose()) * 0.5;
159 Gw, CmW, reg, nOrient,
160 weightNorm, pickOri, reduceRank, invMethod,
164 qWarning(
"InvDICS::makeDICS - Filter computation failed at frequency %d (%.1f Hz)!",
165 fi, frequencies(fi));
181 result.
proj = projMat;
191 result.
rank =
static_cast<int>(nChannels);
197 verts.resize(forward.
src[0].vertno.
size() + forward.
src[1].vertno.
size());
198 verts << forward.
src[0].vertno, forward.
src[1].vertno;
199 }
else if(forward.
src.
size() == 1) {
200 verts = forward.
src[0].vertno;
204 qInfo(
"InvDICS::makeDICS - Done. %d frequency filters computed.", nFreqs);
212 const VectorXd &frequencies,
216 qWarning(
"InvDICS::applyDICSCsd - Invalid or non-DICS filters!");
220 const int nFreqs =
static_cast<int>(csdMatrices.size());
221 const int nFilterFreqs = filters.
nFreqs();
223 if(nFreqs != nFilterFreqs) {
224 qWarning(
"InvDICS::applyDICSCsd - CSD count (%d) does not match filter count (%d)!",
225 nFreqs, nFilterFreqs);
229 const int nOrient = filters.
nOrient();
230 const int nSources = filters.
nSources();
231 const int nChannels = filters.
nChannels();
234 MatrixXd powerMat(nSources, nFreqs);
236 for(
int fi = 0; fi < nFreqs; ++fi) {
237 MatrixXd Cm = csdMatrices[fi];
245 powerMat.col(fi) = power;
249 float fmin = (frequencies.size() > 0) ?
static_cast<float>(frequencies(0)) : 0.0f;
250 float fstep = (frequencies.size() > 1)
251 ?
static_cast<float>(frequencies(1) - frequencies(0))
271 qWarning(
"InvDICS::applyDICS - Invalid or non-DICS filters!");
274 if(freqIdx < 0 || freqIdx >= filters.
nFreqs()) {
275 qWarning(
"InvDICS::applyDICS - freqIdx %d out of range (0..%d)!",
276 freqIdx, filters.
nFreqs() - 1);
281 MatrixXd processed = data;
282 if(filters.
proj.size() > 0 && filters.
proj.rows() == data.rows()) {
283 processed = filters.
proj * processed;
285 if(filters.
whitener.size() > 0 && filters.
whitener.rows() == processed.rows()) {
286 processed = filters.
whitener * processed;
289 MatrixXd sol = filters.
weights[freqIdx] * processed;
292 const int nOrient = filters.
nOrient();
294 const int nSources =
static_cast<int>(sol.rows()) / 3;
295 const int nTimes =
static_cast<int>(sol.cols());
296 MatrixXd combined(nSources, nTimes);
297 for(
int s = 0; s < nSources; ++s) {
298 combined.row(s) = sol.middleRows(s * 3, 3).colwise().norm();
Shared beamformer computation routines for LCMV and DICS.
InvDICS class declaration — Dynamic Imaging of Coherent Sources beamformer.
FiffInfo class declaration.
#define FIFFV_MNE_FREE_ORI
FiffCov class declaration.
MNEForwardSolution class declaration.
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
Inverse source estimation (MNE, dSPM, sLORETA, dipole fitting).
FIFF measurement file information.
Computed beamformer spatial filter container.
BeamformerPickOri pickOri
Eigen::VectorXd frequencies
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 InvBeamformer makeDICS(const FIFFLIB::FiffInfo &info, const MNELIB::MNEForwardSolution &forward, const std::vector< Eigen::MatrixXd > &csdMatrices, const Eigen::VectorXd &frequencies, double reg=0.05, bool realFilter=true, const FIFFLIB::FiffCov &noiseCov=FIFFLIB::FiffCov(), BeamformerPickOri pickOri=BeamformerPickOri::None, BeamformerWeightNorm weightNorm=BeamformerWeightNorm::UnitNoiseGain, bool reduceRank=false, BeamformerInversion invMethod=BeamformerInversion::Matrix)
static InvSourceEstimate applyDICS(const Eigen::MatrixXd &data, float tmin, float tstep, const InvBeamformer &filters, int freqIdx=0)
static InvSourceEstimate applyDICSCsd(const std::vector< Eigen::MatrixXd > &csdMatrices, const Eigen::VectorXd &frequencies, const InvBeamformer &filters)
InvSourceSpaceType sourceSpaceType
InvOrientationType orientationType
MNELIB::MNESourceSpaces src
FIFFLIB::fiff_int_t source_ori
Eigen::MatrixX3f source_nn
FIFFLIB::FiffNamedMatrix::SDPtr sol