Hi @dvbridges, thank you for this suggestion.
I included the code you suggested in the code component in Psychopy (screenshots below), synced it with Pavlovia, but the marker size is still not affected.
I created a separate program with just the slider, to make things easier for this troubleshooting (Pavlovia). Please see below for the code after syncing. Wondering if you might be able to catch an issue here that I am missing. Thank you so much for helping troubleshoot this!
/*************************
* Affective_Slider Test *
*************************/
import { PsychoJS } from 'https://pavlovia.org/lib/core-3.2.js';
import * as core from 'https://pavlovia.org/lib/core-3.2.js';
import { TrialHandler } from 'https://pavlovia.org/lib/data-3.2.js';
import { Scheduler } from 'https://pavlovia.org/lib/util-3.2.js';
import * as util from 'https://pavlovia.org/lib/util-3.2.js';
import * as visual from 'https://pavlovia.org/lib/visual-3.2.js';
import { Sound } from 'https://pavlovia.org/lib/sound-3.2.js';
// init psychoJS:
var psychoJS = new PsychoJS({
debug: true
});
// open window:
psychoJS.openWindow({
fullscr: true,
color: new util.Color([0, 0, 0]),
units: 'height',
waitBlanking: true
});
// store info about the experiment session:
let expName = 'affective_slider'; // from the Builder filename that created this script
let expInfo = {'participant': '', 'session': '001'};
// schedule the experiment:
psychoJS.schedule(psychoJS.gui.DlgFromDict({
dictionary: expInfo,
title: expName
}));
const flowScheduler = new Scheduler(psychoJS);
const dialogCancelScheduler = new Scheduler(psychoJS);
psychoJS.scheduleCondition(function() { return (psychoJS.gui.dialogComponent.button === 'OK'); }, flowScheduler, dialogCancelScheduler);
// flowScheduler gets run if the participants presses OK
flowScheduler.add(updateInfo); // add timeStamp
flowScheduler.add(experimentInit);
flowScheduler.add(trialRoutineBegin);
flowScheduler.add(trialRoutineEachFrame);
flowScheduler.add(trialRoutineEnd);
flowScheduler.add(quitPsychoJS, '', true);
// quit if user presses Cancel in dialog box:
dialogCancelScheduler.add(quitPsychoJS, '', false);
psychoJS.start({expName, expInfo});
var frameDur;
function updateInfo() {
expInfo['date'] = util.MonotonicClock.getDateStr(); // add a simple timestamp
expInfo['expName'] = expName;
expInfo['psychopyVersion'] = '3.2.4';
expInfo['OS'] = window.navigator.platform;
// store frame rate of monitor if we can measure it successfully
expInfo['frameRate'] = psychoJS.window.getActualFrameRate();
if (typeof expInfo['frameRate'] !== 'undefined')
frameDur = 1.0/Math.round(expInfo['frameRate']);
else
frameDur = 1.0/60.0; // couldn't get a reliable measure so guess
// add info from the URL:
util.addInfoFromUrl(expInfo);
return Scheduler.Event.NEXT;
}
var trialClock;
var Slider1;
var Intensity_Cue_1;
var Intensity_Cue_2;
var Happy;
var Unhappy;
var wideawake;
var sleepy;
var col;
var newMarkerSize;
var Slider2;
var key_resp;
var globalClock;
var routineTimer;
function experimentInit() {
// Initialize components for Routine "trial"
trialClock = new util.Clock();
Slider1 = new visual.Slider({
win: psychoJS.window, name: 'Slider1',
size: [0.97, 0.01], pos: [0, (- 0.35)], units: 'height',
labels: undefined, ticks: [0, 100],
granularity: 0, style: [visual.Slider.Style.RATING],
color: new util.Color('white'),
fontFamily: 'Arial', bold: true, italic: false,
flip: false,
});
Intensity_Cue_1 = new visual.ImageStim({
win : psychoJS.window,
name : 'Intensity_Cue_1', units : undefined,
image : 'PNGs/AS_intensity_cue.png', mask : undefined,
ori : 0, pos : [0, (- 0.2)], size : [1, 0.07],
color : new util.Color([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 128, interpolate : true, depth : -1.0
});
Intensity_Cue_2 = new visual.ImageStim({
win : psychoJS.window,
name : 'Intensity_Cue_2', units : undefined,
image : 'PNGs/AS_intensity_cue.png', mask : undefined,
ori : 0, pos : [0, (- 0.42)], size : [1, 0.07],
color : new util.Color([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 128, interpolate : true, depth : -2.0
});
Happy = new visual.ImageStim({
win : psychoJS.window,
name : 'Happy', units : undefined,
image : 'PNGs/AS_happy.png', mask : undefined,
ori : 0, pos : [0.56, (- 0.39)], size : [0.13, 0.13],
color : new util.Color([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 128, interpolate : true, depth : -3.0
});
Unhappy = new visual.ImageStim({
win : psychoJS.window,
name : 'Unhappy', units : undefined,
image : 'PNGs/AS_unhappy.png', mask : undefined,
ori : 0, pos : [(- 0.56), (- 0.39)], size : [0.13, 0.13],
color : new util.Color([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 128, interpolate : true, depth : -4.0
});
wideawake = new visual.ImageStim({
win : psychoJS.window,
name : 'wideawake', units : undefined,
image : 'PNGs/AS_wideawake.png', mask : undefined,
ori : 0, pos : [0.56, (- 0.17)], size : [0.13, 0.13],
color : new util.Color([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 128, interpolate : true, depth : -5.0
});
sleepy = new visual.ImageStim({
win : psychoJS.window,
name : 'sleepy', units : undefined,
image : 'PNGs/AS_sleepy.png', mask : undefined,
ori : 0, pos : [(- 0.56), (- 0.17)], size : [0.13, 0.13],
color : new util.Color([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 128, interpolate : true, depth : -6.0
});
// Begin Experiment
col = new util.Color('black') // Create your color once
newMarkerSize = 100 // in pixels
Slider2 = new visual.Slider({
win: psychoJS.window, name: 'Slider2',
size: [0.97, 0.01], pos: [0, (- 0.13)], units: 'height',
labels: undefined, ticks: [1, 100],
granularity: 0, style: [visual.Slider.Style.RATING],
color: new util.Color('white'),
fontFamily: 'HelveticaBold', bold: true, italic: false,
flip: false,
});
key_resp = new core.Keyboard({psychoJS, clock: new util.Clock(), waitForStart: true});
// Create some handy timers
globalClock = new util.Clock(); // to track the time since experiment started
routineTimer = new util.CountdownTimer(); // to track time remaining of each (non-slip) routine
return Scheduler.Event.NEXT;
}
var t;
var frameN;
var trialComponents;
function trialRoutineBegin() {
//------Prepare to start Routine 'trial'-------
t = 0;
trialClock.reset(); // clock
frameN = -1;
// update component parameters for each repeat
Slider1.reset()
// Each Frame
try {
if (Slider1.markerColor.int !== col.int) {
Slider1.markerColor = col;
Slider1.marker.lineStyle(1, col.int, 1, 0.5);
Slider1.marker.beginFill(col.int, 1);
Slider1.marker.drawCircle(0, 0, newMarkerSize / 2);
Slider1.marker.endFill();
Slider1.needUpdate = true;
Slider1.updateIfNeeded();
}
} catch (err) {}
try {
if (Slider2.markerColor.int !== col.int) {
Slider2.markerColor = col;
Slider2.marker.lineStyle(1, col.int, 1, 0.5);
Slider2.marker.beginFill(col.int, 1);
Slider2.marker.drawCircle(0, 0, newMarkerSize / 2);
Slider2.marker.endFill();
Slider2.needUpdate = true;
Slider2.updateIfNeeded();
}
} catch (err) {}
Slider2.reset()
key_resp.keys = undefined;
key_resp.rt = undefined;
// keep track of which components have finished
trialComponents = [];
trialComponents.push(Slider1);
trialComponents.push(Intensity_Cue_1);
trialComponents.push(Intensity_Cue_2);
trialComponents.push(Happy);
trialComponents.push(Unhappy);
trialComponents.push(wideawake);
trialComponents.push(sleepy);
trialComponents.push(Slider2);
trialComponents.push(key_resp);
for (const thisComponent of trialComponents)
if ('status' in thisComponent)
thisComponent.status = PsychoJS.Status.NOT_STARTED;
return Scheduler.Event.NEXT;
}
var continueRoutine;
function trialRoutineEachFrame() {
//------Loop for each frame of Routine 'trial'-------
let continueRoutine = true; // until we're told otherwise
// get current time
t = trialClock.getTime();
frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
// update/draw components on each frame
// *Slider1* updates
if (t >= 0.0 && Slider1.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
Slider1.tStart = t; // (not accounting for frame time here)
Slider1.frameNStart = frameN; // exact frame index
Slider1.setAutoDraw(true);
}
// *Intensity_Cue_1* updates
if (t >= 0.0 && Intensity_Cue_1.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
Intensity_Cue_1.tStart = t; // (not accounting for frame time here)
Intensity_Cue_1.frameNStart = frameN; // exact frame index
Intensity_Cue_1.setAutoDraw(true);
}
// *Intensity_Cue_2* updates
if (t >= 0.0 && Intensity_Cue_2.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
Intensity_Cue_2.tStart = t; // (not accounting for frame time here)
Intensity_Cue_2.frameNStart = frameN; // exact frame index
Intensity_Cue_2.setAutoDraw(true);
}
// *Happy* updates
if (t >= 0.0 && Happy.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
Happy.tStart = t; // (not accounting for frame time here)
Happy.frameNStart = frameN; // exact frame index
Happy.setAutoDraw(true);
}
// *Unhappy* updates
if (t >= 0.0 && Unhappy.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
Unhappy.tStart = t; // (not accounting for frame time here)
Unhappy.frameNStart = frameN; // exact frame index
Unhappy.setAutoDraw(true);
}
// *wideawake* updates
if (t >= 0.0 && wideawake.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
wideawake.tStart = t; // (not accounting for frame time here)
wideawake.frameNStart = frameN; // exact frame index
wideawake.setAutoDraw(true);
}
// *sleepy* updates
if (t >= 0.0 && sleepy.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
sleepy.tStart = t; // (not accounting for frame time here)
sleepy.frameNStart = frameN; // exact frame index
sleepy.setAutoDraw(true);
}
// *Slider2* updates
if (t >= 0.0 && Slider2.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
Slider2.tStart = t; // (not accounting for frame time here)
Slider2.frameNStart = frameN; // exact frame index
Slider2.setAutoDraw(true);
}
// *key_resp* updates
if (t >= 0.0 && key_resp.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
key_resp.tStart = t; // (not accounting for frame time here)
key_resp.frameNStart = frameN; // exact frame index
// keyboard checking is just starting
psychoJS.window.callOnFlip(function() { key_resp.clock.reset(); }); // t=0 on next screen flip
psychoJS.window.callOnFlip(function() { key_resp.start(); }); // start on screen flip
psychoJS.window.callOnFlip(function() { key_resp.clearEvents(); });
}
if (key_resp.status === PsychoJS.Status.STARTED) {
let theseKeys = key_resp.getKeys({keyList: ['space'], waitRelease: false});
// check for quit:
if (theseKeys.length > 0 && theseKeys[0].name === 'escape') {
psychoJS.experiment.experimentEnded = true;
}
if (theseKeys.length > 0) { // at least one key was pressed
key_resp.keys = theseKeys[0].name; // just the last key pressed
key_resp.rt = theseKeys[0].rt;
// a response ends the routine
continueRoutine = false;
}
}
// check for quit (typically the Esc key)
if (psychoJS.experiment.experimentEnded || psychoJS.eventManager.getKeys({keyList:['escape']}).length > 0) {
return psychoJS.quit('The [Escape] key was pressed. Goodbye!', false);
}
// check if the Routine should terminate
if (!continueRoutine) { // a component has requested a forced-end of Routine
return Scheduler.Event.NEXT;
}
continueRoutine = false; // reverts to True if at least one component still running
for (const thisComponent of trialComponents)
if ('status' in thisComponent && thisComponent.status !== PsychoJS.Status.FINISHED) {
continueRoutine = true;
break;
}
// refresh the screen if continuing
if (continueRoutine) {
return Scheduler.Event.FLIP_REPEAT;
}
else {
return Scheduler.Event.NEXT;
}
}
function trialRoutineEnd() {
//------Ending Routine 'trial'-------
for (const thisComponent of trialComponents) {
if (typeof thisComponent.setAutoDraw === 'function') {
thisComponent.setAutoDraw(false);
}
}
psychoJS.experiment.addData('Slider1.response', Slider1.getRating());
psychoJS.experiment.addData('Slider1.rt', Slider1.getRT());
psychoJS.experiment.addData('Slider2.response', Slider2.getRating());
psychoJS.experiment.addData('Slider2.rt', Slider2.getRT());
psychoJS.experiment.addData('key_resp.keys', key_resp.keys);
if (typeof key_resp.keys !== undefined) { // we had a response
psychoJS.experiment.addData('key_resp.rt', key_resp.rt);
routineTimer.reset();
}
key_resp.stop();
// the Routine "trial" was not non-slip safe, so reset the non-slip timer
routineTimer.reset();
return Scheduler.Event.NEXT;
}
function endLoopIteration({thisScheduler, isTrials=true}) {
// ------Prepare for next entry------
return function () {
// ------Check if user ended loop early------
if (currentLoop.finished) {
// Check for and save orphaned data
if (Object.keys(psychoJS.experiment._thisEntry).length > 0) {
psychoJS.experiment.nextEntry();
}
thisScheduler.stop();
} else if (isTrials) {
psychoJS.experiment.nextEntry();
}
return Scheduler.Event.NEXT;
};
}
function importConditions(loop) {
const trialIndex = loop.getTrialIndex();
return function () {
loop.setTrialIndex(trialIndex);
psychoJS.importAttributes(loop.getCurrentTrial());
return Scheduler.Event.NEXT;
};
}
function quitPsychoJS(message, isCompleted) {
// Check for and save orphaned data
if (Object.keys(psychoJS.experiment._thisEntry).length > 0) {
psychoJS.experiment.nextEntry();
}
psychoJS.window.close();
psychoJS.quit({message: message, isCompleted: isCompleted});
return Scheduler.Event.QUIT;
}