PyHab Class (base)

This is the base class that is used to actually run PyHab studies. There is an extension of this base class for preferential looking paradigms, see Preferential Looking

class PyHab.PyHabClass.PyHab(settingsDict)

PyHab looking time coding + stimulus control system

Jonathan Kominsky, 2016-2018

Keyboard coding: A = ready, B = coder 1 on, L = coder 2 on, R = abort trial, Y = end experiment (for fussouts)

Between-trials: R = redo previous trial, J = jump to test trial, I = insert additional habituation trial (hab only)

Throughout this script, win2 is the coder display, win is the stimulus presentation window. dataMatrix is the primary data storage for the summary data file. It is a list of dicts, each dict corresponds to a trial.

Anything called “verbose” is part of the verbose data file. There are up to four such structures: On (for gaze-on events) Off (for gaze-off events) On2 and Off2 (for the optional secondary coder) Each coder’s on and off are recorded in a separate dict with trial, gaze on/off, start, end, and duration.

SetupWindow()

Sets up the stimulus presentation and coder windows, loads all the stimuli, then starts the experiment with doExperiment()

Returns:
Return type:
abortTrial(onArray, offArray, trial, ttype, onArray2, offArray2, stimName='', habTrialNo=0)

Only happens when the ‘abort’ button is pressed during a trial. Creates a “bad trial” entry out of any data recorded for the trial so far, to be saved later.

Parameters:
  • onArray (list of dicts {trial, trialType, startTime, endTime, duration}) – Gaze-on events for coder 1
  • offArray (list of dicts {trial, trialType, startTime, endTime, duration}) – Gaze-off events for coder 1
  • trial (int) – trial number
  • ttype (string) – trial type
  • onArray2 (list of dicts) – Gaze-on events for (optional) coder 2
  • offArray2 (list of dicts) – Gaze-off events for (optional) coder 2
  • stimName (string) – If presenting stimuli, name of the stim file
Returns:

Return type:

attnGetter(trialType)

Plays either a default attention-getter animation or a user-defined one. Separate settings for audio w/shape and video file attention-getters.

Returns:
Return type:
avgObsAgree(timewarp, timewarp2)

Computes average observer agreement as agreement in each trial, divided by number of trials.

Parameters:
  • timewarp (list) – List of every individual frame’s gaze-on/gaze-off code for coder A
  • timewarp2 (list) – As above for coder B
Returns:

average observer agreement or N/A if no valid data

Return type:

float

blockExpander(blockTrials, prefixes, hab=False, habNum=0, insert=-1)

A method for constructing actualTrialOrder while dealing with recursive blocks. Can create incredibly long trial codes, but ensures that all information is accurately preserved. Works for both hab blocks and other things. For hab blocks, we can take advantage of the fact that hab cannot appear inside any other block. It will always be the top-level block, and so we can adjust the prefix once and it will carry through.

Parameters:
  • blockTrials (list) – The list of trials in self.blockList or self.habSubTrials
  • prefixes (str) – A recursively growing stack of prefixes. If block A has B and block B has C, then an instance of A will be A.B.C in self.actualTrialOrder. This keeps track of the A.B. part.
  • hab (bool) – Are we dealing with a habituation trial expansion?
  • habNum (int) – If we are dealing with a habituation trial expansion, what number of it are we on?
  • insert (int) – An int specifying where in actualTrialOrder to put a trial. Needed to generalize this function for insertHab
Returns:

Return type:

checkStop()

After a hab trial, checks the habitution criteria and returns ‘true’ if any of them are met. Also responsible for setting the habituation criteria according to settings. Prior to any criteria being set, self.HabCrit is 0, and self.habSetWhen is -1.

Uses a sort of parallel data structure that just tracks hab-relevant gaze totals. As a bonus, this means it now works for both single-target and preferential looking designs with no modification.

Returns:True if hab criteria have been met, False otherwise
Return type:
cohensKappa(timewarp, timewarp2)

