49static QString extractShaftPrefix(
const QString& name)
52 for (
int i = 0; i < name.size(); ++i) {
69 QMap<QString, QStringList> groups;
70 QStringList groupOrder;
72 for (
const QString& name : channelNames) {
73 QString prefix = extractShaftPrefix(name);
74 if (!groups.contains(prefix)) {
75 groupOrder.append(prefix);
77 groups[prefix].append(name);
81 QVector<DerivationRule> rules;
82 for (
const QString& prefix : groupOrder) {
83 const QStringList& group = groups[prefix];
84 for (
int i = 0; i < group.size() - 1; ++i) {
86 rule.
outputName = group[i] +
"-" + group[i + 1];
100 const int N = channelNames.size();
105 const double invN = 1.0 /
static_cast<double>(N);
107 QVector<DerivationRule> rules;
110 for (
const QString& target : channelNames) {
113 for (
const QString& ch : channelNames) {
127 const MatrixXd& matData,
128 const QStringList& channelNames,
129 const QVector<DerivationRule>& rules)
132 QMap<QString, int> chIndex;
133 for (
int i = 0; i < channelNames.size(); ++i) {
134 chIndex[channelNames[i]] = i;
137 const Eigen::Index nTimes = matData.cols();
138 MatrixXd matResult = MatrixXd::Zero(rules.size(), nTimes);
139 QStringList outputNames;
140 outputNames.reserve(rules.size());
142 for (
int r = 0; r < rules.size(); ++r) {
147 auto idxIt = chIndex.constFind(it.key());
148 if (idxIt == chIndex.constEnd()) {
149 qWarning() <<
"ChannelDerivation::apply - channel not found:" << it.key()
153 matResult.row(r) += it.value() * matData.row(idxIt.value());
157 return qMakePair(matResult, outputNames);
168 QVector<DerivationRule> rules;
170 rules.append({definition.first, definition.second});
180 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
181 qWarning() <<
"ChannelDerivation::writeDefinitionFile - cannot open:" << path;
185 QTextStream out(&file);
186 out <<
"# Channel derivations: \"name\" = weight * \"input\" + ...\n";
188 out <<
'"' << rule.outputName <<
"\" =";
189 for (
auto it = rule.inputWeights.constBegin(); it != rule.inputWeights.constEnd(); ++it) {
190 out <<
' ' << (it.value() < 0.0 ?
'-' :
'+') <<
' ' << QString::number(std::fabs(it.value()),
'g', 17) <<
" * \"" << it.key() <<
'"';
Linear channel derivations — bipolar montages and arbitrary weighted recombinations.
Set of channel derivations (montages): MNE-C derivation files, text definitions and matching to recor...
Core MNE data structures (source spaces, source estimates, hemispheres).
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
A single derivation rule mapping input channels (with weights) to one output channel.
QString outputName
Name of the derived output channel.
QMap< QString, double > inputWeights
Map of input channel name → weight.
static QPair< Eigen::MatrixXd, QStringList > apply(const Eigen::MatrixXd &matData, const QStringList &channelNames, const QVector< DerivationRule > &rules)
Apply derivation rules to a data matrix.
static QVector< DerivationRule > buildCommonAverage(const QStringList &channelNames)
Build common-average reference derivation rules.
static QVector< DerivationRule > buildBipolar(const QStringList &channelNames)
Build bipolar derivation rules from sequential electrode pairs.
static QVector< DerivationRule > readDefinitionFile(const QString &path)
Read derivation rules from an MNE-C derivation text file (MNELIB::MNEDerivSet::readText).
static bool writeDefinitionFile(const QString &path, const QVector< DerivationRule > &rules)
Write derivation rules in MNE-C derivation text syntax, readable by readDefinitionFile and mne_make_d...
QPair< QString, QMap< QString, double > > Definition
static std::optional< MNEDerivSet > readText(const QString &path)