Function description

List of functions in the src folder.

src.initPTB(cfg)

This will initialize PsychToolBox:

  • screen

    • the windon opened takes the whole screen unless cfg.debug.smallWin is set to true

    • can skip synch test if you ask for it (nicely)

    • window transparency enabled by cfg.debug.transpWin set to true

    • gets the flip interval

    • computes the pixel per degree of visual angle: the computation for ppd assumes the windows takes the whole screen width

  • set font details

  • keyboard

  • hides cursor

  • sound

USAGE:

cfg = initPTB(cfg)

See the set up page of the documentation for more details on the content of cfg

src.drawFieldOfVIew(cfg, centerOnScreen)

Draws a red rectangle on the screen to materialize the field of view of the participant. This can be used during debugging to help design the stimuli if you know the FOV of the participant will be obstructed by something

USAGE:

fov = drawFieldOfVIew(cfg, centerOnScreen)
Parameters:
  • cfg (structure) –

  • centerOnScreen (boolean) –

Returns:

  • fov:

    (array) PTB rectangle

src.eyeTracker(input, cfg, varargin)

Wrapper function that deals with all the necessary actions to implement Eye Tracker recording with eyelink.

USAGE:

function [el, cfg] = eyeTracker(input, cfg, [message])

Parameters:
  • input (string) – Defines what we want the function to do

  • cfg (struct) – structure that stores any info regarding the experiment

  • message (string) – optional argument to pass in when you want to tag the output in a specific moment of the experiment (for example Experiment-start)

Returns:

  • el:

    (struct) stores info related to the Eye Tracker

  • cfg:

    (struct)

  • Calibration to initialize EyeLink and run calibration

    • default calibration (default) will run a calibration with 6 points

    • custom calibration (cfg.eyeTracker.defaultCalibration = 'false') will run a calibration with 6 points but the experimenter can choose their position on the screen

  • StartRecording: to start eye movements recording

  • Message: will add a tag (e.g. Block_n1) in the ET output file, the tag is a string and it is input from varargin

  • StopRecordings: to stop eye movements recording

  • Shutdown: to save the .edf file with BIDS compliant name, from cpp-lln-lab/CPP_BIDS, in the output folder and shut the connection between the stimulation computer and the EyeLink computer

src.getExperimentEnd(cfg)

Wrapper function that will show a fixation cross and display in the console the whole experiment’s duration in minutes and seconds

src.getExperimentStart(cfg)

Wrapper function that will show a fixation cross and collect a start timestamp in cfg.experimentStart

USAGE:

cfg = getExperimentStart(cfg)
src.isOctave()

Return: true if the environment is Octave. mostly used to testing when PTB is not in the path

Must stay in the ‘src’ folder for continuous integration with github action to work. Not sure why.

src.waitForTrigger(varargin)

Counts a certain number of triggers coming from the scanner before returning.

USAGE:

[lastTriggerTimeStamp] = waitForTrigger([cfg,] …

[deviceNumber,] … [quietMode,] … [nbTriggersToWait])

Parameters:
  • cfg (struct) –

  • deviceNumber (integer) – device number of the keyboard or trigger box in MRI

  • quietMode (boolean) – a boolean to make sure nothing is printed on the screen or the prompt

  • nbTriggersToWait (integer) – number of triggers to wait

Returns:

  • lastTriggerTimeStamp:

    (optional) it can be used as experimentStart timestamp (cfg.experimentStart)

If you are not using the quietMode, it flips and waits for half a TR before starting to check for the next trigger (unless this was the last trigger to wait for and in this case it returns immediately).

Will print the count down in the command line and on the PTB window if one is opened.

If the fMRI sequence RT is provided (cgf.MRI.repetitionTime) then it will wait for half a RT before starting to check for next trigger, otherwise it will wait 500 ms.

When no deviceNumber is set then it will check the default device: this is probably only useful in debug as you will want to make sure you get the triggers coming from the scanner in a real case scenario.

src.waitFor(cfg, timeToWait)

Will either wait for a certain amount of time or a number of triggers.

USAGE:

waitFor(cfg, timeToWait)

Defaults

List of functions in the src/defaults folder.

