diff --git a/examples/webgazer.html b/examples/webgazer.html
index e0790a65..ec2a21f9 100644
--- a/examples/webgazer.html
+++ b/examples/webgazer.html
@@ -20,17 +20,20 @@
var calibration = {
type: 'webgazer-calibrate',
- calibration_points: [[50,50], [25,25], [25,75], [75,25], [75,75]],
+ //calibration_points: [[50,50], [25,25], [25,75], [75,25], [75,75]],
+ calibration_points: [[10,10],[10,30],[10,50],[10,70],[10,90],[30,10],[30,30],[30,50],[30,70],[30,90],[50,10],[50,30],[50,50],[50,70],[50,90],[70,10],[70,30],[70,50],[70,70],[70,90],[90,10],[90,30],[90,50],[90,70],[90,90]],
repetitions_per_point: 1,
randomize_calibration_order: true,
- time_per_point: 1000,
+ //calibration_mode: 'view',
+ time_per_point: 500,
time_to_saccade: 1000
}
var validation = {
type: 'webgazer-validate',
validation_points: [[-200,-200], [-200,200], [200,-200], [200,200]],
- validation_point_mode: 'center-offset-pixels'
+ validation_point_coordinates: 'center-offset-pixels',
+ show_validation_data: true
}
var fixation = {
diff --git a/extensions/jspsych-ext-webgazer.js b/extensions/jspsych-ext-webgazer.js
index b1e3ee63..e9eb3080 100644
--- a/extensions/jspsych-ext-webgazer.js
+++ b/extensions/jspsych-ext-webgazer.js
@@ -70,7 +70,7 @@ jsPsych.extensions['webgazer'] = (function () {
// send back the gazeData
return {
- gazeData: JSON.stringify(state.currentTrialData)
+ webgazer_gaze_data: state.currentTrialData
}
}
diff --git a/plugins/jspsych-webgazer-calibrate.js b/plugins/jspsych-webgazer-calibrate.js
index ca01582e..5f92f445 100644
--- a/plugins/jspsych-webgazer-calibrate.js
+++ b/plugins/jspsych-webgazer-calibrate.js
@@ -15,6 +15,10 @@ jsPsych.plugins["webgazer-calibrate"] = (function() {
type: jsPsych.plugins.parameterType.INT,
default: [[10,10], [10,50], [10,90], [50,10], [50,50], [50,90], [90,10], [90,50], [90,90]]
},
+ calibration_mode: {
+ type: jsPsych.plugins.parameterType.STRING,
+ default: 'click', // options: 'click', 'view'
+ },
repetitions_per_point: {
type: jsPsych.plugins.parameterType.INT,
default: 1
@@ -64,10 +68,6 @@ jsPsych.plugins["webgazer-calibrate"] = (function() {
"
Use the video in the upper-left corner as a guide. Center your face in the box.
"+
"When your face is centered in the box and the box turns green, you can click to continue.
"+
""
- // "Quality of detection:
"+
- // ""+
""
@@ -81,20 +81,7 @@ jsPsych.plugins["webgazer-calibrate"] = (function() {
document.querySelector('#jspsych-wg-cont').addEventListener('click', function(){
observer.disconnect();
show_begin_calibrate_message();
- })
-
- // function waitForFace(){
- // var score = check_face_score();
- // //wg_container.querySelector('#video-detect-quality-inner').style.width = (score*100) + "%"
- // if(score){
- // document.querySelector('#jspsych-wg-cont').disabled = false;
- // } else {
- // requestAnimationFrame(waitForFace);
- // }
- // }
- // requestAnimationFrame(waitForFace);
-
-
+ })
}
function face_detect_event_observer(mutationsList, observer){
@@ -110,12 +97,22 @@ jsPsych.plugins["webgazer-calibrate"] = (function() {
function show_begin_calibrate_message(){
jsPsych.extensions['webgazer'].hideVideo();
- wg_container.innerHTML = ""+
+ if(trial.calibration_mode == 'view'){
+ wg_container.innerHTML = "
"+
+ "
Great! Now the eye tracker will be calibrated to translate the image of your eyes from the webcam to a location on your screen.
"+
+ "
To do this, you need to look at a series of dots.
"+
+ "
Keep your head still, and focus on each dot as quickly as possible. Keep your gaze fixed on the dot for as long as it is on the screen.
"+
+ "
"+
+ "
"
+ }
+ if(trial.calibration_mode == 'click'){
+ wg_container.innerHTML = "
"+
"
Great! Now the eye tracker will be calibrated to translate the image of your eyes from the webcam to a location on your screen.
"+
- "
To do this, you need to look at a series of dots.
"+
- "
Keep your head still, and focus on each dot as quickly as possible. Keep your gaze fixed on the dot for as long as it is on the screen.
"+
+ "
To do this, you need to click a series of dots.
"+
+ "
Keep your head still, and click on each dot as it appears. Look at the dot as you click it.
"+
"
"+
"
"
+ }
document.querySelector('#begin-calibrate-btn').addEventListener('click', function(){
calibrate();
});
@@ -127,6 +124,9 @@ jsPsych.plugins["webgazer-calibrate"] = (function() {
function calibrate(){
jsPsych.extensions['webgazer'].resume();
+ if(trial.calibration_mode == 'click'){
+ jsPsych.extensions['webgazer'].startMouseCalibration();
+ }
next_calibration_round();
}
@@ -160,36 +160,40 @@ jsPsych.plugins["webgazer-calibrate"] = (function() {
wg_container.innerHTML = pt_html;
var pt_dom = wg_container.querySelector('#calibration-point');
-
- var br = pt_dom.getBoundingClientRect();
- var x = br.left + br.width / 2;
- var y = br.top + br.height / 2;
-
- var pt_start_cal = performance.now() + trial.time_to_saccade;
- var pt_finish = performance.now() + trial.time_to_saccade + trial.time_per_point;
- requestAnimationFrame(function watch_dot(){
-
- if(performance.now() > pt_start_cal){
- jsPsych.extensions['webgazer'].calibratePoint(x,y,'click');
- }
- if(performance.now() < pt_finish){
- requestAnimationFrame(watch_dot);
- } else {
+ if(trial.calibration_mode == 'click'){
+ pt_dom.style.cursor = 'pointer';
+ pt_dom.addEventListener('click', function(){
next_calibration_point();
- }
- })
-
- // jsPsych.pluginAPI.setTimeout(function(){
- // pt_dom.style.backgroundColor = "#fff";
- // pt_dom.addEventListener('click', function(){
- // next_calibration_point();
- // });
- // }, Math.random()*(trial.maximum_dot_change_delay-trial.minimum_dot_change_delay)+trial.minimum_dot_change_delay);
+ })
+ }
+
+ if(trial.calibration_mode == 'view'){
+ var br = pt_dom.getBoundingClientRect();
+ var x = br.left + br.width / 2;
+ var y = br.top + br.height / 2;
+ var pt_start_cal = performance.now() + trial.time_to_saccade;
+ var pt_finish = performance.now() + trial.time_to_saccade + trial.time_per_point;
+
+ requestAnimationFrame(function watch_dot(){
+
+ if(performance.now() > pt_start_cal){
+ jsPsych.extensions['webgazer'].calibratePoint(x,y,'click');
+ }
+ if(performance.now() < pt_finish){
+ requestAnimationFrame(watch_dot);
+ } else {
+ next_calibration_point();
+ }
+ })
+ }
}
function calibration_done(){
+ if(trial.calibration_mode == 'click'){
+ jsPsych.extensions['webgazer'].stopMouseCalibration();
+ }
wg_container.innerHTML = "";
end_trial();
}
diff --git a/plugins/jspsych-webgazer-validate.js b/plugins/jspsych-webgazer-validate.js
index a314353b..8f63eeff 100644
--- a/plugins/jspsych-webgazer-validate.js
+++ b/plugins/jspsych-webgazer-validate.js
@@ -15,7 +15,7 @@ jsPsych.plugins["webgazer-validate"] = (function() {
type: jsPsych.plugins.parameterType.INT,
default: [[10,10], [10,50], [10,90], [50,10], [50,50], [50,90], [90,10], [90,50], [90,90]]
},
- validation_point_mode: {
+ validation_point_coordinates: {
type: jsPsych.plugins.parameterType.STRING,
default: 'percent' // options: 'percent', 'center-offset-pixels'
},
@@ -34,21 +34,20 @@ jsPsych.plugins["webgazer-validate"] = (function() {
point_size:{
type: jsPsych.plugins.parameterType.INT,
default: 10
+ },
+ show_validation_data: {
+ type: jsPsych.plugins.parameterType.BOOL,
+ default: false
}
}
}
- // provide options for calibration routines?
- // dot clicks?
- // track a dot with mouse?
-
- // then a validation phase of staring at the dot in different locations?
-
plugin.trial = function(display_element, trial) {
var trial_data = {}
trial_data.raw_gaze = [];
trial_data.percent_in_roi = [];
+ trial_data.average_offset = [];
var html = `
@@ -125,22 +124,15 @@ jsPsych.plugins["webgazer-validate"] = (function() {
trial_data.raw_gaze.push(pt_data);
next_validation_point();
}
- })
-
- // jsPsych.pluginAPI.setTimeout(function(){
- // pt_dom.style.backgroundColor = "#fff";
- // pt_dom.addEventListener('click', function(){
- // next_calibration_point();
- // });
- // }, Math.random()*(trial.maximum_dot_change_delay-trial.minimum_dot_change_delay)+trial.minimum_dot_change_delay);
+ });
}
function drawValidationPoint(x,y){
- if(trial.validation_point_mode == 'percent'){
+ if(trial.validation_point_coordinates == 'percent'){
return drawValidationPoint_PercentMode(x,y);
}
- if(trial.validation_point_mode == 'center-offset-pixels'){
+ if(trial.validation_point_coordinates == 'center-offset-pixels'){
return drawValidationPoint_CenterOffsetMode(x,y);
}
}
@@ -154,43 +146,45 @@ jsPsych.plugins["webgazer-validate"] = (function() {
}
function drawCircle(target_x, target_y, dx, dy, r){
- if(trial.validation_point_mode == 'percent'){
+ if(trial.validation_point_coordinates == 'percent'){
return drawCircle_PercentMode(target_x, target_y, dx, dy, r);
}
- if(trial.validation_point_mode == 'center-offset-pixels'){
+ if(trial.validation_point_coordinates == 'center-offset-pixels'){
return drawCircle_CenterOffsetMode(target_x, target_y, dx, dy, r);
}
}
function drawCircle_PercentMode(target_x, target_y, dx, dy, r){
var html = `
-
+
`
return html;
}
function drawCircle_CenterOffsetMode(target_x, target_y, dx, dy, r){
var html = `
-
+
`
return html;
}
function drawRawDataPoint(target_x, target_y, dx, dy, ){
- if(trial.validation_point_mode == 'percent'){
+ if(trial.validation_point_coordinates == 'percent'){
return drawRawDataPoint_PercentMode(target_x, target_y, dx, dy);
}
- if(trial.validation_point_mode == 'center-offset-pixels'){
+ if(trial.validation_point_coordinates == 'center-offset-pixels'){
return drawRawDataPoint_CenterOffsetMode(target_x, target_y, dx, dy);
}
}
function drawRawDataPoint_PercentMode(target_x, target_y, dx, dy){
- return `
`
+ var color = Math.sqrt(dx*dx + dy*dy) <= trial.roi_radius ? '#afa' : '#faa';
+ return `
`
}
function drawRawDataPoint_CenterOffsetMode(target_x, target_y, dx, dy){
- return `
`
+ var color = Math.sqrt(dx*dx + dy*dy) <= trial.roi_radius ? '#afa' : '#faa';
+ return `
`
}
function median(arr){
@@ -247,23 +241,31 @@ jsPsych.plugins["webgazer-validate"] = (function() {
}
function validation_done(){
+ for(var i=0; i
Continue';
+ html += '