Files
BCIgui/Masterarbeit/openvibe/extras-master/plugins/processing/simple-visualization/src/ovpCBufferDatabase.h
T
2021-10-14 13:47:35 +02:00

368 lines
13 KiB
C++

#pragma once
#include <cfloat>
#include <deque>
#include <string>
#include <vector>
#include <array>
#include "ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SimpleVisualization {
class CSignalDisplayDrawable;
/**
* Abtract class of objects than can be updated by a CBufferDatabase
*/
class CSignalDisplayDrawable
{
public:
virtual ~CSignalDisplayDrawable() = default;
virtual void init() = 0;
virtual void redraw() = 0;
};
/**
* This class is used to store information about the incoming signal stream. It can request a CSignalDisplayDrawable
* object to redraw himself in case of some changes in its data.
*/
class CBufferDatabase
{
public:
//! Number of channels
int64_t m_NElectrodes = 0;
//! Number of channels and number of samples per buffer
std::array<size_t, 2> m_DimSizes;
//! Channel labels, buffer labels
std::array<std::vector<std::string>, 2> m_DimLabels;
//! Flag set to true once first buffer is received
bool m_HasFirstBuffer = false;
//! Sampling frequency of the incoming stream
size_t m_Sampling = 0;
//! double-linked list of pointers to the samples buffers of the current time window
std::deque<double*> m_SampleBuffers;
//! stimulations to display. pair values are <date, stimcode>
std::deque<std::pair<uint64_t, uint64_t>> m_Stimulations;
//electrode spherical coordinates (in degrees)
//CMatrix m_oElectrodesSphericalCoords;
//flag set to true once channel lookup indices are determined
bool m_ChannelLookupTableInitialized = false;
//indices of electrodes in channel localisation database
std::vector<size_t> m_ChannelLookupIdxs;
//electrode labels (standardized)
//std::vector<CString> m_oElectrodesLabels;
//! Number of buffer to display at the same time
uint64_t m_NBufferToDisplay = 2;
//! The global maximum value of the signal (up to now)
double m_MaxValue = -DBL_MAX;
//! The global minimum value of the signal (up to now)
double m_MinValue = +DBL_MAX;
//! Double-linked list of the start times of the current buffers
std::deque<uint64_t> m_StartTime;
//! Double-linked list of the end times of the current buffers
std::deque<uint64_t> m_EndTime;
//! Duration to display in seconds
double m_TotalDuration = 0;
/*! Duration to display in openvibe time units.
Computed once every time the user changes the total duration to display,
when the maximum number of buffers to store are received.*/
uint64_t m_TotalDurationOV = 0;
/*! Duration of a single buffer.
Computed once, but not constant when sampling frequency is not a multiple of buffer size!*/
uint64_t m_BufferDuration = 0;
/*! Time step separating the start times of m_NBufferToDisplay+1 buffers.
Recomputed once every time the user changes the total duration to display,
but not constant when sampling frequency is not a multiple of buffer size!*/
uint64_t m_TotalStep = 0;
/*! Time step separating the start times of 2 consecutive buffers.
Computed once, but not constant when sampling frequency is not a multiple of buffer size!*/
uint64_t m_BufferStep = 0;
// When did the last inserted buffer end
uint64_t m_LastBufferEndTime = 0;
// Did we print a warning about noncontinuity?
bool m_WarningPrinted = false;
//! Pointer to the drawable object to update (if needed)
CSignalDisplayDrawable* m_Drawable = nullptr;
std::vector<std::deque<std::pair<double, double>>> m_LocalMinMaxValue;
Toolkit::TBoxAlgorithm<IBoxAlgorithm>& m_ParentPlugin;
bool m_Error = false;
//! Redraws the associated SignalDisplayDrawable upon new data reception if true (default)
bool m_RedrawOnNewData = true;
protected:
/* \name Channel localisation */
//@{
//channel localisation decoder
Kernel::IAlgorithmProxy* m_decoder = nullptr;
//flag set to true once channel localisation buffer is received
bool m_channelLocalisationHeaderReceived = false;
//dynamic channel localisation flag (e.g. localisation is constantly updated with MEG)
bool m_dynamicChannelLocalisation = false;
//channel labels database
std::vector<CString> m_channelLocalisationLabels;
//flag stating whether streamed coordinates are cartesian (as opposed to spherical)
bool m_cartesianCoords = false;
//! double-linked list of streamed channel coordinates (if cartesian, expressed in normalized space (X right Y front Z up))
std::deque<std::pair<CMatrix*, bool>> m_channelLocalisationCoords;
//! double-linked list of channel coordinates (spherical if streamed coords aere cartesian and vice versa)
//std::deque< std::pair<CMatrix*, bool> > m_oChannelLocalisationAlternateCoords;
//pointer to double linked list of cartesian coordinates
//std::deque< std::pair<CMatrix*, bool> > * m_pChannelLocalisationCartesianCoords = nullptr;
//pointer to double linked list of spherical coordinates
//std::deque< std::pair<CMatrix*, bool> > * m_pChannelLocalisationSphericalCoords = nullptr;
//! double-linked list of start/end times of channel coordinates
std::deque<std::pair<uint64_t, uint64_t>> m_channelLocalisationTimes;
//@}
//! Redraw mode (shift or scan)
CIdentifier m_displayMode = Scan;
public:
explicit CBufferDatabase(Toolkit::TBoxAlgorithm<IBoxAlgorithm>& parent);
virtual ~CBufferDatabase();
/**
* \brief Decode a channel localisation memory buffer
* \param buffer Memory buffer to decode
* \param startTime Start time of memory buffer
* \param endTime End time of memory buffer
* \return True if memory buffer could be properly decoded, false otherwise
*/
virtual bool decodeChannelLocalisationMemoryBuffer(const IMemoryBuffer* buffer, uint64_t startTime, uint64_t endTime);
/**
* \brief Callback called upon channel localisation buffer reception
* \param index Index of newly received channel localisation buffer
* \return True if buffer data was correctly processed, false otherwise
*/
virtual bool onChannelLocalisationBufferReceived(const size_t index);
/**
* \brief Sets the drawable object to update.
* \param drawable drawable object to update.
*/
virtual void setDrawable(CSignalDisplayDrawable* drawable) { m_Drawable = drawable; }
/**
* \brief Get error status
* \return Error status. If true, an error occurred.
*/
virtual bool getErrorStatus() { return m_Error; }
/**
* \brief Determines whether first buffer has been received yet
* \return True if first buffer has been received already, false otherwise
*/
virtual bool hasFirstBuffer() { return m_HasFirstBuffer; }
/**
* \brief Determines whether first channel localisation buffer has been processed yet
* When this condition is true, channel coordinates may be retrieved using the
* corresponding methods in this class.
* \return True if first chanloc buffer was processed
*/
virtual bool isFirstChannelLocalisationBufferProcessed();
/**
* Compute the number of buffers needed to display the signal for a certain time period.
* \param time the time window's width in seconds.
*/
virtual bool adjustNumberOfDisplayedBuffers(double time);
/**
* \brief Get time interval covered by data held in this object
* \return Time interval in ms
*/
virtual double getDisplayedTimeIntervalWidth() const { return (m_NBufferToDisplay * ((m_DimSizes[1] * 1000.0) / m_Sampling)); }
/**
* \brief Determine whether time passed in parameter lies in displayed data interval
* \param time Time to test
* \return True if time lies in displayed time interval, false otherwise
*/
virtual bool isTimeInDisplayedInterval(const uint64_t& time) const;
/**
* \brief Get index of sample buffer which starts at a given time
* \param time[in] Start time of buffer
* \param index[out] Buffer index
* \return True if buffer index could be determined, false otherwise
*/
virtual bool getIndexOfBufferStartingAtTime(const uint64_t& time, size_t& index) const;
//! Returns the min/max values currently displayed for the given channel
virtual void getDisplayedChannelLocalMinMaxValue(const size_t channel, double& min, double& max);
//! Returns the min/max values currently displayed (all channels taken into account)
virtual void getDisplayedGlobalMinMaxValue(double& min, double& max);
virtual void getDisplayedChannelLocalMeanValue(const size_t /*channel*/, double& /*mean*/) {}
//! Returns the min/max values of the last buffer arrived for the given channel
virtual void getLastBufferChannelLocalMinMaxValue(const size_t channel, double& min, double& max)
{
min = m_LocalMinMaxValue[channel].back().first;
max = m_LocalMinMaxValue[channel].back().second;
}
//! Returns the min/max values of the last buffer arrived (all channels taken into account)
virtual void getLastBufferMinMaxValue(double& min, double& max)
{
min = +DBL_MAX;
max = -DBL_MAX;
for (auto& pair : m_LocalMinMaxValue)
{
min = (pair.back().first < min) ? pair.back().first : min;
max = (pair.back().second > max) ? pair.back().second : max;
}
}
/**
* \brief Get number of eletrodes in database
* \return Number of electrodes
*/
virtual size_t getElectrodeCount() { return m_channelLocalisationLabels.size(); }
/**
* \brief Get electrode normalized position
* \remarks Position expressed in normalized cartesian frame where X is right, Y front, Z up
* \param[in] index Index of electrode in database whose position is to be retrieved
* \param[out] position Pointer to an array of 3 floats where to store coordinates
* \return True if electrode position could be retrieved
*/
virtual bool getElectrodePosition(const size_t index, double* position);
/**
* \brief Get electrode normalized position
* \remarks Position expressed in normalized cartesian frame where X is right, Y front, Z up
* \param[in] label Label of electrode whose position is to be retrieved
* \param[out] position Pointer to an array of 3 floats where to store coordinates
* \return True if electrode position could be retrieved
*/
virtual bool getElectrodePosition(const CString& label, double* position);
/**
* \brief Get electrode label
* \param[in] index Index of electrode in database whose label is to be retrieved
* \param[out] label Electrode label
* \return True if electrode label could be retrieved
*/
virtual bool getElectrodeLabel(const size_t index, CString& label);
/**
* \brief Get number of channels
* \return Number of channels
*/
virtual size_t getChannelCount() const { return m_DimSizes[0]; }
/**
* \brief Get channel normalized position
* \remarks Position expressed in normalized cartesian frame where X is right, Y front, Z up
* \param[in] index Index of channel whose position is to be retrieved
* \param[out] position Reference on a double pointer
* \return True if channel position could be retrieved (position then points to an array of 3 floats)
*/
virtual bool getChannelPosition(const size_t index, double*& position);
/**
* \brief Get channel spherical coordinates in degrees
* \param[in] index Index of channel whose coordinates are to be retrieved
* \param[out] theta Reference on a float to be set with theta angle
* \param[out] phi Reference on a float to be set with phi angle
* \return True if channel coordinates could be retrieved
*/
virtual bool getChannelSphericalCoordinates(const size_t index, double& theta, double& phi);
/**
* \brief Get channel label
* \param[in] index Index of channel whose label is to be retrieved
* \param[out] label Channel label
* \return True if channel label could be retrieved
*/
virtual bool getChannelLabel(const size_t index, CString& label);
virtual void setMatrixDimensionCount(const size_t count);
virtual void setMatrixDimensionSize(const size_t index, const size_t size);
virtual void setMatrixDimensionLabel(const size_t idx1, const size_t idx2, const char* label);
// Returns false on failure
virtual bool setMatrixBuffer(const double* buffer, uint64_t startTime, uint64_t endTime);
// Sets the sampling frequency. If this is not called, the frequency is estimated from the stream chunk properties.
// Mainly used to force a warning if stream-specified rate differs from the chunk-estimated rate.
virtual bool setSampling(const size_t sampling);
virtual void setStimulationCount(const size_t /*count*/) {}
virtual void setStimulation(const size_t index, uint64_t identifier, uint64_t date);
/**
* \brief Set display mode
* \remarks Used by signal display and time ruler to determine how they should be updated
* \param mode New display mode
*/
virtual void setDisplayMode(const CIdentifier& mode) { m_displayMode = mode; }
/**
* \brief Get current display mode
* \return Current display mode
*/
virtual CIdentifier getDisplayMode() { return m_displayMode; }
/**
* \brief Set flag stating whether to redraw associated SignalDisplayDrawable objet when new data is available
* \param set Value to set flag with
*/
virtual void setRedrawOnNewData(const bool set) { m_RedrawOnNewData = set; }
protected:
/**
* \brief Initialize table storing indices of electrodes in channel localisation database
* \return True if table could be initialized
*/
virtual bool fillChannelLookupTable();
/**
* \brief Convert a cartesian coordinates triplet to spherical coordinates
* \param[in] cartesian Pointer to cartesian coordinates triplet
* \param[out] theta Equivalent theta angle
* \param[out] phi Equivalent phi angle
* \return True if coordinates were successfully converted
*/
bool convertCartesianToSpherical(const double* cartesian, double& theta, double& phi) const;
};
} // namespace SimpleVisualization
} // namespace Plugins
} // namespace OpenViBE