Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Showing
with 1144 additions and 1298 deletions
File added
File added
File added
<group>
<0>100</0>
<1>0</1>
<2>44</2>
<3>0</3>
<4>100</4>
<5>0</5>
<6>45</6>
<7>0</7>
<8>100</8>
<9>0</9>
<10>45</10>
<11>0</11>
</group>
#include "ofMain.h"
#include "ofApp.h"
//========================================================================
int main( ){
ofSetupOpenGL(1024,768,OF_WINDOW); // <-------- setup the GL context
// this kicks off the running of my app
// can be OF_WINDOW or OF_FULLSCREEN
// pass in width and height too:
ofRunApp(new ofApp());
}
#include <array>
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
myo.setup();
//gui
probsClear.addListener(this, &ofApp::probsClearPressed);
resetModel.addListener(this, &ofApp::resetModelPressed);
guiTong.setup("tong");
guiTong.add(tong0.setup("1", 50, 0, 100));
guiTong.add(tong1.setup("2", 0, 0, 100));
guiTong.add(tong2.setup("3", 90, 0, 100));
guiTong.add(tong3.setup("4", 0, 0, 100));
guiTong.add(tong4.setup("5", 90, 0, 100));
guiTong.add(tong5.setup("6", 0, 0, 100));
guiTong.add(tong6.setup("7", 0, 0, 100));
guiTong.add(tong7.setup("8", 60, 0, 100));
guiTong.add(tong8.setup("9", 0, 0, 100));
guiTong.add(tong9.setup("10", 90, 0, 100));
guiTong.add(tong10.setup("11", 0, 0, 100));
guiTong.add(tong11.setup("12", 0, 0, 100));
ofColor green(0, 255, 0);
guiTong.setHeaderBackgroundColor(green);
guiThung.setup("thung", "thung", 250, 10);
guiThung.add(thung0.setup("1", 100, 0, 100));
guiThung.add(thung1.setup("2", 0, 0, 100));
guiThung.add(thung2.setup("3", 10, 0, 100));
guiThung.add(thung3.setup("4", 0, 0, 100));
guiThung.add(thung4.setup("5", 60, 0, 100));
guiThung.add(thung5.setup("6", 0, 0, 100));
guiThung.add(thung6.setup("7", 10, 0, 100));
guiThung.add(thung7.setup("8", 0, 0, 100));
guiThung.add(thung8.setup("9", 60, 0, 100));
guiThung.add(thung9.setup("10", 0, 0, 100));
guiThung.add(thung10.setup("11", 30, 0, 100));
guiThung.add(thung11.setup("12", 0, 0, 100));
ofColor yellow(255, 255, 0);
guiThung.setHeaderBackgroundColor(yellow);
guiGeneral.setup("general", "general", 500, 10);
guiGeneral.add(gain.setup("gain", 1., 0., 1.));
guiGeneral.add(modelControl.setup("run model", false));
guiGeneral.add(resetModel.setup("reset model"));
guiGeneral.add(inputDevice.setup("myo", false));
guiGeneral.add(probsClear.setup("clear"));
//This will make life easier later
allSliders.push_back(tong0);
allSliders.push_back(tong1);
allSliders.push_back(tong2);
allSliders.push_back(tong3);
allSliders.push_back(tong4);
allSliders.push_back(tong5);
allSliders.push_back(tong6);
allSliders.push_back(tong7);
allSliders.push_back(tong8);
allSliders.push_back(tong9);
allSliders.push_back(tong10);
allSliders.push_back(tong11);
allSliders.push_back(thung0);
allSliders.push_back(thung1);
allSliders.push_back(thung2);
allSliders.push_back(thung3);
allSliders.push_back(thung4);
allSliders.push_back(thung5);
allSliders.push_back(thung6);
allSliders.push_back(thung7);
allSliders.push_back(thung8);
allSliders.push_back(thung9);
allSliders.push_back(thung10);
allSliders.push_back(thung11);
//RapidLib
trained = false;
//loading samples
saron_sbpl1.load(ofToDataPath("saron-sbpl1.wav"));
saron_sbpl2.load(ofToDataPath("saron-sbpl2.wav"));
saron_sbpl3.load(ofToDataPath("saron-sbpl3.wav"));
saron_sbpl4.load(ofToDataPath("saron-sbpl4.wav"));
saron_sbpl5.load(ofToDataPath("saron-sbpl5.wav"));
ciblon_tong.load(ofToDataPath("drums-ciblon-medium-tong.wav"));
ciblon_thung.load(ofToDataPath("drums-ciblon-medium-thung.wav"));
//maxi Clock
myClock.setTicksPerBeat(4);//This sets the number of ticks per beat
myClock.setTempo(120);// This sets the tempo in Beats Per Minute
//audio setup
sampleRate = 44100;
bufferSize = 512;
ofxMaxiSettings::setup(sampleRate, 2, initialBufferSize);
ofSoundStreamSetup(2,2,this, sampleRate, bufferSize, 4);
}
//--------------------------------------------------------------
void ofApp::update(){
if (inputDevice) { //Only when Myo is toggled on
//Simple gain control
float emg = myo.getDevices()[0]->getEmgSamples()[4];
streamBuf.pushToWindow(double(emg));
gain = streamBuf.rms() * 0.01;
//Machine learning with quarternions
double myoX = myo.getDevices()[0]->getQuaternion().x();
double myoY = myo.getDevices()[0]->getQuaternion().y();
double myoZ = myo.getDevices()[0]->getQuaternion().z();
double myoW = myo.getDevices()[0]->getQuaternion().w();
if (inputDevice) {
if (recordingState > 0) {
trainingExample tempExample;
tempExample.input = { myoX, myoY, myoZ, myoW };
for (int i = 0; i < allSliders.size() ; ++i) {
tempExample.output.push_back(double(allSliders[i]));
}
trainingSet.push_back(tempExample);
} else if (trained && modelControl == 1) {
std::vector<double> inputVec;
inputVec.push_back(myoX);
inputVec.push_back(myoY);
inputVec.push_back(myoZ);
inputVec.push_back(myoW);
std::vector<double> output = myNN.run(inputVec);
for (int i = 0; i < output.size(); ++i) {
allSliders[i] = int(output[i]);
}
}
}
}
}
//--------------------------------------------------------------
void ofApp::exit(){
myo.stop();
}
//--------------------------------------------------------------
void ofApp::draw(){
//ofClear(0);
ofDrawBitmapString(currentBeat, 100, 300);
ofDrawBitmapString("Hold space to record", 200, 300);
guiTong.draw();
guiThung.draw();
guiGeneral.draw();
if (inputDevice) {
ofSetColor(255);
for ( int i=0; i<myo.getDevices().size(); i++ ) {
stringstream s;
s << "id: " << myo.getDevices()[i]->getId() << endl;
s << "which: " << myo.getDevices()[i]->getWhichArm() << endl;
s << "pose: " << myo.getDevices()[i]->getPose() << endl;
s << "accel: ";
s << myo.getDevices()[i]->getAccel().x << ",";
s << myo.getDevices()[i]->getAccel().y << ",";
s << myo.getDevices()[i]->getAccel().z << endl;
s << "gyro: ";
s << myo.getDevices()[i]->getGyro().x << ",";
s << myo.getDevices()[i]->getGyro().y << ",";
s << myo.getDevices()[i]->getGyro().z << endl;
s << "quaternion: ";
s << myo.getDevices()[i]->getQuaternion().x() << ",";
s << myo.getDevices()[i]->getQuaternion().y() << ",";
s << myo.getDevices()[i]->getQuaternion().z() << ",";
s << myo.getDevices()[i]->getQuaternion().w() << endl;
s << "roll/pitch/yaw: ";
s << myo.getDevices()[i]->getRoll() << ",";
s << myo.getDevices()[i]->getPitch() << ",";
s << myo.getDevices()[i]->getYaw() << endl;
s << "raw data: ";
for ( int j=0; j<8; j++ ) {
s << myo.getDevices()[i]->getEmgSamples()[j];
s << ",";
}
s << endl;
ofSetColor(0);
ofDrawBitmapString(s.str(), 10, 400 + i*100);
}
}
}
//--------------------------------------------------------------
void ofApp::probsClearPressed() {
std::cout << "clearing probs" << std::endl;
for (int i = 0; i < allSliders.size(); ++i) {
allSliders[i] = 0;
}
}
//--------------------------------------------------------------
void ofApp::resetModelPressed() {
std::cout << "resetting models" << std::endl;
myNN.reset();
trainingSet.clear();
modelControl = false;
}
//--------------------------------------------------------------
bool eventTest(int prob) {
int testRand = rand() % 100;
if (testRand < prob) {
return true;
}
return false;
}
//--------------------------------------------------------------
void ofApp::audioOut(float * output, int bufferSize, int nChannels) {
//probs = { tong0, tong1, tong2, tong3, tong4, tong5, tong6, tong7, tong8, tong9, tong10, tong11 };
//probs2 = { thung0, thung1, thung2, thung3, thung4, thung5, thung6, thung7, thung8, thung9, thung10, thung11 };
bool beatsTong[12];
bool beats2[12];
for (int i = 0; i < 12; ++i) {
beatsTong[i] = eventTest(allSliders[i]);
beats2[i] = eventTest(allSliders[i + 12]);
}
int lastCount = 0;
int testMe = 0;
for (int i = 0; i < bufferSize; i++){
myClock.ticker();
if (myClock.tick) {
if (beatsTong[currentBeat]) {
ciblon_tong.trigger();
}
if (beats2[currentBeat]) {
ciblon_thung.trigger();
}
currentBeat = (currentBeat + 1) % 12;
}
outputs[0] = ciblon_tong.playOnce() * gain;
outputs[1] = ciblon_thung.playOnce() * gain;
output[i*nChannels ] = outputs[0];
output[i*nChannels + 1] = outputs[1];
}
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key){
//std::cout << "key: " << key << std::endl;
switch(key) {
case 32:
recordingState = 1;
break;
case 13:
modelControl = (modelControl) ? false : true;
break;
}
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key){
recordingState = 0;
if (trainingSet.size() > 0) {
trained = myNN.train(trainingSet);
std::cout << "trained: " << trained << std::endl;
}
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){
if (inputDevice == false) { //don't do this with Myo is on
if (recordingState > 0) {
trainingExample tempExample;
tempExample.input = { double(x), double(y) };
for (int i = 0; i < allSliders.size() ; ++i) {
tempExample.output.push_back(double(allSliders[i]));
}
trainingSet.push_back(tempExample);
} else if (trained && modelControl == 1) {
std::vector<double> inputVec;
inputVec.push_back(double(x));
inputVec.push_back(double(y));
std::vector<double> output = myNN.run(inputVec);
for (int i = 0; i < output.size(); ++i) {
allSliders[i] = int(output[i]);
}
}
}
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){
}
#pragma once
#include <vector>
#include "ofMain.h"
#include "ofxGui.h"
#include "ofxMyo.h"
#include "ofxMaxim.h"
#include "regression.h"
#include "rapidStream.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void exit();
void keyPressed(int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseEntered(int x, int y);
void mouseExited(int x, int y);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
void probsClearPressed();
void resetModelPressed();
ofxIntSlider thung0, thung1, thung2, thung3;
ofxIntSlider thung4, thung5, thung6, thung7;
ofxIntSlider thung8, thung9, thung10, thung11;
std::vector<ofxIntSlider> thungs;
ofxPanel guiThung;
ofxIntSlider tong0, tong1, tong2, tong3;
ofxIntSlider tong4, tong5, tong6, tong7;
ofxIntSlider tong8, tong9, tong10, tong11;
ofxPanel guiTong;
ofxFloatSlider gain;
ofxToggle inputDevice;
ofxToggle modelControl;
ofxButton resetModel;
ofxButton probsClear;
ofxPanel guiGeneral;
std::vector<ofxIntSlider> allSliders;
//Maxi
void audioOut(float * output, int bufferSize, int nChannels);
//void audioIn(float * input, int bufferSize, int nChannels);
int bufferSize;
int initialBufferSize;
int sampleRate;
private:
ofxMyo::Myo myo;
//---------Maxi---------------//
double outputs[2];
maxiSample saron_sbpl1;
maxiSample saron_sbpl2;
maxiSample saron_sbpl3;
maxiSample saron_sbpl4;
maxiSample saron_sbpl5;
maxiSample ciblon_tong;
maxiSample ciblon_thung;
maxiClock myClock;
int currentBeat;
//---------RapidLib---------------//
regression myNN;
std::vector<trainingExample> trainingSet;
int recordingState;
bool trained;
rapidStream streamBuf = rapidStream(25);
};
#!/bin/bash
#Make sure we've got the latest version
git pull
git submodule update --init --recursive
rm -rf build/
mkdir build
cd build
cmake ..
make
./rapidmixTest
cp ./helloRapidMix ../examples/HelloRapidMix/helloRapidMix
\ No newline at end of file
/*
* machineLearning.cpp
* Created by Michael Zbyszynski on 10 Jan 2016
/**
* @file machineLearning.cpp
* @author Michael Zbyszynski
* @date 10 Jan 2016
* @copyright
* Copyright © 2017 Goldsmiths. All rights reserved.
*/
#include "machineLearning.h"
RAPIDMIX_BEGIN_NAMESPACE
void trainingData2rapidLib (const trainingData &newTrainingData, std::vector<trainingExample> &trainingSet) {
for (int h = 0; h < newTrainingData.trainingSet.size(); ++h) { //Go through every phrase
for (int i = 0; i < newTrainingData.trainingSet[h].elements.size(); ++i) { //...and every element
trainingExample tempExample;
tempExample.input = newTrainingData.trainingSet[h].elements[i].input;
if (newTrainingData.trainingSet[h].elements[i].output.size() > 0) {
tempExample.output = newTrainingData.trainingSet[h].elements[i].output;
} else {
tempExample.output.push_back(double(h));
namespace rapidmix {
//////////////////////////////////////////////////////////////////////// Generic train
template <class MachineLearningModule>
bool machineLearning<MachineLearningModule>::train(const trainingData &newTrainingData) {
return MachineLearningModule::train(newTrainingData);
}
/////////////////////////////////////////////////////////////////////// RapidLib specializations
void trainingData2rapidLib (const trainingData &newTrainingData, std::vector<trainingExample> &trainingSet) {
for (int h = 0; h < newTrainingData.trainingSet.size(); ++h) { //Go through every phrase
for (int i = 0; i < newTrainingData.trainingSet[h].elements.size(); ++i) { //...and every element
trainingExample tempExample;
tempExample.input = newTrainingData.trainingSet[h].elements[i].input;
if (newTrainingData.trainingSet[h].elements[i].output.size() > 0) {
tempExample.output = newTrainingData.trainingSet[h].elements[i].output;
} else {
tempExample.output.push_back(double(h));
}
trainingSet.push_back(tempExample);
}
trainingSet.push_back(tempExample);
}
};
/////////////////////////////////////////////////////////////////////// RapidLib classification
template<>
bool machineLearning<classification>::train(const trainingData &newTrainingData) {
std::vector<trainingExample> trainingSet;
labels.clear();
for (int i = 0; i < newTrainingData.trainingSet.size(); ++i) {
labels.push_back(newTrainingData.trainingSet[i].label);
}
trainingData2rapidLib(newTrainingData, trainingSet);
return classification::train(trainingSet);
}
};
template<>
bool machineLearning<classification>::train(const trainingData &newTrainingData) {
std::vector<trainingExample> trainingSet;
labels.clear();
for (int i = 0; i < newTrainingData.trainingSet.size(); ++i) {
labels.push_back(newTrainingData.trainingSet[i].label);
template<>
std::string machineLearning<classification>::run(const std::vector<double> &inputVector, const std::string &label) {
int classIndex = classification::run(inputVector)[0];
return labels[classIndex];
};
/////////////////////////////////////////////////////////////////////// RapidLib regression
template<>
bool machineLearning<regression>::train(const trainingData &newTrainingData) {
std::vector<trainingExample> trainingSet;
trainingData2rapidLib(newTrainingData, trainingSet);
return regression::train(trainingSet);
}
trainingData2rapidLib(newTrainingData, trainingSet);
return classification::train(trainingSet);
}
template<>
bool machineLearning<regression>::train(const trainingData &newTrainingData) {
std::vector<trainingExample> trainingSet;
trainingData2rapidLib(newTrainingData, trainingSet);
return regression::train(trainingSet);
}
template<>
bool machineLearning<seriesClassification>::train(const trainingData &newTrainingData) {
std::vector<trainingSeries> seriesSet;
for (int i = 0; i < newTrainingData.trainingSet.size(); ++i) { //each phrase
trainingSeries tempSeries;
tempSeries.label = newTrainingData.trainingSet[i].label;
for (int j = 0; j < newTrainingData.trainingSet[i].elements.size(); ++j) { //each element
tempSeries.input.push_back(newTrainingData.trainingSet[i].elements[j].input);
/////////////////////////////////////////////////////////////////////// RapidLib seriesClassification
template<>
bool machineLearning<seriesClassification>::train(const trainingData &newTrainingData) {
std::vector<trainingSeries> seriesSet;
for (int i = 0; i < newTrainingData.trainingSet.size(); ++i) { //each phrase
trainingSeries tempSeries;
tempSeries.label = newTrainingData.trainingSet[i].label;
for (int j = 0; j < newTrainingData.trainingSet[i].elements.size(); ++j) { //each element
tempSeries.input.push_back(newTrainingData.trainingSet[i].elements[j].input);
}
seriesSet.push_back(tempSeries);
}
seriesSet.push_back(tempSeries);
return seriesClassification::train(seriesSet);
}
template<>
std::string machineLearning<seriesClassification>::run(const std::vector<std::vector<double> > &inputSeries) {
return seriesClassification::run(inputSeries);
}
/////////////////////////////////////////////////////////////////////// GVF
template<>
bool machineLearning<rapidGVF>::train(const trainingData &newTrainingData) {
return rapidGVF::train(newTrainingData);
}
return seriesClassification::trainLabel(seriesSet);
}
template<>
bool machineLearning<rapidGVF>::train(const trainingData &newTrainingData) {
return rapidGVF::train(newTrainingData);
}
///Generic train
template <class MachineLearningModule>
bool machineLearning<MachineLearningModule>::train(const trainingData &newTrainingData) {
return MachineLearningModule::train(newTrainingData);
}
template<>
std::string machineLearning<classification>::run(const std::vector<double> &inputVector, const std::string &label) {
int classIndex = classification::run(inputVector)[0];
return labels[classIndex];
};
template<>
std::string machineLearning<seriesClassification>::run(const std::vector<std::vector<double> > &inputSeries) {
return seriesClassification::runLabel(inputSeries);
}
RAPIDMIX_END_NAMESPACE
......@@ -10,107 +10,107 @@
#ifndef machineLearning_h
#define machineLearning_h
#include "rapidMix.h"
#include "trainingData.h"
#include <vector>
#include "../rapidmix.h"
////////// Include all of the machine learning algorithms here
#include "classification.h"
#include "regression.h"
#include "seriesClassification.h"
#include "rapidXMM.h"
#include "rapidGVF.h"
#include "./rapidXMM/rapidXMM.h"
#include "./rapidGVF/rapidGVF.h"
// forward declaration
namespace rapidmix { class trainingData; }
RAPIDMIX_BEGIN_NAMESPACE
/** @brief A generic ouptut struct to fit all kinds of models */
typedef struct runResults_t {
std::vector<double> likelihoods;
std::vector<double> regression;
std::vector<double> progressions;
std::string likeliest;
} runResults;
/**
* @brief Host class for machine learning algorithms
*/
template <typename MachineLearningModule>
class machineLearning : public MachineLearningModule {
public:
namespace rapidmix {
//* Constructors */
machineLearning() : MachineLearningModule() {};
// forward declaration
class trainingData;
template<class T>
machineLearning(T type) : MachineLearningModule(type) {};
/** @brief A generic ouptut struct to fit all kinds of models */
typedef struct runResults_t {
std::vector<double> likelihoods;
std::vector<double> regression;
std::vector<double> progressions;
std::string likeliest;
} runResults;
/**
* @brief This function becomes specialized in the implementation
* @brief Host class for machine learning algorithms
*/
bool train(const trainingData &newTrainingData);
template <typename MachineLearningModule>
class machineLearning : public MachineLearningModule {
public:
//* Constructors */
machineLearning() : MachineLearningModule() {};
template<class T>
machineLearning(T type) : MachineLearningModule(type) {};
/**
* @brief This function becomes specialized in the implementation
*/
bool train(const trainingData &newTrainingData);
//* this function is not being specialized
std::vector<double> run(const std::vector<double> &inputVector) {
return MachineLearningModule::run(inputVector);
}
// This is a hack while I think about how to do this. -MZ //
std::string run(const std::vector<double> &inputVector, const std::string &label);
//* This is the one I'm using for DTW */
std::string run(const std::vector<std::vector<double> > &inputSeries);
bool reset() {
return MachineLearningModule::reset();
}
private:
MachineLearningModule module;
//this holds string labels
std::vector<std::string> labels; //FIXME: This probably should be pushed down into rapidLib?
std::string getLabel(int value);
};
//* this function is not being specialized
std::vector<double> run(const std::vector<double> &inputVector) {
return MachineLearningModule::run(inputVector);
}
////////// typedefs for calling different algorithms
// This is a hack while I think about how to do this. -MZ //
std::string run(const std::vector<double> &inputVector, const std::string &label);
///// RapidLib
//* This is the one I'm using for DTW */
std::string run(const std::vector<std::vector<double> > &inputSeries);
/** @brief static classification using KNN from RapidLib */
typedef machineLearning<classification> staticClassification;
bool reset() {
return MachineLearningModule::reset();
}
/** @brief static regression using Neural Networks from RapidLib */
typedef machineLearning<regression> staticRegression;
private:
MachineLearningModule module;
/** @brief temporal classification using Dynamic Time Warping from RapidLib */
typedef machineLearning<seriesClassification> dtwTemporalClassification;
//this holds string labels
std::vector<std::string> labels; //FIXME: This probably should be pushed down into rapidLib?
std::string getLabel(int value);
};
////////// typedefs for calling different algorithms
///// RapidLib
/** @brief static classification using KNN from RapidLib */
typedef machineLearning<classification> staticClassification;
/** @brief static regression using Neural Networks from RapidLib */
typedef machineLearning<regression> staticRegression;
/** @brief temporal classification using Dynamic Time Warping from RapidLib */
typedef machineLearning<seriesClassification> dtwTemporalClassification;
///// XMM
/** @brief configuration for XMM based algorithms */
typedef xmmToolConfig xmmConfig;
/** @brief static classification using Gaussian Mixture Models from XMM */
typedef machineLearning<rapidXmmGmm> xmmStaticClassification;
/** @brief static regression using Gaussian Mixture Models from XMM */
typedef machineLearning<rapidXmmGmr> xmmStaticRegression;
/** @brief temporal classification using Hierarchical Hidden Markov Models from XMM */
typedef machineLearning<rapidXmmHmm> xmmTemporalClassification;
/** @brief temporal regression using Hierarchical Hidden Markov Models from XMM */
typedef machineLearning<rapidXmmHmr> xmmTemporalRegression;
///// GVF
/** @brief temporal variation estimation using GVF library */
typedef machineLearning<rapidGVF> gvfTemporalVariation;
RAPIDMIX_END_NAMESPACE
///// XMM
/** @brief configuration for XMM based algorithms */
typedef xmmToolConfig xmmConfig;
/** @brief static classification using Gaussian Mixture Models from XMM */
typedef machineLearning<rapidXmmGmm> xmmStaticClassification;
/** @brief static regression using Gaussian Mixture Models from XMM */
typedef machineLearning<rapidXmmGmr> xmmStaticRegression;
/** @brief temporal classification using Hierarchical Hidden Markov Models from XMM */
typedef machineLearning<rapidXmmHmm> xmmTemporalClassification;
/** @brief temporal regression using Hierarchical Hidden Markov Models from XMM */
typedef machineLearning<rapidXmmHmr> xmmTemporalRegression;
///// GVF
/** @brief temporal variation estimation using GVF library */
typedef machineLearning<rapidGVF> gvfTemporalVariation;
}
#endif
......@@ -6,24 +6,17 @@
//
#include "rapidGVF.h"
#include "trainingData.h"
#include "../trainingData.h"
rapidGVF::rapidGVF()
{
// Initialised with default configuration
this->gvf = new GVF();
this->currentGesture = GVFGesture();
}
rapidGVF::rapidGVF() {}
rapidGVF::~rapidGVF()
{
delete this->gvf;
this->currentGesture = NULL;
}
rapidGVF::~rapidGVF() {}
bool rapidGVF::train(const rapidmix::trainingData &newTrainingData) {
bool rapidGVF::train(const rapidmix::trainingData &newTrainingData)
{
if (newTrainingData.trainingSet.size() < 1) {
if (newTrainingData.trainingSet.size() < 1)
{
// no recorded phrase
return false;
}
......@@ -33,54 +26,77 @@ bool rapidGVF::train(const rapidmix::trainingData &newTrainingData) {
return false;
}
if(gvf->getState() != GVF::STATE_LEARNING)
if(gvf.getState() != GVF::STATE_LEARNING)
{
gvf->setState(GVF::STATE_LEARNING);
gvf.setState(GVF::STATE_LEARNING);
}
//Go through every phrase
for (int h = 0; h < newTrainingData.trainingSet.size(); ++h) { //I changed this because the default set is gone. -MZ
this->gvf->startGesture();
for (int i = 0; i < newTrainingData.trainingSet[h].elements.size(); ++i) {
for (int h = 0; h < newTrainingData.trainingSet.size(); ++h)
{
gvf.startGesture();
for (int i = 0; i < newTrainingData.trainingSet[h].elements.size(); ++i)
{
std::vector<double> vd = newTrainingData.trainingSet[h].elements[i].input;
// Using template <class InputIterator> vector to change for vec<double> to vec<float>
std::vector<float> vf(vd.begin(), vd.end());
this->currentGesture.addObservation(vf);
}
this->gvf->addGestureTemplate(this->currentGesture);
gvf.addGestureTemplate(this->currentGesture);
}
return true;
}
std::vector<double> rapidGVF::run(const std::vector<double> &inputVector){
std::vector<double> rapidGVF::run(const std::vector<double> &inputVector)
{
if (inputVector.size() == 0) {
if (inputVector.size() == 0)
{
return std::vector<double>();
}
gvf->restart();
gvf.restart();
if(gvf->getState() != GVF::STATE_FOLLOWING)
if (gvf.getState() != GVF::STATE_FOLLOWING)
{
gvf->setState(GVF::STATE_FOLLOWING);
gvf.setState(GVF::STATE_FOLLOWING);
}
// Using template <class InputIterator> vector to change for vec<double> to vec<float>
std::vector<float> vf(inputVector.begin(),inputVector.end());
this->currentGesture.addObservation(vf);
this->outcomes = this->gvf->update(this->currentGesture.getLastObservation());
outcomes = gvf.update(this->currentGesture.getLastObservation());
std::vector<double> output;
output.push_back(this->outcomes.likeliestGesture);
output.insert(output.end(), this->outcomes.likelihoods.begin(), this->outcomes.likelihoods.end());
output.insert(output.end(), this->outcomes.alignments.begin(), this->outcomes.alignments.end());
// output.insert(output.end(), this->outcomes.dynamics.begin(), this->outcomes.dynamics.end());
// output.insert(output.end(), this->outcomes.scalings.begin(), this->outcomes.scalings.end());
// output.insert(output.end(), this->outcomes.rotations.begin(), this->outcomes.rotations.end());
//
output.push_back(outcomes.likeliestGesture);
output.insert(output.end(), outcomes.likelihoods.begin(), outcomes.likelihoods.end());
output.insert(output.end(), outcomes.alignments.begin(), outcomes.alignments.end());
return output;
}
const std::vector<float> rapidGVF::getLikelihoods()
{
return outcomes.likelihoods;
};
const std::vector<float> rapidGVF::getAlignments()
{
return outcomes.alignments;
};
const std::vector<std::vector<float> > * rapidGVF::getDynamics()
{
return &outcomes.dynamics;
};
const std::vector<std::vector<float> > * rapidGVF::getScalings()
{
return &outcomes.scalings;
};
const std::vector<std::vector<float> > * rapidGVF::getRotations()
{
return &outcomes.rotations;
};
......@@ -19,17 +19,23 @@ namespace rapidmix { class trainingData; }
* @brief This class is an adapter for the GVF library from Baptiste Caramiaux
*/
class rapidGVF {
public:
rapidGVF();
~rapidGVF();
bool train(const rapidmix::trainingData &newTrainingData);
std::vector<double> run(const std::vector<double> &inputVector);
//TODO: needs a "reset" message
const std::vector<float> getLikelihoods();
const std::vector<float> getAlignments();
const std::vector<std::vector<float> > * getDynamics();
const std::vector<std::vector<float> > * getScalings();
const std::vector<std::vector<float> > * getRotations();
protected:
GVF * gvf;
private:
GVF gvf;
GVFGesture currentGesture;
GVFOutcomes outcomes;
};
......
#include "rapidXMM.h"
#include "trainingData.h"
#include "machineLearning.h"
#include "../trainingData.h"
#include "../machineLearning.h"
static bool trainingData2xmmTrainingSet(const rapidmix::trainingData& data, xmm::TrainingSet& set) {
if (data.trainingSet.size() < 1) {
......@@ -81,25 +81,27 @@ bool xmmTool<SingleClassModel, Model>::train(const rapidmix::trainingData& newTr
template <class SingleClassModel, class Model>
Json::Value xmmTool<SingleClassModel, Model>::toJSON(/*std::string modelType*/) {
Json::Value root;
Json::Value metadata;
Json::Value modelSet;
metadata["creator"] = "Rapid API C++";
metadata["version"] = "v0.1.1"; //TODO: This should be a macro someplace
metadata["family"] = "xmm";
root["metadata"] = metadata;
root["docType"] = "rapid-mix:ml-model";
root["docVersion"] = RAPIDMIX_JSON_DOC_VERSION;
modelSet.append(model.toJson());
root["modelSet"] = modelSet;
Json::Value target;
target["name"] = "xmm";
target["version"] = "v1.0.0";
root["target"] = target;
root["payload"] = model.toJson();
return root;
}
template <class SingleClassModel, class Model>
bool xmmTool<SingleClassModel, Model>::fromJSON(Json::Value &jm) {
if (jm["metadata"]["family"].asString().compare("xmm") == 0 &&
jm["modelSet"].size() > 0) {
model.fromJson(jm["modelSet"][0]);
if (jm["docType"].asString().compare("rapid-mix:ml-model") == 0 &&
jm["target"]["name"].asString().compare("xmm") == 0 &&
jm["payload"].size() > 0) {
model.fromJson(jm["payload"]);
model.reset();
return true;
}
......@@ -143,7 +145,6 @@ bool xmmTool<SingleClassModel, Model>::readJSON(const std::string &filepath) {
//============================== xmmGmmTool ==================================//
// std::vector<double> xmmGmmTool::run(const std::vector<double>& inputVector) {
std::vector<double> rapidXmmGmm::run(const std::vector<double>& inputVector) {
xmmTool::preProcess(inputVector);
return model.results.smoothed_normalized_likelihoods;
......@@ -151,7 +152,6 @@ std::vector<double> rapidXmmGmm::run(const std::vector<double>& inputVector) {
//============================== xmmGmrTool ==================================//
// std::vector<double> xmmGmrTool::run(const std::vector<double>& inputVector) {
std::vector<double> rapidXmmGmr::run(const std::vector<double>& inputVector) {
xmmTool::preProcess(inputVector);
std::vector<float> *res = &model.results.output_values;
......@@ -161,7 +161,6 @@ std::vector<double> rapidXmmGmr::run(const std::vector<double>& inputVector) {
//============================== xmmHmmTool ==================================//
// std::vector<double> xmmHmmTool::run(const std::vector<double>& inputVector) {
std::vector<double> rapidXmmHmm::run(const std::vector<double>& inputVector) {
xmmTool::preProcess(inputVector);
std::vector<double> res;
......@@ -178,7 +177,6 @@ std::vector<double> rapidXmmHmm::run(const std::vector<double>& inputVector) {
//============================== xmmHmrTool ==================================//
// std::vector<double> xmmHmrTool::run(const std::vector<double>& inputVector) {
std::vector<double> rapidXmmHmr::run(const std::vector<double>& inputVector) {
xmmTool::preProcess(inputVector);
std::vector<float> *res = &model.results.output_values;
......@@ -187,20 +185,25 @@ std::vector<double> rapidXmmHmr::run(const std::vector<double>& inputVector) {
}
///////////////////////////////////////////////////////////////////////////
///// generic train method and forward declaration of specialized templates
///// generic train method and forward declaration of specialized templates
///////////////////////////////////////////////////////////////////////////
template class xmmTool<xmm::GMM, xmm::GMM>;
template class xmmTool<xmm::HMM, xmm::HierarchicalHMM>;
template class xmmStaticTool<xmm::GMM, xmm::GMM>;
template class xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM>;
//I wonder why this can't be defined in machineLearning.cpp? -MZ
// It is needed by the template instantiations below.
// You get an undefined symbols error otherwise.
template <class MachineLearningModule>
bool rapidmix::machineLearning<MachineLearningModule>::train(const trainingData &newTrainingData) {
return MachineLearningModule::train(newTrainingData);
}
// template class rapidmix::machineLearning<xmmGmmTool>;
// template class rapidmix::machineLearning<xmmGmrTool>;
// template class rapidmix::machineLearning<xmmHmmTool>;
// template class rapidmix::machineLearning<xmmHmrTool>;
template class rapidmix::machineLearning<rapidXmmGmm>;
template class rapidmix::machineLearning<rapidXmmGmr>;
template class rapidmix::machineLearning<rapidXmmHmm>;
......
/**
* @file rapidXMM.h
* @author joseph larralde
*
*
* @copyright
* Copyright (C) 2016 - 2017 by IRCAM - Centre Pompidou, Paris, France.
* All rights reserved.
......@@ -140,7 +140,7 @@ protected:
mCfg.gaussians.set(cfg.gaussians);
mCfg.relative_regularization.set(cfg.relativeRegularization);
mCfg.absolute_regularization.set(cfg.absoluteRegularization);
xmm::MultiClassRegressionEstimator mcre;
switch (cfg.regressionEstimator) {
case xmmLikeliestRegression:
......@@ -224,16 +224,10 @@ public:
/**
* @brief Static classification using Gaussian Mixture Models
*/
// class xmmGmmTool : public xmmStaticTool<xmm::GMM, xmm::GMM> {
// class GMM : public xmmStaticTool<xmm::GMM, xmm::GMM> {
class rapidXmmGmm : public xmmStaticTool<xmm::GMM, xmm::GMM> {
public:
// xmmGmmTool(xmmToolConfig cfg = xmmToolConfig()) :
// GMM(xmmToolConfig cfg = xmmToolConfig()) :
rapidXmmGmm(xmmToolConfig cfg = xmmToolConfig()) :
xmmStaticTool<xmm::GMM, xmm::GMM>(cfg, false) {}
// ~xmmGmmTool() {}
// ~GMM() {}
~rapidXmmGmm() {}
std::vector<double> run(const std::vector<double>& inputVector);
......@@ -242,16 +236,10 @@ public:
/**
* @brief Static regression using Gaussian Mixture Models
*/
// class xmmGmrTool : public xmmStaticTool<xmm::GMM, xmm::GMM> {
// class GMR : public xmmStaticTool<xmm::GMM, xmm::GMM> {
class rapidXmmGmr : public xmmStaticTool<xmm::GMM, xmm::GMM> {
public:
// xmmGmrTool(xmmToolConfig cfg = xmmToolConfig()) :
// GMR(xmmToolConfig cfg = xmmToolConfig()) :
rapidXmmGmr(xmmToolConfig cfg = xmmToolConfig()) :
xmmStaticTool<xmm::GMM, xmm::GMM>(cfg, true) {}
// ~xmmGmrTool() {}
// ~GMR() {}
~rapidXmmGmr() {}
std::vector<double> run(const std::vector<double>& inputVector);
......@@ -260,16 +248,10 @@ public:
/**
* @brief Temporal classification using Hierarchical Hidden Markov Models
*/
// class xmmHmmTool : public xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM> {
// class HMM : public xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM> {
class rapidXmmHmm : public xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM> {
public:
// xmmHmmTool(xmmToolConfig cfg = xmmToolConfig()) :
// HMM(xmmToolConfig cfg = xmmToolConfig()) :
rapidXmmHmm(xmmToolConfig cfg = xmmToolConfig()) :
xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM>(cfg, false) {}
// ~xmmHmmTool() {}
// ~HMM() {}
~rapidXmmHmm() {}
std::vector<double> run(const std::vector<double>& inputVector);
......@@ -278,16 +260,10 @@ public:
/**
* @brief Temporal regression using Hierarchical Hidden Markov Models
*/
// class xmmHmrTool : public xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM> {
// class HMR : public xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM> {
class rapidXmmHmr : public xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM> {
public:
// xmmHmrTool(xmmToolConfig cfg = xmmToolConfig()) :
// HMR(xmmToolConfig cfg = xmmToolConfig()) :
rapidXmmHmr(xmmToolConfig cfg = xmmToolConfig()) :
xmmTemporalTool<xmm::HMM, xmm::HierarchicalHMM>(cfg, true) {}
// ~xmmHmrTool() {}
// ~HMR() {}
~rapidXmmHmr() {}
std::vector<double> run(const std::vector<double>& inputVector);
......
/*
* trainingData.cpp
* Created by Michael Zbyszynski on 2 Feb 2017
* Copyright © 2017 Goldsmiths. All rights reserved.
/**
* @file trainingData.cpp
* @author Michael Zbyszynski
* @date 2 Feb 2017
* @copyright Copyright © 2017 Goldsmiths. All rights reserved.
*/
#include <fstream>
#include "trainingData.h"
RAPIDMIX_BEGIN_NAMESPACE
trainingData::trainingData () {
currentId = 0;
targetPhrase = 0;
};
uint32_t trainingData::assignCurrentId() {
uint32_t returnVal = currentId;
++currentId;
return returnVal;
}
uint32_t trainingData::startRecording() {
phrase tempPhrase = { assignCurrentId(), std::to_string(tempPhrase.uniqueId) }; //TODO: Is this label helpful? -MZ
trainingSet.push_back(tempPhrase);
targetPhrase = int(trainingSet.size() - 1);
return tempPhrase.uniqueId;
};
uint32_t trainingData::startRecording(const std::string &label) {
phrase tempPhrase = { assignCurrentId(), label };
trainingSet.push_back(tempPhrase);
targetPhrase = int(trainingSet.size() - 1);
return tempPhrase.uniqueId;
namespace rapidmix {
};
uint32_t trainingData::addElement(const std::vector<double> &input, const std::vector<double> &output) {
element newElement;
newElement.uniqueId = assignCurrentId();
newElement.input = input;
newElement.output = output;
newElement.timeStamp = NULL;
trainingSet[targetPhrase].elements.push_back(newElement);
return newElement.uniqueId;
}
uint32_t trainingData::addElement(const std::vector<double> &input) {
element newElement;
newElement.uniqueId = assignCurrentId();
newElement.input = input;
newElement.timeStamp = NULL;
trainingSet[targetPhrase].elements.push_back(newElement);
return newElement.uniqueId;
}
void trainingData::stopRecording() {
//TODO: This doesn't do much. -MZ
}
uint32_t trainingData::recordSingleElement(const std::string &label, const std::vector<double> &input) {
startRecording(label);
int returnId = addElement(input);
stopRecording();
return returnId;
};
uint32_t trainingData::recordSingleElement(const std::string &label, const std::vector<double> &input, const std::vector<double> &output) {
startRecording(label);
int returnId = addElement(input, output);
stopRecording();
return returnId;
};
std::vector<std::string> trainingData::getColumnNames() {
return trainingSet[targetPhrase].columnNames;
}
void trainingData::setColumnNames(const std::vector<std::string> &column_names) {
trainingSet[targetPhrase].columnNames = column_names;
}
Json::Value trainingData::parse2json() {
Json::Value root;
Json::Value metadata;
Json::Value trainingSetJSON;
metadata["creator"] = "RAPID-MIX API C++";
metadata["version"] = RAPIDMIX_VERSION;
//Go through all the phrases
for (int i = 0; i < trainingSet.size(); ++i) {
Json::Value thisPhrase;
thisPhrase.append(trainingSet[i].uniqueId);
thisPhrase.append(trainingSet[i].label);
Json::Value column_names;
for (int j = 0; j < trainingSet[i].columnNames.size(); ++j) {
column_names.append(trainingSet[i].columnNames[j]);
}
thisPhrase.append(column_names);
trainingData::trainingData () {
currentId = 0;
targetPhrase = 0;
};
uint32_t trainingData::assignCurrentId() {
uint32_t returnVal = currentId;
++currentId;
return returnVal;
}
std::vector<trainingData::phrase>::iterator trainingData::createNewPhrase(std::string label) {
phrase tempPhrase = { assignCurrentId(), label };
trainingSet.push_back(tempPhrase);
std::vector<trainingData::phrase>::iterator it = --trainingSet.end();
return it;
};
uint32_t trainingData::startRecording() {
phrase tempPhrase = { assignCurrentId(), std::to_string(tempPhrase.uniqueId) }; //TODO: Is this label helpful? -MZ
trainingSet.push_back(tempPhrase);
targetPhrase = int(trainingSet.size() - 1);
return tempPhrase.uniqueId;
};
uint32_t trainingData::startRecording(const std::string &label) {
phrase tempPhrase = { assignCurrentId(), label };
trainingSet.push_back(tempPhrase);
targetPhrase = int(trainingSet.size() - 1);
return tempPhrase.uniqueId;
Json::Value elements;
for (int j = 0; j < trainingSet[i].elements.size(); ++j) {
Json::Value singleElement;
};
uint32_t trainingData::addElement(const std::vector<double> &input, const std::vector<double> &output) {
element newElement;
newElement.uniqueId = assignCurrentId();
newElement.input = input;
newElement.output = output;
newElement.timeStamp = 0.0;
trainingSet[targetPhrase].elements.push_back(newElement);
return newElement.uniqueId;
}
uint32_t trainingData::addElement(const std::vector<double> &input) {
element newElement;
newElement.uniqueId = assignCurrentId();
newElement.input = input;
newElement.timeStamp = 0.0;
trainingSet[targetPhrase].elements.push_back(newElement);
return newElement.uniqueId;
}
void trainingData::stopRecording() {
//TODO: This doesn't do much. -MZ
}
uint32_t trainingData::recordSingleElement(const std::string &label, const std::vector<double> &input) {
startRecording(label);
int returnId = addElement(input);
stopRecording();
return returnId;
};
uint32_t trainingData::recordSingleElement(const std::vector<double> &input, const std::vector<double> &output) {
startRecording();
int returnId = addElement(input, output);
stopRecording();
return returnId;
};
uint32_t trainingData::recordSingleElement(const std::string &label, const std::vector<double> &input, const std::vector<double> &output) {
startRecording(label);
int returnId = addElement(input, output);
stopRecording();
return returnId;
};
std::vector<std::string> trainingData::getColumnNames() {
return trainingSet[targetPhrase].columnNames;
}
void trainingData::setColumnNames(const std::vector<std::string> &column_names) {
trainingSet[targetPhrase].columnNames = column_names;
}
Json::Value trainingData::parse2json() {
Json::Value root;
Json::Value metadata;
Json::Value trainingSetJSON;
metadata["creator"] = "RAPID-MIX API C++";
metadata["version"] = RAPIDMIX_VERSION;
//Go through all the phrases
for (int i = 0; i < trainingSet.size(); ++i) {
Json::Value thisPhrase;
thisPhrase.append(trainingSet[i].uniqueId);
thisPhrase.append(trainingSet[i].label);
Json::Value elementInput;
for (int k = 0; k < trainingSet[i].elements[j].input.size(); ++k) {
elementInput.append(trainingSet[i].elements[j].input[k]);
Json::Value column_names;
for (int j = 0; j < trainingSet[i].columnNames.size(); ++j) {
column_names.append(trainingSet[i].columnNames[j]);
}
singleElement.append(elementInput);
thisPhrase.append(column_names);
Json::Value elementOutput;
for (int k = 0; k < trainingSet[i].elements[j].output.size(); ++k) {
elementOutput.append(trainingSet[i].elements[j].output[k]);
Json::Value elements;
for (int j = 0; j < trainingSet[i].elements.size(); ++j) {
Json::Value singleElement;
Json::Value elementInput;
for (int k = 0; k < trainingSet[i].elements[j].input.size(); ++k) {
elementInput.append(trainingSet[i].elements[j].input[k]);
}
singleElement.append(elementInput);
Json::Value elementOutput;
for (int k = 0; k < trainingSet[i].elements[j].output.size(); ++k) {
elementOutput.append(trainingSet[i].elements[j].output[k]);
}
singleElement.append(elementOutput);
singleElement.append(trainingSet[i].elements[j].timeStamp);
elements.append(singleElement);
}
singleElement.append(elementOutput);
thisPhrase.append(elements);
singleElement.append(trainingSet[i].elements[j].timeStamp);
elements.append(singleElement);
trainingSetJSON.append(thisPhrase);
}
thisPhrase.append(elements);
trainingSetJSON.append(thisPhrase);
root["metadata"] = metadata;
root["trainingSet"] = trainingSetJSON;
return root;
}
root["metadata"] = metadata;
root["trainingSet"] = trainingSetJSON;
return root;
}
std::string trainingData::getJSON() {
Json::Value root = parse2json();
return root.toStyledString();
}
void trainingData::writeJSON(const std::string &filepath) {
Json::Value root = parse2json();
std::ofstream jsonOut;
jsonOut.open (filepath);
Json::StyledStreamWriter writer;
writer.write(jsonOut, root);
jsonOut.close();
}
void trainingData::json2trainingSet(const Json::Value &root) {
trainingSet = {};
for (const Json::Value& jsonPhrase : root["trainingSet"]) {
std::string trainingData::getJSON() {
Json::Value root = parse2json();
return root.toStyledString();
}
phrase tempPhrase = { jsonPhrase[0].asUInt(), jsonPhrase[1].asString() };
for (int i = 0; i < jsonPhrase[2].size(); ++i) {
tempPhrase.columnNames.push_back(jsonPhrase[2][i].asString());
}
void trainingData::writeJSON(const std::string &filepath) {
Json::Value root = parse2json();
std::ofstream jsonOut;
jsonOut.open (filepath);
Json::StyledStreamWriter writer;
writer.write(jsonOut, root);
jsonOut.close();
for (int i = 0; i < jsonPhrase[3].size(); ++i) {
element tempElement;
for (int j = 0; j < jsonPhrase[3][i][0].size(); ++j) {
tempElement.input.push_back(jsonPhrase[3][i][0][j].asDouble());
}
for (int j = 0; j < jsonPhrase[3][i][1].size(); ++j) {
tempElement.output.push_back(jsonPhrase[3][i][1][j].asDouble());
}
void trainingData::json2trainingSet(const Json::Value &root) {
trainingSet = {};
for (const Json::Value& jsonPhrase : root["trainingSet"]) {
phrase tempPhrase = { jsonPhrase[0].asUInt(), jsonPhrase[1].asString() };
for (int i = 0; i < jsonPhrase[2].size(); ++i) {
tempPhrase.columnNames.push_back(jsonPhrase[2][i].asString());
}
tempElement.timeStamp = jsonPhrase[3][i][2].asDouble();
tempPhrase.elements.push_back(tempElement);
for (int i = 0; i < jsonPhrase[3].size(); ++i) {
element tempElement;
for (int j = 0; j < jsonPhrase[3][i][0].size(); ++j) {
tempElement.input.push_back(jsonPhrase[3][i][0][j].asDouble());
}
for (int j = 0; j < jsonPhrase[3][i][1].size(); ++j) {
tempElement.output.push_back(jsonPhrase[3][i][1][j].asDouble());
}
tempElement.timeStamp = jsonPhrase[3][i][2].asDouble();
tempPhrase.elements.push_back(tempElement);
}
trainingSet.push_back(tempPhrase);
}
trainingSet.push_back(tempPhrase);
}
}
bool trainingData::putJSON(const std::string &jsonMessage) {
Json::Value parsedFromString;
Json::Reader reader;
bool parsingSuccessful = reader.parse(jsonMessage, parsedFromString);
if (parsingSuccessful)
{
json2trainingSet(parsedFromString);
bool trainingData::putJSON(const std::string &jsonMessage) {
Json::Value parsedFromString;
Json::Reader reader;
bool parsingSuccessful = reader.parse(jsonMessage, parsedFromString);
if (parsingSuccessful)
{
json2trainingSet(parsedFromString);
}
return parsingSuccessful;
}
return parsingSuccessful;
}
bool trainingData::readJSON(const std::string &filepath) {
Json::Value root;
std::ifstream file(filepath);
file >> root;
json2trainingSet(root);
return true; //TODO: check something first
bool trainingData::readJSON(const std::string &filepath) {
Json::Value root;
std::ifstream file(filepath);
file >> root;
json2trainingSet(root);
return true; //TODO: check something first
}
}
RAPIDMIX_END_NAMESPACE
/**
* @file trainingData.h
* Created by Michael Zbyszynski on 2 Feb 2017
* @author Michael Zbyszynski
* @date 2 Feb 2017
* @copyright
* Copyright © 2017 Goldsmiths. All rights reserved.
*
* @ingroup machinelearning
......@@ -13,81 +15,100 @@
#include <string>
#include <unordered_map>
#include "rapidMix.h"
#include "../rapidmix.h"
#include "json.h"
RAPIDMIX_BEGIN_NAMESPACE
/** This is used by both NN and KNN models for training */
class trainingData {
public:
trainingData();
struct element{
uint32_t uniqueId; //MZ: Does this scope of this id need to extend beyond this instantiation?
std::vector<double> input;
std::vector<double> output;
double timeStamp;
};
struct phrase {
uint32_t uniqueId;
std::string label; //TODO: Need to work this with templates
std::vector<std::string> columnNames;
std::vector<element> elements;
namespace rapidmix {
/** This is used by both NN and KNN models for training */
class trainingData {
public:
trainingData();
struct element{
uint32_t uniqueId; //MZ: Does this scope of this id need to extend beyond this instantiation?
std::vector<double> input;
std::vector<double> output;
double timeStamp;
};
struct phrase {
uint32_t uniqueId;
std::string label; //TODO: Need to work this with templates
std::vector<std::string> columnNames; //equal to the number of inputs
std::vector<element> elements;
//TODO: This is just a design idea right now.
void addElement (const std::vector<double> &input, const std::vector<double> &output)
{
element tempElement;
// tempElement.uniqueId = assignCurrentId(); //TODO: how to do this? Do we need this?
tempElement.input = input;
tempElement.output = output;
//tempElement.timeStamp = NULL;
this->elements.push_back(tempElement);
}
};
std::vector<phrase> trainingSet;
//TODO: Deleting phrases (last or by label)
//Design ideas to make phrase building stateless:
std::vector<phrase>::iterator createNewPhrase(); //??? Do we need this?
std::vector<phrase>::iterator createNewPhrase(std::string label);
/** Create a new phrase that can be recorded into. Returns phrase id */
uint32_t startRecording(); //FIXME: this should go away. -MZ
/** Create new phrase, with a label, that can be recorded into. Returns phrase id */
uint32_t startRecording(const std::string &label);
/** Add an element with input and output to the phrase that is recording,
or to the default phrase if recording is stopped. Returns phrase id. */
uint32_t addElement(const std::vector<double> &input, const std::vector<double> &output);
/** Add an element with just input to the phrase that is recording,
or to the default phrase if recording is stopped. Returns phrase id. */
uint32_t addElement(const std::vector<double> &input);
void stopRecording();
/** Create a phrase with a single element that has a label and input. Returns phrase id. */
uint32_t recordSingleElement(const std::string &label, const std::vector<double> &input);
/** Create a phrase with a single element that has input, and output. Returns phrase id. */
uint32_t recordSingleElement(const std::vector<double> &input, const std::vector<double> &output);
/** Create a phrase with a single element that has a label, input, and output. Returns phrase id. */
uint32_t recordSingleElement(const std::string &label, const std::vector<double> &input, const std::vector<double> &output);
std::vector<std::string> getColumnNames();
void setColumnNames(const std::vector<std::string> &columnNames);
/** Get a JSON representation of the data set in the form of a styled string */
std::string getJSON();
/** Write a JSON version of the training set to specified file path */
void writeJSON(const std::string &filepath);
/** populate a data set with string. See getJSON() */
bool putJSON(const std::string &jsonMessage);
/** read a JSON file at file path and build a training set from it */
bool readJSON(const std::string &filepath);
private:
int targetPhrase;
uint32_t currentId;
//* Returns and increments current id */
uint32_t assignCurrentId();
Json::Value parse2json();
void json2trainingSet(const Json::Value &newTrainingData);
};
std::vector<phrase> trainingSet;
/** Create a new phrase that can be recorded into. Returns phrase id */
uint32_t startRecording(); //FIXME: this should go away. -MZ
/** Create new phrase, with a label, that can be recorded into. Returns phrase id */
uint32_t startRecording(const std::string &label);
/** Add an element with input and output to the phrase that is recording,
or to the default phrase if recording is stopped. Returns phrase id. */
uint32_t addElement(const std::vector<double> &input, const std::vector<double> &output);
/** Add an element with just input to the phrase that is recording,
or to the default phrase if recording is stopped. Returns phrase id. */
uint32_t addElement(const std::vector<double> &input);
void stopRecording();
/** Create a phrase with a single element that has a label and input. Returns phrase id. */
uint32_t recordSingleElement(const std::string &label, const std::vector<double> &input);
/** Create a phrase with a single element that has a label, input, and output. Returns phrase id. */
uint32_t recordSingleElement(const std::string &label, const std::vector<double> &input, const std::vector<double> &output);
std::vector<std::string> getColumnNames();
void setColumnNames(const std::vector<std::string> &columnNames);
/** Get a JSON representation of the data set in the form of a styled string */
std::string getJSON();
/** Write a JSON version of the training set to specified file path */
void writeJSON(const std::string &filepath);
/** populate a data set with string. See getJSON() */
bool putJSON(const std::string &jsonMessage);
/** read a JSON file at file path and build a training set from it */
bool readJSON(const std::string &filepath);
private:
int targetPhrase;
uint32_t currentId;
//* Returns and increments current id */
uint32_t assignCurrentId();
Json::Value parse2json();
void json2trainingSet(const Json::Value &newTrainingData);
};
RAPIDMIX_END_NAMESPACE
}
#endif
......@@ -9,10 +9,10 @@
/**
* @mainpage RAPID-MIX API
*
*
* @section Introduction
*
* Hello, API ! <br>
* Hello, API ! <br>
* All the classes, functions and structs documented here belong to the
* <code>rapidmix</code> namespace.
*
......@@ -36,16 +36,14 @@
#define rapidmix_h
#define RAPIDMIX_VERSION_MAJOR 2
#define RAPIDMIX_VERSION_MINOR 1
#define RAPIDMIX_VERSION_MINOR 3
#define RAPIDMIX_VERSION_PATCH 0
#define RAPIDMIX_VERSION "2.0.1"
#define RAPIDMIX_REVISION "13-JULY-2017"
#define RAPIDMIX_BEGIN_NAMESPACE namespace rapidmix {
#define RAPIDMIX_END_NAMESPACE }
#define RAPIDMIX_VERSION "2.3.1"
#define RAPIDMIX_JSON_DOC_VERSION "1.0.0"
#define RAPIDMIX_REVISION "2-MAY-2018"
#include "machineLearning.h"
#include "trainingData.h"
#include "signalProcessing.h"
#include "machineLearning/machineLearning.h"
#include "machineLearning/trainingData.h"
#include "signalProcessing/signalProcessing.h"
#endif
#include "rapidmix.h"
#include "rapidPiPoHost.h"
#include <iostream>
#include <fstream>
//=========================== H O S T === U T I L S ==========================//
/*
static const unsigned int maxWordLen = 256;
static bool getPiPoInstanceAndAttrName(const char *attrName,
char *instanceName,
char *pipoAttrName)
{
const char *dot = std::strrchr(attrName, '.');
if (dot != NULL)
{
long pipoAttrNameLen = dot - attrName;
std::strcpy(pipoAttrName, dot + 1);
if (pipoAttrNameLen > maxWordLen)
{
pipoAttrNameLen = maxWordLen;
}
std::strncpy(instanceName, attrName, pipoAttrNameLen);
instanceName[pipoAttrNameLen] = '\0';
return true;
}
return false;
}
//*/
static void fromPiPoStreamAttributes(PiPoStreamAttributes &src,
pipoStreamAttributes &dst)
RapidPiPoStreamAttributes &dst)
{
unsigned int numCols = src.dims[0];
unsigned int numLabels = src.numLabels;
if (numLabels > PIPO_MAX_LABELS) {
numLabels = PIPO_MAX_LABELS;
}
if (numLabels > numCols) {
numLabels = numCols;
}
......@@ -76,7 +47,7 @@ static void fromPiPoStreamAttributes(PiPoStreamAttributes &src,
}
static void toPiPoStreamAttributes(pipoStreamAttributes &src,
static void toPiPoStreamAttributes(RapidPiPoStreamAttributes &src,
PiPoStreamAttributes &dst)
{
const char *labs[src.labels.size()];
......@@ -101,258 +72,31 @@ static void toPiPoStreamAttributes(pipoStreamAttributes &src,
//========================= H O S T === M E T H O D S ========================//
PiPoHost::PiPoHost() :
inputStreamAttrs(PIPO_MAX_LABELS),
outputStreamAttrs(PIPO_MAX_LABELS)
{
PiPoCollection::init();
this->out = new PiPoOut(this);
this->graph = nullptr;
}
PiPoHost::~PiPoHost()
{
if (this->graph != nullptr)
{
delete this->graph;
}
delete this->out;
}
bool
PiPoHost::setGraph(std::string name)
{
if (this->graph != nullptr)
{
delete this->graph;
}
this->graph = PiPoCollection::create(name);
if (this->graph != NULL)
{
this->graphName = name;
this->graph->setReceiver((PiPo *)this->out);
return true;
}
this->graph = nullptr;
this->graphName = "undefined";
return false;
}
void
PiPoHost::clearGraph()
{
if (this->graph != nullptr)
{
delete this->graph;
this->graph = nullptr;
}
}
void
PiPoHost::onNewFrameOut(double time, std::vector<PiPoValue> &frame)
{
std::cout << time << std::endl;
std::cout << "please override this method" << std::endl;
}
std::vector<PiPoValue>
PiPoHost::getLastFrameOut()
{
return this->out->getLastFrame();
}
int
PiPoHost::setInputStreamAttributes(pipoStreamAttributes &sa, bool propagate)
RapidPiPoHost::setInputStreamAttributes(RapidPiPoStreamAttributes &rpsa)
{
toPiPoStreamAttributes(sa, inputStreamAttrs);
if (propagate)
{
return this->propagateInputStreamAttributes();
}
return 0;
PiPoStreamAttributes psa;
toPiPoStreamAttributes(rpsa, psa);
return PiPoHost::setInputStreamAttributes(psa);
}
pipoStreamAttributes
PiPoHost::getOutputStreamAttributes()
{
pipoStreamAttributes sa;
fromPiPoStreamAttributes(this->outputStreamAttrs, sa);
return sa;
}
int
PiPoHost::frames(double time, double weight, PiPoValue *values, unsigned int size,
unsigned int num)
{
return this->graph->frames(time, weight, values, size, num);
}
// bool
// setAttr(const std::string &attrName, bool value)
// {
// }
// bool
// setAttr(const std::string &attrName, int value)
// {
// }
bool
PiPoHost::setAttr(const std::string &attrName, double value)
{
PiPo::Attr *attr = this->graph->getAttr(attrName.c_str());
if (attr != NULL)
{
int iAttr = attr->getIndex();
return this->graph->setAttr(iAttr, value);
}
return false;
}
bool
PiPoHost::setAttr(const std::string &attrName, const std::vector<double> &values)
{
PiPo::Attr *attr = this->graph->getAttr(attrName.c_str());
if (attr != NULL)
{
int iAttr = attr->getIndex();
double vals[values.size()];
unsigned int i = 0;
for (auto &value : values)
{
vals[i] = value;
i++;
}
return this->graph->setAttr(iAttr, &vals[0], static_cast<unsigned int>(values.size()));
}
return false;
}
bool
PiPoHost::setAttr(const std::string &attrName, const std::string &value) // for enums
{
PiPo::Attr *attr = this->graph->getAttr(attrName.c_str());
if (attr != NULL)
{
// int iAttr = attr->getIndex();
PiPo::Type type = attr->getType();
if (type == PiPo::Type::Enum)
{
std::vector<const char *> *list = attr->getEnumList();
for (int i = 0; i < list->size(); i++)
{
if (strcmp(list->at(i), value.c_str()) == 0)
{
attr->set(0, i);
return true;
}
}
}
}
return false;
}
std::vector<std::string>
PiPoHost::getAttrNames()
{
std::vector<std::string> res;
for (unsigned int i = 0; i < this->graph->getNumAttrs(); ++i)
{
res.push_back(this->graph->getAttr(i)->getName());
}
return res;
}
double
PiPoHost::getDoubleAttr(const std::string &attrName)
{
PiPo::Attr *attr = this->graph->getAttr(attrName.c_str());
if (attr != NULL) {
// int iAttr = attr->getIndex();
PiPo::Type type = attr->getType();
if (type == PiPo::Type::Double) {
return attr->getDbl(0);
}
}
return 0;
}
std::vector<double>
PiPoHost::getDoubleArrayAttr(const std::string &attrName)
{
std::vector<double> res;
PiPo::Attr *attr = this->graph->getAttr(attrName.c_str());
if (attr != NULL) {
// int iAttr = attr->getIndex();
PiPo::Type type = attr->getType();
if (type == PiPo::Type::Double) {
for (int i = 0; i < attr->getSize(); ++i) {
res.push_back(attr->getDbl(i));
}
}
}
return res;
}
std::string
PiPoHost::getEnumAttr(const std::string &attrName)
void
RapidPiPoHost::onNewFrame(double time, double weight, PiPoValue *values, unsigned int size)
{
PiPo::Attr *attr = this->graph->getAttr(attrName.c_str());
if (attr != NULL) {
// int iAttr = attr->getIndex();
PiPo::Type type = attr->getType();
if (type == PiPo::Type::Enum) {
return attr->getStr(0);
}
}
return "";
std::cout << "I received " << size << " new frame(s)" << std::endl;
}
//============================= JSON FORMATTING ==============================//
//----------------------------- JSON FORMATTING ------------------------------//
std::string
PiPoHost::getJSON()
RapidPiPoHost::getJSON()
{
Json::Value result = toJSON();
return result.toStyledString();
}
void
PiPoHost::writeJSON(const std::string &filepath)
RapidPiPoHost::writeJSON(const std::string &filepath)
{
Json::Value root = toJSON();
std::ofstream jsonOut;
......@@ -363,7 +107,7 @@ PiPoHost::writeJSON(const std::string &filepath)
}
bool
PiPoHost::putJSON(const std::string &jsonMessage)
RapidPiPoHost::putJSON(const std::string &jsonMessage)
{
Json::Value parsedFromString;
Json::Reader reader;
......@@ -372,7 +116,7 @@ PiPoHost::putJSON(const std::string &jsonMessage)
}
bool
PiPoHost::readJSON(const std::string &filepath)
RapidPiPoHost::readJSON(const std::string &filepath)
{
Json::Value root;
std::ifstream file(filepath);
......@@ -380,23 +124,26 @@ PiPoHost::readJSON(const std::string &filepath)
return fromJSON(root);
}
//======================== PROTECTED HOST METHODS ============================//
//-------------------------- PRIVATE HOST METHODS ----------------------------//
Json::Value
PiPoHost::toJSON()
RapidPiPoHost::toJSON()
{
Json::Value root;
Json::Value metadata;
Json::Value pipodata;
metadata["creator"] = "RAPID-MIX API";// C++";
metadata["version"] = "v0.1.1"; //TODO: This should be a macro someplace
metadata["family"] = "pipo";
root["metadata"] = metadata;
//*
root["docType"] = "rapid-mix:signal-processing";
root["docVersion"] = RAPIDMIX_JSON_DOC_VERSION;
Json::Value target;
target["name"] = "pipo";
target["version"] = PIPO_SDK_VERSION;
root["target"] = target;
Json::Value pipodata;
pipodata["description"] = this->graphName;
Json::Value inputStream;
inputStream["hasTimeTags"] = inputStreamAttrs.hasTimeTags;
inputStream["rate"] = inputStreamAttrs.rate;
......@@ -407,7 +154,7 @@ PiPoHost::toJSON()
inputStream["hasVarSize"] = inputStreamAttrs.hasVarSize;
inputStream["domain"] = inputStreamAttrs.domain;
inputStream["maxFrames"] = inputStreamAttrs.maxFrames;
Json::Value outputStream;
outputStream["hasTimeTags"] = outputStreamAttrs.hasTimeTags;
outputStream["rate"] = outputStreamAttrs.rate;
......@@ -422,9 +169,9 @@ PiPoHost::toJSON()
Json::Value streams;
streams["input"] = inputStream;
streams["output"] = outputStream;
pipodata["streamAttributes"] = streams;
Json::Value params;
int n = this->graph->getNumAttrs();
params.resize(static_cast<Json::ArrayIndex>(n));
......@@ -434,331 +181,111 @@ PiPoHost::toJSON()
Json::Value param;
PiPo::Attr *a = this->graph->getAttr(i);
param["name"] = a->getName();
param["value"] = a->getDbl(0);
switch (a->getType())
{
case PiPo::Bool:
param["type"] = "Bool";
param["value"] = a->getInt(0);
break;
case PiPo::Enum:
param["type"] = "Enum";
param["value"] = std::string(a->getStr(0));
break;
case PiPo::String:
param["type"] = "String";
param["value"] = std::string(a->getStr(0));
break;
case PiPo::Int:
param["type"] = "Int";
param["value"] = Json::Value(Json::arrayValue);
for (int i = 0; i < a->getSize(); ++i)
{
param["value"].append(a->getInt(i));
}
break;
case PiPo::Double:
param["type"] = "Double";
param["value"] = Json::Value(Json::arrayValue);
for (int i = 0; i < a->getSize(); ++i)
{
param["value"].append(a->getDbl(i));
}
break;
default:
std::cout << a->getType() << std::endl;
break;
}
params[i] = param;
}
pipodata["parameters"] = params;
root["pipodata"] = pipodata;
root["payload"] = pipodata;
//*/
return root;
}
bool
PiPoHost::fromJSON(Json::Value &jv)
RapidPiPoHost::fromJSON(Json::Value &jv)
{
if (jv["metadata"]["family"].asString().compare("pipo") == 0 &&
jv["pipodata"].size() > 0) {
//*
if (jv["docType"].asString().compare("rapid-mix:signal-processing") == 0 &&
//jv["docVersion"].asString().compare(RAPIDMIX_JSON_DOC_VERSION) == 0 &&
jv["target"]["name"].asString().compare("pipo") == 0 &&
jv["payload"].size() > 0) {
this->setGraph(jv["pipodata"]["description"].asString());
Json::Value inputStream = jv["pipodata"]["streamAttributes"]["input"];
// setInputStreamAttributes(
// inputStream["hasTimeTags"].getDbl()//,
// //...
// );
return true;
}
return false;
}
this->setGraph(jv["payload"]["description"].asString());
//========================= PRIVATE HOST METHODS =============================//
Json::Value params = jv["payload"]["parameters"];
unsigned int nAttrs = params.size();
int
PiPoHost::propagateInputStreamAttributes()
{
if (this->graph != nullptr)
{
return this->graph->streamAttributes(this->inputStreamAttrs.hasTimeTags,
this->inputStreamAttrs.rate,
this->inputStreamAttrs.offset,
this->inputStreamAttrs.dims[0],
this->inputStreamAttrs.dims[1],
this->inputStreamAttrs.labels,
this->inputStreamAttrs.hasVarSize,
this->inputStreamAttrs.domain,
this->inputStreamAttrs.maxFrames);
}
return 0;
}
for (unsigned int i = 0; i < nAttrs; ++i)
{
std::string type = params[i]["type"].asString();
const char *name = params[i]["name"].asString().c_str();
void
PiPoHost::setOutputAttributes(bool hasTimeTags, double rate, double offset,
unsigned int width, unsigned int height,
const char **labels, bool hasVarSize,
double domain, unsigned int maxFrames) {
if (labels != NULL) {
int numLabels = width;
if (numLabels > PIPO_MAX_LABELS) {
numLabels = PIPO_MAX_LABELS;
}
for (unsigned int i = 0; i < numLabels; i++) {
try {
this->outputStreamAttrs.labels[i] = labels[i];
} catch(std::exception e) {
this->outputStreamAttrs.labels[i] = "unnamed";
if (type.compare("Bool") == 0)
{
this->setAttr(name, params[i]["value"].asInt());
}
}
this->outputStreamAttrs.numLabels = numLabels;
} else {
this->outputStreamAttrs.numLabels = 0;
}
this->outputStreamAttrs.hasTimeTags = hasTimeTags;
this->outputStreamAttrs.rate = rate;
this->outputStreamAttrs.offset = offset;
this->outputStreamAttrs.dims[0] = width;
this->outputStreamAttrs.dims[1] = height;
this->outputStreamAttrs.hasVarSize = hasVarSize;
this->outputStreamAttrs.domain = domain;
this->outputStreamAttrs.maxFrames = maxFrames;
}
// void
// PiPoHost::streamAttributesChanged(PiPo *pipo, PiPo::Attr *attr) {
// this->propagateInputAttributes();
// }
// void
// PiPoHost::signalError(PiPo *pipo, std::string errorMsg) {
// // todo
// }
// void
// PiPoHost::signalWarning(PiPo *pipo, std::string warningMsg) {
// // todo
// }
//--------------------- INPUT STREAM ATTRIBUTES SETTERS ----------------------//
/*
void
PiPoHost::setInputHasTimeTags(bool hasTimeTags, bool propagate) {
this->inputStreamAttrs.hasTimeTags = hasTimeTags;
if (propagate) {
this->propagateInputAttributes();
}
}
#define MIN_PIPO_SAMPLERATE (1.0 / 31536000000.0) // once a year
#define MAX_PIPO_SAMPLERATE (96000000000.0)
void
PiPoHost::setInputFrameRate(double rate, bool propagate) {
if (rate <= MIN_PIPO_SAMPLERATE) {
this->inputStreamAttrs.rate = MIN_PIPO_SAMPLERATE;
} else if (rate >= MAX_PIPO_SAMPLERATE) {
this->inputStreamAttrs.rate = MAX_PIPO_SAMPLERATE;
} else {
this->inputStreamAttrs.rate = rate;
}
if (propagate) {
this->propagateInputAttributes();
}
}
void
PiPoHost::setInputFrameOffset(double offset, bool propagate) {
this->inputStreamAttrs.offset = offset;
if (propagate) {
this->propagateInputAttributes();
}
}
void
PiPoHost::setInputDims(int width, int height, bool propagate) {
this->inputStreamAttrs.dims[0] = width;
this->inputStreamAttrs.dims[1] = height;
if (propagate) {
this->propagateInputAttributes();
}
}
void
PiPoHost::setInputLabels(const std::vector<std::string> &labels, bool propagate) {
const char *labs[labels.size()];
for (unsigned int i = 0; i < labels.size(); ++i) {
labs[i] = labels[i].c_str();
}
this->inputStreamAttrs.labels = &labs[0];
if (propagate) {
this->propagateInputAttributes();
}
}
void
PiPoHost::setInputHasVarSize(bool hasVarSize, bool propagate) {
this->inputStreamAttrs.hasVarSize = hasVarSize;
if (propagate) {
this->propagateInputAttributes();
}
}
void
PiPoHost::setInputDomain(double domain, bool propagate) {
this->inputStreamAttrs.domain = domain;
if (propagate) {
this->propagateInputAttributes();
}
}
void
PiPoHost::setInputMaxFrames(int maxFrames, bool propagate) {
this->inputStreamAttrs.maxFrames = maxFrames;
if (propagate) {
this->propagateInputAttributes();
}
}
//*/
//--------------------- INPUT STREAM ATTRIBUTES GETTERS ----------------------//
/*
bool
PiPoHost::getInputHasTimeTags() {
return this->inputStreamAttrs.hasTimeTags;
}
double
PiPoHost::getInputFrameRate() {
return this->inputStreamAttrs.rate;
}
double
PiPoHost::getInputFrameOffset() {
return this->inputStreamAttrs.offset;
}
void
PiPoHost::getInputDims(int &width, int &height) {
width = this->inputStreamAttrs.dims[0];
height = this->inputStreamAttrs.dims[1];
}
void
PiPoHost::getInputLabels(std::vector<std::string> &labels) {
//for (unsigned int i = 0; i < )
}
bool
PiPoHost::getInputHasVarSize() {
return this->inputStreamAttrs.hasVarSize;
}
double
PiPoHost::getInputDomain() {
return this->inputStreamAttrs.domain;
}
int
PiPoHost::getInputMaxFrames() {
return this->inputStreamAttrs.maxFrames;
}
//*/
//--------------------- OUTPUT STREAM ATTRIBUTES GETTERS ---------------------//
// void
// PiPoHost::setOutputAttributes(bool hasTimeTags, double rate, double offset,
// unsigned int width, unsigned int height,
// const char **labels, bool hasVarSize,
// double domain, unsigned int maxFrames) {
// if (labels != NULL) {
// int numLabels = width;
// if (numLabels > PIPO_MAX_LABELS) {
// numLabels = PIPO_MAX_LABELS;
// }
// for (unsigned int i = 0; i < numLabels; i++) {
// try {
// this->outputStreamAttrs.labels[i] = labels[i];
// } catch(std::exception e) {
// this->outputStreamAttrs.labels[i] = "unnamed";
// }
// }
// this->outputStreamAttrs.numLabels = numLabels;
// } else {
// this->outputStreamAttrs.numLabels = 0;
// }
// this->outputStreamAttrs.hasTimeTags = hasTimeTags;
// this->outputStreamAttrs.rate = rate;
// this->outputStreamAttrs.offset = offset;
// this->outputStreamAttrs.dims[0] = width;
// this->outputStreamAttrs.dims[1] = height;
// this->outputStreamAttrs.hasVarSize = hasVarSize;
// this->outputStreamAttrs.domain = domain;
// this->outputStreamAttrs.maxFrames = maxFrames;
// }
/*
bool
PiPoHost::getOutputHasTimeTags() {
return this->outputStreamAttrs.hasTimeTags;
}
double
PiPoHost::getOutputFrameRate() {
return this->outputStreamAttrs.rate;
}
double
PiPoHost::getOutputFrameOffset() {
return this->outputStreamAttrs.offset;
}
else if (type.compare("Enum") == 0 || type.compare("String") == 0)
{
this->setAttr(name, params[i]["value"].asString());
}
else if (type.compare("Int") == 0)
{
std::vector<int> values;
void
PiPoHost::getOutputDims(int &width, int &height) {
width = this->outputStreamAttrs.dims[0];
height = this->outputStreamAttrs.dims[1];
}
for (int j = 0; j < params[i]["value"].size(); ++j)
{
values.push_back(params[i]["value"][j].asInt());
}
void
PiPoHost::getOutputLabels(std::vector<std::string> &labels) {
labels.clear();
this->setAttr(name, values);
}
else if (type.compare("Double") == 0)
{
std::vector<double> values;
for (unsigned int i = 0; this->outputStreamAttrs.numLabels; ++i) {
for (int j = 0; j < params[i]["value"].size(); ++j)
{
values.push_back(params[i]["value"][j].asDouble());
}
if (this->outputStreamAttrs.labels[i] != NULL) {
labels.push_back(std::string(this->outputStreamAttrs.labels[i]));
} else {
labels.push_back("unnamed");
this->setAttr(name, values);
}
}
}
}
bool
PiPoHost::getOutputHasVarSize() {
return this->outputStreamAttrs.hasVarSize;
}
double
PiPoHost::getOutputDomain() {
return this->outputStreamAttrs.domain;
}
Json::Value inputStream = jv["pipodata"]["streamAttributes"]["input"];
// setInputStreamAttributes(
// inputStream["hasTimeTags"].getDbl()//,
// //...
// );
return true;
}
//*/
int
PiPoHost::getOutputMaxFrames() {
return this->outputStreamAttrs.maxFrames;
return false;
}
//*/
......@@ -3,7 +3,6 @@
#include "PiPo.h"
#include "PiPoHost.h"
#include "PiPoCollection.h"
//#ifdef EXTERNAL_JSONCPP_PATH
#define EXTERNAL_JSONCPP_PATH "json.h"
......@@ -12,13 +11,12 @@
#define MIN_PIPO_SAMPLERATE (1.0 / 31536000000.0) /* once a year */
#define MAX_PIPO_SAMPLERATE (96000000000.0)
#define DEFAULT_PIPO_SAMPLERATE 1000.0
#define PIPO_OUT_RING_SIZE 2
struct pipoStreamAttributes {
pipoStreamAttributes() : // default parameters suited for audio
struct RapidPiPoStreamAttributes {
RapidPiPoStreamAttributes() : // default parameters suited for audio
hasTimeTags(false),
rate(MIN_PIPO_SAMPLERATE),
rate(DEFAULT_PIPO_SAMPLERATE),
offset(0),
width(1),
height(1),
......@@ -38,212 +36,25 @@ struct pipoStreamAttributes {
unsigned int maxFrames;
};
//class PiPoObserver;
class PiPoOut;
//================================ H O S T ===================================//
class PiPoHost : public PiPo::Parent {
friend class PiPoOut;
private:
PiPo *graph;
std::string graphName;
PiPoOut *out;
// PiPoObserver *obs;
PiPoStreamAttributes inputStreamAttrs;
PiPoStreamAttributes outputStreamAttrs;
class RapidPiPoHost : public PiPoHost {
public:
// PiPoHost(PiPoObserver *obs);
PiPoHost();
~PiPoHost();
// PiPoObserver *getObserver();
virtual bool setGraph(std::string name);
virtual void clearGraph();
// override this method when inheriting !!!
virtual void onNewFrameOut(double time, std::vector<PiPoValue> &frame);
virtual std::vector<PiPoValue> getLastFrameOut();
virtual int setInputStreamAttributes(pipoStreamAttributes &sa, bool propagate = true);
virtual pipoStreamAttributes getOutputStreamAttributes();
virtual int frames(double time, double weight, PiPoValue *values, unsigned int size,
unsigned int num);
// virtual bool setAttr(const std::string &attrName, bool value);
// virtual bool setAttr(const std::string &attrName, int value);
virtual bool setAttr(const std::string &attrName, double value);
virtual bool setAttr(const std::string &attrName, const std::vector<double> &values);
virtual bool setAttr(const std::string &attrName, const std::string &value); // for enums
// virtual const std::vector<std::string>& getAttrNames();
// virtual bool isBoolAttr(const std::string &attrName);
// virtual bool isEnumAttr(const std::string &attrName);
// virtual bool isIntAttr(const std::string &attrName);
// virtual bool isIntArrayAttr(const std::string &attrName);
// virtual bool isFloatAttr(const std::string &attrName);
// virtual bool isFloatArrayAttr(const std::string &attrName);
// virtual bool isStringAttr(const std::string &attrName);
virtual std::vector<std::string> getAttrNames();
virtual double getDoubleAttr(const std::string &attrName);
virtual std::vector<double> getDoubleArrayAttr(const std::string &attrName);
virtual std::string getEnumAttr(const std::string &attrName);
/** Get a JSON representation of the model in the form of a styled string */
virtual std::string getJSON();
/** Write a JSON model description to specified file path */
virtual void writeJSON(const std::string &filepath);
/** configure empty model with string. See getJSON() */
virtual bool putJSON(const std::string &jsonMessage);
/** read a JSON file at file path and build a modelSet from it */
virtual bool readJSON(const std::string &filepath);
virtual int setInputStreamAttributes(RapidPiPoStreamAttributes &a);
virtual void onNewFrame(double time, double weight, PiPoValue *values, unsigned int size);
/** Get a JSON representation of the model in the form of a styled string */
virtual std::string getJSON();
/** Write a JSON model description to specified file path */
virtual void writeJSON(const std::string &filepath);
/** configure empty model with string. See getJSON() */
virtual bool putJSON(const std::string &jsonMessage);
/** read a JSON file at file path and build a modelSet from it */
virtual bool readJSON(const std::string &filepath);
// int streamAttributes(bool hasTimeTags, double rate, double offset,
// unsigned int width, unsigned int height,
// const std::vector<std::string> &labels,
// bool hasVarSize, double domain, unsigned int maxFrames,
// bool propagate = true);
// void propagateInputAttributes();
// void streamAttributesChanged(PiPo *pipo, PiPo::Attr *attr);
// void signalError(PiPo *pipo, std::string errorMsg);
// void signalWarning(PiPo *pipo, std::string warningMsg);
/*
void setInputHasTimeTags(bool hasTimeTags, bool propagate = true);
void setInputFrameRate(double rate, bool propagate = true);
void setInputFrameOffset(double offset, bool propagate = true);
void setInputDims(int width, int height, bool propagate = true);
void setInputLabels(const std::vector<std::string> &labels, bool propagate = true);
void setInputHasVarSize(bool hasVarSize, bool propagate = true);
void setInputDomain(double domain, bool propagate = true);
void setInputMaxFrames(int maxFrames, bool propagate = true);
bool getInputHasTimeTags();
double getInputFrameRate();
double getInputFrameOffset();
void getInputDims(int &width, int &height);
void getInputLabels(std::vector<std::string> &labels);
bool getInputHasVarSize();
double getInputDomain();
int getInputMaxFrames();
bool getOutputHasTimeTags();
double getOutputFrameRate();
double getOutputFrameOffset();
void getOutputDims(int &width, int &height);
void getOutputLabels(std::vector<std::string> &labels);
bool getOutputHasVarSize();
double getOutputDomain();
int getOutputMaxFrames();
// void setPiPoParam(PiPoParam *param);
//*/
protected:
private:
Json::Value toJSON();
bool fromJSON(Json::Value &jv);
private:
int propagateInputStreamAttributes();
void setOutputAttributes(bool hasTimeTags, double rate, double offset,
unsigned int width, unsigned int height,
const char **labels, bool hasVarSize,
double domain, unsigned int maxFrames);
};
//================================= PiPoOut ==================================//
class PiPoOut : public PiPo {
private:
PiPoHost *host;
std::atomic<int> writeIndex, readIndex;
std::vector<std::vector<PiPoValue>> ringBuffer;
// std::function<void(std::vector<PiPoValue>, PiPoObserver *rpo)> frameCallback;
// std::function<void(std::vector<PiPoValue>)> simpleFrameCallback;
public:
PiPoOut(PiPoHost *host) :
PiPo((PiPo::Parent *)host) {
this->host = host;
writeIndex = 0;
readIndex = 0;
ringBuffer.resize(PIPO_OUT_RING_SIZE);
}
~PiPoOut() {}
int streamAttributes(bool hasTimeTags,
double rate, double offset,
unsigned int width, unsigned int height,
const char **labels, bool hasVarSize,
double domain, unsigned int maxFrames) {
this->host->setOutputAttributes(hasTimeTags, rate, offset, width, height,
labels, hasVarSize, domain, maxFrames);
for (int i = 0; i < PIPO_OUT_RING_SIZE; ++i) {
ringBuffer[i].resize(width * height);
}
return 0;
}
int frames(double time, double weight, float *values,
unsigned int size, unsigned int num) {
if (num > 0) {
for (int i = 0; i < num; ++i) {
for (int j = 0; j < size; ++j) {
ringBuffer[writeIndex][j] = values[i * size + j];
}
// atomic swap ?
writeIndex = 1 - writeIndex;
readIndex = 1 - writeIndex;
this->host->onNewFrameOut(time, ringBuffer[readIndex]);
if (writeIndex + 1 == PIPO_OUT_RING_SIZE) {
writeIndex = 0;
} else {
writeIndex++;
}
}
}
return 0;
}
//void setFrameCallback(std::function<void(std::vector<PiPoValue>,
// PiPoObserver *obs)> f) {
// frameCallback = f;
//}
// void setSimpleFrameCallback(std::function<void(std::vector<PiPoValue>)> f) {
// simpleFrameCallback = f;
// }
std::vector<PiPoValue> getLastFrame() {
std::vector<PiPoValue> f;
if (readIndex > -1) {
f = ringBuffer[readIndex];
}
return f;
}
};
#endif /* _RAPID_PIPO_HOST_H_ */
......@@ -3,7 +3,7 @@
#include "rapidPiPoHost.h"
typedef PiPoHost pipoHost;
typedef pipoStreamAttributes pipoStreamAttributes;
typedef RapidPiPoStreamAttributes signalAttributes;
typedef RapidPiPoHost signalProcessingHost;
# endif /* _RAPID_PIPO_TOOLS_H_ */
#endif /* _RAPID_PIPO_TOOLS_H_ */