define('RidgeThreadedReg', ['util', 'regression', 'matrix'], function(util, reg, mat) {
var ridgeParameter = Math.pow(10,-5);
var resizeWidth = 10;
var resizeHeight = 6;
var dataWindow = 700;
var weights = {'X':[0],'Y':[0]};
var trailDataWindow = 10;
function getEyeFeats(eyes) {
var resizedLeft = util.resizeEye(eyes.left, resizeWidth, resizeHeight);
var resizedright = util.resizeEye(eyes.right, resizeWidth, resizeHeight);
var leftGray = util.grayscale(resizedLeft.data, resizedLeft.width, resizedLeft.height);
var rightGray = util.grayscale(resizedright.data, resizedright.width, resizedright.height);
var histLeft = [];
util.equalizeHistogram(leftGray, 5, histLeft);
var histRight = [];
util.equalizeHistogram(rightGray, 5, histRight);
var leftGrayArray = Array.prototype.slice.call(histLeft);
var rightGrayArray = Array.prototype.slice.call(histRight);
return leftGrayArray.concat(rightGrayArray);
}
function updateWeights(event) {
console.log(event.data);
this.weights = event.data;
}
/**
* Constructor for the RidgeThreadedReg Object which uses unweighted ridge regression to correlate click and mouse movement to eye patch features
* This class has the same functionality as RidgeReg with two large differences:
* 1. training examples are batched for retraining the model instead of retraining on each new example
* 2. the training runs on a separate thread which should enable better running time
* @alias module:RidgeThreadedReg
* @exports RidgeThreadedReg
*/
var RidgeThreadedReg = function() {
this.screenXClicksArray = new util.DataWindow(dataWindow);
this.screenYClicksArray = new util.DataWindow(dataWindow);
this.eyeFeaturesClicks = new util.DataWindow(dataWindow);
this.screenXTrailArray = new util.DataWindow(trailDataWindow);
this.screenYTrailArray = new util.DataWindow(trailDataWindow);
this.eyeFeaturesTrail = new util.DataWindow(trailDataWindow);
this.dataClicks = new util.DataWindow(dataWindow);
this.dataTrail = new util.DataWindow(dataWindow);
this.worker = new Worker('../src/ridgeWorker.js');
this.worker.onerror = function(err) { console.log(err.message); };
this.worker.onmessage = function(event) {
weights = event.data;
};
}
/**
* adds data to the regression model
* @param {object} eyes - util.eyes Object containing left and right data
* @param {array} screenPos - the screen [x,y] position when a training event happens
* @param {string} type - the type of event
*/
RidgeThreadedReg.prototype.addData = function(eyes, screenPos, type) {
if (!eyes) {
return;
}
if (eyes.left.blink || eyes.right.blink) {
return;
}
this.worker.postMessage({'eyes':getEyeFeats(eyes), 'screenPos':screenPos, 'type':type})
}
/**
* gets a prediction based on the current set of training data
* @param {object} eyesObj - util.eyes Object
* @return {Object} prediction - Object containing the prediction data
* @return {integer} prediction.x - the x screen coordinate predicted
* @return {integer} prediction.y - the y screen coordinate predicted
*/
RidgeThreadedReg.prototype.predict = function(eyesObj) {
console.log('in predict1');
if (!eyesObj) {
return null;
}
console.log(weights);
var coefficientsX = weights.X;
var coefficientsY = weights.Y;
var eyeFeats = getEyeFeats(eyesObj);
var predictedX = 0;
for(var i=0; i< eyeFeats.length; i++){
predictedX += eyeFeats[i] * coefficientsX[i];
}
var predictedY = 0;
for(var i=0; i< eyeFeats.length; i++){
predictedY += eyeFeats[i] * coefficientsY[i];
}
predictedX = Math.floor(predictedX);
predictedY = Math.floor(predictedY);
return {
x: predictedX,
y: predictedY
};
}
/**
* seeds the model with initial training data in case data is stored in a separate location
* @params {Object[]} data - array of util.eyes objects
*/
RidgeThreadedReg.prototype.setData = function(data) {
for (var i = 0; i < data.length; i++) {
//TODO this is a kludge, needs to be fixed
data[i].eyes.left.patch = new ImageData(new Uint8ClampedArray(data[i].eyes.left.patch), data[i].eyes.left.width, data[i].eyes.left.height);
data[i].eyes.right.patch = new ImageData(new Uint8ClampedArray(data[i].eyes.right.patch), data[i].eyes.right.width, data[i].eyes.right.height);
this.addData(data[i].eyes, data[i].screenPos, data[i].type);
}
}
/**
* gets the training data stored in this regression model, *this is not the model itself, but merely its training data*
* @return {Object[]} the set of training data stored in this regression class
*/
RidgeThreadedReg.prototype.getData = function() {
return this.dataClicks.data.concat(this.dataTrail.data);
}
RidgeThreadedReg.prototype.name = 'RidgeThreadedReg';
return RidgeThreadedReg;
});