58 m_sourceSpaces.reserve(p_MNESourceSpaces.m_sourceSpaces.size());
59 for (
const auto& sp : p_MNESourceSpaces.m_sourceSpaces)
60 m_sourceSpaces.push_back(sp->clone());
73 m_sourceSpaces.clear();
80 m_sourceSpaces.push_back(space.
clone());
87 QList<VectorXi> p_vertices;
88 for (qint32 i = 0; i < static_cast<qint32>(m_sourceSpaces.size()); ++i)
89 p_vertices.push_back(m_sourceSpaces[i]->vertno);
100 QList<VectorXi> vertno;
101 vertno << this->m_sourceSpaces[0]->vertno << this->m_sourceSpaces[1]->vertno;
103 if (p_label.
hemi == 0)
106 vertno[0] = vertno_sel;
107 vertno[1] = VectorXi();
108 }
else if (p_label.
hemi == 1)
111 src_sel.array() +=
static_cast<int>(vertno[0].size());
112 vertno[0] = VectorXi();
113 vertno[1] = vertno_sel;
141 qWarning(
"Unknown hemisphere type\n");
142 vertno[0] = VectorXi::Zero(0);
143 vertno[1] = VectorXi::Zero(0);
153 Q_UNUSED(p_qListLabels);
157 for (qint32 h = 0; h < 2; ++h) {
158 auto& srcSpace = *selectedSrc.m_sourceSpaces[h];
159 const auto& origSpace = *this->m_sourceSpaces[h];
161 auto* origHemi =
dynamic_cast<const MNEHemisphere*
>(&origSpace);
163 VectorXi selVertices;
167 for (qint32 i = 0; i < p_qListLabels.size(); ++i) {
168 if (p_qListLabels[i].hemi == h) {
169 VectorXi currentSelection;
171 Linalg::intersect(origSpace.vertno, p_qListLabels[i].vertices, currentSelection);
173 selVertices.conservativeResize(iSize + currentSelection.size());
174 selVertices.block(iSize, 0, currentSelection.size(), 1) = currentSelection;
175 iSize = selVertices.size();
181 VectorXi newVertno(selVertices.size());
183 srcSpace.inuse = VectorXi::Zero(srcSpace.np);
185 for (qint32 i = 0; i < selVertices.size(); ++i) {
186 newVertno[i] = origSpace.vertno[selVertices[i]];
187 srcSpace.inuse[newVertno[i]] = 1;
190 srcSpace.nuse = selVertices.size();
191 srcSpace.vertno = newVertno;
196 VectorXi idx_select = VectorXi::Zero(origSpace.use_itris.rows());
197 for (qint32 i = 0; i < 3; ++i) {
198 VectorXi tri_dim = origSpace.use_itris.col(i);
202 for (qint32 j = 0; j < idx_dim.size(); ++j)
203 idx_select[idx_dim[j]] = 1;
207 for (qint32 i = 0; i < idx_select.size(); ++i)
208 if (idx_select[i] == 1)
211 srcSpace.nuse_tri = countSel;
213 MatrixX3i use_tris_new(countSel, 3);
214 MatrixX3d use_tri_cent_new(countSel, 3);
215 MatrixX3d use_tri_nn_new(countSel, 3);
216 VectorXd use_tri_area_new(countSel);
219 for (qint32 i = 0; i < idx_select.size(); ++i) {
220 if (idx_select[i] == 1) {
221 use_tris_new.row(countSel) = origSpace.use_itris.row(i);
222 if (origHemi && selHemi) {
223 use_tri_cent_new.row(countSel) = origHemi->use_tri_cent.row(i);
224 use_tri_nn_new.row(countSel) = origHemi->use_tri_nn.row(i);
225 use_tri_area_new[countSel] = origHemi->use_tri_area[i];
231 srcSpace.use_itris = use_tris_new;
233 selHemi->use_tri_cent = use_tri_cent_new;
234 selHemi->use_tri_nn = use_tri_nn_new;
235 selHemi->use_tri_area = use_tri_area_new;
237 if (origHemi && origHemi->patch_inds.size() == origSpace.nuse) {
238 selHemi->patch_inds.resize(selVertices.size());
239 for (qint32 i = 0; i < selVertices.size(); ++i)
240 selHemi->patch_inds[i] = origHemi->patch_inds[selVertices[i]];
261 bool open_here =
false;
264 if (!p_pStream->device()->isOpen()) {
265 QString t_sFileName = p_pStream->streamName();
267 t_file.setFileName(t_sFileName);
269 if (!p_pStream->open())
279 if (spaces.size() == 0) {
282 qWarning() <<
"No source spaces found";
286 for (
int k = 0; k < spaces.size(); ++k) {
287 auto p_Hemisphere = std::make_shared<MNEHemisphere>();
288 qInfo(
"\tReading a source space...");
289 MNESourceSpaces::read_source_space(p_pStream, spaces[k], *p_Hemisphere);
292 p_Hemisphere->complete_source_space_info();
294 p_SourceSpace.m_sourceSpaces.push_back(p_Hemisphere);
299 qInfo(
"\t%lld source spaces read\n",
static_cast<long long>(spaces.size()));
318 for (
size_t k = 0; k < this->m_sourceSpaces.size(); ++k) {
319 auto* hemi =
dynamic_cast<MNEHemisphere*
>(m_sourceSpaces[k].get());
321 if (!hemi->transform_hemisphere_to(dest, trans)) {
322 qWarning(
"Could not transform source space.");
334 p_Hemisphere.
clear();
342 p_Hemisphere.
id = *t_pTag->toInt();
349 throw std::runtime_error(
"error: Number of vertices not found.");
352 p_Hemisphere.
np = *t_pTag->toInt();
357 p_Hemisphere.
ntri = 0;
359 p_Hemisphere.
ntri = *t_pTag->toInt();
361 p_Hemisphere.
ntri = *t_pTag->toInt();
368 throw std::runtime_error(
"Coordinate frame information not found.");
379 throw std::runtime_error(
"Vertex data not found.");
382 p_Hemisphere.
rr = t_pTag->toFloatMatrix().transpose();
383 qint32 rows_rr = p_Hemisphere.
rr.rows();
386 if (rows_rr != p_Hemisphere.
np) {
388 throw std::runtime_error(
"Vertex information is incorrect.");
395 throw std::runtime_error(
"Vertex normals not found.");
398 p_Hemisphere.
nn = t_pTag->toFloatMatrix().transpose();
399 qint32 rows_nn = p_Hemisphere.
nn.rows();
401 if (rows_nn != p_Hemisphere.
np) {
403 throw std::runtime_error(
"Vertex normal information is incorrect.");
408 if (p_Hemisphere.
ntri > 0) {
412 throw std::runtime_error(
"Triangulation not found.");
414 p_Hemisphere.
itris = t_pTag->toIntMatrix().transpose();
415 p_Hemisphere.
itris.array() -= 1;
418 p_Hemisphere.
itris = t_pTag->toIntMatrix().transpose();
419 p_Hemisphere.
itris.array() -= 1;
421 if (p_Hemisphere.
itris.rows() != p_Hemisphere.
ntri) {
423 throw std::runtime_error(
"Triangulation information is incorrect.");
426 p_Hemisphere.
itris.resize(0, 3);
434 p_Hemisphere.
nuse = 0;
435 p_Hemisphere.
inuse = VectorXi::Zero(p_Hemisphere.
nuse);
436 VectorXi p_defaultVector;
437 p_Hemisphere.
vertno = p_defaultVector;
439 p_Hemisphere.
nuse = *t_pTag->toInt();
442 throw std::runtime_error(
"Source selection information missing.");
444 p_Hemisphere.
inuse = VectorXi(Map<VectorXi>(t_pTag->toInt(), t_pTag->size() / 4, 1));
446 p_Hemisphere.
vertno = VectorXi::Zero(p_Hemisphere.
nuse);
447 if (p_Hemisphere.
inuse.rows() != p_Hemisphere.
np) {
449 throw std::runtime_error(
"Incorrect number of entries in source space selection.");
452 for (
int p = 0; p < p_Hemisphere.
np; ++p) {
453 if (p_Hemisphere.
inuse(p) == 1) {
454 p_Hemisphere.
vertno(pp) = p;
467 MatrixX3i p_defaultMatrix;
469 p_Hemisphere.
use_itris = p_defaultMatrix;
471 p_Hemisphere.
nuse_tri = *t_pTag1->toInt();
472 p_Hemisphere.
use_itris = t_pTag2->toIntMatrix().transpose();
484 VectorXi nearestIdx = VectorXi(Map<VectorXi>(t_pTag1->toInt(), t_pTag1->size() / 4, 1));
485 VectorXd nearestDist = VectorXd((Map<const VectorXf>(t_pTag2->toFloat(), t_pTag2->size() / 4, 1)).cast<
double>());
491 qInfo(
"\tPatch information added...");
496 p_Hemisphere.
dist = FiffSparseMatrix();
501 auto dist_full = dist_lower->mne_add_upper_triangle_rcs();
503 p_Hemisphere.
dist = std::move(*dist_full);
506 p_Hemisphere.
dist_limit = *t_pTag2->toFloat();
521bool MNESourceSpaces::complete_source_space_info(
MNEHemisphere& p_Hemisphere)
530 for (
size_t h = 0; h < m_sourceSpaces.size(); ++h) {
531 qInfo(
"\tWrite a source space... ");
533 auto* hemi =
dynamic_cast<MNEHemisphere*
>(m_sourceSpaces[h].get());
539 qInfo(
"\t%zu source spaces written\n", m_sourceSpaces.size());
546 if (
static_cast<qint32
>(m_sourceSpaces.size()) > idx)
547 return *m_sourceSpaces[idx];
549 qWarning(
"Warning: Index out of bound! Returning last element.");
550 return *m_sourceSpaces.back();
558 if (
static_cast<qint32
>(m_sourceSpaces.size()) > idx)
559 return *m_sourceSpaces[idx];
561 qWarning(
"Warning: Index out of bound! Returning last element.");
562 return *m_sourceSpaces.back();
570 if (idt.compare(
"lh") == 0)
571 return *m_sourceSpaces[0];
572 else if (idt.compare(
"rh") == 0)
573 return *m_sourceSpaces[1];
575 qWarning(
"Warning: Identifier is not 'lh' or 'rh'! Returning 'lh'.");
576 return *m_sourceSpaces[0];
584 if (idt.compare(
"lh") == 0)
585 return *m_sourceSpaces[0];
586 else if (idt.compare(
"rh") == 0)
587 return *m_sourceSpaces[1];
589 qWarning(
"Warning: Identifier is not 'lh' or 'rh'! Returning 'lh'.");
590 return *m_sourceSpaces[0];
598 if (idx >= 0 && idx <
static_cast<qint32
>(m_sourceSpaces.size()))
599 return dynamic_cast<MNEHemisphere*
>(m_sourceSpaces[idx].get());
607 if (idx >= 0 && idx <
static_cast<qint32
>(m_sourceSpaces.size()))
608 return dynamic_cast<const MNEHemisphere*
>(m_sourceSpaces[idx].get());
616 return m_sourceSpaces.at(idx);
623 return m_sourceSpaces.at(idx);
#define FIFF_MNE_SOURCE_SPACE_ID
#define FIFF_MNE_SOURCE_SPACE_DIST_LIMIT
#define FIFF_MNE_COORD_FRAME
#define FIFFV_MNE_SURF_UNKNOWN
#define FIFF_MNE_SOURCE_SPACE_SELECTION
#define FIFF_MNE_SOURCE_SPACE_USE_TRIANGLES
#define FIFF_MNE_SOURCE_SPACE_NUSE_TRI
#define FIFF_MNE_SOURCE_SPACE_NORMALS
#define FIFF_MNE_SOURCE_SPACE_NEAREST_DIST
#define FIFF_MNE_SOURCE_SPACE_DIST
#define FIFF_MNE_SOURCE_SPACE_POINTS
#define FIFF_MNE_SOURCE_SPACE_NTRI
#define FIFFB_MNE_SOURCE_SPACE
#define FIFF_MNE_SOURCE_SPACE_NPOINTS
#define FIFF_MNE_SOURCE_SPACE_TRIANGLES
#define FIFF_MNE_SOURCE_SPACE_NUSE
#define FIFF_MNE_SOURCE_SPACE_NEAREST
#define FIFF_BEM_SURF_TRIANGLES
#define FIFF_BEM_SURF_NTRI
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).
Container pairing the left and right cortical source spaces of a subject.
Per-source-space-vertex nearest-cortex-vertex mapping.
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.
QSharedPointer< FiffDirNode > SPtr
static FiffSparseMatrix::UPtr fiff_get_float_sparse_matrix(const FIFFLIB::FiffTag::UPtr &tag)
FIFF tag-stream reader/writer: wraps a QIODevice and exposes typed read_* / write_* methods for every...
fiff_long_t start_block(fiff_int_t kind)
QSharedPointer< FiffStream > SPtr
fiff_long_t end_block(fiff_int_t kind, fiff_int_t next=FIFFV_NEXT_SEQ)
std::unique_ptr< FiffTag > UPtr
A FreeSurfer/MNE surface label: per-vertex indices, Tk-RAS positions and scalar values for one hemisp...
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)
Hemisphere provides geometry information.
void writeToStream(FIFFLIB::FiffStream *p_pStream)
bool complete_source_space_info()
bool compute_patch_info()
This defines a source space.
virtual MNESourceSpace::SPtr clone() const
qint32 find_source_space_hemi() const
void writeToStream(FIFFLIB::FiffStream *p_pStream)
MNESourceSpaces pick_regions(const QList< FSLIB::FsLabel > &p_qListLabels) const
bool transform_source_space_to(FIFFLIB::fiff_int_t dest, FIFFLIB::FiffCoordTrans &trans)
MNEHemisphere * hemisphereAt(qint32 idx)
void append(const MNESourceSpace &space)
static bool patch_info(MNEHemisphere &p_Hemisphere)
static qint32 find_source_space_hemi(MNESourceSpace &p_SourceSpace)
QList< Eigen::VectorXi > label_src_vertno_sel(const FSLIB::FsLabel &p_label, Eigen::VectorXi &src_sel) const
MNESourceSpace & operator[](qint32 idx)
static bool readFromStream(FIFFLIB::FiffStream::SPtr &p_pStream, bool add_geom, MNESourceSpaces &p_SourceSpace)
std::shared_ptr< MNESourceSpace > & at(qint32 idx)
QList< Eigen::VectorXi > get_vertno() const
void setNearestData(const Eigen::VectorXi &nearestIdx, const Eigen::VectorXd &nearestDist)
FIFFLIB::FiffSparseMatrix dist
std::vector< MNENearest > nearest