init
This commit is contained in:
+101
@@ -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
|
||||
+88
@@ -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
|
||||
+182
@@ -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
|
||||
+117
@@ -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
|
||||
+92
@@ -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
|
||||
+82
@@ -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
|
||||
Reference in New Issue
Block a user