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();
109 else if (p_label.
hemi == 1)
112 src_sel.array() += p_label.
vertices.size();
113 vertno[0] = VectorXi();
114 vertno[1] = vertno_sel;
143 qWarning(
"Unknown hemisphere type\n");
144 vertno[0] = VectorXi::Zero(0);
145 vertno[1] = VectorXi::Zero(0);
155 Q_UNUSED(p_qListLabels);
159 for(qint32 h = 0; h < 2; ++h)
161 auto& srcSpace = *selectedSrc.m_sourceSpaces[h];
162 const auto& origSpace = *this->m_sourceSpaces[h];
164 auto* origHemi =
dynamic_cast<const MNEHemisphere*
>(&origSpace);
166 VectorXi selVertices;
170 for(qint32 i = 0; i < p_qListLabels.size(); ++i)
172 if(p_qListLabels[i].hemi == h)
174 VectorXi currentSelection;
176 Linalg::intersect(origSpace.vertno, p_qListLabels[i].vertices, currentSelection);
178 selVertices.conservativeResize(iSize+currentSelection.size());
179 selVertices.block(iSize,0,currentSelection.size(),1) = currentSelection;
180 iSize = selVertices.size();
186 VectorXi newVertno(selVertices.size());
188 srcSpace.inuse = VectorXi::Zero(srcSpace.np);
190 for(qint32 i = 0; i < selVertices.size(); ++i)
192 srcSpace.inuse[selVertices[i]] = 1;
193 newVertno[i] = origSpace.vertno[selVertices[i]];
196 srcSpace.nuse = selVertices.size();
197 srcSpace.vertno = newVertno;
202 VectorXi idx_select = VectorXi::Zero(origSpace.use_itris.rows());
203 for(qint32 i = 0; i < 3; ++i)
205 VectorXi tri_dim = origSpace.use_itris.col(i);
209 for(qint32 j = 0; j < idx_dim.size(); ++j)
210 idx_select[idx_dim[j]] = 1;
214 for(qint32 i = 0; i < idx_select.size(); ++i)
215 if(idx_select[i] == 1)
218 srcSpace.nuse_tri = countSel;
220 MatrixX3i use_tris_new(countSel,3);
221 MatrixX3d use_tri_cent_new(countSel,3);
222 MatrixX3d use_tri_nn_new(countSel,3);
223 VectorXd use_tri_area_new(countSel);
226 for(qint32 i = 0; i < idx_select.size(); ++i)
228 if(idx_select[i] == 1)
230 use_tris_new.row(countSel) = origSpace.use_itris.row(i);
231 if (origHemi && selHemi) {
232 use_tri_cent_new.row(countSel) = origHemi->use_tri_cent.row(i);
233 use_tri_nn_new.row(countSel) = origHemi->use_tri_nn.row(i);
234 use_tri_area_new[countSel] = origHemi->use_tri_area[i];
240 srcSpace.use_itris = use_tris_new;
242 selHemi->use_tri_cent = use_tri_cent_new;
243 selHemi->use_tri_nn = use_tri_nn_new;
244 selHemi->use_tri_area = use_tri_area_new;
264 bool open_here =
false;
267 if (!p_pStream->device()->isOpen())
269 QString t_sFileName = p_pStream->streamName();
271 t_file.setFileName(t_sFileName);
273 if(!p_pStream->open())
283 if (spaces.size() == 0)
287 qWarning() <<
"No source spaces found";
291 for(
int k = 0; k < spaces.size(); ++k)
293 auto p_Hemisphere = std::make_shared<MNEHemisphere>();
294 qInfo(
"\tReading a source space...");
295 MNESourceSpaces::read_source_space(p_pStream, spaces[k], *p_Hemisphere);
296 qInfo(
"\t[done]\n" );
298 p_Hemisphere->complete_source_space_info();
300 p_SourceSpace.m_sourceSpaces.push_back(p_Hemisphere);
305 qInfo(
"\t%lld source spaces read\n", spaces.size());
324 for(
size_t k = 0; k < this->m_sourceSpaces.size(); ++k)
326 auto* hemi =
dynamic_cast<MNEHemisphere*
>(m_sourceSpaces[k].get());
328 if(!hemi->transform_hemisphere_to(dest,trans))
330 qWarning(
"Could not transform source space.");
342 p_Hemisphere.
clear();
350 p_Hemisphere.
id = *t_pTag->toInt();
358 throw std::runtime_error(
"error: Number of vertices not found.");
361 p_Hemisphere.
np = *t_pTag->toInt();
367 p_Hemisphere.
ntri = 0;
369 p_Hemisphere.
ntri = *t_pTag->toInt();
373 p_Hemisphere.
ntri = *t_pTag->toInt();
381 throw std::runtime_error(
"Coordinate frame information not found.");
393 throw std::runtime_error(
"Vertex data not found.");
396 p_Hemisphere.
rr = t_pTag->toFloatMatrix().transpose();
397 qint32 rows_rr = p_Hemisphere.
rr.rows();
400 if (rows_rr != p_Hemisphere.
np)
403 throw std::runtime_error(
"Vertex information is incorrect.");
411 throw std::runtime_error(
"Vertex normals not found.");
414 p_Hemisphere.
nn = t_pTag->toFloatMatrix().transpose();
415 qint32 rows_nn = p_Hemisphere.
nn.rows();
417 if (rows_nn != p_Hemisphere.
np)
420 throw std::runtime_error(
"Vertex normal information is incorrect.");
425 if (p_Hemisphere.
ntri > 0)
432 throw std::runtime_error(
"Triangulation not found.");
436 p_Hemisphere.
itris = t_pTag->toIntMatrix().transpose();
437 p_Hemisphere.
itris.array() -= 1;
442 p_Hemisphere.
itris = t_pTag->toIntMatrix().transpose();
443 p_Hemisphere.
itris.array() -= 1;
445 if (p_Hemisphere.
itris.rows() != p_Hemisphere.
ntri)
448 throw std::runtime_error(
"Triangulation information is incorrect.");
453 p_Hemisphere.
itris.resize(0, 3);
462 p_Hemisphere.
nuse = 0;
463 p_Hemisphere.
inuse = VectorXi::Zero(p_Hemisphere.
nuse);
464 VectorXi p_defaultVector;
465 p_Hemisphere.
vertno = p_defaultVector;
469 p_Hemisphere.
nuse = *t_pTag->toInt();
473 throw std::runtime_error(
"Source selection information missing.");
475 p_Hemisphere.
inuse = VectorXi(Map<VectorXi>(t_pTag->toInt(), t_pTag->size()/4, 1));
477 p_Hemisphere.
vertno = VectorXi::Zero(p_Hemisphere.
nuse);
478 if (p_Hemisphere.
inuse.rows() != p_Hemisphere.
np)
481 throw std::runtime_error(
"Incorrect number of entries in source space selection.");
484 for (
int p = 0; p < p_Hemisphere.
np; ++p)
486 if(p_Hemisphere.
inuse(p) == 1)
488 p_Hemisphere.
vertno(pp) = p;
502 MatrixX3i p_defaultMatrix;
504 p_Hemisphere.
use_itris = p_defaultMatrix;
508 p_Hemisphere.
nuse_tri = *t_pTag1->toInt();
509 p_Hemisphere.
use_itris = t_pTag2->toIntMatrix().transpose();
524 VectorXi nearestIdx = VectorXi(Map<VectorXi>(t_pTag1->toInt(), t_pTag1->size()/4, 1));
525 VectorXd nearestDist = VectorXd((Map<const VectorXf>(t_pTag2->toFloat(), t_pTag2->size()/4, 1)).cast<
double>());
531 qInfo(
"\tPatch information added...");
537 p_Hemisphere.
dist = FiffSparseMatrix();
544 auto dist_full = dist_lower->mne_add_upper_triangle_rcs();
546 p_Hemisphere.
dist = std::move(*dist_full);
549 p_Hemisphere.
dist_limit = *t_pTag2->toFloat();
564bool MNESourceSpaces::complete_source_space_info(
MNEHemisphere& p_Hemisphere)
573 for(
size_t h = 0; h < m_sourceSpaces.size(); ++h)
575 qInfo(
"\tWrite a source space... ");
577 auto* hemi =
dynamic_cast<MNEHemisphere*
>(m_sourceSpaces[h].get());
583 qInfo(
"\t%zu source spaces written\n", m_sourceSpaces.size());
590 if(
static_cast<qint32
>(m_sourceSpaces.size()) > idx)
591 return *m_sourceSpaces[idx];
594 qWarning(
"Warning: Index out of bound! Returning last element.");
595 return *m_sourceSpaces.back();
603 if(
static_cast<qint32
>(m_sourceSpaces.size()) > idx)
604 return *m_sourceSpaces[idx];
607 qWarning(
"Warning: Index out of bound! Returning last element.");
608 return *m_sourceSpaces.back();
616 if(idt.compare(
"lh") == 0)
617 return *m_sourceSpaces[0];
618 else if(idt.compare(
"rh") == 0)
619 return *m_sourceSpaces[1];
622 qWarning(
"Warning: Identifier is not 'lh' or 'rh'! Returning 'lh'.");
623 return *m_sourceSpaces[0];
631 if(idt.compare(
"lh") == 0)
632 return *m_sourceSpaces[0];
633 else if(idt.compare(
"rh") == 0)
634 return *m_sourceSpaces[1];
637 qWarning(
"Warning: Identifier is not 'lh' or 'rh'! Returning 'lh'.");
638 return *m_sourceSpaces[0];
646 if(idx >= 0 && idx <
static_cast<qint32
>(m_sourceSpaces.size()))
647 return dynamic_cast<MNEHemisphere*
>(m_sourceSpaces[idx].get());
655 if(idx >= 0 && idx <
static_cast<qint32
>(m_sourceSpaces.size()))
656 return dynamic_cast<const MNEHemisphere*
>(m_sourceSpaces[idx].get());
664 return m_sourceSpaces.at(idx);
671 return m_sourceSpaces.at(idx);
Reader and in-memory representation of a FreeSurfer/MNE surface label (.label).
Per-source-space-vertex nearest-cortex-vertex mapping.
Container pairing the left and right cortical source spaces of a subject.
#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.
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