96 init(p_pFwd, p_bSparsed, p_iN, p_dThr);
113 std::cout <<
"OpenMP enabled" << std::endl;
116 std::cout <<
"OpenMP disabled (to enable it: VS2010->Project Properties->C/C++->Language, then modify OpenMP Support)" << std::endl;
119 std::cout <<
"Available Threats: " <<
m_iMaxNumThreads << std::endl << std::endl;
122 std::cout <<
"##### Initialization RAP MUSIC started ######\n\n";
140 if ( p_pFwd.
sol->data.cols() % 3 != 0 )
142 std::cout <<
"Gain matrix is not associated with a 3D grid!\n";
159 std::cout <<
"Calculate gain matrix combinations. \n";
167 std::cout <<
"Gain matrix combinations calculated. \n\n";
175 std::cout <<
"Number of sources to find: " <<
m_iN <<
"\n\n";
181 std::cout <<
"##### Initialization RAP MUSIC completed ######\n\n\n";
183 Q_UNUSED(p_bSparsed);
208 Q_UNUSED(pick_normal);
214 std::cout <<
"Number of FiffEvoked channels (" << p_fiffEvoked.
data.rows() <<
") doesn't match the number of channels (" <<
m_iNumChannels <<
") of the forward solution." << std::endl;
215 return p_sourceEstimate;
230 p_sourceEstimate.
tmin = p_fiffEvoked.
times[0];
231 p_sourceEstimate.
tstep = p_fiffEvoked.
times[1] - p_fiffEvoked.
times[0];
235 QList< DipolePair<double> > t_RapDipoles;
238 for(qint32 i = 0; i < t_RapDipoles.size(); ++i)
240 double dip1 = sqrt( pow(t_RapDipoles[i].m_Dipole1.phi_x(),2) +
241 pow(t_RapDipoles[i].m_Dipole1.phi_y(),2) +
242 pow(t_RapDipoles[i].m_Dipole1.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
244 double dip2 = sqrt( pow(t_RapDipoles[i].m_Dipole2.phi_x(),2) +
245 pow(t_RapDipoles[i].m_Dipole2.phi_y(),2) +
246 pow(t_RapDipoles[i].m_Dipole2.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
248 RowVectorXd dip1Time = RowVectorXd::Constant(p_fiffEvoked.
data.cols(), dip1);
249 RowVectorXd dip2Time = RowVectorXd::Constant(p_fiffEvoked.
data.cols(), dip2);
251 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx1, 0, 1, p_fiffEvoked.
data.cols()) = dip1Time;
252 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx2, 0, 1, p_fiffEvoked.
data.cols()) = dip2Time;
260 qint32 t_iNumSensors = p_fiffEvoked.
data.rows();
261 qint32 t_iNumSteps = p_fiffEvoked.
data.cols();
264 qint32 t_iSamplesDiscard = t_iSamplesOverlap/2;
268 qint32 curSample = 0;
269 qint32 curResultSample = 0;
274 QList< DipolePair<double> > t_RapDipoles;
287 curSample -= t_iSamplesDiscard;
294 stcWindowSize = p_sourceEstimate.
data.cols() - curResultSample;
296 for(qint32 i = 0; i < t_RapDipoles.size(); ++i)
298 double dip1 = sqrt( pow(t_RapDipoles[i].m_Dipole1.phi_x(),2) +
299 pow(t_RapDipoles[i].m_Dipole1.phi_y(),2) +
300 pow(t_RapDipoles[i].m_Dipole1.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
302 double dip2 = sqrt( pow(t_RapDipoles[i].m_Dipole2.phi_x(),2) +
303 pow(t_RapDipoles[i].m_Dipole2.phi_y(),2) +
304 pow(t_RapDipoles[i].m_Dipole2.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
306 RowVectorXd dip1Time = RowVectorXd::Constant(stcWindowSize, dip1);
307 RowVectorXd dip2Time = RowVectorXd::Constant(stcWindowSize, dip2);
309 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx1, curResultSample, 1, stcWindowSize) = dip1Time;
310 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx2, curResultSample, 1, stcWindowSize) = dip2Time;
314 curResultSample += stcWindowSize;
321 return p_sourceEstimate;
328 Q_UNUSED(pick_normal);
334 std::cout <<
"Number of FiffEvoked channels (" << data.rows() <<
") doesn't match the number of channels (" <<
m_iNumChannels <<
") of the forward solution." << std::endl;
335 return p_sourceEstimate;
349 p_sourceEstimate.
times = RowVectorXf::Zero(data.cols());
350 p_sourceEstimate.
times[0] = tmin;
351 for(qint32 i = 1; i < p_sourceEstimate.
times.size(); ++i)
352 p_sourceEstimate.
times[i] = p_sourceEstimate.
times[i-1] + tstep;
353 p_sourceEstimate.
tmin = tmin;
354 p_sourceEstimate.
tstep = tstep;
356 QList< DipolePair<double> > t_RapDipoles;
359 for(qint32 i = 0; i < t_RapDipoles.size(); ++i)
361 double dip1 = sqrt( pow(t_RapDipoles[i].m_Dipole1.phi_x(),2) +
362 pow(t_RapDipoles[i].m_Dipole1.phi_y(),2) +
363 pow(t_RapDipoles[i].m_Dipole1.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
365 double dip2 = sqrt( pow(t_RapDipoles[i].m_Dipole2.phi_x(),2) +
366 pow(t_RapDipoles[i].m_Dipole2.phi_y(),2) +
367 pow(t_RapDipoles[i].m_Dipole2.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
369 RowVectorXd dip1Time = RowVectorXd::Constant(data.cols(), dip1);
370 RowVectorXd dip2Time = RowVectorXd::Constant(data.cols(), dip2);
372 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx1, 0, 1, data.cols()) = dip1Time;
373 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx2, 0, 1, data.cols()) = dip2Time;
376 return p_sourceEstimate;
383 MNESourceEstimate p_SourceEstimate;
388 std::cout <<
"RAP MUSIC wasn't initialized!";
389 return p_SourceEstimate;
395 std::cout <<
"Lead Field channels do not fit to number of measurement channels!";
396 return p_SourceEstimate;
412 int t_r =
calcPhi_s(p_matMeasurement, t_pMatPhi_s);
414 int t_iMaxSearch =
m_iN < t_r ?
m_iN : t_r;
418 std::cout <<
"Warning: Rank " << t_r <<
" of the measurement data is smaller than the " <<
m_iN;
419 std::cout <<
" sources to find." << std::endl;
420 std::cout <<
" Searching now for " << t_iMaxSearch <<
" correlated sources.";
421 std::cout << std::endl << std::endl;
427 t_matOrthProj.setIdentity();
431 t_matA_k_1.setZero();
447 p_RapDipoles.clear();
449 std::cout <<
"##### Calculation of RAP MUSIC started ######\n\n";
451 MatrixXT t_matProj_Phi_s(t_matOrthProj.rows(), t_pMatPhi_s->cols());
455 for(
int r = 0; r < t_iMaxSearch ; ++r)
457 t_matProj_Phi_s = t_matOrthProj*(*t_pMatPhi_s);
464 Eigen::JacobiSVD< MatrixXT > t_svdProj_Phi_S(t_matProj_Phi_s, Eigen::ComputeThinU);
466 useFullRank(t_svdProj_Phi_S.matrixU(), t_svdProj_Phi_S.singularValues().asDiagonal(), t_matU_B);
474 clock_t start_subcorr, end_subcorr;
475 start_subcorr = clock();
479 #pragma omp parallel num_threads(m_iMaxNumThreads)
489 MatrixX6T t_matProj_G(t_matProj_LeadField.rows(),6);
517 end_subcorr = clock();
519 float t_fSubcorrElapsedTime = ( (float)(end_subcorr-start_subcorr) / (float)CLOCKS_PER_SEC ) * 1000.0f;
520 std::cout <<
"Time Elapsed: " << t_fSubcorrElapsedTime <<
" ms" << std::endl;
525 VectorXT::Index t_iMaxIdx;
527 t_val_roh_k = t_vecRoh.maxCoeff(&t_iMaxIdx);
534 std::cout <<
"Iteration: " << r+1 <<
" of " << t_iMaxSearch
535 <<
"; Correlation: " << t_val_roh_k<<
"; Position (Idx+1): " << t_iIdx1+1 <<
" - " << t_iIdx2+1 <<
"\n\n";
541 MatrixX6T t_matProj_G_k_1(t_matOrthProj.rows(), t_matG_k_1.cols());
542 t_matProj_G_k_1 = t_matOrthProj * t_matG_k_1;
557 std::cout <<
"Searching stopped, last correlation " << t_val_roh_k;
558 std::cout <<
" is smaller then the given threshold " <<
m_dThreshold << std::endl << std::endl;
572 std::cout <<
"##### Calculation of RAP MUSIC completed ######"<< std::endl << std::endl << std::endl;
576 float t_fElapsedTime = ( (float)(end-start) / (float)CLOCKS_PER_SEC ) * 1000.0f;
577 std::cout <<
"Total Time Elapsed: " << t_fElapsedTime <<
" ms" << std::endl << std::endl;
582 return p_SourceEstimate;
591 if (p_matMeasurement.cols() > p_matMeasurement.rows())
594 t_matF =
MatrixXT(p_matMeasurement);
596 Eigen::JacobiSVD<MatrixXT> t_svdF(t_matF, Eigen::ComputeThinU);
598 int t_r =
getRank(t_svdF.singularValues().asDiagonal());
602 if (p_pMatPhi_s != NULL)
609 memcpy(p_pMatPhi_s->data(), t_svdF.matrixU().data(),
sizeof(
double) *
m_iNumChannels * t_iCols);
621 Matrix6XT t_matU_A_T(6, p_matProj_G.rows());
623 Eigen::JacobiSVD<MatrixXT> t_svdProj_G(p_matProj_G, Eigen::ComputeThinU);
625 t_matSigma_A = t_svdProj_G.singularValues().asDiagonal();
626 t_matU_A_T = t_svdProj_G.matrixU().transpose();
635 MatrixXT t_matCor(t_matU_A_T_full.rows(), p_matU_B.cols());
638 t_matCor = t_matU_A_T_full*p_matU_B;
642 if (t_matCor.cols() > t_matCor.rows())
644 MatrixXT t_matCor_H(t_matCor.cols(), t_matCor.rows());
645 t_matCor_H = t_matCor.adjoint();
648 Eigen::JacobiSVD<MatrixXT> t_svdCor_H(t_matCor_H);
650 t_vecSigma_C = t_svdCor_H.singularValues();
654 Eigen::JacobiSVD<MatrixXT> t_svdCor(t_matCor);
656 t_vecSigma_C = t_svdCor.singularValues();
660 double t_dRetSigma_C;
661 t_dRetSigma_C = t_vecSigma_C(0);
666 return t_dRetSigma_C;
679 Eigen::JacobiSVD<MatrixXT> svdOfProj_G(p_matProj_G, Eigen::ComputeThinU | Eigen::ComputeThinV);
681 sigma_A = svdOfProj_G.singularValues().asDiagonal();
682 U_A_T = svdOfProj_G.matrixU().transpose();
683 V_A = svdOfProj_G.matrixV();
692 t_matCor = U_A_T*p_matU_B;
699 if (t_matCor.cols() > t_matCor.rows())
702 Cor_H = t_matCor.adjoint();
704 Eigen::JacobiSVD<MatrixXT> svdOfCor_H(Cor_H, Eigen::ComputeThinV);
706 U_C = svdOfCor_H.matrixV();
707 sigma_C = svdOfCor_H.singularValues();
711 Eigen::JacobiSVD<MatrixXT> svdOfCor(t_matCor, Eigen::ComputeThinU);
713 U_C = svdOfCor.matrixU();
714 sigma_C = svdOfCor.singularValues();
718 sigma_a_inv = sigma_A.inverse();
721 X = (V_A*sigma_a_inv)*U_C;
726 double norm_X = 1/(X_max.norm());
729 p_vec_phi_k_1 = X_max*norm_X;
736 ret_sigma_C = sigma_C(0);
752 VectorXT t_vec_a_theta_k_1(p_matG_k_1.rows(),1);
754 t_vec_a_theta_k_1 = p_matG_k_1*p_matPhi_k_1;
756 p_matA_k_1.block(0,p_iIdxk_1,p_matA_k_1.rows(),1) = t_vec_a_theta_k_1;
765 MatrixXT t_matA_k_1_tmp(p_matA_k_1.cols(), p_matA_k_1.cols());
766 t_matA_k_1_tmp = p_matA_k_1.adjoint()*p_matA_k_1;
768 int t_size = t_matA_k_1_tmp.cols();
770 while (!t_matA_k_1_tmp.block(0,0,t_size,t_size).fullPivLu().isInvertible())
775 MatrixXT t_matA_k_1_tmp_inv(t_matA_k_1_tmp.rows(), t_matA_k_1_tmp.cols());
776 t_matA_k_1_tmp_inv.setZero();
778 t_matA_k_1_tmp_inv.block(0,0,t_size,t_size) = t_matA_k_1_tmp.block(0,0,t_size,t_size).inverse();
780 t_matA_k_1_tmp = MatrixXT::Zero(p_matA_k_1.rows(), p_matA_k_1.cols());
782 t_matA_k_1_tmp = p_matA_k_1*t_matA_k_1_tmp_inv;
784 MatrixXT t_matA_k_1_tmp2(p_matA_k_1.rows(), p_matA_k_1.rows());
786 t_matA_k_1_tmp2 = t_matA_k_1_tmp*p_matA_k_1.adjoint();
791 p_matOrthProj = I-t_matA_k_1_tmp2;
800 const int p_iNumCombinations,
801 Pair** p_ppPairIdxCombinations)
const
808 #pragma omp parallel num_threads(m_iMaxNumThreads) private(idx1, idx2)
814 for (
int i = 0; i < p_iNumCombinations; ++i)
818 Pair* t_pairCombination =
new Pair();
819 t_pairCombination->
x1 = idx1;
820 t_pairCombination->
x2 = idx2;
822 p_ppPairIdxCombinations[i] = t_pairCombination;
831 int ii = p_iPoints*(p_iPoints+1)/2-1-p_iCurIdx;
832 int K = (int)floor((sqrt((
double)(8*ii+1))-1)/2);
834 p_iIdx1 = p_iPoints-1-K;
836 p_iIdx2 = (p_iCurIdx-p_iPoints*(p_iPoints+1)/2 + (K+1)*(K+2)/2)+p_iIdx1;
843 int p_iIdx1,
int p_iIdx2)
845 p_matGainMarix_Pair.block(0,0,p_matGainMarix.rows(),3) = p_matGainMarix.block(0, p_iIdx1*3, p_matGainMarix.rows(), 3);
847 p_matGainMarix_Pair.block(0,3,p_matGainMarix.rows(),3) = p_matGainMarix.block(0, p_iIdx2*3, p_matGainMarix.rows(), 3);
859 t_pRapDipolePair.
m_iIdx1 = p_iDipoleIdx1;
860 t_pRapDipolePair.
m_iIdx2 = p_iDipoleIdx2;
870 t_pRapDipolePair.
m_Dipole1.phi_x() = p_vec_phi_k_1[0];
871 t_pRapDipolePair.
m_Dipole1.phi_y() = p_vec_phi_k_1[1];
872 t_pRapDipolePair.
m_Dipole1.phi_z() = p_vec_phi_k_1[2];
874 t_pRapDipolePair.
m_Dipole2.phi_x() = p_vec_phi_k_1[3];
875 t_pRapDipolePair.
m_Dipole2.phi_y() = p_vec_phi_k_1[4];
876 t_pRapDipolePair.
m_Dipole2.phi_z() = p_vec_phi_k_1[5];
880 p_RapDipoles.append(t_pRapDipolePair);
MNEMath class declaration.
RapMusic algorithm 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).
struct INVERSELIB::Pair Pair
Index pair representing two grid points evaluated together in the RAP MUSIC subspace scan.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Pair of correlated dipole indices and orientations found by the RAP MUSIC scanning step.
Index pair representing two grid points evaluated together in the RAP MUSIC subspace scan.
static double subcorr(MatrixX6T &p_matProj_G, const MatrixXT &p_pMatU_B)
Eigen::Matrix< double, 6, 6 > Matrix6T
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorXT
Eigen::Matrix< double, Eigen::Dynamic, 6 > MatrixX6T
bool init(MNELIB::MNEForwardSolution &p_pFwd, bool p_bSparsed=false, int p_iN=2, double p_dThr=0.5)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixXT
virtual const char * getName() const
static void getPointPair(const int p_iPoints, const int p_iCurIdx, int &p_iIdx1, int &p_iIdx2)
int m_iNumLeadFieldCombinations
static void insertSource(int p_iDipoleIdx1, int p_iDipoleIdx2, const Vector6T &p_vec_phi_k_1, double p_valCor, QList< DipolePair< double > > &p_RapDipoles)
void calcOrthProj(const MatrixXT &p_matA_k_1, MatrixXT &p_matOrthProj) const
void setStcAttr(int p_iSampStcWin, float p_fStcOverlap)
Pair ** m_ppPairIdxCombinations
static MatrixXT makeSquareMat(const MatrixXT &p_matF)
virtual MNELIB::MNESourceEstimate calculateInverse(const FIFFLIB::FiffEvoked &p_fiffEvoked, bool pick_normal=false)
Eigen::Matrix< double, 6, Eigen::Dynamic > Matrix6XT
virtual const MNELIB::MNESourceSpaces & getSourceSpace() const
void calcPairCombinations(const int p_iNumPoints, const int p_iNumCombinations, Pair **p_ppPairIdxCombinations) const
static int useFullRank(const MatrixXT &p_Mat, const MatrixXT &p_matSigma_src, MatrixXT &p_matFull_Rank, int type=NOT_TRANSPOSED)
MNELIB::MNEForwardSolution m_ForwardSolution
static void getGainMatrixPair(const MatrixXT &p_matGainMarix, MatrixX6T &p_matGainMarix_Pair, int p_iIdx1, int p_iIdx2)
int calcPhi_s(const MatrixXT &p_matMeasurement, MatrixXT *&p_pMatPhi_s) const
static int getRank(const MatrixXT &p_matSigma)
Eigen::Matrix< double, 6, 1 > Vector6T
static void calcA_k_1(const MatrixX6T &p_matG_k_1, const Vector6T &p_matPhi_k_1, const int p_iIdxk_1, MatrixXT &p_matA_k_1)
FIFFLIB::fiff_int_t nsource
FIFFLIB::FiffNamedMatrix::SDPtr sol
Source Space descritpion.
static int nchoose2(int n)