43#include <QMutexLocker>
62 QMutexLocker locker(&m_mutex);
65 if (m_lDataQ.size() <
static_cast<int>(m_dSFreq)) {
66 m_lDataQ.append(data);
71 m_lDataLoopQ.append(data);
73 if (m_lDataLoopQ.size() >
static_cast<int>(m_dSFreq) * 10) {
74 m_lDataLoopQ.removeFirst();
83 QMutexLocker locker(&m_mutex);
86 m_vecAverage = Eigen::VectorXd();
95 QMutexLocker locker(&m_mutex);
103 QMutexLocker locker(&m_mutex);
111 QMutexLocker locker(&m_mutex);
112 m_iNumAverages = qMax(1, numAvr);
119 QMutexLocker locker(&m_mutex);
120 m_sColormapType = name;
127 QMutexLocker locker(&m_mutex);
137 QMutexLocker locker(&m_mutex);
138 m_bIsLooping = enabled;
145 QMutexLocker locker(&m_mutex);
146 m_dSFreq = qMax(1.0, sFreq);
152 const QVector<uint32_t> &baseColorsRh)
154 QMutexLocker locker(&m_mutex);
155 m_baseColorsLh = baseColorsLh;
156 m_baseColorsRh = baseColorsRh;
163 QMutexLocker locker(&m_mutex);
164 m_bStreamSmoothedData = bStreamSmoothedData;
171 QMutexLocker locker(&m_mutex);
174 Eigen::VectorXd vecCurrentData;
176 if (!m_lDataQ.isEmpty()) {
177 vecCurrentData = m_lDataQ.takeFirst();
178 }
else if (m_bIsLooping && !m_lDataLoopQ.isEmpty()) {
180 vecCurrentData = m_lDataLoopQ[m_iCurrentSample % m_lDataLoopQ.size()];
188 if (m_iNumAverages > 1) {
189 if (m_vecAverage.size() != vecCurrentData.size()) {
190 m_vecAverage = vecCurrentData;
193 m_vecAverage += vecCurrentData;
197 if (m_iSampleCtr < m_iNumAverages) {
201 vecCurrentData = m_vecAverage /
static_cast<double>(m_iSampleCtr);
202 m_vecAverage = Eigen::VectorXd();
207 Eigen::VectorXf vecAbsData = vecCurrentData.cwiseAbs().cast<
float>();
214 nSourcesLh = m_interpMatLh->cols();
217 nSourcesRh = m_interpMatRh->cols();
220 int nTotalExpected = nSourcesLh + nSourcesRh;
223 if (vecAbsData.size() != nTotalExpected && nTotalExpected > 0) {
225 if (vecAbsData.size() < nTotalExpected) {
226 qWarning() <<
"RtSourceDataWorker: Data size" << vecAbsData.size()
227 <<
"< expected" << nTotalExpected;
233 Eigen::VectorXf dataLh, dataRh;
234 if (nSourcesLh > 0 && vecAbsData.size() >= nSourcesLh) {
235 dataLh = vecAbsData.head(nSourcesLh);
237 if (nSourcesRh > 0 && vecAbsData.size() >= nSourcesLh + nSourcesRh) {
238 dataRh = vecAbsData.segment(nSourcesLh, nSourcesRh);
242 if (!m_bStreamSmoothedData) {
244 Eigen::VectorXd rawLh = dataLh.cast<
double>();
245 Eigen::VectorXd rawRh = dataRh.cast<
double>();
253 QVector<uint32_t> colorsLh = computeHemiColors(dataLh, m_interpMatLh, m_baseColorsLh);
254 QVector<uint32_t> colorsRh = computeHemiColors(dataRh, m_interpMatRh, m_baseColorsRh);
264QVector<uint32_t> RtSourceDataWorker::computeHemiColors(
265 const Eigen::VectorXf &sourceData,
266 const QSharedPointer<Eigen::SparseMatrix<float>> &interpMat,
267 const QVector<uint32_t> &baseColors)
const
269 if (sourceData.size() == 0 || !interpMat || interpMat->rows() == 0) {
270 return QVector<uint32_t>();
274 Eigen::VectorXf interpolated = (*interpMat) * sourceData;
276 int nVertices = interpolated.size();
277 QVector<uint32_t> colors(nVertices);
279 bool hasBaseColors = (baseColors.size() == nVertices);
281 double range = m_dThreshMax - m_dThreshMin;
282 if (range <= 0.0) range = 1.0;
284 for (
int i = 0; i < nVertices; ++i) {
285 float value = interpolated(i);
288 double normalized = (
static_cast<double>(value) - m_dThreshMin) / range;
289 normalized = qBound(0.0, normalized, 1.0);
293 if (value < m_dThreshMin) {
296 colors[i] = baseColors[i];
301 }
else if (value < m_dThreshMid) {
303 double fadeRange = m_dThreshMid - m_dThreshMin;
304 if (fadeRange > 0.0) {
305 alpha =
static_cast<uint8_t
>(255.0 * (value - m_dThreshMin) / fadeRange);
309 if (hasBaseColors && alpha < 255) {
310 uint32_t actColor = valueToColor(normalized, 255);
311 uint32_t baseColor = baseColors[i];
314 uint32_t aR = actColor & 0xFF;
315 uint32_t aG = (actColor >> 8) & 0xFF;
316 uint32_t aB = (actColor >> 16) & 0xFF;
317 uint32_t bR = baseColor & 0xFF;
318 uint32_t bG = (baseColor >> 8) & 0xFF;
319 uint32_t bB = (baseColor >> 16) & 0xFF;
321 uint32_t rR = (aR * alpha + bR * (255 - alpha)) / 255;
322 uint32_t rG = (aG * alpha + bG * (255 - alpha)) / 255;
323 uint32_t rB = (aB * alpha + bB * (255 - alpha)) / 255;
330 colors[i] = valueToColor(normalized, alpha);
338uint32_t RtSourceDataWorker::valueToColor(
double value, uint8_t alpha)
const
342 uint32_t r = qRed(rgb);
343 uint32_t g = qGreen(rgb);
344 uint32_t b = qBlue(rgb);
347 return packABGR(r, g, b,
static_cast<uint32_t
>(alpha));
ColorMap class declaration.
RtSourceDataWorker class declaration.
Lightweight render-related enums shared across the disp3D_rhi library.
uint32_t packABGR(uint32_t r, uint32_t g, uint32_t b, uint32_t a=0xFF)
3-D brain visualisation using the Qt RHI rendering backend.
static QRgb valueToColor(double v, const QString &sMap)
void newRtSmoothedData(const QVector< uint32_t > &colorsLh, const QVector< uint32_t > &colorsRh)
void setInterpolationMatrixRight(QSharedPointer< Eigen::SparseMatrix< float > > mat)
void setColormapType(const QString &name)
void setInterpolationMatrixLeft(QSharedPointer< Eigen::SparseMatrix< float > > mat)
void setLoopState(bool enabled)
RtSourceDataWorker(QObject *parent=nullptr)
void setNumberAverages(int numAvr)
void newRtRawData(const Eigen::VectorXd &dataLh, const Eigen::VectorXd &dataRh)
void setStreamSmoothedData(bool bStreamSmoothedData)
void setThresholds(double min, double mid, double max)
void setSFreq(double sFreq)
void addData(const Eigen::VectorXd &data)
void setSurfaceColor(const QVector< uint32_t > &baseColorsLh, const QVector< uint32_t > &baseColorsRh)