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 BrainTreeModel;
62class BrainRenderer;
63class BrainSurface;
64class DipoleObject;
65class NetworkObject;
66namespace DISP3DLIB { class VideoOverlay; class SliceObject; }
67namespace CONNECTIVITYLIB { class Network; }
68
69//=============================================================================================================
78 QVector3D position;
79 QColor color;
80 float radius = 0.003f;
81 bool transparent = false;
82};
83
84//=============================================================================================================
91class DISP3DSHARED_EXPORT BrainView : public QRhiWidget
92{
93 Q_OBJECT
94
95public:
103
104public:
105 //=========================================================================================================
111 explicit BrainView(QWidget *parent = nullptr);
112
113 //=========================================================================================================
117 ~BrainView();
118
119 //=========================================================================================================
125 void setModel(BrainTreeModel *model);
126
127 //=========================================================================================================
134 void setInitialCameraRotation(const QQuaternion &rotation);
135
136public slots:
137 void onRowsInserted(const QModelIndex &parent, int first, int last);
138 void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
139 //=========================================================================================================
145 void setActiveSurface(const QString &type);
146
147 //=========================================================================================================
153 void setShaderMode(const QString &mode);
154
155 //=========================================================================================================
161 void setBemShaderMode(const QString &mode);
162
166 void syncBemShadersToBrainShaders();
167
168 //=========================================================================================================
174 void setVisualizationMode(const QString &mode);
175
176 //=========================================================================================================
183 void setHemiVisible(int hemiIdx, bool visible);
184
185 //=========================================================================================================
192 void setBemVisible(const QString &name, bool visible);
193
194 //=========================================================================================================
200 void setBemHighContrast(bool enabled);
201
202 //=========================================================================================================
209 void setSensorVisible(const QString &type, bool visible);
210
211 //=========================================================================================================
217 void setSensorTransEnabled(bool enabled);
218
219 //=========================================================================================================
225 void setMegHelmetOverride(const QString &path);
226
227 //=========================================================================================================
237 bool loadMegHelmetSurface(const QString &helmetFilePath);
238
239 //=========================================================================================================
245 void setDipoleVisible(bool visible);
246
247 //=========================================================================================================
255 bool loadNetwork(const CONNECTIVITYLIB::Network &network, const QString &name = "Network");
256
257 //=========================================================================================================
263 void setNetworkVisible(bool visible);
264
265 //=========================================================================================================
271 void setNetworkThreshold(double threshold);
272
273 //=========================================================================================================
279 void setNetworkColormap(const QString &name);
280
281 //=========================================================================================================
287 void setLightingEnabled(bool enabled);
288
289 //=========================================================================================================
293 void saveSnapshot();
294
295 //=========================================================================================================
310 bool savePng(const QString &path, int width = 1200, int height = 800,
311 const QString &surfaceType = QStringLiteral("pial"));
312
313 //=========================================================================================================
317 void showSingleView();
318
319 //=========================================================================================================
323 void showMultiView();
324
325 //=========================================================================================================
332 void setViewCount(int count);
333
337 int viewCount() const { return m_viewCount; }
338
339 //=========================================================================================================
346 void setViewportEnabled(int index, bool enabled);
347
354 void setViewportCameraPreset(int index, int preset);
355
359 void resetSingleViewCameraState();
360
366 void resetViewportCameraState(int index);
367
375 void resetAllSubViewState();
376
383 int viewportCameraPreset(int index) const;
384
388 void resetMultiViewLayout();
389
395 void setVisualizationEditTarget(int target);
396
402 int visualizationEditTarget() const;
403
407 QString activeSurfaceForTarget(int target) const;
408
412 QString shaderModeForTarget(int target) const;
413
417 QString bemShaderModeForTarget(int target) const;
418
422 QString overlayModeForTarget(int target) const;
423
431 bool objectVisibleForTarget(const QString &object, int target) const;
432
439 bool megFieldMapOnHeadForTarget(int target) const;
440
447 bool isViewportEnabled(int index) const;
448
449 //=========================================================================================================
455 void setInfoPanelVisible(bool visible);
456
457 //=========================================================================================================
463 bool isInfoPanelVisible() const { return m_infoPanelVisible; }
464
465 //=========================================================================================================
471 ViewMode viewMode() const { return m_viewMode; }
472
473 //=========================================================================================================
481 bool loadSourceEstimate(const QString &lhPath, const QString &rhPath);
482
483 //=========================================================================================================
490 bool loadSensors(const QString &fifPath);
491
499 QMap<int, QVector3D> cardinalFiducialsInMri() const;
500
510 bool bemTopVertexInMri(QVector3D& pos) const;
511
512 //=========================================================================================================
519 bool loadDipoles(const QString &dipPath);
520
521 //=========================================================================================================
528 bool loadSourceSpace(const QString &fwdPath);
529
530 //=========================================================================================================
541 static QStringList probeEvokedSets(const QString &evokedPath);
542
550 bool loadSensorField(const QString &evokedPath, int aveIndex = 0);
551
552 //=========================================================================================================
558 void setSourceSpaceVisible(bool visible);
559
560 //=========================================================================================================
567 bool loadTransformation(const QString &transPath);
568
569 //=========================================================================================================
575 void setTimePoint(int index);
576
577 //=========================================================================================================
583 void castRay(const QPoint &pos);
584
585 //=========================================================================================================
591 void setSourceColormap(const QString &name);
592
593 //=========================================================================================================
601 void setSourceThresholds(float min, float mid, float max);
602
603 //=========================================================================================================
609 void setSensorFieldTimePoint(int index);
610
611 //=========================================================================================================
618 void setSensorFieldVisible(const QString &type, bool visible);
619
620 //=========================================================================================================
627 void setSensorFieldContourVisible(const QString &type, bool visible);
628
629 //=========================================================================================================
635 void setMegFieldMapOnHead(bool useHead);
636
637 //=========================================================================================================
643 void setSensorFieldColormap(const QString &name);
644
645 //=========================================================================================================
651 float stcStep() const;
652
653 //=========================================================================================================
659 float stcTmin() const;
660
661 //=========================================================================================================
667 int stcNumTimePoints() const;
668
669 //=========================================================================================================
676 int closestSensorFieldIndex(float timeSec) const;
677
678 //=========================================================================================================
685 int closestStcIndex(float timeSec) const;
686
687 //=========================================================================================================
693 void startRealtimeStreaming();
694
695 //=========================================================================================================
699 void stopRealtimeStreaming();
700
701 //=========================================================================================================
707 bool isRealtimeStreaming() const;
708
709 //=========================================================================================================
716 void pushRealtimeSourceData(const Eigen::VectorXd &data);
717
718 //=========================================================================================================
724 void setRealtimeInterval(int msec);
725
726 //=========================================================================================================
732 void setRealtimeLooping(bool enabled);
733
734 //=========================================================================================================
742 bool sensorFieldTimeRange(float &tmin, float &tmax) const;
743
744 //=========================================================================================================
745 // ── Real-time sensor data streaming ────────────────────────────────
746 //=========================================================================================================
747
758 void startRealtimeSensorStreaming(const QString &modality = QStringLiteral("MEG"));
759
760 //=========================================================================================================
764 void stopRealtimeSensorStreaming();
765
766 //=========================================================================================================
772 bool isRealtimeSensorStreaming() const;
773
774 //=========================================================================================================
782 void pushRealtimeSensorData(const Eigen::VectorXf &data);
783
784 //=========================================================================================================
790 void setRealtimeSensorInterval(int msec);
791
792 //=========================================================================================================
798 void setRealtimeSensorLooping(bool enabled);
799
800 //=========================================================================================================
806 void setRealtimeSensorAverages(int numAvr);
807
808 //=========================================================================================================
814 void setRealtimeSensorColormap(const QString &name);
815
816 // ── Data removal ───────────────────────────────────────────────────
817
821 void clearSurfaces();
822
826 void clearBem();
827
831 void clearSourceEstimate();
832
836 void clearDipoles();
837
841 void clearSourceSpace();
842
846 void clearSensors();
847
848 // ── Live marker overlay (lightweight, no model, no scene-bounds) ───
849
856 void setLiveMarkers(const QVector<LiveMarker>& markers);
857
859 void clearLiveMarkers();
860
869 void setLiveRay(const QVector3D& from, const QVector3D& to,
870 const QColor& color, float radius = 0.001f);
871
873 void clearLiveRay();
874
888 void setProbeVisualization(const QVector3D& tip, const QVector3D& direction,
889 float length, const QColor& color,
890 const QColor& glowColor = QColor(0, 0, 0, 0),
891 const QQuaternion& orientation = QQuaternion(0, 0, 0, 0));
892
894 void clearProbeVisualization();
895
900 void setStaticMarkers(const QVector<LiveMarker>& markers);
901
903 void clearStaticMarkers();
904
909 void setCameraFocusOverride(const QVector3D& center, float size);
910
912 void clearCameraFocusOverride();
913
917 void clearEvoked();
918
922 void clearTransformation();
923
927 void clearNetwork();
928
933 void stopAllStreaming();
934
935 //=========================================================================================================
936 // ── Video overlay ──────────────────────────────────────────────────
937 //=========================================================================================================
938
943 void setVideoOverlayEnabled(bool enabled);
944
946 bool isVideoOverlayEnabled() const;
947
949 void setVideoOverlayFocusPosition(const QVector3D &position);
950
952 void setVideoOverlayUpHint(const QVector3D &dir);
953
955 void setVideoOverlaySize(float meters);
956
958 void setVideoOverlayOpacity(float opacity);
959
961 void pushVideoOverlayFrame(const QImage &frame);
962
964 void setVideoDepthEnabled(bool enabled);
965
967 void setVideoDepthScale(float scale);
968
970 void setVideoDepthSteps(int steps);
971
973 void pushVideoDepthFrame(const QImage &depthFrame);
974
986 bool intersectWorldRay(const QVector3D& origin, const QVector3D& direction, QVector3D& hitPoint) const;
987
988 //=========================================================================================================
989 // ── MRI slice rendering ────────────────────────────────────────────
990 //=========================================================================================================
991
998 void setSlice(int slotIndex, DISP3DLIB::SliceObject *slice);
999
1006 void setSliceVisible(int slotIndex, bool visible);
1007
1013 void setMriSlicesVisible(bool visible);
1014
1015signals:
1016 //=========================================================================================================
1023 void timePointChanged(int index, float time);
1024
1025 //=========================================================================================================
1031 void sourceEstimateLoaded(int numTimePoints);
1032
1033 //=========================================================================================================
1039 void sensorFieldLoaded(int numTimePoints, int initialTimePoint = 0);
1040
1041 //=========================================================================================================
1049 void sourceThresholdsUpdated(float min, float mid, float max);
1050
1051 //=========================================================================================================
1058 void stcLoadingProgress(int percent, const QString &message);
1059
1060 //=========================================================================================================
1067 void sensorFieldTimePointChanged(int index, float time);
1068
1069 //=========================================================================================================
1075 void hoveredRegionChanged(const QString &regionName);
1076
1077 //=========================================================================================================
1084
1085 //=========================================================================================================
1094 void viewCountChanged(int count);
1095
1096 //=========================================================================================================
1104 void shaderModeChanged(const QString &modeName);
1105
1110 void surfacePointClicked(const QVector3D &worldPos);
1111
1116 void surfacePointDoubleClicked(const QVector3D &worldPos);
1117
1118private slots:
1119 //=========================================================================================================
1126 void onSourceEstimateLoaded(int numTimePoints);
1127
1128 //=========================================================================================================
1136 void onRealtimeColorsAvailable(const QVector<uint32_t> &colorsLh,
1137 const QVector<uint32_t> &colorsRh);
1138
1139 //=========================================================================================================
1141 void onSensorStreamColorsAvailable(const QString &surfaceKey,
1142 const QVector<uint32_t> &colors);
1143
1144private:
1145 // Note: ViewVisibilityProfile and SubView are defined in core/viewstate.h.
1146 // SplitterHit is defined in view/multiviewlayout.h.
1147
1149 SubView& subViewForTarget(int target);
1150 const SubView& subViewForTarget(int target) const;
1151
1152 ViewVisibilityProfile& visibilityProfileForTarget(int target);
1153 const ViewVisibilityProfile& visibilityProfileForTarget(int target) const;
1154
1155 void refreshSensorTransforms();
1156 void removeSurfacesByPrefix(const QString &prefix);
1157
1158protected:
1159 void initialize(QRhiCommandBuffer *cb) override;
1160 void render(QRhiCommandBuffer *cb) override;
1161
1162 void mousePressEvent(QMouseEvent *event) override;
1163 void mouseMoveEvent(QMouseEvent *event) override;
1164 void mouseReleaseEvent(QMouseEvent *event) override;
1165 void mouseDoubleClickEvent(QMouseEvent *event) override;
1166 void wheelEvent(QWheelEvent *event) override;
1167 void keyPressEvent(QKeyEvent *event) override;
1168 void resizeEvent(QResizeEvent *event) override;
1169
1170private:
1171 // ── Layout helpers (delegate to MultiViewLayout) ───────────────────
1172 QVector<int> enabledViewportIndices() const;
1173 int enabledViewportCount() const;
1174 int viewportIndexAt(const QPoint& pos) const;
1175 QRect multiViewSlotRect(int slot, int numEnabled, const QSize& outputSize) const;
1176 SplitterHit hitTestSplitter(const QPoint& pos, int numEnabled, const QSize& outputSize) const;
1177
1178 // ── Helpers ────────────────────────────────────────────────────────
1179 void updateSplitterCursor(const QPoint& pos);
1180 void updateViewportSeparators();
1181 void updateOverlayLayout();
1182 void updateViewportLabelHighlight();
1183 void showViewportPresetMenu(int viewport, const QPoint &globalPos);
1184 void logPerspectiveRotation(const QString& context) const;
1185 void loadMultiViewSettings();
1186 void saveMultiViewSettings() const;
1187 void updateInflatedSurfaceTransforms();
1188
1189 // ── Rendering ───────────────────────────────────────────────────────
1190 std::unique_ptr<BrainRenderer> m_renderer;
1191 BrainTreeModel* m_model = nullptr;
1192
1193 QMap<const QStandardItem*, std::shared_ptr<BrainSurface>> m_itemSurfaceMap;
1194 QMap<const QStandardItem*, std::shared_ptr<DipoleObject>> m_itemDipoleMap;
1195
1196 QMap<QString, std::shared_ptr<BrainSurface>> m_surfaces;
1197 std::shared_ptr<BrainSurface> m_activeSurface;
1198 QString m_activeSurfaceType;
1199
1200 // ── SubView state ──────────────────────────────────────────────────
1201 static constexpr int kDefaultViewportCount = 4;
1202 SubView m_singleView;
1203 QVector<SubView> m_subViews;
1204 int m_visualizationEditTarget = -1;
1205
1206 // ── Active (runtime) copies — kept in sync with selected SubView ──
1207 ShaderMode m_brainShaderMode = Standard;
1208 ShaderMode m_bemShaderMode = Standard;
1209 VisualizationMode m_currentVisMode = ModeSurface;
1210 bool m_lightingEnabled = true;
1211
1212 // ── Extracted components ───────────────────────────────────────────
1213 CameraController m_camera;
1214 MultiViewLayout m_layout;
1215 SensorFieldMapper m_fieldMapper;
1216 SourceEstimateManager m_sourceManager;
1217 RtSensorStreamManager m_sensorStreamManager;
1218
1219 // ── Camera state ───────────────────────────────────────────────────
1220 QQuaternion m_cameraRotation;
1221 QVector3D m_sceneCenter = QVector3D(0, 0, 0);
1222 float m_sceneSize = 0.3f;
1223 bool m_cameraFocusOverride = false;
1224 QVector3D m_cameraFocusCenter;
1225 float m_cameraFocusSize = 0.3f;
1226 float m_zoom = 0.0f;
1227 QPoint m_lastMousePos;
1228
1229 // ── UI overlays ────────────────────────────────────────────────────
1230 int m_frameCount = 0;
1231 QElapsedTimer m_fpsTimer;
1232 QLabel *m_fpsLabel = nullptr;
1233 QLabel *m_singleViewInfoLabel = nullptr;
1234 bool m_sceneDirty = true;
1235 qint64 m_cachedVertexCount = 0;
1236 bool m_vertexCountDirty = true;
1237 int m_snapshotCounter = 0;
1238 bool m_infoPanelVisible = true;
1239
1240 // ── Scene objects ──────────────────────────────────────────────────
1241 std::unique_ptr<DipoleObject> m_dipoles;
1242 std::unique_ptr<NetworkObject> m_network;
1243 std::unique_ptr<DISP3DLIB::VideoOverlay> m_videoOverlay;
1244
1245 // ── MRI slices ─────────────────────────────────────────────────────
1246 static constexpr int kMaxSliceSlots = 3;
1247 DISP3DLIB::SliceObject *m_slices[kMaxSliceSlots] = {};
1248 bool m_sliceVisible[kMaxSliceSlots] = {true, true, true};
1249
1251 void updateSceneBounds();
1252
1253 // ── Coordinate transforms ──────────────────────────────────────────
1254 FIFFLIB::FiffCoordTrans m_headToMriTrans;
1255 QList<FIFFLIB::FiffDigPoint> m_cardinalDigPoints;
1256 bool m_applySensorTrans = true;
1257 QString m_megHelmetOverridePath;
1258 QMatrix4x4 m_devHeadTrans;
1259 bool m_hasDevHead = false;
1260 bool m_dipolesVisible = true;
1261 bool m_networkVisible = false;
1262
1263 // ── Ray-pick hover state ───────────────────────────────────────────
1264 QStandardItem* m_hoveredItem = nullptr;
1265 int m_hoveredIndex = -1;
1266 QString m_hoveredRegion;
1267 QString m_hoveredSurfaceKey;
1268 QLabel* m_regionLabel = nullptr;
1269 QVector<QLabel*> m_viewportNameLabels;
1270 QVector<QLabel*> m_viewportInfoLabels;
1271
1272 // ── Debug intersection ─────────────────────────────────────────────
1273 std::shared_ptr<BrainSurface> m_debugPointerSurface;
1274 QVector3D m_lastIntersectionPoint;
1275 bool m_hasIntersection = false;
1276
1277
1278
1279 // ── Multi-view support ─────────────────────────────────────────────
1280 ViewMode m_viewMode = SingleView;
1281 int m_viewCount = 1;
1282 float m_multiSplitX = 0.5f;
1283 float m_multiSplitY = 0.5f;
1284 bool m_isDraggingSplitter = false;
1285 SplitterHit m_activeSplitter = SplitterHit::None;
1286 int m_splitterHitTolerancePx = 6;
1287 int m_splitterMinPanePx = 80;
1288 int m_separatorLinePx = 2;
1289 QFrame* m_verticalSeparator = nullptr;
1290 QFrame* m_horizontalSeparator = nullptr;
1291 bool m_perspectiveRotatedSincePress = false;
1292};
1293
1294#endif // BRAINVIEW_H
Lightweight render-related enums (ShaderMode, VisualizationMode) shared across disp3D.
ShaderMode
Definition rendertypes.h:61
@ Standard
Definition rendertypes.h:62
VisualizationMode
Definition rendertypes.h:78
@ ModeSurface
Definition rendertypes.h:79
Per-viewport state (camera preset, zoom, pan, visibility filter) and serialisation helpers.
Viewport geometry, splitter logic and per-pane preset assignment for the disp3D multi-view grid.
SplitterHit
Owns the source-time-course overlay together with its loader, real-time controller and target cortica...
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...
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.
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...
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:98
Per-view toggle flags controlling which data layers (brain, sensors, sources, network) are visible.
Definition viewstate.h:64
Viewport subdivision holding its own camera, projection, and scissor rectangle.
Definition viewstate.h:139
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.
Data model for a single 2-D MRI volume slice.
Definition sliceobject.h:79
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:77
bool transparent
If true, rendered with alpha blending.
Definition brainview.h:81
QColor color
Definition brainview.h:79
QVector3D position
Definition brainview.h:78
float radius
Definition brainview.h:80
Top-level QWidget hosting the QRhi-based 3-D brain visualization with mouse interaction and multi-vie...
Definition brainview.h:92
ViewMode viewMode() const
Definition brainview.h:471
void sourceThresholdsUpdated(float min, float mid, float max)
void wheelEvent(QWheelEvent *event) override
void sourceEstimateLoaded(int numTimePoints)
void shaderModeChanged(const QString &modeName)
void resizeEvent(QResizeEvent *event) override
void keyPressEvent(QKeyEvent *event) override
void mouseDoubleClickEvent(QMouseEvent *event) override
void mouseMoveEvent(QMouseEvent *event) override
void visualizationEditTargetChanged(int target)
void timePointChanged(int index, float time)
int viewCount() const
Definition brainview.h:337
void render(QRhiCommandBuffer *cb) override
void initialize(QRhiCommandBuffer *cb) override
void mouseReleaseEvent(QMouseEvent *event) override
BrainView(QWidget *parent=nullptr)
Definition brainview.cpp:76
void viewCountChanged(int count)
void surfacePointDoubleClicked(const QVector3D &worldPos)
void mousePressEvent(QMouseEvent *event) override
void sensorFieldTimePointChanged(int index, float time)
void surfacePointClicked(const QVector3D &worldPos)
void hoveredRegionChanged(const QString &regionName)
void sensorFieldLoaded(int numTimePoints, int initialTimePoint=0)
bool isInfoPanelVisible() const
Definition brainview.h:463
void stcLoadingProgress(int percent, const QString &message)
Multi-view geometry computations.