src.defaults.checkCppPtbCfg(cfg)

Set some defaults values if none have been set before.

USAGE:

cfg = checkDefaultsPTB(cfg)
Parameters:

cfg (structure) –

Returns:

  • cfg:

    (structure)

src.defaults.cppPtbDefaults(type)

USAGE:

value = cppPtbDefaults(type)
src.defaults.setDefaultFields(structure, fieldsToSet)

Recursively loop through the fields of a structure and sets a value if they don’t exist.

USAGE:

structure = setDefaultFields(structure, fieldsToSet)
Parameters:
  • structure (structure) –

  • fieldsToSet (structure) –

Returns:

  • structure:

    (structure)

Aperture

List of functions in the src/aperture folder.

(to add saveAperture)

src.aperture.apertureTexture(action, cfg, thisEvent)

USAGE:

[cfg, thisEvent] = apertureTexture(action, cfg, thisEvent)
src.aperture.eccenLogSpeed(cfg, time)

Vary CurrScale so that expansion speed is log over eccentricity cf. Tootell 1997; Swisher 2007; Warnking 2002 etc

src.aperture.getApertureName(cfg, apertures, iApert)
src.aperture.saveApertures(saveAps, cfg, apertures)
src.aperture.smoothOval(win, color, rect, fringe)

Draws a filled oval (using the PTB parameters) with a transparent fringe.

USAGE:

SmoothOval(WindowPtr, Color, Rect, Fringe)
src.aperture.smoothRect(win, color, rect, fringe)

Draws a filled rect (using the PTB parameters) with a transparent fringe.

USAGE:

SmoothRect(WindowPtr, Color, Rect, Fringe)

Dot

List of functions in the src/dot folder.

src.dot.computeCartCoord(positions, dotMatrixWidth)

USAGE:

cartesianCoordinates = computeCartCoord(positions, dotMatrixWidth)
src.dot.computeRadialMotionDirection(positions, dotMatrixWidth, dots)
src.dot.decomposeMotion(angleMotion)

Decompose angle of start motion into horizontal and vertical vector.

USAGE:

[horVector, vertVector] = decomposeMotion(angleMotion)
Parameters:

angleMotion (scalar) – in degrees

Returns:

  • horVector:

    horizontal component of motion

  • vertVector:

    vertical component of motion

src.dot.dotMotionSimulation(cfg, thisEvent, nbEvents, doPlot)

To simulate where the dots are more dense on the screen relativeDensityContrast : hard to get it below 0.10.

USAGE:

relativeDensityContrast = dotMotionSimulation(cfg, thisEvent, nbEvents, doPlot)
src.dot.dotTexture(action, cfg, thisEvent)
src.dot.generateNewDotPositions(dotMatrixWidth, nbDots)
src.dot.initDots(cfg, thisEvent)

Initialize dots for RDK

USAGE:

dots = initDots(cfg, thisEvent)
Parameters:
  • cfg (structure) –

  • thisEvent (structure) –

Returns:

  • dots:

    (structure)

  • cfg.dot.lifeTime: dot life time in seconds

  • cfg.dot.number: number of dots

  • cfg.dot.coherence: proportion of coherent dots.

  • thisEvent.direction: direction (an angle in degrees)

  • thisEvent.speed: speed expressed in pixels per frame

  • dots.direction

  • dots.isSignal: signal dots (1) and those are noise dots (0)

  • dots.directionAllDots

  • dots.lifeTime: in frames

  • dots.speeds: [ndots, 2] ; horizontal and vertical speed ; in pixels per frame

  • dots.speedPixPerFrame

src.dot.reseedDots(dots, cfg)
src.dot.seedDots(varargin)
src.dot.setDotDirection(positions, cfg, dots, isSignal)

Creates some new direction for the dots.

USAGE:

directionAllDots = setDotDirection(positions, cfg, dots, isSignal)
Parameters:
  • positions

  • cfg

  • dots

  • isSignal

Returns:

  • directionAllDots:

Coherent dots have a true value in the vector isSignal and get assigned a value equals to the one in dots.direction.

All the other dots get a random value between 0 and 360.

All directions are in end expressed between 0 and 360.

src.dot.updateDots(dots, cfg)

