69 return QStringLiteral(
"unknown");
75 const MatrixXd& matEog,
76 const MatrixXd& matEcg,
81 QList<IcaLabelResult> results;
83 const int nComp =
static_cast<int>(matSources.rows());
87 const double dMuscleThresh = 0.7;
89 for (
int k = 0; k < nComp; ++k) {
95 VectorXd source = matSources.row(k).transpose();
99 if (matEog.rows() > 0 && matEog.cols() == matSources.cols())
103 double ecgCorr = 0.0;
104 if (matEcg.rows() > 0 && matEcg.cols() == matSources.cols())
111 if (eogCorr >= dEogThresh && eogCorr >= ecgCorr && eogCorr >= muscle) {
114 }
else if (ecgCorr >= dEcgThresh && ecgCorr >= eogCorr && ecgCorr >= muscle) {
117 }
else if (muscle >= dMuscleThresh) {
123 res.
confidence = 1.0 - std::max({eogCorr, ecgCorr, muscle});
136 QVector<int> artifacts;
137 for (
const auto& res : labels) {
141 artifacts.append(res.componentIndex);
151 const int n =
static_cast<int>(source.size());
156 double srcMean = source.mean();
157 VectorXd srcCentered = source.array() - srcMean;
158 double srcStd = std::sqrt(srcCentered.squaredNorm() /
static_cast<double>(n - 1));
163 double maxCorr = 0.0;
164 for (
int r = 0; r < matRef.rows(); ++r) {
165 VectorXd ref = matRef.row(r).transpose();
166 double refMean = ref.mean();
167 VectorXd refCentered = ref.array() - refMean;
168 double refStd = std::sqrt(refCentered.squaredNorm() /
static_cast<double>(n - 1));
173 double corr = std::abs(srcCentered.dot(refCentered) / (
static_cast<double>(n - 1) * srcStd * refStd));
188 const int n =
static_cast<int>(source.size());
189 if (n < 3 || dSFreq <= 0.0)
192 double totalVar = 0.0;
193 double srcMean = source.mean();
194 for (
int i = 0; i < n; ++i) {
195 double d = source[i] - srcMean;
198 totalVar /=
static_cast<double>(n - 1);
200 if (totalVar < 1e-30)
205 for (
int i = 1; i < n - 1; ++i) {
206 double d2 = source[i + 1] - 2.0 * source[i] + source[i - 1];
209 hfVar /=
static_cast<double>(n - 2);
213 double ratio = hfVar / (6.0 * totalVar);
215 return std::min(ratio, 1.0);
Automatic ICA component labelling for artefact identification on M/EEG.
Supervised and unsupervised spatial-filter decompositions for M/EEG decoding.
IcaComponentLabel
Categorical label assigned to a single ICA component.
Outcome of labelling a single ICA component.
static QString labelToString(IcaComponentLabel label)
static double muscleScore(const Eigen::VectorXd &source, double dSFreq)
static QList< IcaLabelResult > classify(const Eigen::MatrixXd &matSources, const Eigen::MatrixXd &matEog, const Eigen::MatrixXd &matEcg, double dSFreq, double dEogThresh=0.3, double dEcgThresh=0.3)
static double maxAbsCorrelation(const Eigen::VectorXd &source, const Eigen::MatrixXd &matRef)
static QVector< int > findArtifactComponents(const QList< IcaLabelResult > &labels)