39#include <QtConcurrent>
79 qRegisterMetaType<QSharedPointer<MNELIB::MNEInverseOperator>>(
"QSharedPointer<MNELIB::MNEInverseOperator>");
80 qRegisterMetaType<MNELIB::MNEInverseOperator>(
"MNELIB::MNEInverseOperator");
88 qRegisterMetaType<QSharedPointer<MNELIB::MNEInverseOperator>>(
"QSharedPointer<MNELIB::MNEInverseOperator>");
89 qRegisterMetaType<MNELIB::MNEInverseOperator>(
"MNELIB::MNEInverseOperator");
100 bool limit_depth_chs)
103 qRegisterMetaType<QSharedPointer<MNELIB::MNEInverseOperator>>(
"QSharedPointer<MNELIB::MNEInverseOperator>");
104 qRegisterMetaType<MNELIB::MNEInverseOperator>(
"MNELIB::MNEInverseOperator");
136 qRegisterMetaType<QSharedPointer<MNELIB::MNEInverseOperator>>(
"QSharedPointer<MNELIB::MNEInverseOperator>");
137 qRegisterMetaType<MNELIB::MNEInverseOperator>(
"MNELIB::MNEInverseOperator");
147 const QString& method,
150 SparseMatrix<double>& noise_norm,
151 QList<VectorXi>& vertno)
155 if (method.compare(QLatin1String(
"MNE")) != 0)
158 vertno =
src.get_vertno();
160 typedef Eigen::Triplet<double> T;
161 std::vector<T> tripletList;
165 vertno =
src.label_src_vertno_sel(label, src_sel);
167 if (method.compare(QLatin1String(
"MNE")) != 0 && noise_norm.rows() > 0) {
170 tripletList.reserve(src_sel.size());
171 for (qint32 i = 0; i < src_sel.size(); ++i)
172 tripletList.push_back(T(i, i, noise_norm.coeff(src_sel[i], src_sel[i])));
174 noise_norm = SparseMatrix<double>(src_sel.size(), src_sel.size());
175 noise_norm.setFromTriplets(tripletList.begin(), tripletList.end());
179 VectorXi src_sel_new(src_sel.size() * 3);
181 for (qint32 i = 0; i < src_sel.size(); ++i) {
182 src_sel_new[i * 3] = src_sel[i] * 3;
183 src_sel_new[i * 3 + 1] = src_sel[i] * 3 + 1;
184 src_sel_new[i * 3 + 2] = src_sel[i] * 3 + 2;
186 src_sel = src_sel_new;
190 for (qint32 i = 0; i < src_sel.size(); ++i) {
191 t_eigen_leads.row(i) = t_eigen_leads.row(src_sel[i]);
192 t_source_cov.row(i) = t_source_cov.row(src_sel[i]);
194 t_eigen_leads.conservativeResize(src_sel.size(), t_eigen_leads.cols());
195 t_source_cov.conservativeResize(src_sel.size(), t_source_cov.cols());
200 qWarning(
"Warning: Pick normal can only be used with a free orientation inverse operator.\n");
206 qWarning(
"The pick_normal parameter is only valid when working with loose orientations.\n");
212 for (qint32 i = 2; i < t_eigen_leads.rows(); i += 3) {
213 t_eigen_leads.row(count) = t_eigen_leads.row(i);
216 t_eigen_leads.conservativeResize(count, t_eigen_leads.cols());
219 for (qint32 i = 2; i < t_source_cov.rows(); i += 3) {
220 t_source_cov.row(count) = t_source_cov.row(i);
223 t_source_cov.conservativeResize(count, t_source_cov.cols());
227 tripletList.reserve(
reginv.rows());
228 for (qint32 i = 0; i <
reginv.rows(); ++i)
229 tripletList.push_back(T(i, i,
reginv(i, 0)));
230 SparseMatrix<double> t_reginv(
reginv.rows(),
reginv.rows());
231 t_reginv.setFromTriplets(tripletList.begin(), tripletList.end());
242 qInfo(
"(eigenleads already weighted)...\n");
243 K = t_eigen_leads * trans;
248 qInfo(
"(eigenleads need to be weighted)...\n");
250 std::vector<T> tripletList2;
251 tripletList2.reserve(t_source_cov.rows());
252 for (qint32 i = 0; i < t_source_cov.rows(); ++i)
253 tripletList2.push_back(T(i, i, sqrt(t_source_cov(i, 0))));
254 SparseMatrix<double> t_sourceCov(t_source_cov.rows(), t_source_cov.rows());
255 t_sourceCov.setFromTriplets(tripletList2.begin(), tripletList2.end());
257 K = t_sourceCov * t_eigen_leads * trans;
260 if (method.compare(QLatin1String(
"MNE")) == 0)
261 noise_norm = SparseMatrix<double>();
273 QStringList inv_ch_names = this->
eigen_fields->col_names;
275 bool t_bContains =
true;
276 if (this->
eigen_fields->col_names.size() != this->noise_cov->names.size())
279 for (qint32 i = 0; i < this->
noise_cov->names.size(); ++i) {
280 if (inv_ch_names[i] != this->
noise_cov->names[i]) {
288 qCritical(
"Channels in inverse operator eigen fields do not match noise covariance channels.");
292 QStringList data_ch_names = measInfo.
ch_names;
294 QStringList missing_ch_names;
295 for (qint32 i = 0; i < inv_ch_names.size(); ++i)
296 if (!data_ch_names.contains(inv_ch_names[i]))
297 missing_ch_names.append(inv_ch_names[i]);
299 qint32 n_missing = missing_ch_names.size();
302 qCritical() << n_missing <<
"channels in inverse operator are not present in the data (" << missing_ch_names <<
")";
313 qInfo(
"Cluster kernel using %s.\n", p_sMethod.toUtf8().constData());
315 MatrixXd p_outMT = m_K.transpose();
317 QList<MNEClusterInfo> t_qListMNEClusterInfo;
319 t_qListMNEClusterInfo.append(t_MNEClusterInfo);
320 t_qListMNEClusterInfo.append(t_MNEClusterInfo);
326 qCritical(
"Error: Fixed orientation not implemented yet!\n");
337 for (qint32 h = 0; h < this->
src.size(); ++h) {
341 for (qint32 j = 0; j < h; ++j)
342 offset += this->
src[j].nuse;
345 qInfo(
"Cluster Left Hemisphere\n");
347 qInfo(
"Cluster Right Hemisphere\n");
349 FsColortable t_CurrentColorTable = p_AnnotationSet[h].getColortable();
350 VectorXi label_ids = t_CurrentColorTable.
getLabelIds();
353 VectorXi vertno_labeled = VectorXi::Zero(this->
src[h].vertno.rows());
355 for (qint32 i = 0; i < vertno_labeled.rows(); ++i)
356 vertno_labeled[i] = p_AnnotationSet[h].getLabelIds()[this->
src[h].vertno[i]];
359 QList<RegionMT> m_qListRegionMTIn;
364 for (qint32 i = 0; i < label_ids.rows(); ++i) {
365 if (label_ids[i] != 0) {
366 QString curr_name = t_CurrentColorTable.
struct_names[i];
367 qInfo(
"\tCluster %d / %ld %s...", i + 1, label_ids.rows(), curr_name.toUtf8().constData());
372 VectorXi idcs = VectorXi::Zero(vertno_labeled.rows());
376 for (qint32 j = 0; j < vertno_labeled.rows(); ++j) {
377 if (vertno_labeled[j] == label_ids[i]) {
382 idcs.conservativeResize(c);
385 MatrixXd t_MT(p_outMT.rows(), idcs.rows() * 3);
387 for (qint32 j = 0; j < idcs.rows(); ++j)
388 t_MT.block(0, j * 3, t_MT.rows(), 3) = p_outMT.block(0, (idcs[j] + offset) * 3, t_MT.rows(), 3);
390 qint32 nSens = t_MT.rows();
391 qint32 nSources = t_MT.cols() / 3;
396 t_sensMT.
idcs = idcs;
398 t_sensMT.
nClusters = ceil(
static_cast<double>(nSources) /
static_cast<double>(p_iClusterSize));
402 qInfo(
"%d Cluster(s)... ", t_sensMT.
nClusters);
405 t_sensMT.
matRoiMT = MatrixXd(t_MT.cols() / 3, 3 * nSens);
407 for (qint32 j = 0; j < nSens; ++j)
408 for (qint32 k = 0; k < t_sensMT.
matRoiMT.rows(); ++k)
409 t_sensMT.
matRoiMT.block(k, j * 3, 1, 3) = t_MT.block(j, k * 3, 1, 3);
413 m_qListRegionMTIn.append(t_sensMT);
417 qInfo(
"failed! FsLabel contains no sources.\n");
425 qInfo(
"Clustering... ");
426 QFuture<RegionMTOut> res;
428 res.waitForFinished();
433 MatrixXd t_MT_partial;
437 QList<RegionMT>::const_iterator itIn;
438 itIn = m_qListRegionMTIn.begin();
439 QFuture<RegionMTOut>::const_iterator itOut;
440 for (itOut = res.constBegin(); itOut != res.constEnd(); ++itOut) {
441 nClusters = itOut->ctrs.rows();
442 nSens = itOut->ctrs.cols() / 3;
443 t_MT_partial = MatrixXd::Zero(nSens, nClusters * 3);
448 for (qint32 j = 0; j < nSens; ++j)
449 for (qint32 k = 0; k < nClusters; ++k)
450 t_MT_partial.block(j, k * 3, 1, 3) = itOut->ctrs.block(k, j * 3, 1, 3);
455 for (qint32 j = 0; j < nClusters; ++j) {
456 VectorXi clusterIdcs = VectorXi::Zero(itOut->roiIdx.rows());
457 VectorXd clusterDistance = VectorXd::Zero(itOut->roiIdx.rows());
458 qint32 nClusterIdcs = 0;
459 for (qint32 k = 0; k < itOut->roiIdx.rows(); ++k) {
460 if (itOut->roiIdx[k] == j) {
461 clusterIdcs[nClusterIdcs] = itIn->idcs[k];
462 clusterDistance[nClusterIdcs] = itOut->D(k, j);
466 clusterIdcs.conservativeResize(nClusterIdcs);
467 clusterDistance.conservativeResize(nClusterIdcs);
469 VectorXi clusterVertnos = VectorXi::Zero(clusterIdcs.size());
470 for (qint32 k = 0; k < clusterVertnos.size(); ++k)
471 clusterVertnos(k) = this->
src[h].vertno[clusterIdcs(k)];
473 t_qListMNEClusterInfo[h].clusterVertnos.append(clusterVertnos);
479 if (t_MT_partial.rows() > 0 && t_MT_partial.cols() > 0) {
480 t_MT_new.conservativeResize(t_MT_partial.rows(), t_MT_new.cols() + t_MT_partial.cols());
481 t_MT_new.block(0, t_MT_new.cols() - t_MT_partial.cols(), t_MT_new.rows(), t_MT_partial.cols()) = t_MT_partial;
484 for (qint32 k = 0; k < nClusters; ++k) {
485 double sqec = sqrt((itIn->matRoiMTOrig.block(0, 0, itIn->matRoiMTOrig.rows(), 3) - t_MT_partial.block(0, k * 3, t_MT_partial.rows(), 3)).array().pow(2).sum());
486 double sqec_min = sqec;
488 for (qint32 j = 1; j < itIn->idcs.rows(); ++j) {
489 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());
491 if (sqec < sqec_min) {
509 qint32 totalNumOfClust = 0;
510 for (qint32 h = 0; h < 2; ++h)
511 totalNumOfClust += t_qListMNEClusterInfo[h].clusterVertnos.size();
514 p_D = MatrixXd::Zero(p_outMT.cols(), totalNumOfClust);
516 p_D = MatrixXd::Zero(p_outMT.cols(), totalNumOfClust * 3);
518 QList<VectorXi> t_vertnos =
src.get_vertno();
520 qint32 currentCluster = 0;
521 for (qint32 h = 0; h < 2; ++h) {
522 int hemiOffset = h == 0 ? 0 : t_vertnos[0].size();
523 for (qint32 i = 0; i < t_qListMNEClusterInfo[h].clusterVertnos.size(); ++i) {
525 Linalg::intersect(t_vertnos[h], t_qListMNEClusterInfo[h].clusterVertnos[i], idx_sel);
527 idx_sel.array() += hemiOffset;
529 double selectWeight = 1.0 / idx_sel.size();
531 for (qint32 j = 0; j < idx_sel.size(); ++j)
532 p_D.col(currentCluster)[idx_sel(j)] = selectWeight;
534 qint32 clustOffset = currentCluster * 3;
535 for (qint32 j = 0; j < idx_sel.size(); ++j) {
536 qint32 idx_sel_Offset = idx_sel(j) * 3;
538 p_D(idx_sel_Offset, clustOffset) = selectWeight;
540 p_D(idx_sel_Offset + 1, clustOffset + 1) = selectWeight;
542 p_D(idx_sel_Offset + 2, clustOffset + 2) = selectWeight;
565 bool limit_depth_chs)
571 if (!is_fixed_ori && (fixed || loose < 1.0f)) {
576 if (fixed && loose > 0) {
577 qWarning(
"Warning: When invoking make_inverse_operator with fixed = true, the loose parameter is ignored.\n");
581 if (is_fixed_ori && !fixed) {
582 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");
587 qCritical(
"Forward solution is not oriented in surface coordinates. loose parameter should be 0 not %f.", loose);
591 if (loose < 0 || loose > 1) {
592 qWarning(
"Warning: Loose value should be in interval [0,1] not %f.\n", loose);
593 loose = loose > 1 ? 1 : 0;
594 qInfo(
"Setting loose to %f.\n", loose);
597 if (depth < 0 || depth > 1) {
598 qWarning(
"Warning: Depth value should be in interval [0,1] not %f.\n", depth);
599 depth = depth > 1 ? 1 : 0;
600 qInfo(
"Setting depth to %f.\n", depth);
620 MatrixXd patch_areas;
626 p_depth_prior->data = MatrixXd::Ones(gain.cols(), 1);
628 p_depth_prior->diag =
true;
629 p_depth_prior->dim = gain.cols();
630 p_depth_prior->nfree = 1;
635 if (depth < 0 || depth > 1) {
637 qInfo(
"\tPicking elements from free-orientation depth prior into fixed-orientation one.\n");
641 qWarning(
"Warning: For a fixed-orientation inverse, the forward solution must be surface-oriented. Skipping fixed conversion.\n");
645 for (qint32 i = 2; i < p_depth_prior->data.rows(); i += 3) {
646 p_depth_prior->data.row(count) = p_depth_prior->data.row(i);
647 gain.col(count) = gain.col(i);
650 p_depth_prior->data.conservativeResize(count, 1);
651 p_depth_prior->dim = count;
652 gain.conservativeResize(Eigen::NoChange, count);
659 qInfo(
"\tComputing inverse operator with %lld channels.\n",
static_cast<long long>(gain_info.
ch_names.size()));
664 qInfo(
"\tCreating the source covariance matrix\n");
671 p_source_cov->data.array() *= p_orient_prior->data.array();
680 qInfo(
"\tWhitening the forward solution.\n");
691 qInfo(
"\tAdjusting source covariance matrix.\n");
692 RowVectorXd source_std = p_source_cov->data.array().sqrt().transpose();
694 for (qint32 i = 0; i < gain.rows(); ++i)
695 gain.row(i) = gain.row(i).array() * source_std.array();
697 double trace_GRGT = (gain * gain.transpose()).trace();
698 double scaling_source_cov =
static_cast<double>(n_nzero) / trace_GRGT;
700 p_source_cov->data.array() *= scaling_source_cov;
702 gain.array() *= sqrt(scaling_source_cov);
707 qInfo(
"Computing SVD of whitened and weighted lead field matrix.\n");
708 JacobiSVD<MatrixXd>
svd(gain, ComputeThinU | ComputeThinV);
710 VectorXd p_sing =
svd.singularValues();
711 MatrixXd t_U =
svd.matrixU();
714 svd.matrixU().rows(),
719 p_sing =
svd.singularValues();
720 MatrixXd t_V =
svd.matrixV();
723 svd.matrixV().cols(),
727 qInfo(
"\tlargest singular value = %f\n", p_sing.maxCoeff());
728 qInfo(
"\tscaling factor to adjust the trace = %f\n", trace_GRGT);
733 bool has_meg =
false;
734 bool has_eeg =
false;
736 RowVectorXd ch_idx(
info.chs.size());
738 for (qint32 i = 0; i <
info.chs.size(); ++i) {
744 ch_idx.conservativeResize(count);
746 for (qint32 i = 0; i < ch_idx.size(); ++i) {
747 QString ch_type =
info.channel_type(ch_idx[i]);
748 if (ch_type ==
"eeg")
750 if ((ch_type ==
"mag") || (ch_type ==
"grad"))
756 if (has_eeg && has_meg)
770 inv.
nchan = p_sing.rows();
798 qCritical(
"The number of averages should be positive\n");
801 qInfo(
"Preparing the inverse operator for use...\n");
806 float scale =
static_cast<float>(inv.
nave) /
static_cast<float>(nAve);
814 qInfo(
"\tScaled noise and source covariance from nave = %d to nave = %d\n", inv.
nave, nAve);
819 VectorXd tmp = inv.
sing.cwiseProduct(inv.
sing) + VectorXd::Constant(inv.
sing.size(), lambda2);
820 inv.
reginv = VectorXd(inv.
sing.cwiseQuotient(tmp));
821 qInfo(
"\tCreated the regularized inverter\n");
828 qInfo(
"\tCreated an SSP operator (subspace dimension = %d)\n", ncomp);
843 for (k = 0; k < inv.
noise_cov->dim; ++k) {
853 qInfo(
"\tCreated the whitener using a full noise covariance matrix (%d small eigenvalues omitted)\n", inv.
noise_cov->dim - nnzero);
861 qInfo(
"\tCreated the whitener using a diagonal noise covariance matrix (%d small eigenvalues discarded)\n", ncomp);
866 if (dSPM || sLORETA) {
867 VectorXd noise_norm = VectorXd::Zero(inv.
eigen_leads->nrow);
868 VectorXd noise_weight;
870 qInfo(
"\tComputing noise-normalization factors (dSPM)...");
871 noise_weight = VectorXd(inv.
reginv);
873 qInfo(
"\tComputing noise-normalization factors (sLORETA)...");
874 VectorXd sLoretaScale = (VectorXd::Constant(inv.
sing.size(), 1) + inv.
sing.cwiseProduct(inv.
sing) / lambda2);
875 noise_weight = inv.
reginv.cwiseProduct(sLoretaScale.cwiseSqrt());
881 noise_norm[k] = sqrt(one.dot(one));
887 one = c * (inv.
eigen_leads->data.row(k).transpose()).cwiseProduct(noise_weight);
888 noise_norm[k] = sqrt(one.dot(one));
895 VectorXd noise_norm_new = noise_norm;
900 noise_norm_new = t.cwiseSqrt();
902 VectorXd vOnes = VectorXd::Ones(noise_norm_new.size());
903 VectorXd noiseNormInv = vOnes.cwiseQuotient(noise_norm_new.cwiseAbs());
905 typedef Eigen::Triplet<double> T;
906 std::vector<T> tripletList;
907 tripletList.reserve(noise_norm_new.size());
908 for (qint32 i = 0; i < noise_norm_new.size(); ++i)
909 tripletList.push_back(T(i, i, noiseNormInv[i]));
911 inv.
noisenorm = SparseMatrix<double>(noise_norm_new.size(), noise_norm_new.size());
912 inv.
noisenorm.setFromTriplets(tripletList.begin(), tripletList.end());
930 qInfo(
"Reading inverse operator decomposition from %s...\n", t_pStream->streamName().toUtf8().constData());
932 if (!t_pStream->open())
938 if (invs_list.size() == 0) {
939 qCritical(
"No inverse solutions in %s\n", t_pStream->streamName().toUtf8().constData());
947 if (parent_mri.size() == 0) {
948 qCritical(
"No parent MRI information in %s", t_pStream->streamName().toUtf8().constData());
951 qInfo(
"\tReading inverse operator info...");
957 qCritical(
"Modalities not found\n");
962 inv.
methods = *t_pTag->toInt();
965 qCritical(
"Source orientation constraints not found\n");
971 qCritical(
"Number of sources not found\n");
974 inv.
nsource = *t_pTag->toInt();
980 qCritical(
"Coordinate frame tag not found\n");
989 inv.
units = *t_pTag->toInt();
996 qCritical(
"Source orientation information not found\n");
1000 inv.
source_nn = t_pTag->toFloatMatrix();
1007 qInfo(
"\tReading inverse operator decomposition...");
1009 qCritical(
"Singular values not found\n");
1013 inv.
sing = Map<const VectorXf>(t_pTag->toFloat(), t_pTag->size() / 4).cast<
double>();
1022 qCritical(
"Error reading eigenleads named matrix.\n");
1032 qCritical(
"Error reading eigenfields named matrix.\n");
1040 qInfo(
"\tNoise covariance matrix read.\n");
1042 qCritical(
"\tError: Not able to read noise covariance matrix.\n");
1047 qInfo(
"\tSource covariance matrix read.\n");
1049 qCritical(
"\tError: Not able to read source covariance matrix.\n");
1056 qInfo(
"\tOrientation priors read.\n");
1061 qInfo(
"\tDepth priors read.\n");
1066 qInfo(
"\tfMRI priors read.\n");
1074 qCritical(
"\tError: Could not read the source spaces.\n");
1077 for (qint32 k = 0; k < inv.
src.
size(); ++k)
1084 qCritical(
"MRI/head coordinate transformation not found\n");
1091 qCritical(
"MRI/head coordinate transformation not found");
1101 t_pStream->read_meas_info_base(t_pStream->dirtree(), inv.
info);
1108 qCritical(
"Only inverse solutions computed in MRI or head coordinates are acceptable");
1116 inv.
projs = t_pStream->read_proj(t_pStream->dirtree());
1121 qCritical(
"Could not transform source space.\n");
1123 qInfo(
"\tSource spaces transformed to the inverse solution coordinate frame\n");
1139 qInfo(
"Write inverse operator decomposition in %s...", t_pStream->streamName().toUtf8().constData());
1141 t_pStream->end_file();
1151 qInfo(
"\tWriting inverse operator info...\n");
1161 if (this->
units > 0)
1164 VectorXf tmp_sing = this->
sing.cast<
float>();
1181 qInfo(
"\t[done]\n");
1185 qInfo(
"\tWriting noise covariance matrix.");
1188 qInfo(
"\tWriting source covariance matrix.\n");
1193 qInfo(
"\tWriting orientation priors.\n");
1218 this->
src.writeToStream(p_pStream);
#define FIFF_MNE_INVERSE_FIELDS
#define FIFF_MNE_INVERSE_LEADS
#define FIFF_MNE_INVERSE_SOURCE_ORIENTATIONS
#define FIFF_MNE_COORD_FRAME
#define FIFF_MNE_SOURCE_ORIENTATION
#define FIFFV_MNE_NOISE_COV
#define FIFF_MNE_INVERSE_SOURCE_UNIT
#define FIFFV_MNE_FMRI_PRIOR_COV
#define FIFF_MNE_INVERSE_LEADS_WEIGHTED
#define FIFF_MNE_INCLUDED_METHODS
#define FIFFB_MNE_INVERSE_SOLUTION
#define FIFF_MNE_SOURCE_SPACE_NPOINTS
#define FIFF_MNE_INVERSE_SING
#define FIFFV_MNE_MEG_EEG
#define FIFFV_MNE_SOURCE_COV
#define FIFFV_MNE_ORIENT_PRIOR_COV
#define FIFFB_MNE_PARENT_MRI_FILE
#define FIFFV_MNE_DEPTH_PRIOR_COV
#define FIFFV_MNE_FREE_ORI
Eigen::JacobiSVD< Eigen::Matrix3f > svd(S, Eigen::ComputeFullU|Eigen::ComputeFullV)
Static linear-algebra helpers: SVD-based conditioning, block-diagonal assembly, sorted index pairs.
Reader and in-memory representation of a FreeSurfer/MNE surface label (.label).
Pre-computed inverse operator (whitened SVD of the forward model) for MNE/dSPM/sLORETA.
Core MNE data structures (source spaces, source estimates, hemispheres).
FreeSurfer surface, annotation and parcellation I/O for mne-cpp.
FIFF file I/O, in-memory data structures and high-level readers/writers.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Labelled 4x4 FIFF affine: source frame, destination frame, rotation, translation and cached inverse.
FIFF noise / data covariance: matrix, channel names, kind, applied projectors, bads,...
QSharedDataPointer< FiffCov > SDPtr
QSharedPointer< FiffDirNode > SPtr
Full FIFF measurement info: per-channel descriptors, sampling and filter setup, projectors,...
FIFF named matrix: dense / sparse Eigen matrix plus row-name and column-name string lists.
QSharedDataPointer< FiffNamedMatrix > SDPtr
void transpose_named_matrix()
static fiff_int_t make_projector(const QList< FiffProj > &projs, const QStringList &ch_names, Eigen::MatrixXd &proj, const QStringList &bads=defaultQStringList, Eigen::MatrixXd &U=defaultMatrixXd)
FIFF tag-stream reader/writer: wraps a QIODevice and exposes typed read_* / write_* methods for every...
fiff_long_t write_cov(const FiffCov &p_FiffCov)
fiff_long_t start_block(fiff_int_t kind)
fiff_long_t write_float_matrix(fiff_int_t kind, const Eigen::MatrixXf &mat)
fiff_long_t write_proj(const QList< FiffProj > &projs)
QSharedPointer< FiffStream > SPtr
fiff_long_t write_int(fiff_int_t kind, const fiff_int_t *data, fiff_int_t nel=1, fiff_int_t next=FIFFV_NEXT_SEQ)
fiff_long_t write_float(fiff_int_t kind, const float *data, fiff_int_t nel=1)
fiff_long_t write_coord_trans(const FiffCoordTrans &trans)
fiff_long_t write_named_matrix(fiff_int_t kind, const FiffNamedMatrix &mat)
static FiffStream::SPtr start_file(QIODevice &p_IODevice)
fiff_long_t write_info_base(const FiffInfoBase &p_FiffInfoBase)
fiff_long_t end_block(fiff_int_t kind, fiff_int_t next=FIFFV_NEXT_SEQ)
std::unique_ptr< FiffTag > UPtr
Container holding the lh and/or rh FsAnnotation for one parcellation atlas.
FreeSurfer colour lookup table: region name + RGBA + packed label, indexed by entry.
Eigen::VectorXi getLabelIds() const
A FreeSurfer/MNE surface label: per-vertex indices, Tk-RAS positions and scalar values for one hemisp...
static Eigen::VectorXd combine_xyz(const Eigen::VectorXd &vec)
static Eigen::VectorXi sort(Eigen::Matrix< T, Eigen::Dynamic, 1 > &v, bool desc=true)
static Eigen::VectorXi intersect(const Eigen::VectorXi &v1, const Eigen::VectorXi &v2, Eigen::VectorXi &idx_sel)
Cluster table used to compress and reconstruct a clustered leadfield.
In-memory representation of an -fwd.fif forward solution.
FIFFLIB::fiff_int_t nsource
void convert_to_surf_ori()
FIFFLIB::FiffInfoBase info
static FIFFLIB::FiffCov compute_depth_prior(const Eigen::MatrixXd &Gain, const FIFFLIB::FiffInfo &gain_info, bool is_fixed_ori, double exp=0.8, double limit=10.0, const Eigen::MatrixXd &patch_areas=FIFFLIB::defaultConstMatrixXd, bool limit_depth_chs=false)
MNELIB::MNESourceSpaces src
FIFFLIB::fiff_int_t source_ori
void prepare_forward(const FIFFLIB::FiffInfo &p_info, const FIFFLIB::FiffCov &p_noise_cov, bool p_pca, FIFFLIB::FiffInfo &p_outFwdInfo, Eigen::MatrixXd &gain, FIFFLIB::FiffCov &p_outNoiseCov, Eigen::MatrixXd &p_outWhitener, qint32 &p_outNumNonZero) const
FIFFLIB::FiffCoordTrans mri_head_t
bool isFixedOrient() const
Eigen::MatrixX3f source_nn
FIFFLIB::FiffCov compute_orient_prior(float loose=0.2)
FIFFLIB::fiff_int_t coord_frame
Input parameters for multi-threaded KMeans clustering on a single cortical region.
Eigen::MatrixXd matRoiMTOrig
RegionMTOut cluster() const
Run KMeans clustering on this region.
MNEInverseOperator()
Constructs an empty inverse operator with invalid sentinel values.
FIFFLIB::FiffCov::SDPtr fmri_prior
Eigen::MatrixXd cluster_kernel(const FSLIB::FsAnnotationSet &annotationSet, qint32 clusterSize, Eigen::MatrixXd &D, const QString &method=QStringLiteral("cityblock")) const
Cluster the inverse kernel by cortical parcellation.
FIFFLIB::fiff_int_t coord_frame
QList< FIFFLIB::FiffProj > projs
Eigen::SparseMatrix< double > noisenorm
FIFFLIB::FiffCov::SDPtr orient_prior
static MNEInverseOperator make_inverse_operator(const FIFFLIB::FiffInfo &info, MNEForwardSolution forward, const FIFFLIB::FiffCov &noiseCov, float loose=0.2f, float depth=0.8f, bool fixed=false, bool limit_depth_chs=true)
Assemble an inverse operator from a forward solution and noise covariance.
FIFFLIB::fiff_int_t nchan
bool eigen_leads_weighted
FIFFLIB::fiff_int_t methods
FIFFLIB::FiffNamedMatrix::SDPtr eigen_leads
FIFFLIB::fiff_int_t units
bool check_ch_names(const FIFFLIB::FiffInfo &info) const
Verify that inverse-operator channels are present in the measurement info.
FIFFLIB::FiffCoordTrans mri_head_t
FIFFLIB::fiff_int_t nsource
MNEInverseOperator prepare_inverse_operator(qint32 nave, float lambda2, bool dSPM, bool sLORETA=false) const
Prepare the inverse operator for source estimation.
Eigen::MatrixXf source_nn
FIFFLIB::FiffCov::SDPtr depth_prior
FIFFLIB::fiff_int_t source_ori
bool assemble_kernel(const FSLIB::FsLabel &label, const QString &method, bool pick_normal, Eigen::MatrixXd &K, Eigen::SparseMatrix< double > &noise_norm, QList< Eigen::VectorXi > &vertno)
Assemble the inverse kernel matrix.
void writeToStream(FIFFLIB::FiffStream *p_pStream)
Write the inverse operator into an already-open FIFF stream.
FIFFLIB::FiffInfoBase info
~MNEInverseOperator()
Destructor.
FIFFLIB::FiffCov::SDPtr noise_cov
FIFFLIB::FiffCov::SDPtr source_cov
static bool read_inverse_operator(QIODevice &p_IODevice, MNEInverseOperator &inv)
Read an inverse operator from a FIFF file.
bool isFixedOrient() const
Check whether the inverse operator uses fixed source orientations.
bool write(QIODevice &p_IODevice)
Write the inverse operator to a FIFF file.
FIFFLIB::FiffNamedMatrix::SDPtr eigen_fields
bool transform_source_space_to(FIFFLIB::fiff_int_t dest, FIFFLIB::FiffCoordTrans &trans)
static qint32 find_source_space_hemi(MNESourceSpace &p_SourceSpace)
static bool readFromStream(FIFFLIB::FiffStream::SPtr &p_pStream, bool add_geom, MNESourceSpaces &p_SourceSpace)