Errors

List of functions in the src/errors folder.

src.errors.errorAbort()
src.errors.errorAbortGetReponse()
src.errors.errorDistanceToScreen(cfg)
src.errors.errorRestrictedKeysGetReponse()

Fixation

List of functions in the src/fixation folder.

src.fixation.drawFixation(cfg)

Define the parameters of the fixation cross in cfg.

USAGE:

drawFixation(cfg)

There are 3 types of fixations:

  • cross

  • dot

  • bestFixation

See initFixation for more info.

src.fixation.initFixation(cfg)

Prepare the details for fixation “cross”.

USAGE:

cfg = initFixation(cfg)

the fixation has a width defined by cfg.fixation.width : in degrees of visual

The horizontal and vertical offset (in degrees of visual) with respect to the center of the screen is defined by:

  • cfg.fixation.xDisplacement

  • cfg.fixation.yDisplacement

For cfg.fixation.type == ‘bestFixation’

Code adapted from: “What is the best fixation target?” DOI 10.1016/j.visres.2012.10.012

Contains a fixation cross and a dot


Keyboard

List of functions in the src/keyboard folder.

src.keyboard.getResponse(action, deviceNumber, cfg, getOnlyPress)

Wrapper function to use KbQueue which is definitely what you should use to collect responses. You can easily collect responses while running some other code at the same time.

The queue will be listening to key presses on a keyboard device: cfg.keyboard.responseBox or cfg.keyboard.keyboard are 2 main examples.

When no deviceNumber is set then it will listen to the default device.

You can use it in a way so that it only takes responses from certain keys and ignore others (like the triggers from an MRI scanner).

Check the CPP_getResponseDemo for a quick script on how to use it.

USAGE:

responseEvents = getResponse(action, deviceNumber, cfg, getOnlyPress)
Parameters:
  • action – Defines what we want the function to do

  • deviceNumber (integer) – device number of the keyboard or trigger box in MRI

  • cfg

  • getOnlyPress – if set to true the function will only return the key presses and will not return when the keys were released (default=true). See the section on Returns below for more info

Returns:

  • responseEvents:

    returns all the keypresses and return them as a structure with field names that make it easier to save the output of in a BIDS format

    • responseEvents.onset this is an absolute value and you should subtract the “experiment start time” to get a value relative to when the experiment was started.

    • responseEvents.trial_type = response

    • responseEvents.duration = 0

    • responseEvents.keyName the name of the key pressed

    • responseEvents(iEvent,1).pressed if

      • pressed == 1 –> the key was pressed

      • pressed == 0 –> the key was released

action options:

  • init to initialise the queue. Initialize the buffer for key presses on a given device (you can also specify the keys of interest that should be listened to).

  • start to start listening to the key presses (carefully insert into your script - where do you want to start buffering the responses).

  • check checks all the key presses events since ‘start’, or since last ‘check’ or ‘flush’ (whichever was the most recent)

    • can check for demand to abort if the escapeKey is listed in the Keys of interest

    • can only check for demands to abort when getResponse('check') is called so there will be a delay between the key press and the experiment stopping

    • abort errors send specific signals that allow the catch to get them and allows us to “close” nicely

  • flush empties the queue of events in case you want to restart from a clean queue

  • stop stops listening to key presses

src.keyboard.checkAbort(cfg, deviceNumber)

Will quit your experiment if you press the key you have defined in cfg.keyboard.escapeKey. When no deviceNumber is set then it will check the default device. When an abort key is detected this will throw a specific error that can then be caught.

USAGE:

checkAbort(cfg, deviceNumber)

EXAMPLE:

try

% Your awesome experiment

catch ME % when something goes wrong

    switch ME.identifier

      case 'checkAbort:abortRequested'

      % stuff to do when an abort is requested (save data...)

      otherwise

       % stuff to do otherwise
       rethrow(ME) % display the error

    end
end
src.keyboard.checkAbortGetResponse(responseEvents, cfg)
src.keyboard.collectAndSaveResponses(cfg, logFile, experimentStart)
src.keyboard.pressSpaceForMe()

Use that to stop your script and only restart when the space bar is pressed. This can be useful if as an experimenter you want to have one final check on some set up before giving the green light.

