52 using namespace INVERSELIB;
53 using namespace MNELIB;
54 using namespace FIFFLIB;
55 using namespace UTILSLIB;
66 , m_iNumLeadFieldCombinations(0)
67 , m_ppPairIdxCombinations(NULL)
70 , m_iSamplesStcWindow(-1)
82 , m_iNumLeadFieldCombinations(0)
83 , m_ppPairIdxCombinations(NULL)
86 , m_iSamplesStcWindow(-1)
90 init(p_pFwd, p_bSparsed, p_iN, p_dThr);
107 std::cout <<
"OpenMP enabled" << std::endl;
110 std::cout <<
"OpenMP disabled (to enable it: VS2010->Project Properties->C/C++->Language, then modify OpenMP Support)" << std::endl;
113 std::cout <<
"Available Threats: " <<
m_iMaxNumThreads << std::endl << std::endl;
116 std::cout <<
"##### Initialization RAP MUSIC started ######\n\n";
134 if ( p_pFwd.
sol->data.cols() % 3 != 0 )
136 std::cout <<
"Gain matrix is not associated with a 3D grid!\n";
153 std::cout <<
"Calculate gain matrix combinations. \n";
161 std::cout <<
"Gain matrix combinations calculated. \n\n";
169 std::cout <<
"Number of sources to find: " <<
m_iN <<
"\n\n";
175 std::cout <<
"##### Initialization RAP MUSIC completed ######\n\n\n";
177 Q_UNUSED(p_bSparsed);
202 Q_UNUSED(pick_normal);
208 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;
209 return p_sourceEstimate;
224 p_sourceEstimate.
tmin = p_fiffEvoked.
times[0];
225 p_sourceEstimate.
tstep = p_fiffEvoked.
times[1] - p_fiffEvoked.
times[0];
229 QList< DipolePair<double> > t_RapDipoles;
232 for(qint32 i = 0; i < t_RapDipoles.size(); ++i)
234 double dip1 = sqrt( pow(t_RapDipoles[i].m_Dipole1.phi_x(),2) +
235 pow(t_RapDipoles[i].m_Dipole1.phi_y(),2) +
236 pow(t_RapDipoles[i].m_Dipole1.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
238 double dip2 = sqrt( pow(t_RapDipoles[i].m_Dipole2.phi_x(),2) +
239 pow(t_RapDipoles[i].m_Dipole2.phi_y(),2) +
240 pow(t_RapDipoles[i].m_Dipole2.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
242 RowVectorXd dip1Time = RowVectorXd::Constant(p_fiffEvoked.
data.cols(), dip1);
243 RowVectorXd dip2Time = RowVectorXd::Constant(p_fiffEvoked.
data.cols(), dip2);
245 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx1, 0, 1, p_fiffEvoked.
data.cols()) = dip1Time;
246 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx2, 0, 1, p_fiffEvoked.
data.cols()) = dip2Time;
254 qint32 t_iNumSensors = p_fiffEvoked.
data.rows();
255 qint32 t_iNumSteps = p_fiffEvoked.
data.cols();
258 qint32 t_iSamplesDiscard = t_iSamplesOverlap/2;
262 qint32 curSample = 0;
263 qint32 curResultSample = 0;
268 QList< DipolePair<double> > t_RapDipoles;
281 curSample -= t_iSamplesDiscard;
288 stcWindowSize = p_sourceEstimate.
data.cols() - curResultSample;
290 for(qint32 i = 0; i < t_RapDipoles.size(); ++i)
292 double dip1 = sqrt( pow(t_RapDipoles[i].m_Dipole1.phi_x(),2) +
293 pow(t_RapDipoles[i].m_Dipole1.phi_y(),2) +
294 pow(t_RapDipoles[i].m_Dipole1.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
296 double dip2 = sqrt( pow(t_RapDipoles[i].m_Dipole2.phi_x(),2) +
297 pow(t_RapDipoles[i].m_Dipole2.phi_y(),2) +
298 pow(t_RapDipoles[i].m_Dipole2.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
300 RowVectorXd dip1Time = RowVectorXd::Constant(stcWindowSize, dip1);
301 RowVectorXd dip2Time = RowVectorXd::Constant(stcWindowSize, dip2);
303 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx1, curResultSample, 1, stcWindowSize) = dip1Time;
304 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx2, curResultSample, 1, stcWindowSize) = dip2Time;
308 curResultSample += stcWindowSize;
315 return p_sourceEstimate;
322 Q_UNUSED(pick_normal);
328 std::cout <<
"Number of FiffEvoked channels (" << data.rows() <<
") doesn't match the number of channels (" <<
m_iNumChannels <<
") of the forward solution." << std::endl;
329 return p_sourceEstimate;
343 p_sourceEstimate.
times = RowVectorXf::Zero(data.cols());
344 p_sourceEstimate.
times[0] = tmin;
345 for(qint32 i = 1; i < p_sourceEstimate.
times.size(); ++i)
346 p_sourceEstimate.
times[i] = p_sourceEstimate.
times[i-1] + tstep;
347 p_sourceEstimate.
tmin = tmin;
348 p_sourceEstimate.
tstep = tstep;
353 for(qint32 i = 0; i < t_RapDipoles.size(); ++i)
355 double dip1 = sqrt( pow(t_RapDipoles[i].m_Dipole1.phi_x(),2) +
356 pow(t_RapDipoles[i].m_Dipole1.phi_y(),2) +
357 pow(t_RapDipoles[i].m_Dipole1.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
359 double dip2 = sqrt( pow(t_RapDipoles[i].m_Dipole2.phi_x(),2) +
360 pow(t_RapDipoles[i].m_Dipole2.phi_y(),2) +
361 pow(t_RapDipoles[i].m_Dipole2.phi_z(),2) ) * t_RapDipoles[i].m_vCorrelation;
363 RowVectorXd dip1Time = RowVectorXd::Constant(data.cols(), dip1);
364 RowVectorXd dip2Time = RowVectorXd::Constant(data.cols(), dip2);
366 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx1, 0, 1, data.cols()) = dip1Time;
367 p_sourceEstimate.
data.block(t_RapDipoles[i].m_iIdx2, 0, 1, data.cols()) = dip2Time;
370 return p_sourceEstimate;
382 std::cout <<
"RAP MUSIC wasn't initialized!";
383 return p_SourceEstimate;
389 std::cout <<
"Lead Field channels do not fit to number of measurement channels!";
390 return p_SourceEstimate;
406 int t_r =
calcPhi_s(p_matMeasurement, t_pMatPhi_s);
408 int t_iMaxSearch =
m_iN < t_r ?
m_iN : t_r;
412 std::cout <<
"Warning: Rank " << t_r <<
" of the measurement data is smaller than the " <<
m_iN;
413 std::cout <<
" sources to find." << std::endl;
414 std::cout <<
" Searching now for " << t_iMaxSearch <<
" correlated sources.";
415 std::cout << std::endl << std::endl;
421 t_matOrthProj.setIdentity();
425 t_matA_k_1.setZero();
441 p_RapDipoles.clear();
443 std::cout <<
"##### Calculation of RAP MUSIC started ######\n\n";
445 MatrixXT t_matProj_Phi_s(t_matOrthProj.rows(), t_pMatPhi_s->cols());
449 for(
int r = 0; r < t_iMaxSearch ; ++r)
451 t_matProj_Phi_s = t_matOrthProj*(*t_pMatPhi_s);
458 Eigen::JacobiSVD< MatrixXT > t_svdProj_Phi_S(t_matProj_Phi_s, Eigen::ComputeThinU);
460 useFullRank(t_svdProj_Phi_S.matrixU(), t_svdProj_Phi_S.singularValues().asDiagonal(), t_matU_B);
468 clock_t start_subcorr, end_subcorr;
469 start_subcorr = clock();
473 #pragma omp parallel num_threads(m_iMaxNumThreads)
483 MatrixX6T t_matProj_G(t_matProj_LeadField.rows(),6);
511 end_subcorr = clock();
513 float t_fSubcorrElapsedTime = ( (float)(end_subcorr-start_subcorr) / (float)CLOCKS_PER_SEC ) * 1000.0f;
514 std::cout <<
"Time Elapsed: " << t_fSubcorrElapsedTime <<
" ms" << std::endl;
519 VectorXT::Index t_iMaxIdx;
521 t_val_roh_k = t_vecRoh.maxCoeff(&t_iMaxIdx);
528 std::cout <<
"Iteration: " << r+1 <<
" of " << t_iMaxSearch
529 <<
"; Correlation: " << t_val_roh_k<<
"; Position (Idx+1): " << t_iIdx1+1 <<
" - " << t_iIdx2+1 <<
"\n\n";
535 MatrixX6T t_matProj_G_k_1(t_matOrthProj.rows(), t_matG_k_1.cols());
536 t_matProj_G_k_1 = t_matOrthProj * t_matG_k_1;
551 std::cout <<
"Searching stopped, last correlation " << t_val_roh_k;
552 std::cout <<
" is smaller then the given threshold " <<
m_dThreshold << std::endl << std::endl;
566 std::cout <<
"##### Calculation of RAP MUSIC completed ######"<< std::endl << std::endl << std::endl;
570 float t_fElapsedTime = ( (float)(end-start) / (float)CLOCKS_PER_SEC ) * 1000.0f;
571 std::cout <<
"Total Time Elapsed: " << t_fElapsedTime <<
" ms" << std::endl << std::endl;
576 return p_SourceEstimate;
585 if (p_matMeasurement.cols() > p_matMeasurement.rows())
588 t_matF =
MatrixXT(p_matMeasurement);
590 Eigen::JacobiSVD<MatrixXT> t_svdF(t_matF, Eigen::ComputeThinU);
592 int t_r =
getRank(t_svdF.singularValues().asDiagonal());
596 if (p_pMatPhi_s != NULL)
603 memcpy(p_pMatPhi_s->data(), t_svdF.matrixU().data(),
sizeof(
double) *
m_iNumChannels * t_iCols);
615 Matrix6XT t_matU_A_T(6, p_matProj_G.rows());
617 Eigen::JacobiSVD<MatrixXT> t_svdProj_G(p_matProj_G, Eigen::ComputeThinU);
619 t_matSigma_A = t_svdProj_G.singularValues().asDiagonal();
620 t_matU_A_T = t_svdProj_G.matrixU().transpose();
629 MatrixXT t_matCor(t_matU_A_T_full.rows(), p_matU_B.cols());
632 t_matCor = t_matU_A_T_full*p_matU_B;
636 if (t_matCor.cols() > t_matCor.rows())
638 MatrixXT t_matCor_H(t_matCor.cols(), t_matCor.rows());
639 t_matCor_H = t_matCor.adjoint();
642 Eigen::JacobiSVD<MatrixXT> t_svdCor_H(t_matCor_H);
644 t_vecSigma_C = t_svdCor_H.singularValues();
648 Eigen::JacobiSVD<MatrixXT> t_svdCor(t_matCor);
650 t_vecSigma_C = t_svdCor.singularValues();
654 double t_dRetSigma_C;
655 t_dRetSigma_C = t_vecSigma_C(0);
660 return t_dRetSigma_C;
673 Eigen::JacobiSVD<MatrixXT> svdOfProj_G(p_matProj_G, Eigen::ComputeThinU | Eigen::ComputeThinV);
675 sigma_A = svdOfProj_G.singularValues().asDiagonal();
676 U_A_T = svdOfProj_G.matrixU().transpose();
677 V_A = svdOfProj_G.matrixV();
686 t_matCor = U_A_T*p_matU_B;
693 if (t_matCor.cols() > t_matCor.rows())
696 Cor_H = t_matCor.adjoint();
698 Eigen::JacobiSVD<MatrixXT> svdOfCor_H(Cor_H, Eigen::ComputeThinV);
700 U_C = svdOfCor_H.matrixV();
701 sigma_C = svdOfCor_H.singularValues();
705 Eigen::JacobiSVD<MatrixXT> svdOfCor(t_matCor, Eigen::ComputeThinU);
707 U_C = svdOfCor.matrixU();
708 sigma_C = svdOfCor.singularValues();
712 sigma_a_inv = sigma_A.inverse();
715 X = (V_A*sigma_a_inv)*U_C;
720 double norm_X = 1/(X_max.norm());
723 p_vec_phi_k_1 = X_max*norm_X;
730 ret_sigma_C = sigma_C(0);
746 VectorXT t_vec_a_theta_k_1(p_matG_k_1.rows(),1);
748 t_vec_a_theta_k_1 = p_matG_k_1*p_matPhi_k_1;
750 p_matA_k_1.block(0,p_iIdxk_1,p_matA_k_1.rows(),1) = t_vec_a_theta_k_1;
759 MatrixXT t_matA_k_1_tmp(p_matA_k_1.cols(), p_matA_k_1.cols());
760 t_matA_k_1_tmp = p_matA_k_1.adjoint()*p_matA_k_1;
762 int t_size = t_matA_k_1_tmp.cols();
764 while (!t_matA_k_1_tmp.block(0,0,t_size,t_size).fullPivLu().isInvertible())
769 MatrixXT t_matA_k_1_tmp_inv(t_matA_k_1_tmp.rows(), t_matA_k_1_tmp.cols());
770 t_matA_k_1_tmp_inv.setZero();
772 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();
774 t_matA_k_1_tmp = MatrixXT::Zero(p_matA_k_1.rows(), p_matA_k_1.cols());
776 t_matA_k_1_tmp = p_matA_k_1*t_matA_k_1_tmp_inv;
778 MatrixXT t_matA_k_1_tmp2(p_matA_k_1.rows(), p_matA_k_1.rows());
780 t_matA_k_1_tmp2 = t_matA_k_1_tmp*p_matA_k_1.adjoint();
785 p_matOrthProj = I-t_matA_k_1_tmp2;
794 const int p_iNumCombinations,
795 Pair** p_ppPairIdxCombinations)
const
802 #pragma omp parallel num_threads(m_iMaxNumThreads) private(idx1, idx2)
808 for (
int i = 0; i < p_iNumCombinations; ++i)
812 Pair* t_pairCombination =
new Pair();
813 t_pairCombination->
x1 = idx1;
814 t_pairCombination->
x2 = idx2;
816 p_ppPairIdxCombinations[i] = t_pairCombination;
825 int ii = p_iPoints*(p_iPoints+1)/2-1-p_iCurIdx;
826 int K = (int)floor((sqrt((
double)(8*ii+1))-1)/2);
828 p_iIdx1 = p_iPoints-1-K;
830 p_iIdx2 = (p_iCurIdx-p_iPoints*(p_iPoints+1)/2 + (K+1)*(K+2)/2)+p_iIdx1;
837 int p_iIdx1,
int p_iIdx2)
839 p_matGainMarix_Pair.block(0,0,p_matGainMarix.rows(),3) = p_matGainMarix.block(0, p_iIdx1*3, p_matGainMarix.rows(), 3);
841 p_matGainMarix_Pair.block(0,3,p_matGainMarix.rows(),3) = p_matGainMarix.block(0, p_iIdx2*3, p_matGainMarix.rows(), 3);
853 t_pRapDipolePair.
m_iIdx1 = p_iDipoleIdx1;
854 t_pRapDipolePair.
m_iIdx2 = p_iDipoleIdx2;
864 t_pRapDipolePair.
m_Dipole1.phi_x() = p_vec_phi_k_1[0];
865 t_pRapDipolePair.
m_Dipole1.phi_y() = p_vec_phi_k_1[1];
866 t_pRapDipolePair.
m_Dipole1.phi_z() = p_vec_phi_k_1[2];
868 t_pRapDipolePair.
m_Dipole2.phi_x() = p_vec_phi_k_1[3];
869 t_pRapDipolePair.
m_Dipole2.phi_y() = p_vec_phi_k_1[4];
870 t_pRapDipolePair.
m_Dipole2.phi_z() = p_vec_phi_k_1[5];
874 p_RapDipoles.append(t_pRapDipolePair);