71 const std::vector<VectorXi> &vecNeighborVertices,
72 VectorXi &vecVertSubset,
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());
83 QSharedPointer<MatrixXd> returnMat = QSharedPointer<MatrixXd>::create(matVertices.rows(), iCols);
86 int iCores = QThread::idealThreadCount();
92 iCores = qMin(iCores, 2);
95 qint32 iSubArraySize = int(
double(vecVertSubset.size()) /
double(iCores));
96 QVector<QFuture<void> > vecThreads(iCores);
98 qint32 iEnd = iSubArraySize;
100 for (
int i = 0; i < vecThreads.size(); ++i) {
101 if(i == vecThreads.size()-1)
105 std::cref(matVertices),
106 std::cref(vecNeighborVertices),
107 std::cref(vecVertSubset),
109 static_cast<qint32
>(vecVertSubset.size()),
117 std::cref(matVertices),
118 std::cref(vecNeighborVertices),
119 std::cref(vecVertSubset),
123 iBegin += iSubArraySize;
124 iEnd += iSubArraySize;
128 for (QFuture<void>& f : vecThreads) {
138 const MatrixX3f &matVertices,
139 const std::vector<VectorXi> &vecNeighborVertices,
140 const VectorXi &vecVertSubset,
141 double (*interpolationFunction)(
double),
143 std::function<
void(
int,
int)> progressCallback)
145 const qint32 nVerts =
static_cast<qint32
>(matVertices.rows());
146 const qint32 nSources =
static_cast<qint32
>(vecVertSubset.size());
147 const qint32 nAdj =
static_cast<qint32
>(vecNeighborVertices.size());
151 QSet<qint32> sourceVertexSet;
152 QHash<qint32, qint32> vertexToSourceIdx;
153 for (qint32 s = 0; s < nSources; ++s) {
154 sourceVertexSet.insert(vecVertSubset[s]);
155 vertexToSourceIdx.insert(vecVertSubset[s], s);
164 struct VertexWeight {
171 std::vector<std::vector<VertexWeight>> perVertexWeights(nVerts);
174 QVector<double> vecMinDists(nAdj);
175 std::set<std::pair<double, qint32>> vertexQ;
178 for (qint32 s = 0; s < nSources; ++s) {
179 if (progressCallback && s > 0 && s % 100 == 0) {
180 progressCallback(s, nSources);
183 qint32 iRoot = vecVertSubset[s];
185 vecMinDists.fill(INF);
186 vecMinDists[iRoot] = 0.0;
187 vertexQ.insert(std::make_pair(0.0, iRoot));
189 while (!vertexQ.empty()) {
190 const double dDist = vertexQ.begin()->first;
191 const qint32 u = vertexQ.begin()->second;
192 vertexQ.erase(vertexQ.begin());
194 if (dDist <= dCancelDist) {
195 const VectorXi& vecNeighbours = vecNeighborVertices[u];
197 for (Eigen::Index ne = 0; ne < vecNeighbours.size(); ++ne) {
198 qint32 v = vecNeighbours[ne];
200 const double dDistX = matVertices(u, 0) - matVertices(v, 0);
201 const double dDistY = matVertices(u, 1) - matVertices(v, 1);
202 const double dDistZ = matVertices(u, 2) - matVertices(v, 2);
203 const double dDistWithU = dDist + sqrt(dDistX * dDistX + dDistY * dDistY + dDistZ * dDistZ);
205 if (dDistWithU < vecMinDists[v]) {
206 vertexQ.erase(std::make_pair(vecMinDists[v], v));
207 vecMinDists[v] = dDistWithU;
208 vertexQ.insert(std::make_pair(vecMinDists[v], v));
215 for (qint32 m = 0; m < nAdj; ++m) {
216 if (vecMinDists[m] < dCancelDist) {
217 perVertexWeights[m].push_back({s,
static_cast<float>(vecMinDists[m])});
224 QVector<Eigen::Triplet<float>> vecTriplets;
226 vecTriplets.reserve(nVerts * 10);
228 for (qint32 r = 0; r < nVerts; ++r) {
229 if (sourceVertexSet.contains(r)) {
231 vecTriplets.push_back(Eigen::Triplet<float>(r, vertexToSourceIdx[r], 1.0f));
233 const auto& weights = perVertexWeights[r];
234 if (weights.empty())
continue;
237 float dWeightsSum = 0.0f;
238 QVector<QPair<qint32, float>> vecBelowThresh;
239 vecBelowThresh.reserve(
static_cast<int>(weights.size()));
241 for (
const auto& w : weights) {
242 const float dValueWeight = std::fabs(1.0f /
static_cast<float>(interpolationFunction(w.dist)));
243 dWeightsSum += dValueWeight;
244 vecBelowThresh.push_back(qMakePair(w.sourceIdx, dValueWeight));
247 for (
const auto& qp : vecBelowThresh) {
248 vecTriplets.push_back(Eigen::Triplet<float>(r, qp.first, qp.second / dWeightsSum));
253 auto interpMat = QSharedPointer<SparseMatrix<float>>::create(nVerts, nSources);
254 interpMat->setFromTriplets(vecTriplets.begin(), vecTriplets.end());
262 const MatrixX3f &matSensorPositions)
264 const qint32 iNumSensors =
static_cast<qint32
>(matSensorPositions.rows());
266 qint32 iCores = QThread::idealThreadCount();
272 iCores = qMin(iCores, (qint32)2);
275 const qint32 iSubArraySize = int(
double(iNumSensors) /
double(iCores));
277 if(iSubArraySize <= 1)
279 return nearestNeighbor(matVertices, matSensorPositions, 0, iNumSensors);
282 QVector<QFuture<VectorXi> > vecThreads(iCores);
283 qint32 iBeginOffset = 0;
284 qint32 iEndOffset = iBeginOffset + iSubArraySize;
285 for(qint32 i = 0; i < vecThreads.size(); ++i)
287 if(i == vecThreads.size()-1)
303 iBeginOffset = iEndOffset;
304 iEndOffset += iSubArraySize;
308 for (QFuture<VectorXi>& f : vecThreads) {
313 VectorXi vecOutputArray(iNumSensors);
315 for(qint32 i = 0; i < vecThreads.size(); ++i)
317 const VectorXi& partial = vecThreads[i].result();
318 vecOutputArray.segment(iOffset, partial.size()) = partial;
319 iOffset +=
static_cast<qint32
>(partial.size());
322 return vecOutputArray;
328 const MatrixX3f &matSensorPositions,
332 VectorXi vecMappedSensors(iEnd - iBegin);
334 for(qint32 s = iBegin; s < iEnd; ++s)
336 qint32 iChampionId = 0;
337 double iChampDist = std::numeric_limits<double>::max();
338 for(qint32 i = 0; i < matVertices.rows(); ++i)
340 double dDist = sqrt(
squared(matVertices(i, 0) - matSensorPositions(s, 0))
341 +
squared(matVertices(i, 1) - matSensorPositions(s, 1))
342 +
squared(matVertices(i, 2) - matSensorPositions(s, 2)));
343 if(dDist < iChampDist)
349 vecMappedSensors[s - iBegin] = iChampionId;
352 return vecMappedSensors;
358 const MatrixX3f &matVertices,
359 const std::vector<VectorXi> &vecNeighborVertices,
360 const VectorXi &vecVertSubset,
363 double dCancelDistance) {
364 const std::vector<VectorXi> &vecAdjacency = vecNeighborVertices;
365 qint32 n =
static_cast<qint32
>(vecAdjacency.size());
366 QVector<double> vecMinDists(n);
367 std::set< std::pair< double, qint32> > vertexQ;
370 for (qint32 i = iBegin; i < iEnd; ++i) {
371 if ((i - iBegin) > 0 && (i - iBegin) % 100 == 0) {
372 qDebug() <<
"GeometryInfo::iterativeDijkstra progress:" << (i - iBegin) <<
"/" << (iEnd - iBegin) <<
" (Thread range:" << iBegin <<
"-" << iEnd <<
")";
375 qint32 iRoot = vecVertSubset[i];
377 vecMinDists.fill(INF);
378 vecMinDists[iRoot] = 0.0;
379 vertexQ.insert(std::make_pair(vecMinDists[iRoot], iRoot));
381 while (vertexQ.empty() ==
false) {
382 const double dDist = vertexQ.begin()->first;
383 const qint32 u = vertexQ.begin()->second;
384 vertexQ.erase(vertexQ.begin());
386 if (dDist <= dCancelDistance) {
387 const VectorXi& vecNeighbours = vecAdjacency[u];
389 for (Eigen::Index ne = 0; ne < vecNeighbours.size(); ++ne) {
390 qint32 v = vecNeighbours[ne];
392 const double dDistX = matVertices(u, 0) - matVertices(v, 0);
393 const double dDistY = matVertices(u, 1) - matVertices(v, 1);
394 const double dDistZ = matVertices(u, 2) - matVertices(v, 2);
395 const double dDistWithU = dDist + sqrt(dDistX * dDistX + dDistY * dDistY + dDistZ * dDistZ);
397 if (dDistWithU < vecMinDists[v]) {
398 vertexQ.erase(std::make_pair(vecMinDists[v], v));
399 vecMinDists[v] = dDistWithU;
400 vertexQ.insert(std::make_pair(vecMinDists[v], v));
406 for (qint32 m = 0; m < vecMinDists.size(); ++m) {
407 matOutputDistMatrix->coeffRef(m , i) = vecMinDists[m];
416 qint32 iSensorType) {
417 std::vector<int> vecBadColumns;
418 QVector<const FiffChInfo*> vecSensors;
421 vecSensors.push_back(&s);
425 for(
const QString& b : fiffInfo.
bads){
426 for(
int col = 0; col < vecSensors.size(); ++col){
427 if(vecSensors[col]->ch_name == b){
428 vecBadColumns.push_back(col);
429 for(
int row = 0; row < matDistanceTable->rows(); ++row){
437 return Eigen::Map<VectorXi>(vecBadColumns.data(),
static_cast<Eigen::Index
>(vecBadColumns.size()));
static QSharedPointer< Eigen::SparseMatrix< float > > scdcInterpolationMat(const Eigen::MatrixX3f &matVertices, const std::vector< Eigen::VectorXi > &vecNeighborVertices, const Eigen::VectorXi &vecVertSubset, double(*interpolationFunction)(double), double dCancelDist, std::function< void(int, int)> progressCallback=nullptr)
scdcInterpolationMat Computes geodesic distances (SCDC) and builds the sparse interpolation matrix in...