v2.0.0
Loading...
Searching...
No Matches
brainview.h
Go to the documentation of this file.
1//=============================================================================================================
25
26#ifndef BRAINVIEW_H
27#define BRAINVIEW_H
28
29//=============================================================================================================
30// INCLUDES
31//=============================================================================================================
32
33#include "../disp3D_global.h"
34
35#include "../core/rendertypes.h"
36#include "multiviewlayout.h"
37#include "core/viewstate.h"
42
44#include <fiff/fiff_dig_point.h>
45#include <QRhiWidget>
46#include <QMap>
47#include <QElapsedTimer>
48#include <memory>
49#include <QQuaternion>
50#include <Eigen/Core>
51#include <QRect>
52#include <QImage>
53
54//=============================================================================================================
55// FORWARD DECLARATIONS
56//=============================================================================================================
57
58class QLabel;
59class QStandardItem;
60class QFrame;
61class QTimer;
62namespace CONNECTIVITYLIB
63{
64class Network;
65}
66
67namespace DISP3DLIB
68{
69
70class BrainTreeModel;
71class BrainRenderer;
72class BrainSurface;
73class DipoleObject;
74class NetworkObject;
75class PolylineObject;
76class VideoOverlay;
77class SliceObject;
78
79//=============================================================================================================
90{
91 QVector3D position;
92 QColor color;
93 float radius = 0.003f;
94 bool transparent = false;
95};
96
97//=============================================================================================================
106class DISP3DSHARED_EXPORT BrainView : public QRhiWidget
107{
108 Q_OBJECT
109
110public:
119
120public:
121 //=========================================================================================================
127 explicit BrainView(QWidget* parent = nullptr);
128
129 //=========================================================================================================
133 ~BrainView();
134
135 //=========================================================================================================
142 void setModel(BrainTreeModel* model);
143
144 //=========================================================================================================
151 void setInitialCameraRotation(const QQuaternion& rotation);
152
153public slots:
154 void onRowsInserted(const QModelIndex& parent, int first, int last);
155 void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles);
156 //=========================================================================================================
162 void setActiveSurface(const QString& type);
163
164 //=========================================================================================================
170 void setShaderMode(const QString& mode);
171
172 //=========================================================================================================
178 void setBemShaderMode(const QString& mode);
179
183 void syncBemShadersToBrainShaders();
184
185 //=========================================================================================================
191 void setVisualizationMode(const QString& mode);
192
193 //=========================================================================================================
200 void setHemiVisible(int hemiIdx, bool visible);
201
202 //=========================================================================================================
209 void setBemVisible(const QString& name, bool visible);
210
211 //=========================================================================================================
217 void setBemHighContrast(bool enabled);
218
219 //=========================================================================================================
226 void setSensorVisible(const QString& type, bool visible);
227
228 //=========================================================================================================
234 void setSensorTransEnabled(bool enabled);
235
236 //=========================================================================================================
242 void setMegHelmetOverride(const QString& path);
243
244 //=========================================================================================================
254 bool loadMegHelmetSurface(const QString& helmetFilePath);
255
256 //=========================================================================================================
262 void setDipoleVisible(bool visible);
263
264 //=========================================================================================================
272 bool loadNetwork(const CONNECTIVITYLIB::Network& network, const QString& name = "Network");
273
274 //=========================================================================================================
280 void setNetworkVisible(bool visible);
281
282 //=========================================================================================================
288 void setNetworkThreshold(double threshold);
289
290 //=========================================================================================================
296 void setNetworkColormap(const QString& name);
297
298 //=========================================================================================================
304 void setLightingEnabled(bool enabled);
305
306 //=========================================================================================================
316 void setAutomatedRotation(bool enabled);
317
318 //=========================================================================================================
324 bool automatedRotation() const;
325
326 //=========================================================================================================
339 void setHeadMovementPath(const QVector<Eigen::Vector3f>& vecPositions);
340
341 //=========================================================================================================
345 void clearHeadMovementPath();
346
347 //=========================================================================================================
353 bool saveSnapshot();
354
355 //=========================================================================================================
362 bool takeScreenshot(const QString& fileName);
363
364 //=========================================================================================================
379 bool savePng(const QString& path, int width = 1200, int height = 800,
380 const QString& surfaceType = QStringLiteral("pial"));
381
382 //=========================================================================================================
386 void showSingleView();
387
388 //=========================================================================================================
392 void showMultiView();
393
394 //=========================================================================================================
401 void setViewCount(int count);
402
406 int viewCount() const
407 {
408 return m_viewCount;
409 }
410
411 //=========================================================================================================
418 void setViewportEnabled(int index, bool enabled);
419
426 void setViewportCameraPreset(int index, int preset);
427
431 void resetSingleViewCameraState();
432
438 void resetViewportCameraState(int index);
439
447 void resetAllSubViewState();
448
455 int viewportCameraPreset(int index) const;
456
460 void resetMultiViewLayout();
461
467 void setVisualizationEditTarget(int target);
468
474 int visualizationEditTarget() const;
475
479 QString activeSurfaceForTarget(int target) const;
480
484 QString shaderModeForTarget(int target) const;
485
489 QString bemShaderModeForTarget(int target) const;
490
494 QString overlayModeForTarget(int target) const;
495
503 bool objectVisibleForTarget(const QString& object, int target) const;
504
511 bool megFieldMapOnHeadForTarget(int target) const;
512
519 bool isViewportEnabled(int index) const;
520
521 //=========================================================================================================
527 void setInfoPanelVisible(bool visible);
528
529 //=========================================================================================================
536 {
537 return m_infoPanelVisible;
538 }
539
540 //=========================================================================================================
547 {
548 return m_viewMode;
549 }
550
551 //=========================================================================================================
559 bool loadSourceEstimate(const QString& lhPath, const QString& rhPath);
560
561 //=========================================================================================================
568 bool loadSensors(const QString& fifPath);
569
577 QMap<int, QVector3D> cardinalFiducialsInMri() const;
578
588 bool bemTopVertexInMri(QVector3D& pos) const;
589
590 //=========================================================================================================
597 bool loadDipoles(const QString& dipPath);
598
599 //=========================================================================================================
606 bool loadSourceSpace(const QString& fwdPath);
607
608 //=========================================================================================================
619 static QStringList probeEvokedSets(const QString& evokedPath);
620
628 bool loadSensorField(const QString& evokedPath, int aveIndex = 0);
629
630 //=========================================================================================================
636 void setSourceSpaceVisible(bool visible);
637
638 //=========================================================================================================
645 bool loadTransformation(const QString& transPath);
646
647 //=========================================================================================================
653 void setTimePoint(int index);
654
655 //=========================================================================================================
661 void castRay(const QPoint& pos);
662
663 //=========================================================================================================
669 void setSourceColormap(const QString& name);
670
671 //=========================================================================================================
679 void setSourceThresholds(float min, float mid, float max);
680
681 //=========================================================================================================
687 void setSensorFieldTimePoint(int index);
688
689 //=========================================================================================================
696 void setSensorFieldVisible(const QString& type, bool visible);
697
698 //=========================================================================================================
705 void setSensorFieldContourVisible(const QString& type, bool visible);
706
707 //=========================================================================================================
713 void setMegFieldMapOnHead(bool useHead);
714
715 //=========================================================================================================
721 void setSensorFieldColormap(const QString& name);
722
723 //=========================================================================================================
729 float stcStep() const;
730
731 //=========================================================================================================
737 float stcTmin() const;
738
739 //=========================================================================================================
745 int stcNumTimePoints() const;
746
747 //=========================================================================================================
754 int closestSensorFieldIndex(float timeSec) const;
755
756 //=========================================================================================================
763 int closestStcIndex(float timeSec) const;
764
765 //=========================================================================================================
771 void startRealtimeStreaming();
772
773 //=========================================================================================================
777 void stopRealtimeStreaming();
778
779 //=========================================================================================================
785 bool isRealtimeStreaming() const;
786
787 //=========================================================================================================
794 void pushRealtimeSourceData(const Eigen::VectorXd& matData);
795
796 //=========================================================================================================
802 void setRealtimeInterval(int msec);
803
804 //=========================================================================================================
810 void setRealtimeLooping(bool enabled);
811
812 //=========================================================================================================
820 bool sensorFieldTimeRange(float& tmin, float& tmax) const;
821
822 //=========================================================================================================
823 // ── Real-time sensor data streaming ────────────────────────────────
824 //=========================================================================================================
825
836 void startRealtimeSensorStreaming(const QString& modality = QStringLiteral("MEG"));
837
838 //=========================================================================================================
842 void stopRealtimeSensorStreaming();
843
844 //=========================================================================================================
850 bool isRealtimeSensorStreaming() const;
851
852 //=========================================================================================================
860 void pushRealtimeSensorData(const Eigen::VectorXf& vecData);
861
862 //=========================================================================================================
868 void setRealtimeSensorInterval(int msec);
869
870 //=========================================================================================================
876 void setRealtimeSensorLooping(bool enabled);
877
878 //=========================================================================================================
884 void setRealtimeSensorAverages(int numAvr);
885
886 //=========================================================================================================
892 void setRealtimeSensorColormap(const QString& name);
893
894 // ── Data removal ───────────────────────────────────────────────────
895
899 void clearSurfaces();
900
904 void clearBem();
905
909 void clearSourceEstimate();
910
914 void clearDipoles();
915
919 void clearSourceSpace();
920
924 void clearSensors();
925
926 // ── Live marker overlay (lightweight, no model, no scene-bounds) ───
927
934 void setLiveMarkers(const QVector<LiveMarker>& markers);
935
937 void clearLiveMarkers();
938
947 void setLiveRay(const QVector3D& from, const QVector3D& to,
948 const QColor& color, float radius = 0.001f);
949
951 void clearLiveRay();
952
966 void setProbeVisualization(const QVector3D& tip, const QVector3D& direction,
967 float length, const QColor& color,
968 const QColor& glowColor = QColor(0, 0, 0, 0),
969 const QQuaternion& orientation = QQuaternion(0, 0, 0, 0));
970
972 void clearProbeVisualization();
973
978 void setStaticMarkers(const QVector<LiveMarker>& markers);
979
981 void clearStaticMarkers();
982
987 void setCameraFocusOverride(const QVector3D& center, float size);
988
990 void clearCameraFocusOverride();
991
995 void clearEvoked();
996
1000 void clearTransformation();
1001
1005 void clearNetwork();
1006
1011 void stopAllStreaming();
1012
1013 //=========================================================================================================
1014 // ── Video overlay ──────────────────────────────────────────────────
1015 //=========================================================================================================
1016
1021 void setVideoOverlayEnabled(bool enabled);
1022
1024 bool isVideoOverlayEnabled() const;
1025
1027 void setVideoOverlayFocusPosition(const QVector3D& position);
1028
1030 void setVideoOverlayUpHint(const QVector3D& dir);
1031
1033 void setVideoOverlaySize(float meters);
1034
1036 void setVideoOverlayOpacity(float opacity);
1037
1039 void pushVideoOverlayFrame(const QImage& frame);
1040
1042 void setVideoDepthEnabled(bool enabled);
1043
1045 void setVideoDepthScale(float scale);
1046
1048 void setVideoDepthSteps(int steps);
1049
1051 void pushVideoDepthFrame(const QImage& depthFrame);
1052
1064 bool intersectWorldRay(const QVector3D& origin, const QVector3D& direction, QVector3D& hitPoint) const;
1065
1066 //=========================================================================================================
1067 // ── MRI slice rendering ────────────────────────────────────────────
1068 //=========================================================================================================
1069
1076 void setSlice(int slotIndex, DISP3DLIB::SliceObject* slice);
1077
1084 void setSliceVisible(int slotIndex, bool visible);
1085
1091 void setMriSlicesVisible(bool visible);
1092
1093signals:
1094 //=========================================================================================================
1101 void timePointChanged(int index, float time);
1102
1103 //=========================================================================================================
1109 void sourceEstimateLoaded(int numTimePoints);
1110
1111 //=========================================================================================================
1117 void sensorFieldLoaded(int numTimePoints, int initialTimePoint = 0);
1118
1119 //=========================================================================================================
1127 void sourceThresholdsUpdated(float min, float mid, float max);
1128
1129 //=========================================================================================================
1136 void stcLoadingProgress(int percent, const QString& message);
1137
1138 //=========================================================================================================
1145 void sensorFieldTimePointChanged(int index, float time);
1146
1147 //=========================================================================================================
1153 void hoveredRegionChanged(const QString& regionName);
1154
1155 //=========================================================================================================
1162
1163 //=========================================================================================================
1172 void viewCountChanged(int count);
1173
1174 //=========================================================================================================
1182 void shaderModeChanged(const QString& modeName);
1183
1188 void surfacePointClicked(const QVector3D& worldPos);
1189
1194 void surfacePointDoubleClicked(const QVector3D& worldPos);
1195
1196private slots:
1197 //=========================================================================================================
1204 void onSourceEstimateLoaded(int numTimePoints);
1205
1206 //=========================================================================================================
1214 void onRealtimeColorsAvailable(const QVector<uint32_t>& colorsLh,
1215 const QVector<uint32_t>& colorsRh);
1216
1217 //=========================================================================================================
1219 void onSensorStreamColorsAvailable(const QString& surfaceKey,
1220 const QVector<uint32_t>& colors);
1221
1222private:
1223 // Note: ViewVisibilityProfile and SubView are defined in core/viewstate.h.
1224 // SplitterHit is defined in view/multiviewlayout.h.
1225
1227 SubView& subViewForTarget(int target);
1228 const SubView& subViewForTarget(int target) const;
1229
1230 ViewVisibilityProfile& visibilityProfileForTarget(int target);
1231 const ViewVisibilityProfile& visibilityProfileForTarget(int target) const;
1232
1233 void refreshSensorTransforms();
1234 QMatrix4x4 itemTransform(const QStandardItem* item) const;
1235 void removeSurfacesByPrefix(const QStringList& prefixes);
1236
1237protected:
1238 void initialize(QRhiCommandBuffer* cb) override;
1239 void render(QRhiCommandBuffer* cb) override;
1240
1241 void mousePressEvent(QMouseEvent* event) override;
1242 void mouseMoveEvent(QMouseEvent* event) override;
1243 void mouseReleaseEvent(QMouseEvent* event) override;
1244 void mouseDoubleClickEvent(QMouseEvent* event) override;
1245 void wheelEvent(QWheelEvent* event) override;
1246 void keyPressEvent(QKeyEvent* event) override;
1247 void resizeEvent(QResizeEvent* event) override;
1248
1249private:
1250 // ── Layout helpers (delegate to MultiViewLayout) ───────────────────
1251 QVector<int> enabledViewportIndices() const;
1252 int enabledViewportCount() const;
1253 int viewportIndexAt(const QPoint& pos) const;
1254 QRect multiViewSlotRect(int slot, int numEnabled, const QSize& outputSize) const;
1255 SplitterHit hitTestSplitter(const QPoint& pos, int numEnabled, const QSize& outputSize) const;
1256
1257 // ── Helpers ────────────────────────────────────────────────────────
1258 void updateSplitterCursor(const QPoint& pos);
1259 void updateViewportSeparators();
1260 void updateOverlayLayout();
1261 void updateViewportLabelHighlight();
1262 void showViewportPresetMenu(int viewport, const QPoint& globalPos);
1263 void logPerspectiveRotation(const QString& context) const;
1264 void loadMultiViewSettings();
1265 void saveMultiViewSettings() const;
1266 void updateInflatedSurfaceTransforms();
1267
1268 // ── Rendering ───────────────────────────────────────────────────────
1269 std::unique_ptr<BrainRenderer> m_renderer;
1270 BrainTreeModel* m_model = nullptr;
1271
1272 QMap<const QStandardItem*, std::shared_ptr<BrainSurface>> m_itemSurfaceMap;
1273 QMap<const QStandardItem*, std::shared_ptr<DipoleObject>> m_itemDipoleMap;
1274
1275 QMap<QString, std::shared_ptr<BrainSurface>> m_surfaces;
1276 std::shared_ptr<BrainSurface> m_activeSurface;
1277 QString m_activeSurfaceType;
1278
1279 // ── SubView state ──────────────────────────────────────────────────
1280 static constexpr int kDefaultViewportCount = 4;
1281 SubView m_singleView;
1282 QVector<SubView> m_subViews;
1283 int m_visualizationEditTarget = -1;
1284
1285 // ── Active (runtime) copies — kept in sync with selected SubView ──
1286 ShaderMode m_brainShaderMode = Standard;
1287 ShaderMode m_bemShaderMode = Standard;
1288 VisualizationMode m_currentVisMode = ModeSurface;
1289 bool m_lightingEnabled = true;
1290
1291 // ── Extracted components ───────────────────────────────────────────
1292 CameraController m_camera;
1293 MultiViewLayout m_layout;
1294 SensorFieldMapper m_fieldMapper;
1295 SourceEstimateManager m_sourceManager;
1296 RtSensorStreamManager m_sensorStreamManager;
1297
1298 // ── Camera state ───────────────────────────────────────────────────
1299 QQuaternion m_cameraRotation;
1300 QVector3D m_sceneCenter = QVector3D(0, 0, 0);
1301 float m_sceneSize = 0.3f;
1302 bool m_cameraFocusOverride = false;
1303 QVector3D m_cameraFocusCenter;
1304 float m_cameraFocusSize = 0.3f;
1305 QPoint m_lastMousePos;
1306 QTimer* m_pAutoRotateTimer = nullptr;
1307
1308 // ── UI overlays ────────────────────────────────────────────────────
1309 int m_frameCount = 0;
1310 QElapsedTimer m_fpsTimer;
1311 QLabel* m_fpsLabel = nullptr;
1312 QLabel* m_singleViewInfoLabel = nullptr;
1313 bool m_sceneDirty = true;
1314 qint64 m_cachedVertexCount = 0;
1315 bool m_vertexCountDirty = true;
1316 bool m_infoPanelVisible = true;
1317
1318 // ── Scene objects ──────────────────────────────────────────────────
1319 std::unique_ptr<DipoleObject> m_dipoles;
1320 std::unique_ptr<NetworkObject> m_network;
1321 std::unique_ptr<PolylineObject> m_headPath;
1322 std::unique_ptr<DISP3DLIB::VideoOverlay> m_videoOverlay;
1323
1324 // ── MRI slices ─────────────────────────────────────────────────────
1325 static constexpr int kMaxSliceSlots = 3;
1326 DISP3DLIB::SliceObject* m_slices[kMaxSliceSlots] = {};
1327 bool m_sliceVisible[kMaxSliceSlots] = {true, true, true};
1328
1330 void updateSceneBounds();
1331
1332 // ── Coordinate transforms ──────────────────────────────────────────
1333 FIFFLIB::FiffCoordTrans m_headToMriTrans;
1334 QList<FIFFLIB::FiffDigPoint> m_cardinalDigPoints;
1335 bool m_applySensorTrans = true;
1336 QString m_megHelmetOverridePath;
1337 QMatrix4x4 m_devHeadTrans;
1338 bool m_hasDevHead = false;
1339 bool m_dipolesVisible = true;
1340 bool m_networkVisible = false;
1341
1342 // ── Ray-pick hover state ───────────────────────────────────────────
1343 QStandardItem* m_hoveredItem = nullptr;
1344 int m_hoveredIndex = -1;
1345 QString m_hoveredRegion;
1346 QString m_hoveredSurfaceKey;
1347 QLabel* m_regionLabel = nullptr;
1348 QVector<QLabel*> m_viewportNameLabels;
1349 QVector<QLabel*> m_viewportInfoLabels;
1350
1351 // ── Debug intersection ─────────────────────────────────────────────
1352 std::shared_ptr<BrainSurface> m_debugPointerSurface;
1353 QVector3D m_lastIntersectionPoint;
1354 bool m_hasIntersection = false;
1355
1356
1357 // ── Multi-view support ─────────────────────────────────────────────
1358 ViewMode m_viewMode = SingleView;
1359 int m_viewCount = 1;
1360 float m_multiSplitX = 0.5f;
1361 float m_multiSplitY = 0.5f;
1362 bool m_isDraggingSplitter = false;
1363 SplitterHit m_activeSplitter = SplitterHit::None;
1364 int m_splitterHitTolerancePx = 6;
1365 int m_splitterMinPanePx = 80;
1366 int m_separatorLinePx = 2;
1367 QFrame* m_verticalSeparator = nullptr;
1368 QFrame* m_horizontalSeparator = nullptr;
1369 bool m_perspectiveRotatedSincePress = false;
1370 bool m_draggedSincePress = false;
1371};
1372
1373} // namespace DISP3DLIB
1374
1375#endif // BRAINVIEW_H
4x4 affine FIFF coordinate transform (FIFF_COORD_TRANS) annotated with source/destination coordinate-...
Single digitization point (FIFF_DIG_POINT) with kind (cardinal/HPI/EEG/extra), identifier and 3D coor...
Library export/import macros and namespace marker for the disp3D library.
#define DISP3DSHARED_EXPORT
Camera state and projection / view / model matrix computation for single- and multi-view layouts.
Viewport geometry, splitter logic and per-pane preset assignment for the disp3D multi-view grid.
Per-viewport state (camera preset, zoom, pan, visibility filter) and serialisation helpers.
Lightweight render-related enums (ShaderMode, VisualizationMode) shared across disp3D.
Manager that wires real-time sensor data into the scene: owns the data controller,...
Builds the dense sensor-to-surface mapping matrix and the iso-contour overlay for MEG / EEG evoked da...
Owns the source-time-course overlay together with its loader, real-time controller and target cortica...
Functional connectivity metrics (coherence, PLV, cross-correlation, etc.).
3-D brain visualisation using the Qt RHI rendering backend.
Graph container for one connectivity metric; nodes + weighted edges + threshold/visualisation state.
Definition network.h:106
Per-view toggle flags controlling which data layers (brain, sensors, sources, network) are visible.
Definition viewstate.h:68
Viewport subdivision holding its own camera, projection, and scissor rectangle.
Definition viewstate.h:143
Camera state and matrix computation.
Hierarchical item model organizing all 3-D scene objects (surfaces, sensors, sources,...
Renderable cortical surface mesh with per-vertex color, curvature data, and GPU buffer management.
Renderable dipole arrow set with instanced GPU rendering for QRhi.
Renderable network visualization for QRhi.
Connected line segments through an ordered list of points.
Data model for a single 2-D MRI volume slice.
Definition sliceobject.h:82
Camera-facing textured quad rendered at a focus point in the 3-D scene.
Real-time sensor streaming lifecycle manager.
Sensor-to-surface field mapper that interpolates MEG/EEG measurements onto cortical meshes and genera...
Source estimate lifecycle manager.
Qt RHI-based 3-D renderer managing scene objects, lighting, camera, and render pipeline for brain vis...
Lightweight live overlay marker rendered as a single sphere.
Definition brainview.h:90
bool transparent
If true, rendered with alpha blending.
Definition brainview.h:94
Top-level QWidget hosting the QRhi-based 3-D brain visualization with mouse interaction and multi-vie...
Definition brainview.h:107
void initialize(QRhiCommandBuffer *cb) override
void surfacePointClicked(const QVector3D &worldPos)
void keyPressEvent(QKeyEvent *event) override
bool isInfoPanelVisible() const
Definition brainview.h:535
void visualizationEditTargetChanged(int target)
void wheelEvent(QWheelEvent *event) override
void timePointChanged(int index, float time)
void mouseDoubleClickEvent(QMouseEvent *event) override
void surfacePointDoubleClicked(const QVector3D &worldPos)
void sourceEstimateLoaded(int numTimePoints)
int viewCount() const
Definition brainview.h:406
void resizeEvent(QResizeEvent *event) override
void viewCountChanged(int count)
void shaderModeChanged(const QString &modeName)
void render(QRhiCommandBuffer *cb) override
void sensorFieldLoaded(int numTimePoints, int initialTimePoint=0)
BrainView(QWidget *parent=nullptr)
Definition brainview.cpp:97
void hoveredRegionChanged(const QString &regionName)
void mousePressEvent(QMouseEvent *event) override
void mouseMoveEvent(QMouseEvent *event) override
void stcLoadingProgress(int percent, const QString &message)
void mouseReleaseEvent(QMouseEvent *event) override
ViewMode viewMode() const
Definition brainview.h:546
void sensorFieldTimePointChanged(int index, float time)
void sourceThresholdsUpdated(float min, float mid, float max)
Multi-view geometry computations.
Labelled 4x4 FIFF affine: source frame, destination frame, rotation, translation and cached inverse.