52 #include <QtConcurrent>
64 using namespace UTILSLIB;
65 using namespace MNELIB;
66 using namespace FIFFLIB;
67 using namespace FSLIB;
68 using namespace Eigen;
74 MNEInverseOperator::MNEInverseOperator()
80 , eigen_leads_weighted(false)
90 qRegisterMetaType<QSharedPointer<MNELIB::MNEInverseOperator> >(
"QSharedPointer<MNELIB::MNEInverseOperator>");
91 qRegisterMetaType<MNELIB::MNEInverseOperator>(
"MNELIB::MNEInverseOperator");
99 qRegisterMetaType<QSharedPointer<MNELIB::MNEInverseOperator> >(
"QSharedPointer<MNELIB::MNEInverseOperator>");
100 qRegisterMetaType<MNELIB::MNEInverseOperator>(
"MNELIB::MNEInverseOperator");
111 bool limit_depth_chs)
114 qRegisterMetaType<QSharedPointer<MNELIB::MNEInverseOperator> >(
"QSharedPointer<MNELIB::MNEInverseOperator>");
115 qRegisterMetaType<MNELIB::MNEInverseOperator>(
"MNELIB::MNEInverseOperator");
121 : info(p_MNEInverseOperator.info)
122 , methods(p_MNEInverseOperator.methods)
123 , source_ori(p_MNEInverseOperator.source_ori)
124 , nsource(p_MNEInverseOperator.nsource)
125 , nchan(p_MNEInverseOperator.nchan)
126 , coord_frame(p_MNEInverseOperator.coord_frame)
127 , source_nn(p_MNEInverseOperator.source_nn)
128 , sing(p_MNEInverseOperator.sing)
129 , eigen_leads_weighted(p_MNEInverseOperator.eigen_leads_weighted)
130 , eigen_leads(p_MNEInverseOperator.eigen_leads)
131 , eigen_fields(p_MNEInverseOperator.eigen_fields)
132 , noise_cov(p_MNEInverseOperator.noise_cov)
133 , source_cov(p_MNEInverseOperator.source_cov)
134 , orient_prior(p_MNEInverseOperator.orient_prior)
135 , depth_prior(p_MNEInverseOperator.depth_prior)
136 , fmri_prior(p_MNEInverseOperator.fmri_prior)
137 , src(p_MNEInverseOperator.src)
138 , mri_head_t(p_MNEInverseOperator.mri_head_t)
139 , nave(p_MNEInverseOperator.nave)
140 , projs(p_MNEInverseOperator.projs)
141 , proj(p_MNEInverseOperator.proj)
142 , whitener(p_MNEInverseOperator.whitener)
143 , reginv(p_MNEInverseOperator.reginv)
144 , noisenorm(p_MNEInverseOperator.noisenorm)
146 qRegisterMetaType<QSharedPointer<MNELIB::MNEInverseOperator> >(
"QSharedPointer<MNELIB::MNEInverseOperator>");
147 qRegisterMetaType<MNELIB::MNEInverseOperator>(
"MNELIB::MNEInverseOperator");
162 SparseMatrix<double> &noise_norm,
163 QList<VectorXi> &vertno)
166 MatrixXd t_source_cov = this->
source_cov->data;
167 if(method.compare(
"MNE") != 0)
172 typedef Eigen::Triplet<double> T;
173 std::vector<T> tripletList;
177 qDebug() <<
"ToDo: Label selection needs to be debugged - not done jet!";
181 if(method.compare(
"MNE") != 0)
184 tripletList.reserve(noise_norm.nonZeros());
186 for (qint32
k = 0;
k < noise_norm.outerSize(); ++
k)
188 for (SparseMatrix<double>::InnerIterator it(noise_norm,
k); it; ++it)
192 for(qint32 i = 0; i < src_sel.size(); ++i)
193 if(src_sel[i] == it.row())
196 tripletList.push_back(T(it.row(), it.col(), it.value()));
200 noise_norm = SparseMatrix<double>(src_sel.size(),noise_norm.cols());
201 noise_norm.setFromTriplets(tripletList.begin(), tripletList.end());
206 VectorXi src_sel_new(src_sel.size()*3);
208 for(qint32 i = 0; i < src_sel.size(); ++i)
210 src_sel_new[i*3] = src_sel[i]*3;
211 src_sel_new[i*3+1] = src_sel[i]*3+1;
212 src_sel_new[i*3+2] = src_sel[i]*3+2;
214 src_sel = src_sel_new;
217 for(qint32 i = 0; i < src_sel.size(); ++i)
219 t_eigen_leads.row(i) = t_eigen_leads.row(src_sel[i]);
220 t_source_cov = t_source_cov.row(src_sel[i]);
222 t_eigen_leads.conservativeResize(src_sel.size(), t_eigen_leads.cols());
223 t_source_cov.conservativeResize(src_sel.size(), t_source_cov.cols());
230 qWarning(
"Warning: Pick normal can only be used with a free orientation inverse operator.\n");
237 qWarning(
"The pick_normal parameter is only valid when working with loose orientations.\n");
243 for(qint32 i = 2; i < t_eigen_leads.rows(); i+=3)
245 t_eigen_leads.row(count) = t_eigen_leads.row(i);
248 t_eigen_leads.conservativeResize(count, t_eigen_leads.cols());
251 for(qint32 i = 2; i < t_source_cov.rows(); i+=3)
253 t_source_cov.row(count) = t_source_cov.row(i);
256 t_source_cov.conservativeResize(count, t_source_cov.cols());
260 tripletList.reserve(
reginv.rows());
261 for(qint32 i = 0; i <
reginv.rows(); ++i)
262 tripletList.push_back(T(i, i,
reginv(i,0)));
263 SparseMatrix<double> t_reginv(
reginv.rows(),
reginv.rows());
264 t_reginv.setFromTriplets(tripletList.begin(), tripletList.end());
276 printf(
"(eigenleads already weighted)...\n");
277 K = t_eigen_leads*trans;
284 printf(
"(eigenleads need to be weighted)...\n");
286 std::vector<T> tripletList2;
287 tripletList2.reserve(t_source_cov.rows());
288 for(qint32 i = 0; i < t_source_cov.rows(); ++i)
289 tripletList2.push_back(T(i, i, sqrt(t_source_cov(i,0))));
290 SparseMatrix<double> t_sourceCov(t_source_cov.rows(),t_source_cov.rows());
291 t_sourceCov.setFromTriplets(tripletList2.begin(), tripletList2.end());
293 K = t_sourceCov*t_eigen_leads*trans;
296 if(method.compare(
"MNE") == 0)
297 noise_norm = SparseMatrix<double>();
309 QStringList inv_ch_names = this->
eigen_fields->col_names;
311 bool t_bContains =
true;
312 if(this->
eigen_fields->col_names.size() != this->noise_cov->names.size())
316 for(qint32 i = 0; i < this->
noise_cov->names.size(); ++i)
318 if(inv_ch_names[i] != this->
noise_cov->names[i])
328 qCritical(
"Channels in inverse operator eigen fields do not match noise covariance channels.");
334 QStringList missing_ch_names;
335 for(qint32 i = 0; i < inv_ch_names.size(); ++i)
336 if(!data_ch_names.contains(inv_ch_names[i]))
337 missing_ch_names.append(inv_ch_names[i]);
339 qint32 n_missing = missing_ch_names.size();
343 qCritical() << n_missing <<
"channels in inverse operator are not present in the data (" << missing_ch_names <<
")";
354 printf(
"Cluster kernel using %s.\n", p_sMethod.toUtf8().constData());
356 MatrixXd p_outMT = this->m_K.transpose();
358 QList<MNEClusterInfo> t_qListMNEClusterInfo;
360 t_qListMNEClusterInfo.append(t_MNEClusterInfo);
361 t_qListMNEClusterInfo.append(t_MNEClusterInfo);
368 printf(
"Error: Fixed orientation not implemented jet!\n");
401 for(qint32 h = 0; h < this->
src.
size(); ++h )
409 for(qint32 j = 0; j < h; ++j)
410 offset += this->
src[j].nuse;
413 printf(
"Cluster Left Hemisphere\n");
415 printf(
"Cluster Right Hemisphere\n");
417 Colortable t_CurrentColorTable = p_AnnotationSet[h].getColortable();
418 VectorXi label_ids = t_CurrentColorTable.
getLabelIds();
421 VectorXi vertno_labeled = VectorXi::Zero(this->
src[h].vertno.rows());
424 for(qint32 i = 0; i < vertno_labeled.rows(); ++i)
425 vertno_labeled[i] = p_AnnotationSet[h].getLabelIds()[this->
src[h].vertno[i]];
428 QList<RegionMT> m_qListRegionMTIn;
433 for (qint32 i = 0; i < label_ids.rows(); ++i)
435 if (label_ids[i] != 0)
437 QString curr_name = t_CurrentColorTable.
struct_names[i];
438 printf(
"\tCluster %d / %ld %s...", i+1, label_ids.rows(), curr_name.toUtf8().constData());
443 VectorXi idcs = VectorXi::Zero(vertno_labeled.rows());
447 for(qint32 j = 0; j < vertno_labeled.rows(); ++j)
449 if(vertno_labeled[j] == label_ids[i])
455 idcs.conservativeResize(c);
458 MatrixXd t_MT(p_outMT.rows(), idcs.rows()*3);
460 for(qint32 j = 0; j < idcs.rows(); ++j)
461 t_MT.block(0, j*3, t_MT.rows(), 3) = p_outMT.block(0, (idcs[j]+offset)*3, t_MT.rows(), 3);
463 qint32 nSens = t_MT.rows();
464 qint32 nSources = t_MT.cols()/3;
470 t_sensMT.
idcs = idcs;
472 t_sensMT.
nClusters = ceil((
double)nSources/(
double)p_iClusterSize);
476 printf(
"%d Cluster(s)... ", t_sensMT.
nClusters);
479 t_sensMT.
matRoiMT = MatrixXd(t_MT.cols()/3, 3*nSens);
481 for(qint32 j = 0; j < nSens; ++j)
482 for(qint32
k = 0;
k < t_sensMT.
matRoiMT.rows(); ++
k)
483 t_sensMT.
matRoiMT.block(
k,j*3,1,3) = t_MT.block(j,
k*3,1,3);
487 m_qListRegionMTIn.append(t_sensMT);
493 printf(
"failed! Label contains no sources.\n");
501 printf(
"Clustering... ");
502 QFuture< RegionMTOut > res;
503 res = QtConcurrent::mapped(m_qListRegionMTIn, &RegionMT::cluster);
504 res.waitForFinished();
509 MatrixXd t_MT_partial;
513 QList<RegionMT>::const_iterator itIn;
514 itIn = m_qListRegionMTIn.begin();
515 QFuture<RegionMTOut>::const_iterator itOut;
516 for (itOut = res.constBegin(); itOut != res.constEnd(); ++itOut)
518 nClusters = itOut->ctrs.rows();
519 nSens = itOut->ctrs.cols()/3;
520 t_MT_partial = MatrixXd::Zero(nSens, nClusters*3);
528 for(qint32 j = 0; j < nSens; ++j)
529 for(qint32
k = 0;
k < nClusters; ++
k)
530 t_MT_partial.block(j,
k*3, 1, 3) = itOut->ctrs.block(
k,j*3,1,3);
535 for(qint32 j = 0; j < nClusters; ++j)
537 VectorXi clusterIdcs = VectorXi::Zero(itOut->roiIdx.rows());
538 VectorXd clusterDistance = VectorXd::Zero(itOut->roiIdx.rows());
539 qint32 nClusterIdcs = 0;
540 for(qint32
k = 0;
k < itOut->roiIdx.rows(); ++
k)
542 if(itOut->roiIdx[
k] == j)
544 clusterIdcs[nClusterIdcs] = itIn->idcs[
k];
547 clusterDistance[nClusterIdcs] = itOut->D(
k,j);
551 clusterIdcs.conservativeResize(nClusterIdcs);
552 clusterDistance.conservativeResize(nClusterIdcs);
554 VectorXi clusterVertnos = VectorXi::Zero(clusterIdcs.size());
555 for(qint32
k = 0;
k < clusterVertnos.size(); ++
k)
556 clusterVertnos(
k) = this->
src[h].vertno[clusterIdcs(
k)];
558 t_qListMNEClusterInfo[h].clusterVertnos.append(clusterVertnos);
565 if(t_MT_partial.rows() > 0 && t_MT_partial.cols() > 0)
567 t_MT_new.conservativeResize(t_MT_partial.rows(), t_MT_new.cols() + t_MT_partial.cols());
568 t_MT_new.block(0, t_MT_new.cols() - t_MT_partial.cols(), t_MT_new.rows(), t_MT_partial.cols()) = t_MT_partial;
571 for(qint32
k = 0;
k < nClusters; ++
k)
575 double sqec = sqrt((itIn->matRoiMTOrig.block(0, j*3, itIn->matRoiMTOrig.rows(), 3) - t_MT_partial.block(0,
k*3, t_MT_partial.rows(), 3)).array().pow(2).sum());
576 double sqec_min = sqec;
579 for(qint32 j = 1; j < itIn->idcs.rows(); ++j)
581 sqec = sqrt((itIn->matRoiMTOrig.block(0, j*3, itIn->matRoiMTOrig.rows(), 3) - t_MT_partial.block(0,
k*3, t_MT_partial.rows(), 3)).array().pow(2).sum());
615 qint32 totalNumOfClust = 0;
616 for (qint32 h = 0; h < 2; ++h)
617 totalNumOfClust += t_qListMNEClusterInfo[h].clusterVertnos.size();
620 p_D = MatrixXd::Zero(p_outMT.cols(), totalNumOfClust);
622 p_D = MatrixXd::Zero(p_outMT.cols(), totalNumOfClust*3);
629 qint32 currentCluster = 0;
630 for (qint32 h = 0; h < 2; ++h)
632 int hemiOffset = h == 0 ? 0 : t_vertnos[0].size();
633 for(qint32 i = 0; i < t_qListMNEClusterInfo[h].clusterVertnos.size(); ++i)
636 MNEMath::intersect(t_vertnos[h], t_qListMNEClusterInfo[h].clusterVertnos[i], idx_sel);
642 idx_sel.array() += hemiOffset;
646 double selectWeight = 1.0/idx_sel.size();
649 for(qint32 j = 0; j < idx_sel.size(); ++j)
650 p_D.col(currentCluster)[idx_sel(j)] = selectWeight;
654 qint32 clustOffset = currentCluster*3;
655 for(qint32 j = 0; j < idx_sel.size(); ++j)
657 qint32 idx_sel_Offset = idx_sel(j)*3;
659 p_D(idx_sel_Offset,clustOffset) = selectWeight;
661 p_D(idx_sel_Offset+1, clustOffset+1) = selectWeight;
663 p_D(idx_sel_Offset+2, clustOffset+2) = selectWeight;
688 bool limit_depth_chs)
693 std::cout <<
"ToDo MNEInverseOperator::make_inverse_operator: do surf_ori check" << std::endl;
696 if(fixed && loose > 0)
698 qWarning(
"Warning: When invoking make_inverse_operator with fixed = true, the loose parameter is ignored.\n");
702 if(is_fixed_ori && !fixed)
704 qWarning(
"Warning: Setting fixed parameter = true. Because the given forward operator has fixed orientation and can only be used to make a fixed-orientation inverse operator.\n");
710 qCritical(
"Error: Forward solution is not oriented in surface coordinates. loose parameter should be 0 not %f.\n", loose);
711 return p_MNEInverseOperator;
714 if(loose < 0 || loose > 1)
716 qWarning(
"Warning: Loose value should be in interval [0,1] not %f.\n", loose);
717 loose = loose > 1 ? 1 : 0;
718 printf(
"Setting loose to %f.\n", loose);
721 if(depth < 0 || depth > 1)
723 qWarning(
"Warning: Depth value should be in interval [0,1] not %f.\n", depth);
724 depth = depth > 1 ? 1 : 0;
725 printf(
"Setting depth to %f.\n", depth);
745 MatrixXd patch_areas;
748 std::cout <<
"ToDo: patch_areas" << std::endl;
754 p_depth_prior->data = MatrixXd::Ones(gain.cols(), gain.cols());
756 p_depth_prior->diag =
true;
757 p_depth_prior->dim = gain.cols();
758 p_depth_prior->nfree = 1;
764 if(depth < 0 || depth > 1)
767 printf(
"\tToDo: Picked elements from a free-orientation depth-weighting prior into the fixed-orientation one.\n");
773 for(qint32 i = 2; i < p_depth_prior->data.rows(); i+=3)
775 p_depth_prior->data.row(count) = p_depth_prior->data.row(i);
778 p_depth_prior->data.conservativeResize(count, 1);
786 printf(
"\tComputing inverse operator with %lld channels.\n", gain_info.
ch_names.size());
791 printf(
"\tCreating the source covariance matrix\n");
799 p_source_cov->data.array() *= p_orient_prior->data.array();
808 printf(
"\tWhitening the forward solution.\n");
819 printf(
"\tAdjusting source covariance matrix.\n");
820 RowVectorXd source_std = p_source_cov->data.array().sqrt().transpose();
822 for(qint32 i = 0; i < gain.rows(); ++i)
823 gain.row(i) = gain.row(i).array() * source_std.array();
825 double trace_GRGT = (gain * gain.transpose()).trace();
826 double scaling_source_cov = (double)n_nzero / trace_GRGT;
828 p_source_cov->data.array() *= scaling_source_cov;
830 gain.array() *= sqrt(scaling_source_cov);
838 printf(
"Computing SVD of whitened and weighted lead field matrix.\n");
839 JacobiSVD<MatrixXd> svd(gain, ComputeThinU | ComputeThinV);
840 std::cout <<
"ToDo Sorting Necessary?" << std::endl;
841 VectorXd p_sing = svd.singularValues();
842 MatrixXd t_U = svd.matrixU();
843 MNEMath::sort<double>(p_sing, t_U);
845 svd.matrixU().rows(),
850 p_sing = svd.singularValues();
851 MatrixXd t_V = svd.matrixV();
852 MNEMath::sort<double>(p_sing, t_V);
854 svd.matrixV().cols(),
858 printf(
"\tlargest singular value = %f\n", p_sing.maxCoeff());
859 printf(
"\tscaling factor to adjust the trace = %f\n", trace_GRGT);
864 bool has_meg =
false;
865 bool has_eeg =
false;
867 RowVectorXd ch_idx(
info.
chs.size());
869 for(qint32 i = 0; i <
info.
chs.size(); ++i)
877 ch_idx.conservativeResize(count);
879 for(qint32 i = 0; i < ch_idx.size(); ++i)
882 if (ch_type ==
"eeg")
884 if ((ch_type ==
"mag") || (ch_type ==
"grad"))
890 if(has_eeg && has_meg)
891 p_iMethods = FIFFV_MNE_MEG_EEG;
893 p_iMethods = FIFFV_MNE_MEG;
895 p_iMethods = FIFFV_MNE_EEG;
903 p_MNEInverseOperator.
sing = p_sing;
904 p_MNEInverseOperator.
nave = p_nave;
906 p_MNEInverseOperator.
source_cov = p_source_cov;
913 p_MNEInverseOperator.
methods = p_iMethods;
917 p_MNEInverseOperator.
src = forward.
src;
918 p_MNEInverseOperator.
info = forward.
info;
921 return p_MNEInverseOperator;
930 printf(
"The number of averages should be positive\n");
933 printf(
"Preparing the inverse operator for use...\n");
938 float scale = ((float)inv.
nave)/((float)
nave);
946 printf(
"\tScaled noise and source covariance from nave = %d to nave = %d\n",inv.
nave,
nave);
951 VectorXd tmp = inv.
sing.cwiseProduct(inv.
sing) + VectorXd::Constant(inv.
sing.size(), lambda2);
954 inv.
reginv = VectorXd(inv.
sing.cwiseQuotient(tmp));
955 printf(
"\tCreated the regularized inverter\n");
962 printf(
"\tCreated an SSP operator (subspace dimension = %d)\n",ncomp);
991 printf(
"\tCreated the whitener using a full noise covariance matrix (%d small eigenvalues omitted)\n", inv.
noise_cov->dim - nnzero);
1001 printf(
"\tCreated the whitener using a diagonal noise covariance matrix (%d small eigenvalues discarded)\n",ncomp);
1006 if (dSPM || sLORETA)
1008 VectorXd noise_norm = VectorXd::Zero(inv.
eigen_leads->nrow);
1009 VectorXd noise_weight;
1012 printf(
"\tComputing noise-normalization factors (dSPM)...");
1013 noise_weight = VectorXd(inv.
reginv);
1017 printf(
"\tComputing noise-normalization factors (sLORETA)...");
1018 VectorXd tmp = (VectorXd::Constant(inv.
sing.size(), 1) + inv.
sing.cwiseProduct(inv.
sing)/lambda2);
1019 noise_weight = inv.
reginv.cwiseProduct(tmp.cwiseSqrt());
1027 noise_norm[
k] = sqrt(one.dot(one));
1041 one = c*(inv.
eigen_leads->data.row(
k).transpose()).cwiseProduct(noise_weight);
1042 noise_norm[
k] = sqrt(one.dot(one));
1052 VectorXd noise_norm_new;
1063 VectorXd* t = MNEMath::combine_xyz(noise_norm.transpose());
1064 noise_norm_new = t->cwiseSqrt();
1072 VectorXd vOnes = VectorXd::Ones(noise_norm_new.size());
1073 VectorXd tmp = vOnes.cwiseQuotient(noise_norm_new.cwiseAbs());
1077 typedef Eigen::Triplet<double> T;
1078 std::vector<T> tripletList;
1079 tripletList.reserve(noise_norm_new.size());
1080 for(qint32 i = 0; i < noise_norm_new.size(); ++i)
1081 tripletList.push_back(T(i, i, tmp[i]));
1083 inv.
noisenorm = SparseMatrix<double>(noise_norm_new.size(),noise_norm_new.size());
1084 inv.
noisenorm.setFromTriplets(tripletList.begin(), tripletList.end());
1106 printf(
"Reading inverse operator decomposition from %s...\n",t_pStream->streamName().toUtf8().constData());
1108 if(!t_pStream->open())
1113 QList <FiffDirNode::SPtr> invs_list = t_pStream->dirtree()->dir_tree_find(FIFFB_MNE_INVERSE_SOLUTION);
1114 if ( invs_list.size()== 0)
1116 printf(
"No inverse solutions in %s\n", t_pStream->streamName().toUtf8().constData());
1123 QList <FiffDirNode::SPtr> parent_mri = t_pStream->dirtree()->dir_tree_find(FIFFB_MNE_PARENT_MRI_FILE);
1124 if (parent_mri.size() == 0)
1126 printf(
"No parent MRI information in %s", t_pStream->streamName().toUtf8().constData());
1129 printf(
"\tReading inverse operator info...");
1134 if (!invs->find_tag(t_pStream, FIFF_MNE_INCLUDED_METHODS, t_pTag))
1136 printf(
"Modalities not found\n");
1141 inv.
methods = *t_pTag->toInt();
1145 printf(
"Source orientation constraints not found\n");
1152 printf(
"Number of sources not found\n");
1155 inv.
nsource = *t_pTag->toInt();
1162 printf(
"Coordinate frame tag not found\n");
1171 printf(
"Source orientation information not found\n");
1177 inv.
source_nn = t_pTag->toFloatMatrix();
1184 printf(
"\tReading inverse operator decomposition...");
1187 printf(
"Singular values not found\n");
1193 inv.
sing = Map<VectorXf>(t_pTag->toFloat(), t_pTag->size()/4).cast<
double>();
1204 printf(
"Error reading eigenleads named matrix.\n");
1215 printf(
"Error reading eigenfields named matrix.\n");
1224 printf(
"\tNoise covariance matrix read.\n");
1228 printf(
"\tError: Not able to read noise covariance matrix.\n");
1232 if(t_pStream->read_cov(invs, FIFFV_MNE_SOURCE_COV, *inv.
source_cov.data()))
1234 printf(
"\tSource covariance matrix read.\n");
1238 printf(
"\tError: Not able to read source covariance matrix.\n");
1246 printf(
"\tOrientation priors read.\n");
1253 printf(
"\tDepth priors read.\n");
1259 if(t_pStream->read_cov(invs, FIFFV_MNE_FMRI_PRIOR_COV, *inv.
fmri_prior.data()))
1261 printf(
"\tfMRI priors read.\n");
1272 printf(
"\tError: Could not read the source spaces.\n");
1283 printf(
"MRI/head coordinate transformation not found\n");
1294 printf(
"MRI/head coordinate transformation not found");
1306 t_pStream->read_meas_info_base(t_pStream->dirtree(), inv.
info);
1313 printf(
"Only inverse solutions computed in MRI or head coordinates are acceptable");
1321 inv.
projs = t_pStream->read_proj(t_pStream->dirtree());
1333 printf(
"Could not transform source space.\n");
1335 printf(
"\tSource spaces transformed to the inverse solution coordinate frame\n");
1353 printf(
"Write inverse operator decomposition in %s...", t_pStream->streamName().toUtf8().constData());
1355 t_pStream->end_file();
1362 p_pStream->
start_block(FIFFB_MNE_INVERSE_SOLUTION);
1364 printf(
"\tWriting inverse operator info...\n");
1371 VectorXf tmp_sing = this->
sing.cast<
float>();
1391 printf(
"\t[done]\n");
1395 printf(
"\tWriting noise covariance matrix.");
1398 printf(
"\tWriting source covariance matrix.\n");
1403 printf(
"\tWriting orientation priors.\n");
1414 p_pStream->
start_block(FIFFB_MNE_PARENT_MRI_FILE);
1417 p_pStream->
end_block(FIFFB_MNE_PARENT_MRI_FILE);
1437 p_pStream->
end_block(FIFFB_MNE_INVERSE_SOLUTION);