Module eyekit.tools

Functions for performing common procedures, such as discarding out of bounds fixations and snapping fixations to the lines of text.

Functions

def discard_short_fixations(fixation_sequence, threshold=50)

Given a FixationSequence, discard all fixations that are shorter than some threshold value. Operates directly on the sequence and does not return a copy. Note that this only flags fixations as discarded and doesn't actually remove them; to remove discarded fixations, use FixationSequence.purge().

def discard_out_of_bounds_fixations(fixation_sequence, text_block, threshold=100)

Given a FixationSequence and TextBlock, discard all fixations that do not fall within some threshold distance of any character in the text. Operates directly on the sequence and does not return a copy. Note that this only flags fixations as discarded and doesn't actually remove them; to remove discarded fixations, use FixationSequence.purge().

def snap_to_lines(fixation_sequence, text_block, method='warp', **kwargs)

Given a FixationSequence and TextBlock, snap each fixation to the line that it most likely belongs to, eliminating any y-axis variation or drift. Operates directly on the sequence and does not return a copy. Several methods are available, some of which take optional parameters or require SciPy to be installed. For a full description and evaluation of these methods, see Carr et al. (2021). Note that in single-line TextBlocks, the method parameter has no effect: all fixations will be snapped to the one line. If a list of methods is passed in, each fixation will be snapped to the line with the most "votes" across the selection of methods (in the case of a tie, the left-most method takes priority). This "wisdom of the crowd" approach usually (but not always) results in better performance; ideally, you should choose a selection of at least three methods that have different general properties: for example, ['chain', 'cluster', 'warp']. When wisdom of the crowd is used, Fleiss's kappa is returned, indicating how much agreement there is among the methods; if this value is low (e.g. < 0.7), you may want to investigate the trial further.

  • chain : Chain consecutive fixations that are sufficiently close to each other, and then assign chains to their closest text lines. Default params: x_thresh=192, y_thresh=32.

  • cluster : Classify fixations into m clusters based on their Y-values, and then assign clusters to text lines in positional order. Requires SciPy.

  • merge : Form a set of progressive sequences and then reduce the set to m by repeatedly merging those that appear to be on the same line. Merged sequences are then assigned to text lines in positional order. Default params: y_thresh=32, gradient_thresh=0.1, error_thresh=20.

  • regress : Find m regression lines that best fit the fixations and group fixations according to best fit regression lines, and then assign groups to text lines in positional order. Default params: slope_bounds=(-0.1, 0.1), offset_bounds=(-50, 50), std_bounds=(1, 20). Requires SciPy.

  • segment : Segment fixation sequence into m subsequences based on m–1 most-likely return sweeps, and then assign subsequences to text lines in chronological order.

  • split : Split fixation sequence into subsequences based on best candidate return sweeps, and then assign subsequences to closest text lines. Requires SciPy.

  • stretch : Find a stretch factor and offset that results in a good alignment between the fixations and lines of text, and then assign the transformed fixations to the closest text lines. Default params: stretch_bounds=(0.9, 1.1), offset_bounds=(-50, 50). Requires SciPy.

  • warp : Map fixations to word centers using Dynamic Time Warping. This finds a monotonically increasing mapping between fixations and words with the shortest overall distance, effectively resulting in m subsequences. Fixations are then assigned to the lines that their mapped words belong to, effectively assigning subsequences to text lines in chronological order.

def align_to_screenshot(text_block, screenshot_path, output_path=None, show_text=True, show_guide_lines=True, show_bounding_boxes=False)

Given a TextBlock and the path to a PNG screenshot file, produce an image showing the original screenshot overlaid with the text block (shown in green). If no output path is provided, the output image is written to the same directory as the screenshot file. This is useful for establishing TextBlock parameters (position, font size, etc.) that match what participants actually saw in your experiment.

def font_size_at_72dpi(font_size, at_dpi=96)

Convert a font size at some dpi to the equivalent font size at 72dpi. Typically, this can be used to convert a Windows-style 96dpi font size to the equivalent size at 72dpi.