Computes Cohen’s Kappa

Parameters:
  • timewarp (list) – List of every individual frame’s gaze-on/gaze-off code for coder A
  • timewarp2 (list) – As above for coder B
Returns:

Kappa

Return type:

float

dataRec(onArray, offArray, trial, type, onArray2, offArray2, stimName='', habTrialNo=0)

Records the data for a trial that ended normally.

Parameters:
  • onArray (list of dicts {trial, trialType, startTime, endTime, duration}) – Gaze-on events for coder 1
  • offArray (list of dicts {trial, trialType, startTime, endTime, duration}) – Gaze-off events for coder 1
  • trial (int) – trial number
  • type (string) – trial type
  • onArray2 (list) – Gaze-on events for (optional) coder 2
  • offArray2 (list) – Gaze-off events for (optional) coder 2
  • stimName (string) – If presenting stimuli, name of the stim file
  • habTrialNo (int) – If part of a hab block, what hab trial it was part of.
Returns:

Return type:

dispAudioStim(trialType, dispAudio)

For playing audio stimuli. A little more complicated than most because it needs to track whether the audio is playing or not. Audio plays separately from main thread.

Parameters:dispAudio (sound.Sound object) – the stimuli as a sound.Sound object
Returns:an int specifying whether the audio is in progress (0), we are in an ISI (1), or the audio is looping (2)
Return type:int
dispCoderWindow(trialType=-1)

Draws the coder window, according to trial type and blinding settings.

Parameters:trialType (int or string) – -1 = black (betwen trials). 0 = ready state. Otherwise irrelevant.
Returns:
Return type:
dispImageStim(dispImage)

Very simple. Draws still-image stimuli and flips window

Parameters:dispImage (visual.ImageStim object) – the visual.ImageStim object
Returns:constant, 1
Return type:int
dispMovieStim(trialType, dispMovie)

Draws movie stimuli to the stimulus display, including movie-based attention-getters.

Parameters:
  • trialType (int or str) – 0 for paused, otherwise a string
  • dispMovie (moviestim3 object) – The moviestim3 object for the stimuli
Returns:

an int specifying whether the movie is in progress (0), paused on its last frame (1), or ending and looping (2)

Return type:

int

dispTrial(trialType, dispMovie=False)

Draws each frame of the trial. For stimPres, returns a movie-status value for determining when the movie has ended

Parameters:
  • trialType (string) – Current trial type
  • dispMovie (bool or dict) – A dictionary containing both the stimulus type and the object with the stimulus file(s) (if applicable)
Returns:

1 or 0. 1 = end of movie for trials that end on that.

Return type:

int

doExperiment()

The primary control function and main trial loop.

Returns:
Return type:
doTrial(number, ttype, disMovie)

Control function for individual trials, to be called by doExperiment Returns a status value (int) that tells doExperiment what to do next

Parameters:
  • number (int) – Trial number
  • ttype (string) – Trial type
  • disMovie (dictionary) – A dictionary as follows {‘stim’:[psychopy object for stimulus presentation], ‘stimType’:[movie,image,audio, pair]}
Returns:

int, 0 = proceed to next trial, 1 = hab crit met, 2 = end experiment, 3 = trial aborted

Return type:

endExperiment()

End experiment, save all data, calculate reliability if needed, close up shop. Displays “saving data” and end-of-experiment screen.

Returns:
Return type:
flashCoderWindow(rep=False)

Flash the background of the coder window to alert the experimenter they need to initiate the next trial. .2 seconds of white and black, flashed twice. Can lengthen gap between trial but listens for ‘A’ on every flip.

Returns:
Return type:
insertHab(tn, hn=-1)

Literally insert a new hab trial or meta-trial into actualTrialOrder, get the right movie, etc.

Parameters:
  • tn (int) – trial number to insert the trial
  • hn – HabCount number to insert the hab trial. By default, whatever the current habcount is. However, there

