v2.0.0
Loading...
Searching...
No Matches
geometryinfo.cpp
Go to the documentation of this file.
1//=============================================================================================================
35
36//=============================================================================================================
37// INCLUDES
38//=============================================================================================================
39
40#include "geometryinfo.h"
41
42#include <fiff/fiff_info.h>
43
44//=============================================================================================================
45// STL INCLUDES
46//=============================================================================================================
47
48#include <cmath>
49#include <fstream>
50#include <set>
51
52//=============================================================================================================
53// QT INCLUDES
54//=============================================================================================================
55
56#include <QtConcurrent/QtConcurrent>
57
58//=============================================================================================================
59// USED NAMESPACES
60//=============================================================================================================
61
62using namespace DISP3DRHILIB;
63using namespace Eigen;
64using namespace FIFFLIB;
65
66//=============================================================================================================
67// DEFINE MEMBER METHODS
68//=============================================================================================================
69
70QSharedPointer<MatrixXd> GeometryInfo::scdc(const MatrixX3f &matVertices,
71 const std::vector<VectorXi> &vecNeighborVertices,
72 VectorXi &vecVertSubset,
73 double dCancelDist)
74{
75 // create matrix and check for empty subset:
76 qint32 iCols = static_cast<qint32>(vecVertSubset.size());
77 if(vecVertSubset.size() == 0) {
78 qDebug() << "[WARNING] SCDC received empty subset, calculating full distance table, make sure you have enough memory !";
79 vecVertSubset = VectorXi::LinSpaced(matVertices.rows(), 0, static_cast<int>(matVertices.rows()) - 1);
80 iCols = static_cast<qint32>(matVertices.rows());
81 }
82
83 QSharedPointer<MatrixXd> returnMat = QSharedPointer<MatrixXd>::create(matVertices.rows(), iCols);
84
85 // distribute calculation on cores
86 int iCores = QThread::idealThreadCount();
87 if (iCores <= 0) {
88 iCores = 2;
89 }
90
91 qint32 iSubArraySize = int(double(vecVertSubset.size()) / double(iCores));
92 QVector<QFuture<void> > vecThreads(iCores);
93 qint32 iBegin = 0;
94 qint32 iEnd = iSubArraySize;
95
96 for (int i = 0; i < vecThreads.size(); ++i) {
97 if(i == vecThreads.size()-1)
98 {
99 vecThreads[i] = QtConcurrent::run(std::bind(iterativeDijkstra,
100 returnMat,
101 std::cref(matVertices),
102 std::cref(vecNeighborVertices),
103 std::cref(vecVertSubset),
104 iBegin,
105 static_cast<qint32>(vecVertSubset.size()),
106 dCancelDist));
107 break;
108 }
109 else
110 {
111 vecThreads[i] = QtConcurrent::run(std::bind(iterativeDijkstra,
112 returnMat,
113 std::cref(matVertices),
114 std::cref(vecNeighborVertices),
115 std::cref(vecVertSubset),
116 iBegin,
117 iEnd,
118 dCancelDist));
119 iBegin += iSubArraySize;
120 iEnd += iSubArraySize;
121 }
122 }
123
124 for (QFuture<void>& f : vecThreads) {
125 f.waitForFinished();
126 }
127
128 return returnMat;
129}
130
131//=============================================================================================================
132
133VectorXi GeometryInfo::projectSensors(const MatrixX3f &matVertices,
134 const MatrixX3f &matSensorPositions)
135{
136 const qint32 iNumSensors = static_cast<qint32>(matSensorPositions.rows());
137
138 qint32 iCores = QThread::idealThreadCount();
139 if (iCores <= 0)
140 {
141 iCores = 2;
142 }
143
144 const qint32 iSubArraySize = int(double(iNumSensors) / double(iCores));
145
146 if(iSubArraySize <= 1)
147 {
148 return nearestNeighbor(matVertices, matSensorPositions, 0, iNumSensors);
149 }
150
151 QVector<QFuture<VectorXi> > vecThreads(iCores);
152 qint32 iBeginOffset = 0;
153 qint32 iEndOffset = iBeginOffset + iSubArraySize;
154 for(qint32 i = 0; i < vecThreads.size(); ++i)
155 {
156 if(i == vecThreads.size()-1)
157 {
158 vecThreads[i] = QtConcurrent::run(nearestNeighbor,
159 matVertices,
160 matSensorPositions,
161 iBeginOffset,
162 iNumSensors);
163 break;
164 }
165 else
166 {
167 vecThreads[i] = QtConcurrent::run(nearestNeighbor,
168 matVertices,
169 matSensorPositions,
170 iBeginOffset,
171 iEndOffset);
172 iBeginOffset = iEndOffset;
173 iEndOffset += iSubArraySize;
174 }
175 }
176
177 for (QFuture<VectorXi>& f : vecThreads) {
178 f.waitForFinished();
179 }
180
181 // concatenate partial results
182 VectorXi vecOutputArray(iNumSensors);
183 qint32 iOffset = 0;
184 for(qint32 i = 0; i < vecThreads.size(); ++i)
185 {
186 const VectorXi& partial = vecThreads[i].result();
187 vecOutputArray.segment(iOffset, partial.size()) = partial;
188 iOffset += static_cast<qint32>(partial.size());
189 }
190
191 return vecOutputArray;
192}
193
194//=============================================================================================================
195
196VectorXi GeometryInfo::nearestNeighbor(const MatrixX3f &matVertices,
197 const MatrixX3f &matSensorPositions,
198 qint32 iBegin,
199 qint32 iEnd)
200{
201 VectorXi vecMappedSensors(iEnd - iBegin);
202
203 for(qint32 s = iBegin; s < iEnd; ++s)
204 {
205 qint32 iChampionId = 0;
206 double iChampDist = std::numeric_limits<double>::max();
207 for(qint32 i = 0; i < matVertices.rows(); ++i)
208 {
209 double dDist = sqrt(squared(matVertices(i, 0) - matSensorPositions(s, 0))
210 + squared(matVertices(i, 1) - matSensorPositions(s, 1))
211 + squared(matVertices(i, 2) - matSensorPositions(s, 2)));
212 if(dDist < iChampDist)
213 {
214 iChampionId = i;
215 iChampDist = dDist;
216 }
217 }
218 vecMappedSensors[s - iBegin] = iChampionId;
219 }
220
221 return vecMappedSensors;
222}
223
224//=============================================================================================================
225
226void GeometryInfo::iterativeDijkstra(QSharedPointer<MatrixXd> matOutputDistMatrix,
227 const MatrixX3f &matVertices,
228 const std::vector<VectorXi> &vecNeighborVertices,
229 const VectorXi &vecVertSubset,
230 qint32 iBegin,
231 qint32 iEnd,
232 double dCancelDistance) {
233 const std::vector<VectorXi> &vecAdjacency = vecNeighborVertices;
234 qint32 n = static_cast<qint32>(vecAdjacency.size());
235 QVector<double> vecMinDists(n);
236 std::set< std::pair< double, qint32> > vertexQ;
237 const double INF = FLOAT_INFINITY;
238
239 for (qint32 i = iBegin; i < iEnd; ++i) {
240 if ((i - iBegin) > 0 && (i - iBegin) % 100 == 0) {
241 qDebug() << "GeometryInfo::iterativeDijkstra progress:" << (i - iBegin) << "/" << (iEnd - iBegin) << " (Thread range:" << iBegin << "-" << iEnd << ")";
242 }
243
244 qint32 iRoot = vecVertSubset[i];
245 vertexQ.clear();
246 vecMinDists.fill(INF);
247 vecMinDists[iRoot] = 0.0;
248 vertexQ.insert(std::make_pair(vecMinDists[iRoot], iRoot));
249
250 while (vertexQ.empty() == false) {
251 const double dDist = vertexQ.begin()->first;
252 const qint32 u = vertexQ.begin()->second;
253 vertexQ.erase(vertexQ.begin());
254
255 if (dDist <= dCancelDistance) {
256 const VectorXi& vecNeighbours = vecAdjacency[u];
257
258 for (Eigen::Index ne = 0; ne < vecNeighbours.size(); ++ne) {
259 qint32 v = vecNeighbours[ne];
260
261 const double dDistX = matVertices(u, 0) - matVertices(v, 0);
262 const double dDistY = matVertices(u, 1) - matVertices(v, 1);
263 const double dDistZ = matVertices(u, 2) - matVertices(v, 2);
264 const double dDistWithU = dDist + sqrt(dDistX * dDistX + dDistY * dDistY + dDistZ * dDistZ);
265
266 if (dDistWithU < vecMinDists[v]) {
267 vertexQ.erase(std::make_pair(vecMinDists[v], v));
268 vecMinDists[v] = dDistWithU;
269 vertexQ.insert(std::make_pair(vecMinDists[v], v));
270 }
271 }
272 }
273 }
274
275 for (qint32 m = 0; m < vecMinDists.size(); ++m) {
276 matOutputDistMatrix->coeffRef(m , i) = vecMinDists[m];
277 }
278 }
279}
280
281//=============================================================================================================
282
283VectorXi GeometryInfo::filterBadChannels(QSharedPointer<Eigen::MatrixXd> matDistanceTable,
284 const FIFFLIB::FiffInfo& fiffInfo,
285 qint32 iSensorType) {
286 std::vector<int> vecBadColumns;
287 QVector<const FiffChInfo*> vecSensors;
288 for(const FiffChInfo& s : fiffInfo.chs){
289 if(s.kind == iSensorType && (s.unit == FIFF_UNIT_T || s.unit == FIFF_UNIT_V)){
290 vecSensors.push_back(&s);
291 }
292 }
293
294 for(const QString& b : fiffInfo.bads){
295 for(int col = 0; col < vecSensors.size(); ++col){
296 if(vecSensors[col]->ch_name == b){
297 vecBadColumns.push_back(col);
298 for(int row = 0; row < matDistanceTable->rows(); ++row){
299 matDistanceTable->coeffRef(row, col) = FLOAT_INFINITY;
300 }
301 break;
302 }
303 }
304 }
305
306 return Eigen::Map<VectorXi>(vecBadColumns.data(), static_cast<Eigen::Index>(vecBadColumns.size()));
307}
FiffInfo class declaration.
#define FIFF_UNIT_V
#define FIFF_UNIT_T
GeometryInfo class declaration.
#define FLOAT_INFINITY
FIFF file I/O and data structures (raw, epochs, evoked, covariance, forward).
3-D brain visualisation using the Qt RHI rendering backend.
static Eigen::VectorXi nearestNeighbor(const Eigen::MatrixX3f &matVertices, const Eigen::MatrixX3f &matSensorPositions, qint32 iBegin, qint32 iEnd)
static Eigen::VectorXi filterBadChannels(QSharedPointer< Eigen::MatrixXd > matDistanceTable, const FIFFLIB::FiffInfo &fiffInfo, qint32 iSensorType)
filterBadChannels Filters bad channels from distance table.
static void iterativeDijkstra(QSharedPointer< Eigen::MatrixXd > matOutputDistMatrix, const Eigen::MatrixX3f &matVertices, const std::vector< Eigen::VectorXi > &vecNeighborVertices, const Eigen::VectorXi &vecVertSubset, qint32 iBegin, qint32 iEnd, double dCancelDistance)
static double squared(double dBase)
static Eigen::VectorXi projectSensors(const Eigen::MatrixX3f &matVertices, const Eigen::MatrixX3f &matSensorPositions)
projectSensors Calculates the nearest neighbor vertex to each sensor.
static QSharedPointer< Eigen::MatrixXd > scdc(const Eigen::MatrixX3f &matVertices, const std::vector< Eigen::VectorXi > &vecNeighborVertices, Eigen::VectorXi &vecVertSubset, double dCancelDist=FLOAT_INFINITY)
scdc Calculates surface constrained distances on a mesh.
Channel info descriptor.
FIFF measurement file information.
Definition fiff_info.h:85
QList< FiffChInfo > chs