| Title: | Automated Eye Tracking Data Quality Determination for Screen-Based Eye Trackers |
|---|---|
| Description: | Compute common data quality metrics for accuracy, precision and data loss for screen-based eye trackers. The package supports gaze input in screen pixels or degrees and reports angular measures in degrees where appropriate. If you use this package, please cite Niehorster, D.C., Nyström, M., Hessels, R.S., Benjamins, J.S., Andersson, R., and Hooge, I.T.C. (2026). The fundamentals of eye tracking part 7: Determining data quality. Behavior Research Methods. <doi:10.3758/s13428-026-03039-4>. |
| Authors: | Diederick Niehorster [aut, cre, cph] (ORCID: <https://orcid.org/0000-0002-4672-8756>) |
| Maintainer: | Diederick Niehorster <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 1.0.0 |
| Built: | 2026-05-21 11:54:12 UTC |
| Source: | https://github.com/cran/ETDQualitizer |
Calculates the angular offset between gaze and target directions.
accuracy(azi, ele, target_azi, target_ele, central_tendency_fun = mean)accuracy(azi, ele, target_azi, target_ele, central_tendency_fun = mean)
azi |
Gaze azimuth in degrees. |
ele |
Gaze elevation in degrees. |
target_azi |
Target azimuth in degrees. |
target_ele |
Target elevation in degrees. |
central_tendency_fun |
Function to compute central tendency (default: |
A list with offset, offset_azi, and offset_ele, the total, horizontal and vertical offset of gaze from the target (in degrees).
accuracy(c(1, 2), c(1, 2), 0, 0)accuracy(c(1, 2), c(1, 2), 0, 0)
Computes BCEA and ellipse parameters for gaze precision.
bcea(azi, ele, P = 0.68)bcea(azi, ele, P = 0.68)
azi |
Azimuth values in degrees. |
ele |
Elevation values in degrees. |
P |
Cumulative probability (default: 0.68). |
A list with the BCEA (area) and additional info about the BCEA ellipse: orientation, ax1, ax2, and aspect_ratio.
bcea(rnorm(100), rnorm(100))bcea(rnorm(100), rnorm(100))
This function computes a set of data quality metrics for gaze data collected during the PsychoPy validation procedure that is provided in the ETDQualitizer repository on github (https://github.com/dcnieho/ETDQualitizer/tree/master/python/ETDQualitizer/stim). It evaluates accuracy, precision, and optionally data loss and effective sampling frequency, per eye and per target.
compute_data_quality_from_validation( gaze, unit, screen = NULL, advanced = FALSE, include_data_loss = FALSE )compute_data_quality_from_validation( gaze, unit, screen = NULL, advanced = FALSE, include_data_loss = FALSE )
gaze |
A 'data.frame' containing gaze data. Must include columns 'target_id', 'tar_x', 'tar_y', 'timestamp', and eye-specific columns such as 'left_x', 'left_y', 'right_x', 'right_y'. Timestamps should be provided in milliseconds. |
unit |
A character string specifying the unit of measurement for gaze and target coordinates in the gaze data.frame. Must be either '"pixels"' or '"degrees"'. |
screen |
An optional 'ScreenConfiguration' object or numeric scalar used to convert pixel coordinates to degrees. Required if 'unit == "pixels"'. |
advanced |
Logical. If 'TRUE', all available metrics are returned. If 'FALSE', only a simplified subset is included (default is FALSE). |
include_data_loss |
Logical. If 'TRUE', includes data loss and effective frequency metrics in the output (default is FALSE). |
This function uses the following methods in the 'DataQuality' class to compute the returned results: 'accuracy()', 'precision_RMS_S2S()', 'precision_STD()', 'precision_BCEA()', 'data_loss_from_invalid()', and 'effective_frequency()'.
A 'data.frame' with one row per eye-target combination, containing computed metrics: - 'eye', 'target_id': identifiers - 'accuracy', 'accuracy_x', 'accuracy_y': accuracy metrics ('accuracy_x', 'accuracy_y' only if 'advanced' is 'TRUE') - 'rms_s2s', 'rms_s2s_x', 'rms_s2s_y': precision (RMS sample-to-sample) ('rms_s2s_x', 'rms_s2s_y' only if 'advanced' is 'TRUE') - 'std', 'std_x', 'std_y': precision (standard deviation) ('std_x', 'std_y' only if 'advanced' is 'TRUE') - 'bcea', 'bcea_orientation', 'bcea_ax1', 'bcea_ax2', 'bcea_aspect_ratio': precision (BCEA metrics) ('bcea_orientation', 'bcea_ax1', 'bcea_ax2', 'bcea_aspect_ratio' only if 'advanced' is 'TRUE') - 'data_loss', 'effective_frequency': optional metrics if 'include_data_loss = TRUE'
## Not run: # NB: this example requires a gaze data table to run. See the complete example at # https://github.com/dcnieho/ETDQualitizer/blob/master/example/R.R for how to prepare # the input data for this function dq <- compute_data_quality_from_validation(gaze_data, unit = "pixels", screen = my_screen_config) ## End(Not run)## Not run: # NB: this example requires a gaze data table to run. See the complete example at # https://github.com/dcnieho/ETDQualitizer/blob/master/example/R.R for how to prepare # the input data for this function dq <- compute_data_quality_from_validation(gaze_data, unit = "pixels", screen = my_screen_config) ## End(Not run)
Calculates data loss based on expected number of samples.
data_loss_from_expected(a, b, duration, frequency)data_loss_from_expected(a, b, duration, frequency)
a |
Horizontal gaze values (e.g. azimuth or horizontal coordinate in pixels or mm). |
b |
Vertical gaze values (e.g. azimuth or horizontal coordinate in pixels or mm). |
duration |
Duration in seconds. |
frequency |
Sampling frequency in Hz. |
Percentage of data loss.
data_loss_from_expected(c(1, NA, 3), c(1, 2, NA), duration = 1, frequency = 3)data_loss_from_expected(c(1, NA, 3), c(1, 2, NA), duration = 1, frequency = 3)
Calculates percentage of missing gaze samples.
data_loss_from_invalid(a, b)data_loss_from_invalid(a, b)
a |
Horizontal gaze values (e.g. azimuth or horizontal coordinate in pixels or mm). |
b |
Vertical gaze values (e.g. azimuth or horizontal coordinate in pixels or mm). |
Percentage of missing samples.
data_loss_from_invalid(c(1, NA, 3), c(1, 2, NA))data_loss_from_invalid(c(1, NA, 3), c(1, 2, NA))
Provides methods for assessing the quality of gaze data, including accuracy, precision, data loss, and effective sampling frequency.
timestampsVector of timestamps in seconds. Samples with missing data should not be removed, or the RMS calculation would be incorrect.
aziVector of azimuth angles in degrees (Fick angles). Missing data should be coded as NA, not using some special value such as (0,0) or (-xres,-yres).
eleVector of elevation angles in degrees (Fick angles). Missing data should be coded as NA, not using some special value such as (0,0) or (-xres,-yres).
new()
Creates a new DataQuality object from gaze data and timestamps.
DataQuality$new(gaze_x, gaze_y, timestamps, unit, screen = NULL)
gaze_xHorizontal gaze positions (pixels or degrees).
gaze_yVertical gaze positions (pixels or degrees).
timestampsVector of timestamps in seconds.
unitUnit of gaze data: either "pixels" or "degrees".
screenOptional ScreenConfiguration object, required if unit is "pixels".
A new DataQuality object.
dq <- DataQuality$new(gaze_x, gaze_y, timestamps, unit = "pixels", screen = sc)
accuracy()
Calculates the accuracy of gaze data relative to a known target location.
DataQuality$accuracy(target_azi, target_ele, central_tendency_fun = mean)
target_aziTarget azimuth in degrees.
target_eleTarget elevation in degrees.
central_tendency_funFunction to compute central tendency (e.g., mean, median).
Accuracy in degrees.
dq$accuracy(0, 0)
precision_RMS_S2S()
Calculates precision as root mean square of sample-to-sample distances
DataQuality$precision_RMS_S2S(central_tendency_fun = mean)
central_tendency_funFunction to compute central tendency (e.g., mean, median).
Precision in degrees.
dq$precision_RMS_S2S()
precision_STD()
Calculates precision as standard deviation of gaze positions.
DataQuality$precision_STD()
Standard deviation in degrees.
dq$precision_STD()
precision_BCEA()
Calculates the Bivariate Contour Ellipse Area (BCEA) and ellipse parameters for gaze precision.
DataQuality$precision_BCEA(P = 0.68)
PProportion of data to include in the ellipse (default is 0.68).
BCEA in degrees-squared.
dq$precision_BCEA()
data_loss_from_invalid()
Calculates the proportion of missing data (coded as NA).
DataQuality$data_loss_from_invalid()
Proportion of missing samples.
dq$data_loss_from_invalid()
data_loss_from_expected()
Estimates data loss based on expected number of samples given the duration and sampling frequency.
DataQuality$data_loss_from_expected(frequency)
frequencyExpected sampling frequency in Hz.
Proportion of missing samples.
dq$data_loss_from_expected(500)
effective_frequency()
Calculates the effective sampling frequency based on timestamps.
DataQuality$effective_frequency()
Effective frequency in Hz.
dq$effective_frequency()
get_duration()
Computes the total duration of the gaze recording, including the last sample.
DataQuality$get_duration()
Duration in seconds.
dq$get_duration()
precision_using_moving_window()
Calculates precision using a moving window approach.
DataQuality$precision_using_moving_window( window_length, metric, aggregation_fun = median, ... )
window_lengthLength of the moving window in number of samples.
metricPrecision metric to use ("RMS-S2S", "STD", or "BCEA").
aggregation_funFunction to aggregate windowed precision values (e.g., median).
...Additional arguments passed to the precision metric function.
Precision value.
dq$precision_using_moving_window(20, "RMS-S2S")
clone()
The objects of this class are cloneable with this method.
DataQuality$clone(deep = FALSE)
deepWhether to make a deep clone.
sc <- ScreenConfiguration$new(500, 300, 1920, 1080, 600) gaze_x <- c(0, 1, -1) gaze_y <- c(0, 1, -1) timestamps <- c(0, 1, 2) dq <- DataQuality$new(gaze_x, gaze_y, timestamps, unit = "pixels", screen = sc) dq$accuracy(0, 0) dq$precision_RMS_S2S() dq$data_loss_from_invalid() ## ------------------------------------------------ ## Method `DataQuality$new` ## ------------------------------------------------ dq <- DataQuality$new(gaze_x, gaze_y, timestamps, unit = "pixels", screen = sc) ## ------------------------------------------------ ## Method `DataQuality$accuracy` ## ------------------------------------------------ dq$accuracy(0, 0) ## ------------------------------------------------ ## Method `DataQuality$precision_RMS_S2S` ## ------------------------------------------------ dq$precision_RMS_S2S() ## ------------------------------------------------ ## Method `DataQuality$precision_STD` ## ------------------------------------------------ dq$precision_STD() ## ------------------------------------------------ ## Method `DataQuality$precision_BCEA` ## ------------------------------------------------ dq$precision_BCEA() ## ------------------------------------------------ ## Method `DataQuality$data_loss_from_invalid` ## ------------------------------------------------ dq$data_loss_from_invalid() ## ------------------------------------------------ ## Method `DataQuality$data_loss_from_expected` ## ------------------------------------------------ dq$data_loss_from_expected(500) ## ------------------------------------------------ ## Method `DataQuality$effective_frequency` ## ------------------------------------------------ dq$effective_frequency() ## ------------------------------------------------ ## Method `DataQuality$get_duration` ## ------------------------------------------------ dq$get_duration() ## ------------------------------------------------ ## Method `DataQuality$precision_using_moving_window` ## ------------------------------------------------ dq$precision_using_moving_window(20, "RMS-S2S")sc <- ScreenConfiguration$new(500, 300, 1920, 1080, 600) gaze_x <- c(0, 1, -1) gaze_y <- c(0, 1, -1) timestamps <- c(0, 1, 2) dq <- DataQuality$new(gaze_x, gaze_y, timestamps, unit = "pixels", screen = sc) dq$accuracy(0, 0) dq$precision_RMS_S2S() dq$data_loss_from_invalid() ## ------------------------------------------------ ## Method `DataQuality$new` ## ------------------------------------------------ dq <- DataQuality$new(gaze_x, gaze_y, timestamps, unit = "pixels", screen = sc) ## ------------------------------------------------ ## Method `DataQuality$accuracy` ## ------------------------------------------------ dq$accuracy(0, 0) ## ------------------------------------------------ ## Method `DataQuality$precision_RMS_S2S` ## ------------------------------------------------ dq$precision_RMS_S2S() ## ------------------------------------------------ ## Method `DataQuality$precision_STD` ## ------------------------------------------------ dq$precision_STD() ## ------------------------------------------------ ## Method `DataQuality$precision_BCEA` ## ------------------------------------------------ dq$precision_BCEA() ## ------------------------------------------------ ## Method `DataQuality$data_loss_from_invalid` ## ------------------------------------------------ dq$data_loss_from_invalid() ## ------------------------------------------------ ## Method `DataQuality$data_loss_from_expected` ## ------------------------------------------------ dq$data_loss_from_expected(500) ## ------------------------------------------------ ## Method `DataQuality$effective_frequency` ## ------------------------------------------------ dq$effective_frequency() ## ------------------------------------------------ ## Method `DataQuality$get_duration` ## ------------------------------------------------ dq$get_duration() ## ------------------------------------------------ ## Method `DataQuality$precision_using_moving_window` ## ------------------------------------------------ dq$precision_using_moving_window(20, "RMS-S2S")
Calculates effective frequency based on valid samples.
effective_frequency(a, b, duration)effective_frequency(a, b, duration)
a |
Horizontal gaze values (e.g. azimuth or horizontal coordinate in pixels or mm). |
b |
Vertical gaze values (e.g. azimuth or horizontal coordinate in pixels or mm). |
duration |
Duration in seconds. |
Effective frequency in Hz.
effective_frequency(c(1, NA, 3), c(1, 2, NA), duration = 1)effective_frequency(c(1, NA, 3), c(1, 2, NA), duration = 1)
Returns the current version string of the ETDQualitizer tool.
ETDQ_version()ETDQ_version()
A character string representing the version number.
ETDQ_version()ETDQ_version()
Converts azimuth and elevation angles (in degrees) to a 3D unit vector.
Fick_to_vector(azi, ele, rho = 1)Fick_to_vector(azi, ele, rho = 1)
azi |
Azimuth angle in degrees. |
ele |
Elevation angle in degrees. |
rho |
Radius (default is 1.0). |
A list with components x, y, and z.
Fick_to_vector(30, 10)Fick_to_vector(30, 10)
Computes gaze precision using a moving window and selected metric.
precision_using_moving_window( azi, ele, window_length, metric, aggregation_fun = median, ... )precision_using_moving_window( azi, ele, window_length, metric, aggregation_fun = median, ... )
azi |
Azimuth values. |
ele |
Elevation values. |
window_length |
Window size in samples. |
metric |
Precision metric: |
aggregation_fun |
Function to aggregate precision values across the windows (default: |
... |
Additional arguments passed to metric function. |
Aggregated precision value.
precision_using_moving_window(rnorm(100), rnorm(100), 10, "STD")precision_using_moving_window(rnorm(100), rnorm(100), 10, "STD")
This function summarizes data quality metrics from a validation procedure by computing averages per participant and generating descriptive statistics across participants. It also returns a formatted textual summary suitable for reporting.
report_data_quality_table(dq_table)report_data_quality_table(dq_table)
dq_table |
A 'data.frame' containing data quality metrics. Must include columns 'file', 'eye', 'target_id', and relevant numeric metrics such as 'accuracy', 'rms_s2s', and 'std'. This would generally be created by concatenating the output of the compute_data_quality_from_validation() for multiple files. |
The summary text excludes BCEA and data loss metrics. BCEA is considered a niche metric and data loss is best reported across the full dataset rather than just the validation subset.
A named list with two elements:
A character string summarizing key metrics (accuracy, RMS-S2S precision, STD precision).
A list containing:
all: A data frame with per-participant averages (grouped by 'file').
mean, std, min, max: Named numeric vectors with summary statistics across participants.
## Not run: # NB: this example requires a gaze data table to run. See the complete example at # https://github.com/dcnieho/ETDQualitizer/blob/master/example/R.R for how to prepare # the input data for this function result <- report_data_quality_table(dq_table) cat(result$txt) head(result$measures$all) ## End(Not run)## Not run: # NB: this example requires a gaze data table to run. See the complete example at # https://github.com/dcnieho/ETDQualitizer/blob/master/example/R.R for how to prepare # the input data for this function result <- report_data_quality_table(dq_table) cat(result$txt) head(result$measures$all) ## End(Not run)
Computes root mean square of differences between successive gaze samples.
rms_s2s(azi, ele, central_tendency_fun = mean)rms_s2s(azi, ele, central_tendency_fun = mean)
azi |
Azimuth values in degrees. |
ele |
Elevation values in degrees. |
central_tendency_fun |
Function to compute central tendency (default: |
A list with rms, rms_azi, and rms_ele, the total RMS of sample-to-sample distances and that of the azimuthal and elevation components (all in degrees).
rms_s2s(c(1, 2, 3), c(1, 2, 3))rms_s2s(c(1, 2, 3), c(1, 2, 3))
Provides methods for converting between pixel, millimeter, and degree units.
screen_size_x_mmScreen width in mm.
screen_size_y_mmScreen height in mm.
screen_res_x_pixHorizontal screen resolution in pixels.
screen_res_y_pixVertical screen resolution in pixels.
viewing_distance_mmViewing distance in mm.
new()
Creates a new ScreenConfiguration object with screen and viewing distance parameters.
ScreenConfiguration$new( screen_size_x_mm, screen_size_y_mm, screen_res_x_pix, screen_res_y_pix, viewing_distance_mm )
screen_size_x_mmScreen width in millimeters.
screen_size_y_mmScreen height in millimeters.
screen_res_x_pixHorizontal screen resolution in pixels.
screen_res_y_pixVertical screen resolution in pixels.
viewing_distance_mmViewing distance in millimeters.
A new ScreenConfiguration object.
sc <- ScreenConfiguration$new(500, 300, 1920, 1080, 600)
pix_to_mm()
Converts pixel coordinates to millimeter coordinates on the screen.
ScreenConfiguration$pix_to_mm(x, y)
xHorizontal pixel coordinate.
yVertical pixel coordinate.
A list with x and y in millimeters.
sc$pix_to_mm(960, 540)
pix_to_deg()
Converts pixel coordinates to an angular gaze direction in degrees.
ScreenConfiguration$pix_to_deg(x, y)
xHorizontal pixel coordinate.
yVertical pixel coordinate.
A list with azimuth ("azi") and elevation ("ele") in degrees.
sc$pix_to_deg(960, 540)
mm_to_deg()
Converts millimeter coordinates to an angular gaze direction in degrees.
ScreenConfiguration$mm_to_deg(x, y)
xHorizontal position in millimeters.
yVertical position in millimeters.
A list with azimuth ("azi") and elevation ("ele") in degrees.
sc$mm_to_deg(100, 50)
mm_to_pix()
Converts millimeter coordinates on the screen to pixel coordinates.
ScreenConfiguration$mm_to_pix(x, y)
xHorizontal position in millimeters.
yVertical position in millimeters.
A list with x and y in pixels.
sc$mm_to_pix(100, 50)
deg_to_mm()
Converts an angular gaze direction in degrees to millimeter coordinates on the screen.
ScreenConfiguration$deg_to_mm(azi, ele)
aziAzimuth in degrees (Fick angles).
eleElevation in degrees (Fick angles).
A list with x and y in millimeters.
sc$deg_to_mm(2, 1)
deg_to_pix()
Converts an angular gaze direction in degrees to pixel coordinates.
ScreenConfiguration$deg_to_pix(azi, ele)
aziAzimuth in degrees (Fick angles).
eleElevation in degrees (Fick angles).
A list with x and y in pixels.
sc$deg_to_pix(2, 1)
screen_extents()
Computes the horizontal and vertical extents of the screen (in degrees).
ScreenConfiguration$screen_extents()
A list with width and height in degrees.
sc$screen_extents()
clone()
The objects of this class are cloneable with this method.
ScreenConfiguration$clone(deep = FALSE)
deepWhether to make a deep clone.
sc <- ScreenConfiguration$new(500, 300, 1920, 1080, 600) sc$pix_to_deg(960, 540) ## ------------------------------------------------ ## Method `ScreenConfiguration$new` ## ------------------------------------------------ sc <- ScreenConfiguration$new(500, 300, 1920, 1080, 600) ## ------------------------------------------------ ## Method `ScreenConfiguration$pix_to_mm` ## ------------------------------------------------ sc$pix_to_mm(960, 540) ## ------------------------------------------------ ## Method `ScreenConfiguration$pix_to_deg` ## ------------------------------------------------ sc$pix_to_deg(960, 540) ## ------------------------------------------------ ## Method `ScreenConfiguration$mm_to_deg` ## ------------------------------------------------ sc$mm_to_deg(100, 50) ## ------------------------------------------------ ## Method `ScreenConfiguration$mm_to_pix` ## ------------------------------------------------ sc$mm_to_pix(100, 50) ## ------------------------------------------------ ## Method `ScreenConfiguration$deg_to_mm` ## ------------------------------------------------ sc$deg_to_mm(2, 1) ## ------------------------------------------------ ## Method `ScreenConfiguration$deg_to_pix` ## ------------------------------------------------ sc$deg_to_pix(2, 1) ## ------------------------------------------------ ## Method `ScreenConfiguration$screen_extents` ## ------------------------------------------------ sc$screen_extents()sc <- ScreenConfiguration$new(500, 300, 1920, 1080, 600) sc$pix_to_deg(960, 540) ## ------------------------------------------------ ## Method `ScreenConfiguration$new` ## ------------------------------------------------ sc <- ScreenConfiguration$new(500, 300, 1920, 1080, 600) ## ------------------------------------------------ ## Method `ScreenConfiguration$pix_to_mm` ## ------------------------------------------------ sc$pix_to_mm(960, 540) ## ------------------------------------------------ ## Method `ScreenConfiguration$pix_to_deg` ## ------------------------------------------------ sc$pix_to_deg(960, 540) ## ------------------------------------------------ ## Method `ScreenConfiguration$mm_to_deg` ## ------------------------------------------------ sc$mm_to_deg(100, 50) ## ------------------------------------------------ ## Method `ScreenConfiguration$mm_to_pix` ## ------------------------------------------------ sc$mm_to_pix(100, 50) ## ------------------------------------------------ ## Method `ScreenConfiguration$deg_to_mm` ## ------------------------------------------------ sc$deg_to_mm(2, 1) ## ------------------------------------------------ ## Method `ScreenConfiguration$deg_to_pix` ## ------------------------------------------------ sc$deg_to_pix(2, 1) ## ------------------------------------------------ ## Method `ScreenConfiguration$screen_extents` ## ------------------------------------------------ sc$screen_extents()
Computes standard deviation of azimuth and elevation.
std(azi, ele)std(azi, ele)
azi |
Azimuth values in degrees. |
ele |
Elevation values in degrees. |
A list with std, std_azi, and std_ele, the total STD of sample-to-sample distances and that of the azimuthal and elevation components (all in degrees).
std(c(1, 2, 3), c(1, 2, 3))std(c(1, 2, 3), c(1, 2, 3))
Converts a 3D vector to azimuth and elevation angles (in degrees).
vector_to_Fick(x, y, z)vector_to_Fick(x, y, z)
x |
X component of the vector. |
y |
Y component of the vector. |
z |
Z component of the vector. |
A list with components azi and ele.
vector_to_Fick(0.5, 0.2, 0.8)vector_to_Fick(0.5, 0.2, 0.8)