Commit ab69311a authored by Jonathan Peirce's avatar Jonathan Peirce

First commit

parent 2dae7afb
Selectively inspect an image
=======================================
This demo shows the flexibility of dynamic stimuli.
We create an experiment where participants can only see a portion of the image by creating an image (called circleMask.png in this case) that we use to occlude our stimulus images. We set the circleMask to be the "mask" of an image stimulus.
You can see that this sort of dynamic stimulus is useful in various ways:
- you could see what parts of an image people choose to look at while gathering info
- with an eyetracker you could make it a gaze-contingent display and see what happens when the peripheral vision is not permitted (or reverse the mask and see what happens when viewers can *only* use their peripheral vision.
Details: what did we do?
-----------------------------
You can use any image as a mask. When you do this the opacity of the ImageStimulus is determined by the brightness of the pixels in the mask. If you look at the image circleAperture.png you'll see that most of the pixels are white (which will be opqaue) and just a few pixels (a circle in the center of the screen) are black. For this particular mask we've set the image to be 512x512 pixels and then drawn a circle of 20 pixels diameter in the center. We've then smoothed that with a gaussian blur of 10 pixels to give it a nice smooth edge.
We've then applied that image to an Image Component that we've called imageAperture and that has an image set to `color` and the color itself is `white` (meaning that no image is being superimposed, just a white mask). We've set the mask to be our mask image file and we've set the size to be 4x4 in `height` units (so that the outer edges of the mask image are always beyond the screen). You can see how that works by shrinking the size of the imageAperture, as we've done in the `showMeHow` Routine.
The final effect is an aperture that follows the mouse (we've turned on the mouse cursor in the experiment settings so you can see what's happening).
File added
<?xml version="1.0" ?>
<PsychoPy2experiment encoding="utf-8" version="3.0.0alpha3">
<Settings>
<Param name="Monitor" updates="None" val="testMonitor" valType="str"/>
<Param name="color" updates="None" val="$[0,0,0]" valType="str"/>
<Param name="colorSpace" updates="None" val="rgb" valType="str"/>
<Param name="Experiment info" updates="None" val="{u'session': u'001', u'participant': u''}" valType="code"/>
<Param name="JS libs" updates="None" val="packaged" valType="str"/>
<Param name="Units" updates="None" val="height" valType="str"/>
<Param name="Save excel file" updates="None" val="False" valType="bool"/>
<Param name="Completion URL" updates="None" val="https://www.pavlovia.org" valType="str"/>
<Param name="Enable Escape" updates="None" val="True" valType="bool"/>
<Param name="Save psydat file" updates="None" val="True" valType="bool"/>
<Param name="Window size (pixels)" updates="None" val="[2560, 1440]" valType="code"/>
<Param name="Full-screen window" updates="None" val="True" valType="bool"/>
<Param name="blendMode" updates="None" val="avg" valType="str"/>
<Param name="Use version" updates="None" val="" valType="str"/>
<Param name="HTML path" updates="None" val="html" valType="str"/>
<Param name="Save csv file" updates="None" val="False" valType="bool"/>
<Param name="Save log file" updates="None" val="True" valType="bool"/>
<Param name="Save wide csv file" updates="None" val="True" valType="bool"/>
<Param name="Show mouse" updates="None" val="True" valType="bool"/>
<Param name="Data filename" updates="None" val="u'data/%s_%s_%s' % (expInfo['participant'], expName, expInfo['date'])" valType="code"/>
<Param name="Show info dlg" updates="None" val="False" valType="bool"/>
<Param name="expName" updates="None" val="inspect_images" valType="str"/>
<Param name="logging level" updates="None" val="exp" valType="code"/>
<Param name="Screen" updates="None" val="1" valType="num"/>
</Settings>
<Routines>
<Routine name="trial">
<ImageComponent name="imageStimulus">
<Param name="opacity" updates="constant" val="1" valType="code"/>
<Param name="flipVert" updates="constant" val="False" valType="bool"/>
<Param name="colorSpace" updates="constant" val="rgb" valType="str"/>
<Param name="flipHoriz" updates="constant" val="False" valType="bool"/>
<Param name="name" updates="None" val="imageStimulus" valType="code"/>
<Param name="color" updates="constant" val="$[1,1,1]" valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="mask" updates="constant" val="None" valType="str"/>
<Param name="pos" updates="constant" val="(0, 0)" valType="code"/>
<Param name="interpolate" updates="constant" val="linear" valType="str"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="units" updates="None" val="norm" valType="str"/>
<Param name="texture resolution" updates="constant" val="128" valType="code"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="ori" updates="constant" val="0" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="image" updates="set every repeat" val="$imageFile" valType="str"/>
<Param name="size" updates="constant" val="(2, 2)" valType="code"/>
</ImageComponent>
<ImageComponent name="imageAperture">
<Param name="opacity" updates="constant" val="1" valType="code"/>
<Param name="flipVert" updates="constant" val="False" valType="bool"/>
<Param name="colorSpace" updates="constant" val="rgb" valType="str"/>
<Param name="flipHoriz" updates="constant" val="False" valType="bool"/>
<Param name="name" updates="None" val="imageAperture" valType="code"/>
<Param name="color" updates="constant" val="$[1,1,1]" valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="mask" updates="constant" val="images/circleMask.png" valType="str"/>
<Param name="pos" updates="set every frame" val="mouse.getPos()" valType="code"/>
<Param name="interpolate" updates="constant" val="linear" valType="str"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="units" updates="None" val="height" valType="str"/>
<Param name="texture resolution" updates="constant" val="512" valType="code"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="ori" updates="constant" val="0" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="image" updates="constant" val="images/plainWhite.png" valType="str"/>
<Param name="size" updates="constant" val="(4, 4)" valType="code"/>
</ImageComponent>
<MouseComponent name="mouse">
<Param name="name" updates="None" val="mouse" valType="code"/>
<Param name="timeRelativeTo" updates="constant" val="routine" valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="forceEndRoutineOnPress" updates="constant" val="any click" valType="str"/>
<Param name="newClicksOnly" updates="constant" val="True" valType="bool"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="clickable" updates="constant" val="" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="saveParamsClickable" updates="constant" val="name," valType="code"/>
<Param name="saveMouseState" updates="None" val="final" valType="str"/>
</MouseComponent>
</Routine>
<Routine name="instruct">
<TextComponent name="instructFirst">
<Param name="opacity" updates="constant" val="1" valType="code"/>
<Param name="colorSpace" updates="constant" val="rgb" valType="str"/>
<Param name="name" updates="None" val="instructFirst" valType="code"/>
<Param name="wrapWidth" updates="constant" val="" valType="code"/>
<Param name="color" updates="constant" val="black" valType="str"/>
<Param name="text" updates="constant" val="On each trial you have to search the screen to find the ball&amp;#10;(by moving the mouse around)&amp;#10;&amp;#10;Click the mouse to get started" valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="pos" updates="constant" val="(0, 0.3)" valType="code"/>
<Param name="flip" updates="constant" val="" valType="str"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="units" updates="None" val="height" valType="str"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="ori" updates="constant" val="0" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="font" updates="constant" val="Arial" valType="str"/>
<Param name="languageStyle" updates="None" val="LTR" valType="str"/>
<Param name="letterHeight" updates="constant" val="0.05" valType="code"/>
</TextComponent>
<MouseComponent name="finishInstruct">
<Param name="name" updates="None" val="finishInstruct" valType="code"/>
<Param name="timeRelativeTo" updates="constant" val="Mouse onset" valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="forceEndRoutineOnPress" updates="constant" val="any click" valType="str"/>
<Param name="newClicksOnly" updates="constant" val="True" valType="bool"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="clickable" updates="constant" val="" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="saveParamsClickable" updates="constant" val="name," valType="code"/>
<Param name="saveMouseState" updates="None" val="never" valType="str"/>
</MouseComponent>
</Routine>
<Routine name="showMeHow">
<ImageComponent name="imageStimulus_2">
<Param name="opacity" updates="constant" val="1" valType="code"/>
<Param name="flipVert" updates="constant" val="False" valType="bool"/>
<Param name="colorSpace" updates="constant" val="rgb" valType="str"/>
<Param name="flipHoriz" updates="constant" val="False" valType="bool"/>
<Param name="name" updates="None" val="imageStimulus_2" valType="code"/>
<Param name="color" updates="constant" val="$[1,1,1]" valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="mask" updates="constant" val="None" valType="str"/>
<Param name="pos" updates="constant" val="(0, 0)" valType="code"/>
<Param name="interpolate" updates="constant" val="linear" valType="str"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="units" updates="None" val="norm" valType="str"/>
<Param name="texture resolution" updates="constant" val="128" valType="code"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="ori" updates="constant" val="0" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="image" updates="set every repeat" val="$imageFile" valType="str"/>
<Param name="size" updates="constant" val="(2, 2)" valType="code"/>
</ImageComponent>
<ImageComponent name="imageAperture_2">
<Param name="opacity" updates="constant" val="1" valType="code"/>
<Param name="flipVert" updates="constant" val="False" valType="bool"/>
<Param name="colorSpace" updates="constant" val="rgb" valType="str"/>
<Param name="flipHoriz" updates="constant" val="False" valType="bool"/>
<Param name="name" updates="None" val="imageAperture_2" valType="code"/>
<Param name="color" updates="constant" val="$[1,1,1]" valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="mask" updates="constant" val="images/circleMask.png" valType="str"/>
<Param name="pos" updates="set every frame" val="mouse.getPos()" valType="code"/>
<Param name="interpolate" updates="constant" val="linear" valType="str"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="units" updates="None" val="height" valType="str"/>
<Param name="texture resolution" updates="constant" val="512" valType="code"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="ori" updates="constant" val="0" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="image" updates="constant" val="images/plainWhite.png" valType="str"/>
<Param name="size" updates="constant" val="(1,1)" valType="code"/>
</ImageComponent>
<MouseComponent name="mouse_2">
<Param name="name" updates="None" val="mouse_2" valType="code"/>
<Param name="timeRelativeTo" updates="constant" val="Mouse onset" valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="forceEndRoutineOnPress" updates="constant" val="any click" valType="str"/>
<Param name="newClicksOnly" updates="constant" val="True" valType="bool"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="clickable" updates="constant" val="" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="saveParamsClickable" updates="constant" val="name," valType="code"/>
<Param name="saveMouseState" updates="None" val="on click" valType="str"/>
</MouseComponent>
</Routine>
<Routine name="explanation">
<TextComponent name="instruct2">
<Param name="opacity" updates="constant" val="1" valType="code"/>
<Param name="colorSpace" updates="constant" val="rgb" valType="str"/>
<Param name="name" updates="None" val="instruct2" valType="code"/>
<Param name="wrapWidth" updates="constant" val="" valType="code"/>
<Param name="color" updates="constant" val="black" valType="str"/>
<Param name="text" updates="constant" val="This is essentially the same thing but&amp;#10;the mask is now smaller ( w,h = 2,2 in height units) so you can see &amp;#10;what was happening." valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="pos" updates="constant" val="(0, 0.3)" valType="code"/>
<Param name="flip" updates="constant" val="" valType="str"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="units" updates="None" val="height" valType="str"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="ori" updates="constant" val="0" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="font" updates="constant" val="Arial" valType="str"/>
<Param name="languageStyle" updates="None" val="LTR" valType="str"/>
<Param name="letterHeight" updates="constant" val="0.05" valType="code"/>
</TextComponent>
<MouseComponent name="explanationFinish">
<Param name="name" updates="None" val="explanationFinish" valType="code"/>
<Param name="timeRelativeTo" updates="constant" val="Mouse onset" valType="str"/>
<Param name="stopVal" updates="constant" val="" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="forceEndRoutineOnPress" updates="constant" val="any click" valType="str"/>
<Param name="newClicksOnly" updates="constant" val="True" valType="bool"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="clickable" updates="constant" val="" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="saveParamsClickable" updates="constant" val="name," valType="code"/>
<Param name="saveMouseState" updates="None" val="never" valType="str"/>
</MouseComponent>
</Routine>
<Routine name="thanks">
<TextComponent name="text">
<Param name="opacity" updates="constant" val="1" valType="code"/>
<Param name="colorSpace" updates="constant" val="rgb" valType="str"/>
<Param name="name" updates="None" val="text" valType="code"/>
<Param name="wrapWidth" updates="constant" val="" valType="code"/>
<Param name="color" updates="constant" val="white" valType="str"/>
<Param name="text" updates="constant" val="That's all there is to it.&amp;#10;&amp;#10;Bye!" valType="str"/>
<Param name="stopVal" updates="constant" val="1.0" valType="code"/>
<Param name="durationEstim" updates="None" val="" valType="code"/>
<Param name="pos" updates="constant" val="(0, 0)" valType="code"/>
<Param name="flip" updates="constant" val="" valType="str"/>
<Param name="startEstim" updates="None" val="" valType="code"/>
<Param name="units" updates="None" val="from exp settings" valType="str"/>
<Param name="startType" updates="None" val="time (s)" valType="str"/>
<Param name="ori" updates="constant" val="0" valType="code"/>
<Param name="stopType" updates="None" val="duration (s)" valType="str"/>
<Param name="startVal" updates="None" val="0.0" valType="code"/>
<Param name="font" updates="constant" val="Arial" valType="str"/>
<Param name="languageStyle" updates="None" val="LTR" valType="str"/>
<Param name="letterHeight" updates="constant" val="0.1" valType="code"/>
</TextComponent>
</Routine>
</Routines>
<Flow>
<Routine name="instruct"/>
<LoopInitiator loopType="TrialHandler" name="trials">
<Param name="conditionsFile" updates="None" val="conditions.xlsx" valType="str"/>
<Param name="name" updates="None" val="trials" valType="code"/>
<Param name="isTrials" updates="None" val="True" valType="bool"/>
<Param name="random seed" updates="None" val="" valType="code"/>
<Param name="loopType" updates="None" val="random" valType="str"/>
<Param name="nReps" updates="None" val="1" valType="code"/>
<Param name="endPoints" updates="None" val="[0, 1]" valType="num"/>
<Param name="conditions" updates="None" val="[OrderedDict([('imageFile', 'images/7751347612_d058a3e8b3_k.jpg')]), OrderedDict([('imageFile', 'images/7751357630_520971b5f6_k.jpg')]), OrderedDict([('imageFile', 'images/7751351978_d87ea5d14e_k.jpg')])]" valType="str"/>
<Param name="Selected rows" updates="None" val="" valType="str"/>
</LoopInitiator>
<Routine name="trial"/>
<LoopTerminator name="trials"/>
<Routine name="explanation"/>
<LoopInitiator loopType="TrialHandler" name="showMeTrials">
<Param name="conditionsFile" updates="None" val="conditions.xlsx" valType="str"/>
<Param name="name" updates="None" val="showMeTrials" valType="code"/>
<Param name="isTrials" updates="None" val="True" valType="bool"/>
<Param name="random seed" updates="None" val="" valType="code"/>
<Param name="loopType" updates="None" val="random" valType="str"/>
<Param name="nReps" updates="None" val="1" valType="code"/>
<Param name="endPoints" updates="None" val="[0, 1]" valType="num"/>
<Param name="conditions" updates="None" val="[OrderedDict([('imageFile', 'images/7751347612_d058a3e8b3_k.jpg')]), OrderedDict([('imageFile', 'images/7751357630_520971b5f6_k.jpg')]), OrderedDict([('imageFile', 'images/7751351978_d87ea5d14e_k.jpg')])]" valType="str"/>
<Param name="Selected rows" updates="None" val="" valType="str"/>
</LoopInitiator>
<Routine name="showMeHow"/>
<LoopTerminator name="showMeTrials"/>
<Routine name="thanks"/>
</Flow>
</PsychoPy2experiment>
<!doctype html>
<html>
<head>
<title>inspect_images [PsychoPy]</title>
<meta charset="UTF-8">
<!-- external libraries -->
<script type="text/javascript" src="lib/vendors/seedrandom.min.js"></script>
<script type="text/javascript" src="lib/vendors/jquery-2.2.0.min.js"></script>
<script type="text/javascript" src="lib/vendors/jquery-ui-1.11.4.base/jquery-ui.min.js"></script>
<script type="text/javascript" src="lib/vendors/stats.min.js"></script>
<script type="text/javascript" src="lib/vendors/pixi.min.js"></script>
<script type="text/javascript" src="lib/vendors/preloadjs.min.js"></script>
<script type="text/javascript" src="lib/vendors/xlsx.full.min.js"></script>
<script type="text/javascript" src="lib/vendors/log4javascript.min.js"></script>
<script type="text/javascript" src="lib/vendors/Tone.min.js"></script>
<!-- styles -->
<link href="lib/vendors/jquery-ui-1.11.4.base/jquery-ui.min.css" rel="stylesheet">
<link href="lib/psychojs.css" rel="stylesheet">
<!-- PsychoJS library -->
<script type="text/javascript" src="lib/psychojs.3.0.0alpha3.js"></script>
</head>
<body>
<div id="root"/>
<script type="text/javascript" src="./inspect_images.js"></script>
</body>
</html>
/***********************
* Inspect_Images Test *
***********************/
// init psychoJS:
var psychoJS = new PsychoJS({
debug: true
});
var my = psychoJS;
// open window:
psychoJS.openWindow({
fullscr: true,
color: new Color([0, 0, 0]),
units: 'height'
});
// store info about the experiment session:
my.expName = 'inspect_images'; // from the Builder filename that created this script
my.expInfo = {'session': '001', 'participant': ''};
// set up the experiment:
psychoJS.schedule(setupExperiment);
// register all available resources and download them:
psychoJS.scheduleResources();
// dialog box:
psychoJS.schedule(psychoJS.gui.DlgFromDict({
dictionary: my.expInfo,
title: my.expName
}));
const flowScheduler = new Scheduler(psychoJS);
const dialogCancelScheduler = new Scheduler(psychoJS);
psychoJS.scheduleCondition(() => (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(instructRoutineBegin);
flowScheduler.add(instructRoutineEachFrame);
flowScheduler.add(instructRoutineEnd);
const trialsLoopScheduler = new Scheduler(psychoJS);
flowScheduler.add(trialsLoopBegin, trialsLoopScheduler);
flowScheduler.add(trialsLoopScheduler);
flowScheduler.add(trialsLoopEnd);
flowScheduler.add(explanationRoutineBegin);
flowScheduler.add(explanationRoutineEachFrame);
flowScheduler.add(explanationRoutineEnd);
const showMeTrialsLoopScheduler = new Scheduler(psychoJS);
flowScheduler.add(showMeTrialsLoopBegin, showMeTrialsLoopScheduler);
flowScheduler.add(showMeTrialsLoopScheduler);
flowScheduler.add(showMeTrialsLoopEnd);
flowScheduler.add(thanksRoutineBegin);
flowScheduler.add(thanksRoutineEachFrame);
flowScheduler.add(thanksRoutineEnd);
flowScheduler.add(quitPsychoJS);
// quit if user presses Cancel in dialog box:
dialogCancelScheduler.add(quitPsychoJS);
psychoJS.start();
function setupExperiment() {
if (psychoJS.status === PsychoJS.Status.NOT_CONFIGURED) {
psychoJS.status = PsychoJS.Status.CONFIGURING;
psychoJS.configure('config.json')
.then( config => {
// An ExperimentHandler isn't essential but helps with data saving
psychoJS.experiment = new ExperimentHandler({extraInfo: my.expInfo});
/*
// logging:
my.logger.console.setLevel(psychoJS.logging.WARNING);
my.logger.server.set({'level':psychoJS.logging.WARNING, 'saveTo':'EXPERIMENT_SERVER', 'experimentInfo': my.expInfo});*/
// change status to leave setupExperiment loop:
psychoJS.status = PsychoJS.Status.CONFIGURED;
});
}
// the loop will return until the configuration is completed
// at which point the status changes to CONFIGURED
if (psychoJS.status === PsychoJS.Status.CONFIGURED) {
psychoJS.status = PsychoJS.Status.STARTED;
return Scheduler.Event.NEXT;
} else
return Scheduler.Event.FLIP_REPEAT;
}
function updateInfo() {
my.expInfo['date'] = MonotonicClock.getDateStr(); // add a simple timestamp
my.expInfo['expName'] = my.expName;
// store frame rate of monitor if we can measure it successfully
my.expInfo['frameRate'] = my.window.getActualFrameRate();
if (typeof my.expInfo['frameRate'] !== 'undefined')
my.frameDur = 1.0/Math.round(my.expInfo['frameRate']);
else
my.frameDur = 1.0/60.0; // couldn't get a reliable measure so guess
// add info from the URL:
addInfoFromUrl(my.expInfo);
return Scheduler.Event.NEXT;
}
function experimentInit() {
// Initialize components for Routine "instruct"
my.instructClock = new Clock();
my.instructFirst = new TextStim({
win : my.window,
name : 'my.instructFirst',
text : 'On each trial you have to search the screen to find the ball\n(by moving the mouse around)\n\nClick the mouse to get started',
font : 'Arial',
units : 'height', pos : [0, 0.3], height : 0.05, wrapWidth : undefined, ori: 0,
color : new Color('black'), opacity : 1,
depth : 0.0
});
my.finishInstruct = new Mouse({
win: my.window,
});
my.finishInstruct.mouseClock = new Clock();
// Initialize components for Routine "trial"
my.trialClock = new Clock();
my.imageStimulus = new ImageStim({
win : my.window,
name : 'my.imageStimulus', units : 'norm',
image : my.imageFile, mask : undefined,
ori : 0, pos : [0, 0], size : [2, 2],
color : new Color ([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 128, interpolate : true, depth : 0.0
});
my.imageAperture = new ImageStim({
win : my.window,
name : 'my.imageAperture', units : 'height',
image : 'images/plainWhite.png', mask : 'images/circleMask.png',
ori : 0, pos : [0, 0], size : [4, 4],
color : new Color ([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 512, interpolate : true, depth : -1.0
});
my.mouse = new Mouse({
win: my.window,
});
my.mouse.mouseClock = new Clock();
// Initialize components for Routine "explanation"
my.explanationClock = new Clock();
my.instruct2 = new TextStim({
win : my.window,
name : 'my.instruct2',
text : 'This is essentially the same thing but\nthe mask is now smaller ( w,h = 2,2 in height units) so you can see \nwhat was happening.',
font : 'Arial',
units : 'height', pos : [0, 0.3], height : 0.05, wrapWidth : undefined, ori: 0,
color : new Color('black'), opacity : 1,
depth : 0.0
});
my.explanationFinish = new Mouse({
win: my.window,
});
my.explanationFinish.mouseClock = new Clock();
// Initialize components for Routine "showMeHow"
my.showMeHowClock = new Clock();
my.imageStimulus_2 = new ImageStim({
win : my.window,
name : 'my.imageStimulus_2', units : 'norm',
image : my.imageFile, mask : undefined,
ori : 0, pos : [0, 0], size : [2, 2],
color : new Color ([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 128, interpolate : true, depth : 0.0
});
my.imageAperture_2 = new ImageStim({
win : my.window,
name : 'my.imageAperture_2', units : 'height',
image : 'images/plainWhite.png', mask : 'images/circleMask.png',
ori : 0, pos : [0, 0], size : [1, 1],
color : new Color ([1, 1, 1]), opacity : 1,
flipHoriz : false, flipVert : false,
texRes : 512, interpolate : true, depth : -1.0
});
my.mouse_2 = new Mouse({
win: my.window,
});
my.mouse_2.mouseClock = new Clock();
// Initialize components for Routine "thanks"
my.thanksClock = new Clock();
my.text = new TextStim({
win : my.window,
name : 'my.text',
text : "That's all there is to it.\n\nBye!",
font : 'Arial',
pos : [0, 0], height : 0.1, wrapWidth : undefined, ori: 0,
color : new Color('white'), opacity : 1,
depth : 0.0
});
// Create some handy timers
my.globalClock = new Clock(); // to track the time since experiment started
my.routineTimer = new CountdownTimer(); // to track time remaining of each (non-slip) routine
return Scheduler.Event.NEXT;
}
function instructRoutineBegin() {
//------Prepare to start Routine 'instruct'-------
my.t = 0;
my.instructClock.reset(); // clock
my.frameN = -1;
// update component parameters for each repeat
// setup some python lists for storing info about the my.finishInstruct
my.gotValidClick = false; // until a click is received
// keep track of which components have finished
my.instructComponents = [];
my.instructComponents.push(my.instructFirst);
my.instructComponents.push(my.finishInstruct);
for (const thisComponent of my.instructComponents)
if ('status' in thisComponent)
thisComponent.status = PsychoJS.Status.NOT_STARTED;
return Scheduler.Event.NEXT;
}
function instructRoutineEachFrame() {
//------Loop for each frame of Routine 'instruct'-------
let continueRoutine = true; // until we're told otherwise
// get current time
my.t = my.instructClock.getTime();
my.frameN = my.frameN + 1;// number of completed frames (so 0 is the first frame)
// update/draw components on each frame
// *my.instructFirst* updates
if (my.t >= 0.0 && my.instructFirst.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
my.instructFirst.tStart = my.t; // (not accounting for frame time here)
my.instructFirst.frameNStart = my.frameN; // exact frame index
my.instructFirst.setAutoDraw(true);
}
// *my.finishInstruct* updates
if (my.t >= 0.0 && my.finishInstruct.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
my.finishInstruct.tStart = my.t; // (not accounting for frame time here)
my.finishInstruct.frameNStart = my.frameN; // exact frame index
my.finishInstruct.status = PsychoJS.Status.STARTED;
my.finishInstruct.mouseClock.reset();
my.prevButtonState = my.finishInstruct.getPressed(); // if button is down already this ISN'T a new click
}
if (my.finishInstruct.status === PsychoJS.Status.STARTED) { // only update if started and not stopped!
my.buttons = my.finishInstruct.getPressed();
if (!my.buttons.every( (e,i,) => (e == my.prevButtonState[i]) )) { // button state changed?
my.prevButtonState = my.buttons;
if (my.buttons.reduce( (e, acc) => (e+acc) ) > 0) { // state changed to a new click
// abort routine on response
continueRoutine = 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 my.instructComponents)
if ('status' in thisComponent && thisComponent.status != PsychoJS.Status.FINISHED) {
continueRoutine = true;
break;
}
// check for quit (the Esc key)
if (psychoJS.experiment.experimentEnded || psychoJS.eventManager.getKeys({keyList:['escape']}).length > 0) {
psychoJS.quit('The [Escape] key was pressed. Goodbye!');
}
// refresh the screen if continuing
if (continueRoutine) {
return Scheduler.Event.FLIP_REPEAT;
}
else {
return Scheduler.Event.NEXT;
}
}
function instructRoutineEnd() {
//------Ending Routine 'instruct'-------
for (const thisComponent of my.instructComponents) {
if (typeof thisComponent.setAutoDraw === 'function') {
thisComponent.setAutoDraw(false);
}
}
// store data for my.thisExp (ExperimentHandler)
// the Routine "instruct" was not non-slip safe, so reset the non-slip timer
my.routineTimer.reset();
return Scheduler.Event.NEXT;
}
function trialsLoopBegin(thisScheduler) {
// set up handler to look after randomisation of conditions etc
my.trials = new TrialHandler({
psychoJS,
nReps: 1, method: TrialHandler.Method.RANDOM,
extraInfo: my.expInfo, originPath: undefined,
trialList: 'conditions.xlsx',
seed: undefined, name: 'my.trials'});
psychoJS.experiment.addLoop(my.trials); // add the loop to the experiment
// Schedule all the trials in the trialList:
for (const thisTrial of my.trials) {
thisScheduler.add(importTrialAttributes(thisTrial));
thisScheduler.add(trialRoutineBegin);
thisScheduler.add(trialRoutineEachFrame);
thisScheduler.add(trialRoutineEnd);
thisScheduler.add(endLoopIteration(thisTrial));
}
return Scheduler.Event.NEXT;
}
function trialsLoopEnd() {
psychoJS.experiment.removeLoop(my.trials);
psychoJS.experiment.save({
attributes: my.trials.getAttributes()
});
return Scheduler.Event.NEXT;
}
function showMeTrialsLoopBegin(thisScheduler) {
// set up handler to look after randomisation of conditions etc
my.showMeTrials = new TrialHandler({
psychoJS,
nReps: 1, method: TrialHandler.Method.RANDOM,
extraInfo: my.expInfo, originPath: undefined