are edge cases when recovering from “redo” trials when we want to throw in a hab trial further down the line. :type hn: int :return: [disMovie, trialType], the former being the movie file to play if relevant, and the latter being the new trial type :rtype: list

isInt()

silly little function for validating a very narrow usage of “cond” field

Returns:Bool: if arbitrary argument t is an int, true.
Return type:
jumpToTest(tn)

Jumps out of a hab block into whatever the first trial is that is not a hab trial or in a hab meta-trial-type :param tn: trial number :type tn: int :return: [disMovie, trialType] as insertHab, the former being the movie file to play if relevant, and the latter being the new trial type :rtype: list

lookKeysPressed()

A simple boolean function to allow for more modularity with preferential looking Basically, allows you to set an arbitrary set of keys to start a trial once the attngetter has played. In this case, only B (coder A on) is sufficient.

Returns:True if the B key is pressed, False otherwise.
Return type:
pearsonR(verboseMatrix, verboseMatrix2)

Computes Pearson’s R

Parameters:
  • verboseMatrix (dict) – Verbose data, coder A
  • verboseMatrix2 (dict) – Verboase data, coder B
Returns:

Pearson’s R

Return type:

float

redoSetup(tn, autoAdv)

Lays the groundwork for redoTrial, including correcting the trial order, selecting the right stim, etc.

Parameters:
  • tn (int) – Trial number (trialNum)
  • autoAdv (list) – The current auto-advance trial type list (different on first trial for Reasons)
Returns:

list, [disMovie, trialNum], the former being the movie file to play if relevant, and the latter being the new trial number

Return type:

redoTrial(trialNum)

Allows you to redo a trial after it has ended. Similar to abort trial, but under the assumption that the data has already been recorded and needs to be replaced. Decrementing of trial numbers is handled in doExperiment when the relevant key is pressed.

Parameters:trialNum (int) – Trial number to redo
Returns:
Return type:
reliability(verboseMatrix, verboseMatrix2)

Calculates reliability statistics. Constructed originally by Florin Gheorgiu for PyHab, modified by Jonathan Kominsky.

Parameters:
  • verboseMatrix (list) – A 2-dimensional list with the content of the verbose data file for coder 1
  • verboseMatrix2 (list) – A 2-dimensional list with the content of the verbose data file for coder 2
Returns:

A dict of four stats in float form (weighted % agreement, average observer agreement, Cohen’s Kappa, and Pearson’s R)

Return type:

dict

run(testMode=[])

Startup function. Presents subject information dialog to researcher, reads and follows settings and condition files. Now with a testing mode to allow us to skip the dialog and ensure the actualTrialOrder structure is being put together properly in unit testing.

Also expands habituation blocks appropriately and tags trials with habituation iteration number as well as the symbol for the end of a hab block (^)

Parameters:testMode (list) – Optional and primarily only used for unit testing. Will not launch the window and start the experiment. Contains all the info that would appear in the subject info dialog.
Returns:
Return type:
saveBlockFile()

A function that create a block-level summary file and saves it. Copies the primary data matrix (only good trials) and loops over it, compressing all blocks. Does not work for habs, which follow their own rules.

Returns:A condensed copy of dataMatrix with all blocks of the relevant types condensed to one line.
Return type:list
saveHabFile()

Creates a habituation summary data file, which has one line per hab trial, and only looks at parts of the hab trial that were included in calcHabOver. This is notably easier in some ways because the hab trials are already tagged in dataMatrix

Returns:A condensed copy of dataMatrix with all hab trials condensed only to those that were used to compute habituation.
Return type:list
wPA(timewarp, timewarp2)

Calculates weighted percentage agreement, computed as number of agreement frames over total frames.

Parameters:
  • timewarp (list) – List of every individual frame’s gaze-on/gaze-off code for coder A
  • timewarp2 (list) – As above for coder B
Returns:

Weighted Percentage Agreement

Return type:

float