v2.0.0
Loading...
Searching...
No Matches
partial_directed_coherence.cpp
Go to the documentation of this file.
1//=============================================================================================================
12
13//=============================================================================================================
14// INCLUDES
15//=============================================================================================================
16
18#include "mvar_model.h"
21#include "../network/network.h"
23
24//=============================================================================================================
25// QT INCLUDES
26//=============================================================================================================
27
28#include <QDebug>
29
30//=============================================================================================================
31// EIGEN INCLUDES
32//=============================================================================================================
33
34#include <Eigen/Dense>
35
36//=============================================================================================================
37// USED NAMESPACES
38//=============================================================================================================
39
40using namespace CONNECTIVITYLIB;
41using namespace Eigen;
42
43//=============================================================================================================
44// DEFINE GLOBAL METHODS
45//=============================================================================================================
46
47//=============================================================================================================
48// DEFINE MEMBER METHODS
49//=============================================================================================================
50
54
55//=============================================================================================================
56
58{
59 Network finalNetwork("PDC");
60
61 if(connectivitySettings.isEmpty()) {
62 qDebug() << "PartialDirectedCoherence::calculate - Input data is empty";
63 return finalNetwork;
64 }
65
66 finalNetwork.setSamplingFrequency(connectivitySettings.getSamplingFrequency());
67
68 // Average trial data for MVAR fitting
69 const int nTrials = connectivitySettings.size();
70 MatrixXd matDataAvg = connectivitySettings.at(0).matData;
71 for(int t = 1; t < nTrials; ++t) {
72 matDataAvg += connectivitySettings.at(t).matData;
73 }
74 matDataAvg /= static_cast<double>(nTrials);
75
76 const int nCh = static_cast<int>(matDataAvg.rows());
77 const int iNfft = connectivitySettings.getFFTSize();
78 const int iNFreqs = static_cast<int>(std::floor(iNfft / 2.0)) + 1;
79
80 finalNetwork.setFFTSize(iNFreqs);
81 finalNetwork.setUsedFreqBins(iNFreqs);
82
83 // Create nodes
84 RowVectorXf rowVert = RowVectorXf::Zero(3);
85 for(int i = 0; i < nCh; ++i) {
86 rowVert = RowVectorXf::Zero(3);
87 if(connectivitySettings.getNodePositions().rows() != 0 && i < connectivitySettings.getNodePositions().rows()) {
88 rowVert(0) = connectivitySettings.getNodePositions().row(i)(0);
89 rowVert(1) = connectivitySettings.getNodePositions().row(i)(1);
90 rowVert(2) = connectivitySettings.getNodePositions().row(i)(2);
91 }
92 finalNetwork.append(NetworkNode::SPtr(new NetworkNode(i, rowVert)));
93 }
94
95 // Fit MVAR model
96 MvarModel model;
97 model.fit(matDataAvg);
98
99 // Compute A(f) = I - sum_{k=1}^{p} A_k * exp(-2*pi*i*f*k) at normalized frequencies
100 VectorXd vecFreqs = VectorXd::LinSpaced(iNFreqs, 0.0, 0.5);
101 QVector<MatrixXd> coeffs = model.coefficients();
102 int p = model.order();
103
104 const MatrixXcd matI = MatrixXcd::Identity(nCh, nCh);
105 const std::complex<double> jImag(0.0, 1.0);
106
107 // Compute PDC: PDC_{ij}(f) = |A_{ij}(f)| / sqrt(sum_k |A_{kj}(f)|^2)
108 // (normalized per column j)
109 for(int i = 0; i < nCh; ++i) {
110 for(int j = 0; j < nCh; ++j) {
111 MatrixXd matWeight(iNFreqs, 1);
112
113 for(int fi = 0; fi < iNFreqs; ++fi) {
114 // Compute A(f) at this frequency
115 MatrixXcd matAf = matI;
116 for(int k = 0; k < p; ++k) {
117 const double phase = -2.0 * M_PI * vecFreqs(fi) * (k + 1);
118 matAf -= coeffs[k].cast<std::complex<double>>() * std::exp(jImag * phase);
119 }
120
121 // Column normalization: sqrt(sum_k |A_{kj}(f)|^2)
122 double colNorm = 0.0;
123 for(int k = 0; k < nCh; ++k) {
124 colNorm += std::norm(matAf(k, j));
125 }
126 colNorm = std::sqrt(colNorm);
127
128 if(colNorm > 0.0) {
129 matWeight(fi, 0) = std::abs(matAf(i, j)) / colNorm;
130 } else {
131 matWeight(fi, 0) = 0.0;
132 }
133 }
134
135 QSharedPointer<NetworkEdge> pEdge =
136 QSharedPointer<NetworkEdge>(new NetworkEdge(j, i, matWeight));
137
138 finalNetwork.getNodeAt(j)->append(pEdge);
139 finalNetwork.getNodeAt(i)->append(pEdge);
140 finalNetwork.append(pEdge);
141 }
142 }
143
144 return finalNetwork;
145}
#define M_PI
Multivariate autoregressive (MVAR) model fit and its frequency-domain decomposition; backbone of the ...
Partial Directed Coherence (Baccala & Sameshima 2001) between every channel pair, derived from a fitt...
Input-data and parameter container shared by every functional-connectivity metric in CONNECTIVITYLIB.
Weighted edge between two NetworkNode instances; stores the full per-frequency weight matrix and the ...
Node of a connectivity Network; carries a 3D position and the lists of incident (in / out,...
Graph container that stores the result of one functional-connectivity metric as nodes (sources/sensor...
Functional connectivity metrics (coherence, PLV, cross-correlation, etc.).
Aggregates trial data, spectral cache and node geometry shared by all CONNECTIVITYLIB metrics.
const IntermediateTrialData & at(int i) const
const Eigen::MatrixX3f & getNodePositions() const
MVAR model fit; provides H(f) and S(f) for Granger Causality, DTF and PDC.
Definition mvar_model.h:89
void fit(const Eigen::MatrixXd &data, int p=0)
QVector< Eigen::MatrixXd > coefficients() const
static Network calculate(ConnectivitySettings &connectivitySettings)
Graph container for one connectivity metric; nodes + weighted edges + threshold/visualisation state.
Definition network.h:98
void setUsedFreqBins(int iNumberFreqBins)
Definition network.cpp:493
void append(QSharedPointer< NetworkEdge > newEdge)
void setFFTSize(int iFFTSize)
Definition network.cpp:500
void setSamplingFrequency(float fSFreq)
Definition network.cpp:479
QSharedPointer< NetworkNode > getNodeAt(int i)
Definition network.cpp:143
Weighted, directional edge in a Network; carries per-frequency weights plus a band-averaged scalar.
Definition networkedge.h:82
Graph node carrying a 3D position and its incident in/out, full/thresholded edge lists.
Definition networknode.h:80
QSharedPointer< NetworkNode > SPtr
Definition networknode.h:83