Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsPsych as global variable #528

Merged
merged 13 commits into from
Aug 15, 2024
8 changes: 5 additions & 3 deletions src/App/components/JsPsychExperiment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default function JsPsychExperiment({
tempJsPsych.data.addProperties({
app_name: import.meta.env.PACKAGE_NAME,
app_version: import.meta.env.PACKAGE_VERSION,
app_commit: await window.electronAPI.getCommit(),
// app_commit: await window.electronAPI.getCommit(),
eldu marked this conversation as resolved.
Show resolved Hide resolved
study_id: studyID,
participant_id: participantID,
start_date: startDate,
Expand All @@ -67,8 +67,10 @@ export default function JsPsychExperiment({
*/
React.useEffect(() => {
if (jsPsych) {
const timeline = buildTimeline(jsPsych, studyID, participantID);
jsPsych.run(timeline);
// set up jsPsych object as global variable
window.jsPsych = jsPsych;
const timeline = buildTimeline(studyID, participantID);
window.jsPsych.run(timeline);
}
}, [jsPsych]);

Expand Down
10 changes: 5 additions & 5 deletions src/experiment/honeycomb.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@ export const honeycombOptions = {
* @param {Object} jsPsych The jsPsych instance being used to run the task
* @returns {Object} A jsPsych timeline object
*/
export function buildHoneycombTimeline(jsPsych) {
export function buildHoneycombTimeline() {
// Build the trials that make up the start procedure
const startProcedure = buildStartProcedure(jsPsych);
const startProcedure = buildStartProcedure();

// Build the trials that make up the task procedure
const honeycombProcedure = buildHoneycombProcedure(jsPsych);
const honeycombProcedure = buildHoneycombProcedure();

// Builds the trial needed to debrief the participant on their performance
const debriefTrial = buildDebriefTrial(jsPsych);
const debriefTrial = buildDebriefTrial();

// Builds the trials that make up the end procedure
const endProcedure = buildEndProcedure(jsPsych);
const endProcedure = buildEndProcedure();

const timeline = [
startProcedure,
Expand Down
4 changes: 2 additions & 2 deletions src/experiment/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ export const jsPsychOptions = honeycombOptions;
* @param {string} participantID The ID of the participant that was just logged in
* @returns The timeline for JsPsych to run
*/
export function buildTimeline(jsPsych, studyID, participantID) {
export function buildTimeline(studyID, participantID) {
console.log(`Building timeline for participant ${participantID} on study ${studyID}`);

/**
* ! Your timeline should be built in a newly created function, not this one
* https://brown-ccv.github.io/honeycomb-docs/docs/quick_start#2-add-a-file-for-the-task
*/
const timeline = buildHoneycombTimeline(jsPsych);
const timeline = buildHoneycombTimeline();
return timeline;
}
4 changes: 2 additions & 2 deletions src/experiment/procedures/endProcedure.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import { exitFullscreenTrial } from "../trials/fullscreen";
* @param {Object} jsPsych The jsPsych instance being used to run the task
* @returns {Object} A jsPsych (nested) timeline object
*/
export function buildEndProcedure(jsPsych) {
export function buildEndProcedure() {
const procedure = [];

// Conditionally add the camera breakdown trials
if (ENV.USE_CAMERA) {
procedure.push(buildCameraEndTrial(jsPsych));
procedure.push(buildCameraEndTrial());
}

// Add the other trials needed to end the experiment
Expand Down
12 changes: 5 additions & 7 deletions src/experiment/procedures/honeycombProcedure.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ import { buildFixationTrial } from "../trials/fixation";
* @param {Object} jsPsych The jsPsych instance being used to run the task
* @returns {Object} A jsPsych (nested) timeline object
*/
export function buildHoneycombProcedure(jsPsych) {
export function buildHoneycombProcedure() {
const honeycombSettings = SETTINGS.honeycomb;

const fixationTrial = buildFixationTrial(jsPsych);

const fixationTrial = buildFixationTrial();
/**
* Displays a colored circle and waits for participant to response with a keyboard press
*
Expand All @@ -31,7 +29,7 @@ export function buildHoneycombProcedure(jsPsych) {
const taskTrial = {
type: imageKeyboardResponse,
// Display the image passed as a timeline variable
stimulus: jsPsych.timelineVariable("stimulus"),
stimulus: window.jsPsych.timelineVariable("stimulus"),
prompt: function () {
// Conditionally displays the photodiodeGhostBox
if (ENV.USE_PHOTODIODE) return photodiodeGhostBox;
Expand All @@ -42,15 +40,15 @@ export function buildHoneycombProcedure(jsPsych) {
data: {
// Record the correct_response passed as a timeline variable
code: eventCodes.honeycomb,
correct_response: jsPsych.timelineVariable("correct_response"),
correct_response: window.jsPsych.timelineVariable("correct_response"),
},
on_load: function () {
// Conditionally flashes the photodiode when the trial first loads
if (ENV.USE_PHOTODIODE) pdSpotEncode(eventCodes.honeycomb);
},
// Add a boolean value ("correct") to the data - if the user responded with the correct key or not
on_finish: function (data) {
data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);
data.correct = window.jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);
},
};

Expand Down
4 changes: 2 additions & 2 deletions src/experiment/procedures/startProcedure.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { introductionTrial } from "../trials/introduction";
* @param {Object} jsPsych The jsPsych instance being used to run the task
* @returns {Object} A jsPsych (nested) timeline object
*/
export function buildStartProcedure(jsPsych) {
export function buildStartProcedure() {
const procedure = [nameTrial, enterFullscreenTrial, introductionTrial];

// Conditionally add the photodiode setup trials
Expand All @@ -29,7 +29,7 @@ export function buildStartProcedure(jsPsych) {

// Conditionally add the camera setup trials
if (ENV.USE_CAMERA) {
procedure.push(buildCameraStartTrial(jsPsych));
procedure.push(buildCameraStartTrial());
}

// Return the block as a nested timeline
Expand Down
12 changes: 6 additions & 6 deletions src/experiment/trials/camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const WEBCAM_ID = "webcam";
// TODO @brown-ccv #301: Use jsPsych extension, deprecate this function
// TODO @brown-ccv #343: We should be able to make this work on both electron and browser?
// TODO @brown-ccv #301: Rolling save to the deployment (webm is a subset of mkv)
export function buildCameraStartTrial(jsPsych) {
export function buildCameraStartTrial() {
return {
timeline: [
{
Expand Down Expand Up @@ -48,7 +48,7 @@ export function buildCameraStartTrial(jsPsych) {
throw new Error("video recording is only available when running inside Electron");
}

const cameraRecorder = jsPsych.pluginAPI.getCameraRecorder();
const cameraRecorder = window.jsPsych.pluginAPI.getCameraRecorder();
if (!cameraRecorder) {
console.error("Camera is not initialized, no data will be recorded.");
return;
Expand Down Expand Up @@ -76,11 +76,11 @@ export function buildCameraStartTrial(jsPsych) {
// Assign camera feed to the <video> element
const camera = document.getElementById(WEBCAM_ID);

camera.srcObject = jsPsych.pluginAPI.getCameraRecorder().stream;
camera.srcObject = window.jsPsych.pluginAPI.getCameraRecorder().stream;
},
on_finish: function () {
// Begin video recording
jsPsych.pluginAPI.getCameraRecorder().start();
window.jsPsych.pluginAPI.getCameraRecorder().start();
},
},
],
Expand All @@ -93,7 +93,7 @@ export function buildCameraStartTrial(jsPsych) {
* @param {Number} duration How long to show the trial for
* @returns {Object} A jsPsych trial object
*/
export function buildCameraEndTrial(jsPsych) {
export function buildCameraEndTrial() {
const recordingEndMarkup = h1(LANGUAGE.trials.camera.end);

return {
Expand All @@ -107,7 +107,7 @@ export function buildCameraEndTrial(jsPsych) {
throw new Error("video recording is only available when running inside Electron");
}

const cameraRecorder = jsPsych.pluginAPI.getCameraRecorder();
const cameraRecorder = window.jsPsych.pluginAPI.getCameraRecorder();
if (!cameraRecorder) {
console.error("Camera is not initialized, no data will be recorded.");
return;
Expand Down
7 changes: 5 additions & 2 deletions src/experiment/trials/fixation.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { div } from "../../lib/markup/tags";
* @param {Object} jsPsych The global jsPsych object used to build the trial
* @returns {Object} A jsPsych trial object
*/
export function buildFixationTrial(jsPsych) {
export function buildFixationTrial() {
const fixationSettings = SETTINGS.fixation;
const fixationCode = eventCodes.fixation;

Expand All @@ -27,7 +27,10 @@ export function buildFixationTrial(jsPsych) {
trial_duration: function () {
if (fixationSettings.randomize_duration) {
// Select a random duration from the durations array to show the fixation dot for
return jsPsych.randomization.sampleWithoutReplacement(fixationSettings.durations, 1)[0];
return window.jsPsych.randomization.sampleWithoutReplacement(
fixationSettings.durations,
1
)[0];
} else {
// Show the fixation dot for default duration seconds
return fixationSettings.default_duration;
Expand Down
4 changes: 2 additions & 2 deletions src/experiment/trials/honeycombTrials.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const preloadTrial = {
};

/** Trial that calculates and displays some results of the session */
export function buildDebriefTrial(jsPsych) {
export function buildDebriefTrial() {
return {
type: htmlKeyboardResponse,
stimulus: function () {
Expand All @@ -61,7 +61,7 @@ export function buildDebriefTrial(jsPsych) {
* By accessing jsPsych inside the "stimulus" callback we have access to all of the data when this trial is run
* Calling jsPsych outside of the trial object would be executed to soon (when the experiment first starts) and would therefore have no data
*/
const responseTrials = jsPsych.data.get().filter({ code: eventCodes.honeycomb });
const responseTrials = window.jsPsych.data.get().filter({ code: eventCodes.honeycomb });
const correct_trials = responseTrials.filter({ correct: true });
const accuracy = Math.round((correct_trials.count() / responseTrials.count()) * 100);
const reactionTime = Math.round(correct_trials.select("rt").mean());
Expand Down
Loading