v2.0.0
Loading...
Searching...
No Matches
rtsourceinterpolationmatworker.cpp
Go to the documentation of this file.
1//=============================================================================================================
34
35//=============================================================================================================
36// INCLUDES
37//=============================================================================================================
38
42
43#include <fs/label.h>
44
45#include <QDebug>
46
47using namespace DISP3DRHILIB;
48
49//=============================================================================================================
50// MEMBER METHODS
51//=============================================================================================================
52
54 : QObject(parent)
55{
56}
57
58//=============================================================================================================
59
60void RtSourceInterpolationMatWorker::setInterpolationFunction(const QString &sInterpolationFunction)
61{
62 QMutexLocker locker(&m_mutex);
63 m_sInterpolationFunction = sInterpolationFunction;
64}
65
66//=============================================================================================================
67
69{
70 QMutexLocker locker(&m_mutex);
71 m_dCancelDist = dCancelDist;
72}
73
74//=============================================================================================================
75
77 const Eigen::MatrixX3f &matVertices,
78 const std::vector<Eigen::VectorXi> &vecNeighborVertices,
79 const Eigen::VectorXi &vecSourceVertices)
80{
81 QMutexLocker locker(&m_mutex);
82 m_matVerticesLh = matVertices;
83 m_vecNeighborsLh = vecNeighborVertices;
84 m_vecSourceVerticesLh = vecSourceVertices;
85 m_hasLh = (!matVertices.isZero(0) && matVertices.rows() > 0 && vecSourceVertices.size() > 0);
86}
87
88//=============================================================================================================
89
91 const Eigen::MatrixX3f &matVertices,
92 const std::vector<Eigen::VectorXi> &vecNeighborVertices,
93 const Eigen::VectorXi &vecSourceVertices)
94{
95 QMutexLocker locker(&m_mutex);
96 m_matVerticesRh = matVertices;
97 m_vecNeighborsRh = vecNeighborVertices;
98 m_vecSourceVerticesRh = vecSourceVertices;
99 m_hasRh = (!matVertices.isZero(0) && matVertices.rows() > 0 && vecSourceVertices.size() > 0);
100}
101
102//=============================================================================================================
103
105{
106 QMutexLocker locker(&m_mutex);
107 m_iVisualizationType = iVisType;
108}
109
110//=============================================================================================================
111
112void RtSourceInterpolationMatWorker::setAnnotationInfoLeft(const Eigen::VectorXi &vecLabelIds,
113 const QList<FSLIB::Label> &lLabels,
114 const Eigen::VectorXi &vecVertNo)
115{
116 if (vecLabelIds.rows() == 0 || lLabels.isEmpty()) {
117 qDebug() << "RtSourceInterpolationMatWorker::setAnnotationInfoLeft - Annotation data is empty.";
118 return;
119 }
120
121 QMutexLocker locker(&m_mutex);
122 m_lLabelsLh = lLabels;
123 m_mapLabelIdSourcesLh.clear();
124 m_vertNosLh.clear();
125
126 for (qint32 i = 0; i < vecVertNo.rows(); ++i) {
127 m_mapLabelIdSourcesLh.insert(vecVertNo(i), vecLabelIds(vecVertNo(i)));
128 m_vertNosLh.append(vecVertNo(i));
129 }
130
131 m_bAnnotationLhInit = true;
132}
133
134//=============================================================================================================
135
136void RtSourceInterpolationMatWorker::setAnnotationInfoRight(const Eigen::VectorXi &vecLabelIds,
137 const QList<FSLIB::Label> &lLabels,
138 const Eigen::VectorXi &vecVertNo)
139{
140 if (vecLabelIds.rows() == 0 || lLabels.isEmpty()) {
141 qDebug() << "RtSourceInterpolationMatWorker::setAnnotationInfoRight - Annotation data is empty.";
142 return;
143 }
144
145 QMutexLocker locker(&m_mutex);
146 m_lLabelsRh = lLabels;
147 m_mapLabelIdSourcesRh.clear();
148 m_vertNosRh.clear();
149
150 for (qint32 i = 0; i < vecVertNo.rows(); ++i) {
151 m_mapLabelIdSourcesRh.insert(vecVertNo(i), vecLabelIds(vecVertNo(i)));
152 m_vertNosRh.append(vecVertNo(i));
153 }
154
155 m_bAnnotationRhInit = true;
156}
157
158//=============================================================================================================
159
160double (*RtSourceInterpolationMatWorker::resolveInterpolationFunction(const QString &name))(double)
161{
162 if (name == QStringLiteral("linear")) return Interpolation::linear;
163 if (name == QStringLiteral("gaussian")) return Interpolation::gaussian;
164 if (name == QStringLiteral("square")) return Interpolation::square;
165 if (name == QStringLiteral("cubic")) return Interpolation::cubic;
166
167 // Default to cubic
169}
170
171//=============================================================================================================
172
173QSharedPointer<Eigen::SparseMatrix<float>> RtSourceInterpolationMatWorker::computeHemi(
174 const Eigen::MatrixX3f &matVertices,
175 const std::vector<Eigen::VectorXi> &vecNeighborVertices,
176 Eigen::VectorXi vecSourceVertices,
177 double dCancelDist,
178 double (*interpFunc)(double))
179{
180 if (matVertices.rows() == 0 || vecSourceVertices.size() == 0) {
181 return QSharedPointer<Eigen::SparseMatrix<float>>();
182 }
183
184 // Compute surface-constrained distances (SCDC / geodesic)
185 QSharedPointer<Eigen::MatrixXd> distTable = GeometryInfo::scdc(
186 matVertices,
187 vecNeighborVertices,
188 vecSourceVertices,
189 dCancelDist
190 );
191
192 if (!distTable || distTable->rows() == 0) {
193 qWarning() << "RtSourceInterpolationMatWorker: SCDC computation failed.";
194 return QSharedPointer<Eigen::SparseMatrix<float>>();
195 }
196
197 // Create interpolation matrix
199 vecSourceVertices,
200 distTable,
201 interpFunc,
202 dCancelDist
203 );
204
205 return interpMat;
206}
207
208//=============================================================================================================
209
211{
212 // ── Snapshot parameters under lock ─────────────────────────────────
213 Eigen::MatrixX3f vertsLh, vertsRh;
214 std::vector<Eigen::VectorXi> neighborsLh, neighborsRh;
215 Eigen::VectorXi srcVertsLh, srcVertsRh;
216 bool hasLh, hasRh;
217 double cancelDist;
218 QString interpFuncName;
219 int visType;
220
221 // Annotation data snapshots
222 QList<FSLIB::Label> labelsLh, labelsRh;
223 QMap<qint32, qint32> mapLabelIdSrcLh, mapLabelIdSrcRh;
224 QList<int> vertNosLh, vertNosRh;
225 bool annotLhInit, annotRhInit;
226
227 {
228 QMutexLocker locker(&m_mutex);
229 vertsLh = m_matVerticesLh;
230 vertsRh = m_matVerticesRh;
231 neighborsLh = m_vecNeighborsLh;
232 neighborsRh = m_vecNeighborsRh;
233 srcVertsLh = m_vecSourceVerticesLh;
234 srcVertsRh = m_vecSourceVerticesRh;
235 hasLh = m_hasLh;
236 hasRh = m_hasRh;
237 cancelDist = m_dCancelDist;
238 interpFuncName = m_sInterpolationFunction;
239 visType = m_iVisualizationType;
240
241 labelsLh = m_lLabelsLh;
242 labelsRh = m_lLabelsRh;
243 mapLabelIdSrcLh = m_mapLabelIdSourcesLh;
244 mapLabelIdSrcRh = m_mapLabelIdSourcesRh;
245 vertNosLh = m_vertNosLh;
246 vertNosRh = m_vertNosRh;
247 annotLhInit = m_bAnnotationLhInit;
248 annotRhInit = m_bAnnotationRhInit;
249 }
250
251 // ── Annotation-based mode ──────────────────────────────────────────
252 if (visType == AnnotationBased) {
253 qDebug() << "RtSourceInterpolationMatWorker: Computing annotation matrices...";
254
255 if (annotLhInit) {
256 auto mat = computeAnnotationOperator(labelsLh, mapLabelIdSrcLh, vertNosLh);
257 if (mat && mat->rows() > 0) {
258 qDebug() << "RtSourceInterpolationMatWorker: LH annotation matrix:"
259 << mat->rows() << "x" << mat->cols();
261 }
262 }
263
264 if (annotRhInit) {
265 auto mat = computeAnnotationOperator(labelsRh, mapLabelIdSrcRh, vertNosRh);
266 if (mat && mat->rows() > 0) {
267 qDebug() << "RtSourceInterpolationMatWorker: RH annotation matrix:"
268 << mat->rows() << "x" << mat->cols();
270 }
271 }
272
273 qDebug() << "RtSourceInterpolationMatWorker: Annotation matrix computation complete.";
274 return;
275 }
276
277 // ── Interpolation-based mode (default) ─────────────────────────────
278 if (!hasLh && !hasRh) {
279 qDebug() << "RtSourceInterpolationMatWorker: No hemisphere data set, skipping.";
280 return;
281 }
282
283 auto interpFunc = resolveInterpolationFunction(interpFuncName);
284
285 qDebug() << "RtSourceInterpolationMatWorker: Computing interpolation matrices"
286 << "(cancelDist=" << cancelDist << ", func=" << interpFuncName << ")...";
287
288 // ── LH ─────────────────────────────────────────────────────────────
289 if (hasLh) {
290 qDebug() << "RtSourceInterpolationMatWorker: Computing LH matrix ("
291 << vertsLh.rows() << "verts," << srcVertsLh.size() << "sources)...";
292
293 auto mat = computeHemi(vertsLh, neighborsLh, srcVertsLh, cancelDist, interpFunc);
294
295 if (mat && mat->rows() > 0) {
296 qDebug() << "RtSourceInterpolationMatWorker: LH matrix computed:"
297 << mat->rows() << "x" << mat->cols();
299 } else {
300 qWarning() << "RtSourceInterpolationMatWorker: LH interpolation matrix computation failed.";
301 }
302 }
303
304 // ── RH ─────────────────────────────────────────────────────────────
305 if (hasRh) {
306 qDebug() << "RtSourceInterpolationMatWorker: Computing RH matrix ("
307 << vertsRh.rows() << "verts," << srcVertsRh.size() << "sources)...";
308
309 auto mat = computeHemi(vertsRh, neighborsRh, srcVertsRh, cancelDist, interpFunc);
310
311 if (mat && mat->rows() > 0) {
312 qDebug() << "RtSourceInterpolationMatWorker: RH matrix computed:"
313 << mat->rows() << "x" << mat->cols();
315 } else {
316 qWarning() << "RtSourceInterpolationMatWorker: RH interpolation matrix computation failed.";
317 }
318 }
319
320 qDebug() << "RtSourceInterpolationMatWorker: Interpolation matrix computation complete.";
321}
322
323//=============================================================================================================
324
325QSharedPointer<Eigen::SparseMatrix<float>> RtSourceInterpolationMatWorker::computeAnnotationOperator(
326 const QList<FSLIB::Label> &lLabels,
327 const QMap<qint32, qint32> &mapLabelIdSrc,
328 const QList<int> &vertNos)
329{
330 if (lLabels.isEmpty() || vertNos.isEmpty()) {
331 return QSharedPointer<Eigen::SparseMatrix<float>>();
332 }
333
334 // Count total vertices across all labels
335 int iNumVert = 0;
336 for (int i = 0; i < lLabels.size(); ++i) {
337 iNumVert += lLabels.at(i).vertices.rows();
338 }
339
340 auto mat = QSharedPointer<Eigen::SparseMatrix<float>>(
341 new Eigen::SparseMatrix<float>(iNumVert, vertNos.size()));
342
343 // For each label: assign uniform weight to all its vertices from sources in that label
344 for (int i = 0; i < lLabels.size(); ++i) {
345 const FSLIB::Label &label = lLabels.at(i);
346 QList<qint32> listSourcesVertNoLabel = mapLabelIdSrc.keys(label.label_id);
347
348 for (int j = 0; j < label.vertices.rows(); ++j) {
349 for (int k = 0; k < listSourcesVertNoLabel.size(); ++k) {
350 int colIdx = vertNos.indexOf(listSourcesVertNoLabel.at(k));
351 if (colIdx >= 0 && label.vertices(j) < iNumVert) {
352 mat->coeffRef(label.vertices(j), colIdx) = 1.0f / listSourcesVertNoLabel.size();
353 }
354 }
355 }
356 }
357
358 return mat;
359}
RtSourceInterpolationMatWorker class declaration.
GeometryInfo class declaration.
Interpolation class declaration.
Label class declaration.
3-D brain visualisation using the Qt RHI rendering backend.
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.
static double gaussian(const double dIn)
gaussian Gaussian interpolation function (sigma=1).
static double linear(const double dIn)
linear Identity interpolation function.
static double cubic(const double dIn)
cubic Cubic hyperbola interpolation function.
static QSharedPointer< Eigen::SparseMatrix< float > > createInterpolationMat(const Eigen::VectorXi &vecProjectedSensors, const QSharedPointer< Eigen::MatrixXd > matDistanceTable, double(*interpolationFunction)(double), const double dCancelDist=FLOAT_INFINITY, const Eigen::VectorXi &vecExcludeIndex=Eigen::VectorXi())
createInterpolationMat Calculates the weight matrix for interpolation.
static double square(const double dIn)
square Negative parabola interpolation function with y-offset of 1.
void setInterpolationFunction(const QString &sInterpolationFunction)
void setAnnotationInfoLeft(const Eigen::VectorXi &vecLabelIds, const QList< FSLIB::Label > &lLabels, const Eigen::VectorXi &vecVertNo)
void newInterpolationMatrixRightAvailable(QSharedPointer< Eigen::SparseMatrix< float > > interpMat)
void setInterpolationInfoLeft(const Eigen::MatrixX3f &matVertices, const std::vector< Eigen::VectorXi > &vecNeighborVertices, const Eigen::VectorXi &vecSourceVertices)
void newInterpolationMatrixLeftAvailable(QSharedPointer< Eigen::SparseMatrix< float > > interpMat)
void setAnnotationInfoRight(const Eigen::VectorXi &vecLabelIds, const QList< FSLIB::Label > &lLabels, const Eigen::VectorXi &vecVertNo)
void setInterpolationInfoRight(const Eigen::MatrixX3f &matVertices, const std::vector< Eigen::VectorXi > &vecNeighborVertices, const Eigen::VectorXi &vecSourceVertices)
qint32 label_id
Definition label.h:172
Eigen::VectorXi vertices
Definition label.h:166