This commit is contained in:
2021-10-14 13:47:35 +02:00
commit 6625a8dfaa
4026 changed files with 844291 additions and 0 deletions
@@ -0,0 +1,101 @@
#include "CBoxAlgorithmASRProcessor.hpp"
//@todo put functions in this file in sdk it's duplication of file in riemann module
#include "utils/misc.hpp" // For conversion Openvibe to Eigen
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRProcessor::initialize()
{
//***** Codecs *****
m_SignalDecoder.initialize(*this, 0);
m_stimulationEncoder.initialize(*this, 0);
m_signalEncoder.initialize(*this, 1);
m_signalEncoder.getInputSamplingRate().setReferenceTarget(m_SignalDecoder.getOutputSamplingRate()); // Link Sampling
m_signalEncoder.getInputMatrix().setReferenceTarget(m_SignalDecoder.getOutputMatrix()); // Link Matrix
//***** Pointers *****
m_iMatrix = m_SignalDecoder.getOutputMatrix();
m_oStimulation = m_stimulationEncoder.getInputStimulationSet();
m_oMatrix = m_signalEncoder.getInputMatrix();
// Settings
m_filename = CString(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0)).toASCIIString();
OV_ERROR_UNLESS_KRF(!m_filename.empty(), "Invalid empty model filename", Kernel::ErrorType::BadSetting);
OV_ERROR_UNLESS_KRF(m_asr.loadXML(m_filename), "Loading XML Error", Kernel::ErrorType::BadFileRead);
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRProcessor::uninitialize()
{
m_SignalDecoder.uninitialize();
m_stimulationEncoder.uninitialize();
m_signalEncoder.uninitialize();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRProcessor::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRProcessor::process()
{
Kernel::IBoxIO& boxCtx = this->getDynamicBoxContext();
for (size_t i = 0; i < boxCtx.getInputChunkCount(0); ++i)
{
m_SignalDecoder.decode(i); // Decode the chunk
OV_ERROR_UNLESS_KRF(m_iMatrix->getDimensionCount() == 2, "Invalid Input Signal", Kernel::ErrorType::BadInput);
const uint64_t start = boxCtx.getInputChunkStartTime(0, i), // Time Code Chunk Start
end = boxCtx.getInputChunkEndTime(0, i); // Time Code Chunk End
if (m_SignalDecoder.isHeaderReceived()) // Header received
{
m_signalEncoder.encodeHeader();
m_stimulationEncoder.encodeHeader();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
if (m_SignalDecoder.isBufferReceived()) // Buffer received
{
const bool prevTrivial = m_asr.getTrivial();
Eigen::MatrixXd in, out;
MatrixConvert(*m_iMatrix, in);
OV_ERROR_UNLESS_KRF(m_asr.process(in, out), "ASR Process Error", Kernel::ErrorType::BadProcessing);
MatrixConvert(out, *m_oMatrix);
m_signalEncoder.encodeBuffer();
const bool newTrivial = m_asr.getTrivial();
if (!newTrivial && !prevTrivial) // We have reconstruct signal
{
m_oStimulation->appendStimulation(OVTK_StimulationId_Artifact, start, 0);
m_stimulationEncoder.encodeBuffer();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
}
if (m_SignalDecoder.isEndReceived()) // Buffer received
{
m_signalEncoder.encodeEnd();
m_stimulationEncoder.encodeEnd();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
boxCtx.markOutputAsReadyToSend(1, start, end);
}
return true;
}
//---------------------------------------------------------------------------------------------------
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,88 @@
///-------------------------------------------------------------------------------------------------
///
/// \file CBoxAlgorithmASRProcessor.hpp
/// \brief Classes of the box ASR Processor.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 08/12/2020.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "defines.hpp"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <geometry/artifacts/CASR.hpp>
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//-------------------------------------------------------------------------------------------------
/// <summary> The class CBoxAlgorithmASRProcessor describes the box Artifact Subspace Reconstruction (ASR) Processor. </summary>
class CBoxAlgorithmASRProcessor final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, ClassId_Box_ASR_Processor)
protected:
//***** Codecs *****
Toolkit::TSignalDecoder<CBoxAlgorithmASRProcessor> m_SignalDecoder; ///< Input Signal Decoder
Toolkit::TStimulationEncoder<CBoxAlgorithmASRProcessor> m_stimulationEncoder; ///< Output Stimulation Encoder
Toolkit::TSignalEncoder<CBoxAlgorithmASRProcessor> m_signalEncoder; ///< Output Signal Encoder
//***** Pointers *****
CMatrix *m_iMatrix = nullptr, ///< Input Matrix Pointer
*m_oMatrix = nullptr; ///< Output Matrix Pointer
IStimulationSet* m_oStimulation = nullptr; ///< Output Stimulation Pointer
//***** ASR *****
std::string m_filename; ///< ASR Model Path
Geometry::CASR m_asr; ///< ASR Model
};
//-------------------------------------------------------------------------------------------------
/// <summary> Descriptor of the box Artifact Subspace Reconstruction (ASR) Processor. </summary>
class CBoxAlgorithmASRProcessorDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return "ASR Processor"; }
CString getAuthorName() const override { return "Thibaut Monseigne"; }
CString getAuthorCompanyName() const override { return "Inria"; }
CString getShortDescription() const override { return "Artifact Subspace Reconstruction (ASR) Processor."; }
CString getDetailedDescription() const override { return "Artifact Subspace Reconstruction (ASR) Processor."; }
CString getCategory() const override { return "Artifact"; }
CString getVersion() const override { return "0.1"; }
CString getStockItemName() const override { return "gtk-execute"; }
CIdentifier getCreatedClass() const override { return ClassId_Box_ASR_Processor; }
IPluginObject* create() override { return new CBoxAlgorithmASRProcessor; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input Signal", OV_TypeId_Signal);
prototype.addOutput("Signal Reconstructed",OV_TypeId_Stimulations);
prototype.addOutput("Output Signal", OV_TypeId_Signal);
prototype.addSetting("Filename to load model", OV_TypeId_Filename, "${Player_ScenarioDirectory}/ASR-model.xml");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, ClassId_Box_ASR_Processor_Desc)
};
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,182 @@
#include "CBoxAlgorithmASRTrainer.hpp"
//@todo put functions in this file in sdk it's duplication of file in riemann module
#include "utils/misc.hpp" // For conversion Openvibe to Eigen
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::initialize()
{
// Stimulations
m_stimulationDecoder.initialize(*this, 0);
m_iStimulation = m_stimulationDecoder.getOutputStimulationSet();
m_stimulationEncoder.initialize(*this, 0);
m_oStimulation = m_stimulationEncoder.getInputStimulationSet();
// Classes
m_signalEncoder.initialize(*this, 1);
m_iMatrix = m_signalEncoder.getOutputMatrix();
// Settings
m_filename = CString(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0)).toASCIIString();
m_stimulationName = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
m_metric = Geometry::EMetric(uint64_t(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2)));
m_ratio = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
m_rejection = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
OV_ERROR_UNLESS_KRF(!m_filename.empty(), "Invalid empty model filename", Kernel::ErrorType::BadSetting);
OV_ERROR_UNLESS_KRF(Geometry::InRange(m_ratio, 0, 1), "Channel ratio must be in [0;1], actual : " + std::to_string(m_ratio), Kernel::ErrorType::BadSetting);
OV_ERROR_UNLESS_KRF(m_rejection >= 0, "Rejection limit must be positive, actual : " + std::to_string(m_rejection), Kernel::ErrorType::BadSetting);
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::uninitialize()
{
m_stimulationDecoder.uninitialize();
m_signalEncoder.uninitialize();
m_stimulationEncoder.uninitialize();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::process()
{
if (!m_isTrain)
{
Kernel::IBoxIO& boxCtx = this->getDynamicBoxContext();
//***** Stimulations *****
for (size_t i = 0; i < boxCtx.getInputChunkCount(0); ++i)
{
m_stimulationDecoder.decode(i); // Decode the chunk
const uint64_t start = boxCtx.getInputChunkStartTime(0, i), // Time Code Chunk Start
end = boxCtx.getInputChunkEndTime(0, i); // Time Code Chunk End
if (m_stimulationDecoder.isHeaderReceived())
{
m_stimulationEncoder.encodeHeader();
boxCtx.markOutputAsReadyToSend(0, 0, 0);
}
if (m_stimulationDecoder.isBufferReceived()) // Buffer received
{
for (size_t j = 0; j < m_iStimulation->getStimulationCount(); ++j)
{
if (m_iStimulation->getStimulationIdentifier(j) == m_stimulationName)
{
OV_ERROR_UNLESS_KRF(train(), "Train or Save failed", Kernel::ErrorType::BadProcessing);
m_oStimulation->appendStimulation(OVTK_StimulationId_TrainCompleted, m_iStimulation->getStimulationDate(j), 0);
m_isTrain = true;
}
}
m_stimulationEncoder.encodeBuffer();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
if (m_stimulationDecoder.isEndReceived())
{
m_stimulationEncoder.encodeEnd();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
}
//***** Signal *****
for (size_t i = 0; i < boxCtx.getInputChunkCount(1); ++i)
{
m_signalEncoder.decode(i); // Decode the chunk
OV_ERROR_UNLESS_KRF(m_iMatrix->getDimensionCount() == 2, "Invalid Input Signal", Kernel::ErrorType::BadInput);
if (m_signalEncoder.isBufferReceived()) // Buffer received
{
Eigen::MatrixXd m;
MatrixConvert(*m_iMatrix, m);
m_dataset.push_back(m);
}
}
}
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::train()
{
Geometry::CASR asr(m_metric);
asr.setMaxChannel(m_ratio);
this->getLogManager() << Kernel::LogLevel_Info << "Train Beginning...\n";
OV_ERROR_UNLESS_KRF(asr.train(m_dataset, m_rejection), "Train failed", Kernel::ErrorType::BadProcessing);
getLogManager() << Kernel::LogLevel_Info << "Train Finished. Save Beginning...\n";
OV_ERROR_UNLESS_KRF(asr.saveXML(m_filename), "Save failed", Kernel::ErrorType::BadProcessing);
this->getLogManager() << Kernel::LogLevel_Info << "Save Finished.\n";
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainerListener::onSettingValueChanged(Kernel::IBox& box, const size_t index)
{
if (index == 2)
{
CString tmp;
box.getSettingValue(index, tmp);
const Geometry::EMetric m = Geometry::StringToMetric(tmp.toASCIIString());
if (m != Geometry::EMetric::Euclidian && m != Geometry::EMetric::Riemann)
{
const std::string s1 = toString(Geometry::EMetric::Euclidian), s2 = toString(Geometry::EMetric::Riemann);
getLogManager() << Kernel::LogLevel_Warning << "Metric must be " << s1 << " or " << s2 << ". Setting is set to " << s1 << "\n";
box.setSettingValue(index, s1.c_str());
}
}
else if (index == 3)
{
CString tmp;
box.getSettingValue(index, tmp);
double ratio = 0.0;
std::stringstream ss(tmp.toASCIIString());
ss >> ratio;
if (ratio < 0.0)
{
getLogManager() << Kernel::LogLevel_Warning <<
"Channel ratio must be in [0;1] (0 for no reconstruction, 1 for no limit). Setting is set to 0. \n";
box.setSettingValue(index, "0");
}
else if (ratio > 1.0)
{
getLogManager() << Kernel::LogLevel_Warning <<
"Channel ratio must be in [0;1] (0 for no reconstruction, 1 for no limit). Setting is set to 1. \n";
box.setSettingValue(index, "1");
}
}
else if (index == 4)
{
CString tmp;
box.getSettingValue(index, tmp);
double rejection = 0.0;
std::stringstream ss(tmp.toASCIIString());
ss >> rejection;
if (rejection < 0.0)
{
getLogManager() << Kernel::LogLevel_Warning << "Rejection limit must be positive. Setting is set to 0. \n";
box.setSettingValue(index, "0");
}
}
return true;
}
//---------------------------------------------------------------------------------------------------
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,117 @@
///-------------------------------------------------------------------------------------------------
///
/// \file CBoxAlgorithmASRProcessor.hpp
/// \brief Classes of the box ASR Processor.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 08/12/2020.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "defines.hpp"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <geometry/artifacts/CASR.hpp>
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//-------------------------------------------------------------------------------------------------
/// <summary> The class CBoxAlgorithmASRTrainer describes the box Artifact Subspace Reconstruction (ASR) Trainer. </summary>
class CBoxAlgorithmASRTrainer final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, ClassId_Box_ASR_Trainer)
protected:
//***** Codecs *****
Toolkit::TStimulationDecoder<CBoxAlgorithmASRTrainer> m_stimulationDecoder; ///< Input Stimulation Decoder
Toolkit::TSignalDecoder<CBoxAlgorithmASRTrainer> m_signalEncoder; ///< Input Signal Encoder
Toolkit::TStimulationEncoder<CBoxAlgorithmASRTrainer> m_stimulationEncoder; ///< Output Stimulation Encoder
//***** Pointers *****
CMatrix* m_iMatrix = nullptr; ///< Input Matrix pointer
IStimulationSet *m_iStimulation = nullptr, ///< Stimulation receiver
*m_oStimulation = nullptr; ///< Stimulation sender
//***** Settings *****
std::string m_filename; ///< Filename of ASR Model
uint64_t m_stimulationName = OVTK_StimulationId_Train; ///< Name of stimulation to check for train launch
Geometry::EMetric m_metric = Geometry::EMetric::Euclidian; ///< Metric for ASR
double m_ratio = 1.0; ///< Ratio of channel to reconstruct for ASR
double m_rejection = 5.0; ///< Rejection limit of threshold for ASR
//***** Misc *****
std::vector<Eigen::MatrixXd> m_dataset; ///< Dataset stack
bool m_isTrain = false; ///< <c>True</c> if train is already done, <c>False</c> otherwise
bool train();
};
//-------------------------------------------------------------------------------------------------
/// <summary> Listener of the box Artifact Subspace Reconstruction (ASR) Trainer. </summary>
class CBoxAlgorithmASRTrainerListener final : public Toolkit::TBoxListener<IBoxListener>
{
public:
bool onSettingValueChanged(Kernel::IBox& box, const size_t index) override;;
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, OV_UndefinedIdentifier)
};
//-------------------------------------------------------------------------------------------------
/// <summary> Descriptor of the box Artifact Subspace Reconstruction (ASR) Trainer. </summary>
class CBoxAlgorithmASRTrainerDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return "ASR Trainer"; }
CString getAuthorName() const override { return "Thibaut Monseigne"; }
CString getAuthorCompanyName() const override { return "Inria"; }
CString getShortDescription() const override { return "Artifact Subspace Reconstruction (ASR) Trainer."; }
CString getDetailedDescription() const override { return "Artifact Subspace Reconstruction (ASR) Trainer."; }
CString getCategory() const override { return "Artifact"; }
CString getVersion() const override { return "0.1"; }
CString getStockItemName() const override { return "gtk-execute"; }
CIdentifier getCreatedClass() const override { return ClassId_Box_ASR_Trainer; }
IPluginObject* create() override { return new CBoxAlgorithmASRTrainer; }
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmASRTrainerListener; }
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Stimulations",OV_TypeId_Stimulations);
prototype.addInput("Input Signal", OV_TypeId_Signal);
prototype.addOutput("Train-completed Flag",OV_TypeId_Stimulations);
prototype.addSetting("Filename to save model", OV_TypeId_Filename, "${Player_ScenarioDirectory}/ASR-model.xml");
prototype.addSetting("Train trigger", OV_TypeId_Stimulation, "OVTK_StimulationId_Train");
prototype.addSetting("Metric", TypeId_Metric, toString(Geometry::EMetric::Euclidian).c_str());
prototype.addSetting("Channel ratio to reconstruct", OV_TypeId_Float, "1");
prototype.addSetting("Rejection limit", OV_TypeId_Float, "5");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, ClassId_Box_ASR_Trainer_Desc)
};
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,92 @@
#include "CBoxAlgorithmArtifactAmplitude.hpp"
#include <cmath> // Floor
#include <sstream>
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmArtifactAmplitude::initialize()
{
//***** Codecs *****
m_decoder.initialize(*this, 0);
m_iMatrix = m_decoder.getOutputMatrix();
//***** Settings *****
m_max = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
//***** Assert *****
OV_ERROR_UNLESS_KRF(m_max > 0, "Invalid Maximum [" << m_max << "] (expected value > 0)\n", Kernel::ErrorType::BadSetting);
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmArtifactAmplitude::uninitialize()
{
m_decoder.uninitialize();
std::stringstream ss;
ss << m_nArtifact << " artifacts detected in " << m_nSamples << " samples (";
ss.precision(2);
ss << std::fixed << 100.0 * double(m_nArtifact) / double(m_nSamples) << "%)" << std::endl;
this->getLogManager() << Kernel::LogLevel_Info << ss.str();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmArtifactAmplitude::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmArtifactAmplitude::process()
{
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
{
bool artifact = false;
m_decoder.decode(i); // Decode chunk
OV_ERROR_UNLESS_KRF(m_iMatrix->getDimensionCount() == 2, "Invalid Input Signal", Kernel::ErrorType::BadInput);
m_nSamples++;
//if (m_decoder.isHeaderReceived()) {} // Header
if (m_decoder.isBufferReceived()) // Buffer
{
const size_t size = m_iMatrix->getDimensionSize(0) * m_iMatrix->getDimensionSize(1); // get buffer size
const double* iBuffer = m_iMatrix->getBuffer(); // input buffer
for (size_t idx = 0; idx < size; ++idx)
{
if (abs(iBuffer[idx]) >= m_max) // Amplitude comparison
{
this->getLogManager() << Kernel::LogLevel_Trace << "Artifact detected in channel (" << floor(idx / m_iMatrix->getDimensionSize(1)) << ")\n";
artifact = true;
m_nArtifact++;
break;
}
}
}
//if (m_decoder.isEndReceived()) {} // End
// We don't need output codec we copy just the input to the output if there is no amplitude artifact
if (!artifact)
{
uint64_t tStart = 0, tEnd = 0;
size_t size = 0;
const uint8_t* buffer = nullptr;
boxContext.getInputChunk(0, i, tStart, tEnd, size, buffer);
boxContext.appendOutputChunkData(0, buffer, size);
boxContext.markOutputAsReadyToSend(0, tStart, tEnd);
boxContext.markInputAsDeprecated(0, i);
}
}
return true;
}
//---------------------------------------------------------------------------------------------------
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,82 @@
///-------------------------------------------------------------------------------------------------
///
/// \file CBoxAlgorithmArtifactAmplitude.hpp
/// \brief Classes of the box Artifact Amplitude.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 12/08/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "defines.hpp"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//-------------------------------------------------------------------------------------------------
/// <summary> The class CBoxAlgorithmArtifactAmplitude describes the box Artifact Amplitude. </summary>
class CBoxAlgorithmArtifactAmplitude final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, ClassId_Box_Artifact_Amplitude)
protected:
Toolkit::TSignalDecoder<CBoxAlgorithmArtifactAmplitude> m_decoder; ///< Input Signal decoder
CMatrix* m_iMatrix = nullptr; ///< Input Matrix pointer
double m_max = 0; ///< Amplitude max
size_t m_nSamples = 0, ///< Sample checked
m_nArtifact = 0; ///< Artifact found
};
//-------------------------------------------------------------------------------------------------
/// <summary> Descriptor of the box Artifact Detector. </summary>
class CBoxAlgorithmArtifactAmplitudeDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return "Artifact Amplitude"; }
CString getAuthorName() const override { return "Thibaut Monseigne"; }
CString getAuthorCompanyName() const override { return "Inria"; }
CString getShortDescription() const override { return "Simple Artifact Detection"; }
CString getDetailedDescription() const override
{
return "Check if one element is higher than Max setting.\nThe signal is returned if no element exceeds the defined value.";
}
CString getCategory() const override { return "Artifact"; }
CString getVersion() const override { return "1.0"; }
CString getStockItemName() const override { return "gtk-no"; }
CIdentifier getCreatedClass() const override { return ClassId_Box_Artifact_Amplitude; }
IPluginObject* create() override { return new CBoxAlgorithmArtifactAmplitude; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Signal",OV_TypeId_Signal);
prototype.addOutput("Non-artifact signal",OV_TypeId_Signal);
prototype.addSetting("Max (mV)",OV_TypeId_Float, "100");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, ClassId_Box_Artifact_Amplitude_Desc)
};
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,25 @@
///-------------------------------------------------------------------------------------------------
///
/// \file defines.hpp
/// \brief Defines list for Setting, Shortcut Macro and const.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 08/12/2020.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
// Boxes
//---------------------------------------------------------------------------------------------------
#define ClassId_Box_Artifact_Amplitude OpenViBE::CIdentifier(0x41727469, 0xb68095e4)
#define ClassId_Box_Artifact_Amplitude_Desc OpenViBE::CIdentifier(0x41727469, 0x83596875)
#define ClassId_Box_ASR_Processor OpenViBE::CIdentifier(0x41727469, 0x17f1c6e2)
#define ClassId_Box_ASR_Processor_Desc OpenViBE::CIdentifier(0x41727469, 0x1de22c87)
#define ClassId_Box_ASR_Trainer OpenViBE::CIdentifier(0x41727469, 0xc05f38ff)
#define ClassId_Box_ASR_Trainer_Desc OpenViBE::CIdentifier(0x41727469, 0x966737cb)
#ifndef TypeId_Metric
#define TypeId_Metric OpenViBE::CIdentifier(0x5261636B, 0x4D455452)
#endif
@@ -0,0 +1,37 @@
#include <openvibe/ov_all.h>
#include "defines.hpp"
// Boxes Includes
#include "boxes/CBoxAlgorithmArtifactAmplitude.hpp"
#include "boxes/CBoxAlgorithmASRTrainer.hpp"
#include "boxes/CBoxAlgorithmASRProcessor.hpp"
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
template <typename T>
static void setEnumeration(const Kernel::IPluginModuleContext& context, const CIdentifier& typeID, const std::string& name, const std::vector<T>& enumeration)
{
context.getTypeManager().registerEnumerationType(typeID, name.c_str());
for (const auto& e : enumeration) { context.getTypeManager().registerEnumerationEntry(typeID, toString(e).c_str(), size_t(e)); }
}
OVP_Declare_Begin()
// Register boxes
OVP_Declare_New(CBoxAlgorithmArtifactAmplitudeDesc);
OVP_Declare_New(CBoxAlgorithmASRTrainerDesc);
OVP_Declare_New(CBoxAlgorithmASRProcessorDesc);
// Enumeration Metric
const std::vector<Geometry::EMetric> metrics = {
Geometry::EMetric::Riemann, Geometry::EMetric::Euclidian, Geometry::EMetric::LogEuclidian, Geometry::EMetric::LogDet,
Geometry::EMetric::Kullback, Geometry::EMetric::Harmonic, Geometry::EMetric::Identity
};
setEnumeration(context, TypeId_Metric, "Metric", metrics);
OVP_Declare_End()
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,120 @@
#include "utils/misc.hpp"
//*****************************************************
//******************** CONVERSIONS ********************
//*****************************************************
//---------------------------------------------------------------------------------------------------
bool MatrixConvert(const OpenViBE::CMatrix& in, Eigen::MatrixXd& out)
{
if (in.getDimensionCount() != 2) { return false; }
out.resize(in.getDimensionSize(0), in.getDimensionSize(1));
// double loop to avoid the problem of row major and column major storage
size_t idx = 0;
const double* buffer = in.getBuffer();
for (size_t i = 0, nR = out.rows(); i < nR; ++i) { for (size_t j = 0, nC = out.cols(); j < nC; ++j) { out(i, j) = buffer[idx++]; } }
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool MatrixConvert(const Eigen::MatrixXd& in, OpenViBE::CMatrix& out)
{
if (in.rows() == 0 || in.cols() == 0) { return false; }
const size_t nR = in.rows(), nC = in.cols();
MatrixResize(out, nR, nC);
// double loop to avoid the problem of row major and column major storage
size_t idx = 0;
double* buffer = out.getBuffer();
for (size_t i = 0; i < nR; ++i) { for (size_t j = 0; j < nC; ++j) { buffer[idx++] = in(i, j); } }
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool MatrixConvert(const Eigen::RowVectorXd& in, OpenViBE::CMatrix& out)
{
if (in.size() == 0) { return false; }
VectorResize(out, in.size());
//one row system copy doesn't cause problem
memcpy(out.getBuffer(), in.data(), out.getBufferElementCount() * sizeof(double));
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool MatrixConvert(const OpenViBE::CMatrix& in, Eigen::RowVectorXd& out)
{
if (in.getDimensionCount() != 1) { return false; }
out.resize(in.getDimensionSize(0));
//one row system copy doesn't cause problem
memcpy(out.data(), in.getBuffer(), in.getBufferElementCount() * sizeof(double));
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool MatrixConvert(const std::vector<double>& in, OpenViBE::CMatrix& out)
{
if (in.empty()) { return false; }
VectorResize(out, in.size());
//one row system copy doesn't cause problem
memcpy(out.getBuffer(), in.data(), out.getBufferElementCount() * sizeof(double));
return true;
}
//---------------------------------------------------------------------------------------------------
//***********************************************************
//******************** MATRIX MANAGEMENT ********************
//***********************************************************
//---------------------------------------------------------------------------------------------------
bool MatrixInit(OpenViBE::CMatrix& m, const size_t rows, size_t columns)
{
if (columns < 1) { columns = rows; }
MatrixResize(m, rows, columns);
m.resetBuffer(); // Set to 0
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool MatrixResize(OpenViBE::CMatrix& m, const size_t rows, size_t columns)
{
if (columns < 1) { columns = rows; }
if (m.getDimensionCount() != 2 || m.getDimensionSize(0) != rows || m.getDimensionSize(1) != columns)
{
m.setDimensionCount(2);
m.setDimensionSize(0, rows);
m.setDimensionSize(1, columns);
// CHange label to have 1 to N label on row and column (Square Matrix Feature)
for (size_t i = 0; i < rows; ++i) { m.setDimensionLabel(0, i, std::to_string(i + 1).c_str()); }
}
return true;
}
//---------------------------------------------------------------------------------------------------
//***********************************************************
//******************** VECTOR MANAGEMENT ********************
//***********************************************************
//---------------------------------------------------------------------------------------------------
bool VectorInit(OpenViBE::CMatrix& m, const size_t n)
{
VectorResize(m, n);
m.resetBuffer(); // Set to 0
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool VectorResize(OpenViBE::CMatrix& m, const size_t n)
{
if (m.getDimensionCount() != 1 || m.getDimensionSize(0) != n)
{
m.setDimensionCount(1);
m.setDimensionSize(0, n);
}
return true;
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,71 @@
///-------------------------------------------------------------------------------------------------
///
/// \file misc.hpp
/// \brief All functions to Convert OpenViBE::CMatrix and Eigen::MatrixXd, links to Eigen function, manipulate OpenVibe::CMatrix and more.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 26/10/2018.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include <openvibe/ov_all.h>
#include <Eigen/Dense>
//*****************************************************
//******************** Conversions ********************
//*****************************************************
/// <summary> Convert OpenViBE Matrix to Eigen Matrix. </summary>
/// <param name="in"> The Eigen Matrix. </param>
/// <param name="out"> The OpenVibe Matrix. </param>
bool MatrixConvert(const OpenViBE::CMatrix& in, Eigen::MatrixXd& out);
/// <summary> Convert Eigen Matrix to OpenViBE Matrix (It doesn't use Memory::copy because of Eigne store in column major by default). </summary>
/// <param name="in"> The Eigen Matrix. </param>
/// <param name="out"> The OpenVibe Matrix. </param>
bool MatrixConvert(const Eigen::MatrixXd& in, OpenViBE::CMatrix& out);
/// <summary> Convert Eigen Row Vector to OpenViBE Matrix with one dimension. </summary>
/// <param name="in"> The Eigen Row Vector. </param>
/// <param name="out"> The OpenVibe Matrix. </param>
bool MatrixConvert(const Eigen::RowVectorXd& in, OpenViBE::CMatrix& out);
/// <summary> Convert OpenViBE Matrix with one dimension to Eigen Row Vector. </summary>
/// <param name="in"> The OpenVibe Matrix. </param>
/// <param name="out"> The Eigen Row Vector. </param>
bool MatrixConvert(const OpenViBE::CMatrix& in, Eigen::RowVectorXd& out);
/// <summary> Convertvector double to OpenViBE Matrix with one dimension. </summary>
/// <param name="in"> The Vector of double. </param>
/// <param name="out"> The OpenVibe Matrix. </param>
bool MatrixConvert(const std::vector<double>& in, OpenViBE::CMatrix& out);
//***********************************************************
//******************** Matrix Management ********************
//***********************************************************
/// <summary>Initialize the matrix (do not create objects).</summary>
/// <param name="m">The matrix to initialize.</param>
/// <param name="rows">The number of rows.</param>
/// <param name="columns">The number of columns (if &lt; 1 Init to a Square Matrix) .</param>
bool MatrixInit(OpenViBE::CMatrix& m, size_t rows = 2, size_t columns = 0);
/// <summary>Resize the matrix (do not create objects).</summary>
/// <param name="m">The matrix to resize.</param>
/// <param name="rows">The number of rows.</param>
/// <param name="columns">The number of columns (if &lt; 1 resize to a Square Matrix) .</param>
bool MatrixResize(OpenViBE::CMatrix& m, size_t rows = 2, size_t columns = 0);
//***********************************************************
//******************** Vector Management ********************
//***********************************************************
/// <summary>Initialize the vector (matrix with one dimension) (do not create objects).</summary>
/// <param name="m">The vector to initialize.</param>
/// <param name="n">The number of elements.</param>
bool VectorInit(OpenViBE::CMatrix& m, size_t n = 2);
/// <summary>Resize the vector (matrix with one dimension) (do not create objects).</summary>
/// <param name="m">The vector to resize.</param>
/// <param name="n">The number of elements.</param>
bool VectorResize(OpenViBE::CMatrix& m, size_t n = 2);