109 const Eigen::MatrixX3f& vertices,
110 const Eigen::MatrixX3f& normals,
111 const Eigen::MatrixX3i& triangles)
113 QMutexLocker locker(&m_mutex);
114 m_megSurfaceKey = surfaceKey;
115 m_megVertices = vertices;
116 m_megNormals = normals;
117 m_megTriangles = triangles;
118 m_hasMegSurface = (vertices.rows() > 0);
147 bool applySensorTrans;
149 QString megSurfaceKey, eegSurfaceKey;
150 Eigen::MatrixX3f megVerts, megNorms, eegVerts;
151 Eigen::MatrixX3i megTris;
152 bool hasMegSurface, hasEegSurface, hasEvoked;
156 QMutexLocker locker(&m_mutex);
158 hasEvoked = m_hasEvoked;
159 headToMriTrans = m_headToMriTrans;
160 applySensorTrans = m_applySensorTrans;
161 megOnHead = m_megOnHead;
162 megSurfaceKey = m_megSurfaceKey;
163 eegSurfaceKey = m_eegSurfaceKey;
164 megVerts = m_megVertices;
165 megNorms = m_megNormals;
166 megTris = m_megTriangles;
167 hasMegSurface = m_hasMegSurface;
168 eegVerts = m_eegVertices;
169 hasEegSurface = m_hasEegSurface;
174 qDebug() <<
"RtSensorInterpolationMatWorker: No evoked data set, skipping.";
178 qDebug() <<
"RtSensorInterpolationMatWorker: Computing mapping matrices...";
181 bool hasDevHead =
false;
182 QMatrix4x4 devHeadQt;
191 QMatrix4x4 headToMri;
192 if (applySensorTrans && !headToMriTrans.
isEmpty()) {
193 headToMri = toQMatrix4x4(headToMriTrans.
trans);
197 QList<FiffChInfo> megChs, eegChs;
198 QVector<int> megPick, eegPick;
200 for (
int k = 0; k < evoked.
info.
chs.size(); ++k) {
201 const auto& ch = evoked.
info.
chs[k];
202 if (bads.contains(ch.ch_name) || evoked.
info.
bads.contains(ch.ch_name))
205 QVector3D pos(ch.chpos.r0(0), ch.chpos.r0(1), ch.chpos.r0(2));
209 pos = devHeadQt.map(pos);
210 if (applySensorTrans && !headToMriTrans.
isEmpty())
211 pos = headToMri.map(pos);
215 if (applySensorTrans && !headToMriTrans.
isEmpty())
216 pos = headToMri.map(pos);
223 constexpr float kIntrad = 0.06f;
224 constexpr float kMegMiss = 1e-4f;
225 constexpr float kEegMiss = 1e-3f;
239 if (hasMegSurface && !megChs.isEmpty()) {
240 Eigen::MatrixX3f norms = megNorms;
243 if (norms.rows() != megVerts.rows()) {
244 if (megTris.rows() > 0) {
249 if (megVerts.rows() > 0 && norms.rows() == megVerts.rows()) {
250 const QString coilPath = QCoreApplication::applicationDirPath() +
"/../resources/general/coilDefinitions/coil_def.dat";
256 if (megOnHead && !headMri.
isEmpty()) {
262 }
else if (!devHead.
isEmpty()) {
263 devToTarget = devHead;
266 Eigen::Vector3f origin = fittedOrigin;
267 if (megOnHead && !headMri.
isEmpty()) {
268 origin = applyTransform(origin, headMri);
271 auto coils = templates->create_meg_coils(
274 if (coils && coils->ncoil() > 0) {
276 *coils, megVerts, norms, origin, kIntrad, kMegMiss);
278 if (mat && mat->rows() > 0) {
279 qDebug() <<
"RtSensorInterpolationMatWorker: MEG mapping computed:"
280 << mat->rows() <<
"x" << mat->cols();
282 std::shared_ptr<Eigen::MatrixXf>(std::move(mat)), megPick);
290 if (hasEegSurface && !eegChs.isEmpty()) {
291 if (eegVerts.rows() > 0) {
292 Eigen::Vector3f origin = fittedOrigin;
294 origin = applyTransform(origin, headMri);
298 eegChs, eegChs.size(), headMri);
300 if (eegCoils && eegCoils->ncoil() > 0) {
302 *eegCoils, eegVerts, origin, kIntrad, kEegMiss);
304 if (mat && mat->rows() > 0) {
305 qDebug() <<
"RtSensorInterpolationMatWorker: EEG mapping computed:"
306 << mat->rows() <<
"x" << mat->cols();
308 std::shared_ptr<Eigen::MatrixXf>(std::move(mat)), eegPick);
314 qDebug() <<
"RtSensorInterpolationMatWorker: Mapping computation complete.";