v2.0.0
Loading...
Searching...
No Matches
mne_mne_data.cpp
Go to the documentation of this file.
1//=============================================================================================================
16
17//=============================================================================================================
18// INCLUDES
19//=============================================================================================================
20
21#include "mne_mne_data.h"
23
24#include <math/numerics.h>
25
26#include <algorithm>
27#include <cmath>
28
29//=============================================================================================================
30// USED NAMESPACES
31//=============================================================================================================
32
33using namespace MNELIB;
34using namespace Eigen;
35
36//=============================================================================================================
37// DEFINE MEMBER METHODS
38//=============================================================================================================
39
40MNEMneData MNEMneData::compute(const MNEInverseOperator& inv, const MatrixXd& data, double snr)
41{
42 MNEMneData mne;
43 mne.computeRegularization(inv, data);
44 mne.selectRegularization(inv, snr);
45 mne.computePredicted(inv);
46 return mne;
47}
48
49//=============================================================================================================
50
51void MNEMneData::computeRegularization(const MNEInverseOperator& inv, const MatrixXd& data)
52{
53 const MatrixXd white = inv.whitener * inv.proj * data;
54 datap = inv.eigen_fields->data * white;
55
56 // Projected-out channels give zero noise eigenvalues; only the others count.
57 const int rank = inv.noise_cov->diag ? inv.noise_cov->dim : static_cast<int>((inv.noise_cov->eig.array() > 0).count());
58 const int ncomp = std::min(rank, static_cast<int>(inv.sing.size()));
59 SNR = white.colwise().squaredNorm().transpose() / rank;
60
61 const ArrayXd sing2 = inv.sing.head(ncomp).array().square();
62 const double limit = UTILSLIB::Numerics::chi2Isf(1e-3, ncomp - 1);
63 lambda2_est.resize(SNR.size());
64 for (Index t = 0; t < SNR.size(); ++t) {
65 if (SNR(t) < 1.0) {
66 lambda2_est(t) = 100.0;
67 continue;
68 }
69 const ArrayXd alpha = datap.col(t).head(ncomp).array();
70 double lambda2t = 10.0;
71 for (int iter = 0; iter <= 1000; ++iter) {
72 const ArrayXd error = (sing2 > 0.0).select(alpha * lambda2t / (sing2 + lambda2t), alpha);
73 if (error.square().sum() < limit) {
74 break;
75 }
76 lambda2t *= 0.9;
77 }
78 lambda2_est(t) = lambda2t;
79 }
80}
81
82//=============================================================================================================
83
85{
86 if (snr > 0.0) {
87 lambda2 = VectorXd::Constant(lambda2_est.size(), inv.sing.squaredNorm() / inv.nchan / snr);
88 } else {
90 }
91}
92
93//=============================================================================================================
94
96{
97 const ArrayXd sing2 = inv.sing.array().square();
98 MatrixXd weighted(datap.rows(), datap.cols());
99 for (Index t = 0; t < datap.cols(); ++t) {
100 weighted.col(t) = datap.col(t).array() * sing2 / (sing2 + lambda2(t));
101 }
102 const MatrixXd white = inv.eigen_fields->data.transpose() * weighted;
103 if (inv.noise_cov->diag) {
104 predicted = inv.noise_cov->data.col(0).cwiseSqrt().asDiagonal() * white;
105 } else {
106 // Colorer C^(1/2) = eigvec^T sqrt(eig), the rows of eigvec being the eigenvectors.
107 predicted = inv.noise_cov->eigvec.transpose() * (inv.noise_cov->eig.cwiseMax(0.0).cwiseSqrt().asDiagonal() * white);
108 }
109}
General numerical helpers: GCD, log2, histogram binning, baseline rescaling, sparsity tests.
Pre-computed inverse operator (whitened SVD of the forward model) for MNE/dSPM/sLORETA.
Per-data-set results of a minimum-norm computation: eigenfield projections, SNR, lambda2 and predicte...
Core MNE data structures (source spaces, source estimates, hemispheres).
static double chi2Isf(double p, int dof)
Definition numerics.cpp:96
MNE-style inverse operator.
FIFFLIB::FiffCov::SDPtr noise_cov
FIFFLIB::FiffNamedMatrix::SDPtr eigen_fields
void selectRegularization(const MNEInverseOperator &inv, double snr)
MNEMneData()=default
Eigen::VectorXd lambda2
Eigen::MatrixXd predicted
void computeRegularization(const MNEInverseOperator &inv, const Eigen::MatrixXd &data)
void computePredicted(const MNEInverseOperator &inv)
Eigen::VectorXd lambda2_est
Eigen::MatrixXd datap
Eigen::VectorXd SNR
static MNEMneData compute(const MNEInverseOperator &inv, const Eigen::MatrixXd &data, double snr)