21#include <QMutexLocker>
40 QMutexLocker locker(&m_mutex);
43 if (m_lDataQ.size() <
static_cast<int>(m_dSFreq)) {
44 m_lDataQ.append(data);
49 m_lDataLoopQ.append(data);
51 if (m_lDataLoopQ.size() >
static_cast<int>(m_dSFreq) * 10) {
52 m_lDataLoopQ.removeFirst();
61 QMutexLocker locker(&m_mutex);
64 m_vecAverage = Eigen::VectorXd();
73 QMutexLocker locker(&m_mutex);
81 QMutexLocker locker(&m_mutex);
89 QMutexLocker locker(&m_mutex);
90 m_iNumAverages = qMax(1, numAvr);
97 QMutexLocker locker(&m_mutex);
98 m_sColormapType = name;
105 QMutexLocker locker(&m_mutex);
115 QMutexLocker locker(&m_mutex);
116 m_bIsLooping = enabled;
123 QMutexLocker locker(&m_mutex);
124 m_dSFreq = qMax(1.0, sFreq);
130 const QVector<uint32_t> &baseColorsRh)
132 QMutexLocker locker(&m_mutex);
133 m_baseColorsLh = baseColorsLh;
134 m_baseColorsRh = baseColorsRh;
141 QMutexLocker locker(&m_mutex);
142 m_bStreamSmoothedData = bStreamSmoothedData;
149 QMutexLocker locker(&m_mutex);
152 Eigen::VectorXd vecCurrentData;
154 if (!m_lDataQ.isEmpty()) {
155 vecCurrentData = m_lDataQ.takeFirst();
156 }
else if (m_bIsLooping && !m_lDataLoopQ.isEmpty()) {
158 vecCurrentData = m_lDataLoopQ[m_iCurrentSample % m_lDataLoopQ.size()];
166 if (m_iNumAverages > 1) {
167 if (m_vecAverage.size() != vecCurrentData.size()) {
168 m_vecAverage = vecCurrentData;
171 m_vecAverage += vecCurrentData;
175 if (m_iSampleCtr < m_iNumAverages) {
179 vecCurrentData = m_vecAverage /
static_cast<double>(m_iSampleCtr);
180 m_vecAverage = Eigen::VectorXd();
185 Eigen::VectorXf vecAbsData = vecCurrentData.cwiseAbs().cast<
float>();
192 nSourcesLh = m_interpMatLh->cols();
195 nSourcesRh = m_interpMatRh->cols();
198 int nTotalExpected = nSourcesLh + nSourcesRh;
201 if (vecAbsData.size() != nTotalExpected && nTotalExpected > 0) {
203 if (vecAbsData.size() < nTotalExpected) {
204 qWarning() <<
"RtSourceDataWorker: Data size" << vecAbsData.size()
205 <<
"< expected" << nTotalExpected;
211 Eigen::VectorXf dataLh, dataRh;
212 if (nSourcesLh > 0 && vecAbsData.size() >= nSourcesLh) {
213 dataLh = vecAbsData.head(nSourcesLh);
215 if (nSourcesRh > 0 && vecAbsData.size() >= nSourcesLh + nSourcesRh) {
216 dataRh = vecAbsData.segment(nSourcesLh, nSourcesRh);
220 if (!m_bStreamSmoothedData) {
222 Eigen::VectorXd rawLh = dataLh.cast<
double>();
223 Eigen::VectorXd rawRh = dataRh.cast<
double>();
231 QVector<uint32_t> colorsLh = computeHemiColors(dataLh, m_interpMatLh, m_baseColorsLh);
232 QVector<uint32_t> colorsRh = computeHemiColors(dataRh, m_interpMatRh, m_baseColorsRh);
242QVector<uint32_t> RtSourceDataWorker::computeHemiColors(
243 const Eigen::VectorXf &sourceData,
244 const QSharedPointer<Eigen::SparseMatrix<float>> &interpMat,
245 const QVector<uint32_t> &baseColors)
const
247 if (sourceData.size() == 0 || !interpMat || interpMat->rows() == 0) {
248 return QVector<uint32_t>();
252 Eigen::VectorXf interpolated = (*interpMat) * sourceData;
254 int nVertices = interpolated.size();
255 QVector<uint32_t> colors(nVertices);
257 bool hasBaseColors = (baseColors.size() == nVertices);
259 double range = m_dThreshMax - m_dThreshMin;
260 if (range <= 0.0) range = 1.0;
262 for (
int i = 0; i < nVertices; ++i) {
263 float value = interpolated(i);
266 double normalized = (
static_cast<double>(value) - m_dThreshMin) / range;
267 normalized = qBound(0.0, normalized, 1.0);
271 if (value < m_dThreshMin) {
274 colors[i] = baseColors[i];
279 }
else if (value < m_dThreshMid) {
281 double fadeRange = m_dThreshMid - m_dThreshMin;
282 if (fadeRange > 0.0) {
283 alpha =
static_cast<uint8_t
>(255.0 * (value - m_dThreshMin) / fadeRange);
287 if (hasBaseColors && alpha < 255) {
288 uint32_t actColor = valueToColor(normalized, 255);
289 uint32_t baseColor = baseColors[i];
292 uint32_t aR = actColor & 0xFF;
293 uint32_t aG = (actColor >> 8) & 0xFF;
294 uint32_t aB = (actColor >> 16) & 0xFF;
295 uint32_t bR = baseColor & 0xFF;
296 uint32_t bG = (baseColor >> 8) & 0xFF;
297 uint32_t bB = (baseColor >> 16) & 0xFF;
299 uint32_t rR = (aR * alpha + bR * (255 - alpha)) / 255;
300 uint32_t rG = (aG * alpha + bG * (255 - alpha)) / 255;
301 uint32_t rB = (aB * alpha + bB * (255 - alpha)) / 255;
308 colors[i] = valueToColor(normalized, alpha);
316uint32_t RtSourceDataWorker::valueToColor(
double value, uint8_t alpha)
const
320 uint32_t r = qRed(rgb);
321 uint32_t g = qGreen(rgb);
322 uint32_t b = qBlue(rgb);
325 return packABGR(r, g, b,
static_cast<uint32_t
>(alpha));
Background worker that converts streaming source vectors into smoothed per-vertex ABGR colour buffers...
Lightweight render-related enums (ShaderMode, VisualizationMode) shared across disp3D.
uint32_t packABGR(uint32_t r, uint32_t g, uint32_t b, uint32_t a=0xFF)
Static scalar-to-colour lookup helpers (Jet, Hot, Bone, Viridis, Cool, RedBlue, MNE) used by every pl...
3-D brain visualisation using the Qt RHI rendering backend.
static QRgb valueToColor(double v, const QString &sMap)
void setInterpolationMatrixRight(QSharedPointer< Eigen::SparseMatrix< float > > mat)
void setColormapType(const QString &name)
void setInterpolationMatrixLeft(QSharedPointer< Eigen::SparseMatrix< float > > mat)
void setLoopState(bool enabled)
void newRtRawData(const Eigen::VectorXd &dataLh, const Eigen::VectorXd &dataRh)
RtSourceDataWorker(QObject *parent=nullptr)
void setNumberAverages(int numAvr)
void setStreamSmoothedData(bool bStreamSmoothedData)
void setThresholds(double min, double mid, double max)
void setSFreq(double sFreq)
void addData(const Eigen::VectorXd &data)
void newRtSmoothedData(const QVector< uint32_t > &colorsLh, const QVector< uint32_t > &colorsRh)
void setSurfaceColor(const QVector< uint32_t > &baseColorsLh, const QVector< uint32_t > &baseColorsRh)