USAGE:

pressSpaceForMe()
src.keyboard.testKeyboards(cfg)

Checks that the keyboards asked for properly connected.

If no key is pressed on the correct keyboard after the timeOut time, this exits with an error.

USAGE:

testKeyboards(cfg)

Randomization

List of functions in the src/randomization folder.

src.randomization.repeatShuffleConditions(baseConditionVector, nbRepeats)

Given baseConditionVector, a vector of conditions (coded as numbers), this will create a longer vector made of nbRepeats of this base vector and make sure that a given condition is not repeated one after the other.

USAGE:

shuffledRepeats = repeatShuffleConditions(baseConditionVector, nbRepeats)
Parameters:
  • baseConditionVector (vector) –

  • nbRepeats (integer) –

Returns:

  • shuffledRepeats:

    (vector) (dimension)

src.randomization.setTargetPositionInSequence(seqLength, nbTarget, forbiddenPos)

For a sequence of length seqLength where we want to insert nbTarget targets, this will return nbTarget random position in that sequence and make sure that, they are not consecutive positions.

USAGE:

chosenPositions = setTargetPositionInSequence(seqLength, nbTarget, forbiddenPos)
Parameters:
  • seqLength (integer) –

  • nbTarget (integer) –

  • forbiddenPos (vector of integers) –

Returns:

  • chosenPositions:

src.randomization.shuffle(unshuffled)

Is just there to replace the Shuffle function from PTB in case it is not in the path. Can be useful for testing or for continuous integration.

USAGE:

shuffled = shuffle(unshuffled)

Screen

List of functions in the src/screen folder.

src.screen.farewellScreen(cfg)
src.screen.standByScreen(cfg)

It shows a basic one-page instruction stored in cfg.task.instruction and wait for space stroke.

USAGE:

standByScreen(cfg)

Utilities

List of functions in the src/utils folder.

(to add makeGif)

src.utils.checkPtbVersion()

Checks that the right dependencies are installed.

USAGE:

checkPtbVersion()
src.utils.cleanUp()

A wrapper function to close all windows, ports, show mouse cursor, close keyboard queues and give access back to the keyboards.

USAGE:

cleanUp()
src.utils.computeFOV(cfg)

Computes the number of degrees of visual angle in the whole field of view.

USAGE:

FOV = computeFOV(cfg)
Parameters:

cfg (structure) –

Returns:

  • FOV:

    (scalar)

delta = 2 arctan ( d / 2D )

  • delta is the angular diameter

  • d is the actual diameter of the object

  • D is the distance to the object

The result obtained is in radians.

src.utils.degToPix(fieldName, structure, cfg)

For a given field value in degrees of visual angle in the structure, this computes its value in pixel using the pixel per degree value of the cfg structure and returns a structure with an additional field with Pix suffix holding that new value.

USAGE:

structure = degToPix(fieldName, structure, cfg)
Parameters:
  • fieldName (string) –

  • structure (structure) –

  • cfg (structure) –

Returns:

  • structure:

    (structure)

EXAMPLE:

fixation.width = 2;
cfg.screen.ppd = 10;

fixation = degToPix('width', fixation, cfg);
src.utils.pixToDeg(fieldName, structure, cfg)

For a given field value in pixel in the structure, this computes its value in degrees of viual angle using the pixel per degree value of the cfg structure and returns a structure with an additional field holding that new value and with a fieldname with any ‘Pix’ suffix removed and replaced with the ‘DegVA’ suffix .

USAGE:

structure = pixToDeg(fieldName, structure, cfg)
Parameters:
  • fieldName (string) –

  • structure (structure) –

  • cfg (structure) –

Returns:

  • structure:

    (structure)

EXAMPLE:

fixation.widthPix = 20;
cfg.screen.ppd = 10;

fixation = degToPix('widthPix', fixation, cfg);
src.utils.printCreditsCppPtb()
src.utils.printScreen(win, filename, frame)
src.utils.setUpRand()

Resets the seed of the random number generator. Will “adapt” depending on the Matlab / Otave version.

USAGE:

setUpRand()

For an alternative from PTB see ClockRandSeed()