Package 'uSDT'

Title: Hierarchical Signal Detection Theory Models for Unconscious Processing
Description: Fits hierarchical signal detection theory (SDT) models to paired direct and indirect measures, the design used to test for unconscious processing. Continuous indirect measures (typically response times) are dichotomized with the within-subject median split of Meyen et al. (2022) <doi:10.1037/xge0001065> so that both tasks are placed on a common sensitivity scale. The package estimates a binomial probit mixed model in which the two sensitivities are correlated random effects, and tests the three hypotheses of interest: the group-level difference between sensitivities, their latent correlation, and the latent regression of the indirect on the direct measure, whose intercept is the test for unconscious processing. Frequentist estimation uses 'lme4'.
Authors: Ricardo Rey-Sáez [aut, cre] (ORCID: <https://orcid.org/0000-0001-6739-2035>), Francisco Garre-Frutos [aut] (ORCID: <https://orcid.org/0000-0001-9810-186X>), Alicia Franco-Martínez [aut] (ORCID: <https://orcid.org/0000-0002-9710-1240>), Miguel Vadillo [aut] (ORCID: <https://orcid.org/0000-0001-8421-816X>)
Maintainer: Ricardo Rey-Sáez <[email protected]>
License: GPL-3
Version: 0.1.0.9000
Built: 2026-10-07 17:09:16 UTC
Source: https://github.com/ricardoreysaez/usdt

Help Index


Fit a hierarchical signal detection theory model

Description

Fits a bivariate hierarchical SDT model using lme4::glmer() and evaluates the core unconscious processing hypotheses. The model estimates task-specific sensitivities (d′d') and response criteria (cc) as fixed effects, while estimating their variation and correlation across participants via random effects.

Usage

hsdt(
  data,
  estimation = c("frequentist"),
  fix_criteria = c("auto", "none"),
  level = 0.95,
  optimizer = "bobyqa",
  ...
)

## S3 method for class 'hsdt'
summary(object, ...)

## S3 method for class 'hsdt'
print(x, ...)

Arguments

data

A usdt_data object from usdt_data_tasks() or usdt_data_long().

estimation

Estimation framework. Currently only "frequentist" (maximum likelihood via Laplace approximation) is supported.

fix_criteria

How to handle response criteria. "auto" fixes to zero any criterion that is zero by design (such as a task split at the median under deviation coding). "none" estimates all criteria.

level

Confidence level for Wald intervals (default is 0.95).

optimizer

Primary optimizer passed to lme4::glmerControl(). Alternative optimizers are automatically evaluated if the default fails to converge or produces a singular fit.

...

Additional arguments passed to lme4::glmer(). Model formula, family, and data inputs remain managed by the package.

object

An hsdt object.

x

An hsdt object.

Details

The model fits trial counts with a binomial probit link, directly mapping coefficients to standard Signal Detection Theory parameters. Fixed effects capture population sensitivities and criteria, while random effects estimate participant variation and the latent correlation between direct and indirect sensitivity.

Hypotheses evaluated by default:

  • H1: Mean sensitivity difference between tasks.

  • H2: Latent correlation of sensitivities across participants.

  • H3: Latent regression of indirect on direct sensitivity. Its intercept reflects expected indirect performance when direct awareness is zero (dDirect′=0d'_{\mathrm{Direct}} = 0).

When sample sizes or trial counts are low, variance components can reach singular boundaries. In these cases, the function issues a warning, and parametric bootstrap intervals can be calculated using usdt_boot().

Value

An object of class hsdt containing:

  • ⁠$fit⁠: The underlying glmerMod object from lme4.

  • ⁠$tests⁠: Summary table for hypotheses H1, H2, and H3.

  • ⁠$pars⁠: Model parameter estimates on the SDT scale.

  • ⁠$design⁠: Summary of the model specification and formula.

  • ⁠$diagnostics⁠: Convergence flags and singular fit indicators.

See Also

usdt_data_tasks(), usdt_tests(), usdt_boot(), plot.hsdt()

Examples

# Contextual cuing data from Vadillo et al. (2025)
d <- usdt_data_tasks(
  direct   = vadillo_awareness,
  indirect = vadillo_cuing,
  subject_col      = "subj",
  condition_col    = "condition",
  condition_levels = c(signal = "old", noise = "new"),
  response_col     = list(direct = "judged.old", indirect = "rt"),
  response_levels  = list(direct   = c(signal = 1, noise = 0),
                          indirect = c(signal = "faster", noise = "slower")),
  dichotomize      = list(direct = FALSE, indirect = TRUE)
)

m <- hsdt(d)

# Full summary table with SDT parameters and hypothesis tests
summary(m)

# Inspect the model formula (indirect criterion omitted by default)
m$design$formula

Dichotomize response times into binary choices

Description

Splits response times (or other continuous measures) at each subject's overall median, following the preprocessing approach of Meyen et al. (2022). The median is calculated across all trials for each participant without distinguishing between stimulus conditions or other covariates. This produces a binary outcome that allows response times to be mapped onto a Signal Detection Theory sensitivity metric (d′d').

Usage

meyen_split(x, by, signal = c("faster", "slower"), ties = c("noise", "random"))

Arguments

x

Numeric vector of continuous values, typically response times.

by

Vector identifying the subject for each observation in x. Medians are computed independently for each participant.

signal

Character string specifying which side of the median will be treated as the "signal" response under an SDT framework. Use "faster" when the target condition speeds up responses (e.g., facilitatory priming, spatial cueing) or "slower" when it slows responses down (e.g., interference, Stroop-like effects).

ties

How to handle trials that match the subject's median exactly. "noise" assigns them to the noise category (0). "random" breaks ties at random, keeping cell proportions as balanced as possible.

Details

With an odd number of trials (nn), a dataset cannot be split into two equal halves because the median falls exactly on an observed trial. Setting ties = "noise" assigns this middle trial to noise, producing a signal proportion of (n−1)/(2⋅n)(n - 1) / (2\cdot n) and slightly shifting the response criterion. In practice, this difference (1/(2⋅n)1 / (2\cdot n)) is negligible, but setting ties = "random" resolves ties probabilistically to avoid any systematic directional bias.

Value

An integer vector of 0s (noise response) and 1s (signal response) matching the length of x. Missing values (NA) are preserved.

References

Meyen, S., Zerweck, I. A., Amado, C., von Luxburg, U., & Franz, V. H. (2022). Advancing research on unconscious priming: When can scientists claim an indirect task advantage? Journal of Experimental Psychology: General, 151(1), 65–81. doi:10.1037/xge0001065

Examples

rt   <- c(320, 410, 295, 500, 380, 450)
subj <- rep(c("s1", "s2"), each = 3)
meyen_split(rt, by = subj)

Diagnostic and analytical plots for hierarchical SDT models

Description

Generates diagnostic visualizations for a fitted hierarchical SDT model, including observed versus latent regression (H3), shrinkage patterns, participant-level caterpillar intervals, and model-implied ROC curves.

Usage

## S3 method for class 'hsdt'
plot(
  x,
  type = c("regression", "shrinkage", "caterpillar", "roc"),
  subject_id = NULL,
  band = TRUE,
  population_reference = TRUE,
  observed_se = NULL,
  ...
)

Arguments

x

An hsdt object fitted by hsdt().

type

Character string indicating the plot type:

  • "regression": Compares the observed OLS regression with the latent regression line (H3).

  • "shrinkage": Connects observed d′d' to model-implied d′d' for each participant across bivariate contours.

  • "caterpillar": Compares observed d′d' and model-implied d′d' with confidence intervals for each participant alongside zero.

  • "roc": Shows model-implied ROC curves with estimated criteria.

subject_id

Identifier for a specific participant when type = "roc". If omitted, displays population-level curves.

band

Logical. Show confidence bands around regression lines or ROC curves (default is TRUE).

population_reference

Logical. When plotting an individual ROC curve, add population-average curves as dashed reference lines.

observed_se

Variance formulation for empirical intervals in "caterpillar" plots: "gg" (Gourevitch & Galanter, 1967, default) or "miller" (Miller, 1996).

...

Additional arguments passed to underlying plotting methods.

Value

A ggplot object. Its underlying data frame is stored in ⁠$data⁠.

Regression plot (type = "regression")

Compares observed and latent associations across two panels sharing axes. The left panel shows observed d′d' values and an ordinary least-squares line. When direct task reliability is low, trial-level sampling noise attenuates this observed slope toward zero. The right panel plots the latent regression line (dI′d'_I on dD′d'_D) from H3, correcting for measurement error. The value of each line at dD′=0d'_D = 0 marks the intercept testing for unconscious processing, and both panels display it the same way: an open circle at the point estimate with a vertical line spanning its confidence interval. The observed marker is the least-squares intercept and the latent marker is its measurement-error-corrected counterpart, so the two panels place the same hypothesis side by side. Confidence bands are computed via the delta method or bootstrap replicates when usdt_boot() is present.

Shrinkage plot (type = "shrinkage")

Connects each participant's observed d′d' (from sdt_moments() with Hautus correction) to their model-implied d′d'. The lower the reliability of the measures, the higher the shrinkage of observed estimates toward the group-level mean.

Caterpillar plot (type = "caterpillar")

Plots observed d′d' and model-implied d′d' with confidence intervals for every participant. Empirical intervals use normal approximations based on observed_se. Model-implied intervals incorporate uncertainty from population means, variance components, and participant random effects.

ROC plot (type = "roc")

Displays model-implied ROC curves for an average participant or a specific individual, with points marking the estimated response criteria.

See Also

hsdt(), sdt_moments(), usdt_boot()

Examples

# Contextual cuing data from Vadillo et al. (2025)
d <- usdt_data_tasks(
  direct   = vadillo_awareness,
  indirect = vadillo_cuing,
  subject_col      = "subj",
  condition_col    = "condition",
  condition_levels = c(signal = "old", noise = "new"),
  response_col     = list(direct = "judged.old", indirect = "rt"),
  response_levels  = list(direct   = c(signal = 1, noise = 0),
                          indirect = c(signal = "faster", noise = "slower")),
  dichotomize      = list(direct = FALSE, indirect = TRUE)
)

fit <- hsdt(d)

# 1. Observed vs. latent regression (H3)
plot(fit, type = "regression")

# 2. Bivariate shrinkage toward the group mean
plot(fit, type = "shrinkage")

# 3. Participant-level intervals (observed vs. model-implied)
plot(fit, type = "caterpillar")

# 4. Model-implied ROC curves
plot(fit, type = "roc")
plot(fit, type = "roc", subject_id = "2001", population_reference = TRUE)

Signal detection measures for each subject

Description

Computes empirical hit rates, false-alarm rates, sensitivity (d′d'), and response criteria for each participant without fitting a model. It can also calculate sampling variances, standard errors, and expected values for d′d'.

Usage

sdt_moments(
  data,
  subject_col = NULL,
  condition_col = NULL,
  condition_levels = NULL,
  response_col = NULL,
  response_levels = NULL,
  coding = c("deviation", "treatment"),
  correction = c("hautus", "none"),
  variances = FALSE
)

Arguments

data

A usdt_data object or a standard trial-level data frame. When given a usdt_data object, the function processes both tasks and includes a task column in the output.

subject_col, condition_col, response_col

Column names for subject, condition, and response variables. Only required when data is a plain data frame.

condition_levels, response_levels

Named vectors mapping condition and response labels, like c(signal = "old", noise = "new"). Required for a plain data frame. A usdt_data object supplies its own roles and needs neither.

coding

Criterion definition to report: "deviation" measures the criterion from the midpoint between the signal and noise distributions, whereas "treatment" measures it from the noise distribution. A usdt_data object supplies its own coding.

correction

Handling of extreme rates (0 or 1) that make d′d' infinite. "hautus" adds 0.5 to all four cell counts for affected participants. "none" leaves infinite values in place.

variances

Logical. If TRUE, computes the sampling variance of d′d' from Gourevitch and Galanter (1967) and Miller (1996), each with its own standard error, as well as the expected value of d′d' under Miller's distribution.

Details

Edge corrections apply only to participants with extreme rates (0 or 1) rather than the whole sample, leaving well-defined rates unchanged.

When requested, the sampling variance of d′d' is estimated using the asymptotic approximation of Gourevitch and Galanter (1967) and the binomial-distribution approach of Miller (1996). See Suero et al. (2017) for a comparison between the two approaches.

Value

A data frame with one row per subject (or per subject and task for usdt_data inputs) containing:

  • hit, miss, fa, cr: Raw response counts.

  • hr, far: Observed hit and false-alarm rates.

  • zhr, zfar: Probit-transformed rates.

  • dprime, criterion: Descriptive SDT estimates.

  • corrected: Logical flag indicating whether the participant received an edge correction.

  • var_gg, se_gg: Asymptotic variance and standard error from Gourevitch and Galanter (1967), present when variances = TRUE.

  • var_miller, se_miller, expected_dprime: Moments from Miller (1996), present when variances = TRUE.

References

Gourevitch, V., & Galanter, E. (1967). A significance test for one parameter isosensitivity functions. Psychometrika, 32(1), 25–33. doi:10.1007/BF02289402

Hautus, M. J. (1995). Corrections for extreme proportions and their biasing effects on estimated values of d′d'. Behavior Research Methods, Instruments, & Computers, 27(1), 46–51. doi:10.3758/BF03203619

Miller, J. (1996). The sampling distribution of d′d'. Perception & Psychophysics, 58(1), 65–72. doi:10.3758/BF03205476

Suero, M., Privado, J., & Botella, J. (2017). Methods to estimate the variance of some indices of the signal detection theory: A simulation study. Psicologica, 38(1), 77–109.

See Also

hsdt()

Examples

# 1. From a prepared usdt_data object (both tasks at once)
d <- usdt_data_tasks(
  direct   = vadillo_awareness,
  indirect = vadillo_cuing,
  subject_col      = "subj",
  condition_col    = "condition",
  condition_levels = c(signal = "old", noise = "new"),
  response_col     = list(direct = "judged.old", indirect = "rt"),
  response_levels  = list(direct   = c(signal = 1, noise = 0),
                          indirect = c(signal = "faster", noise = "slower")),
  dichotomize      = list(direct = FALSE, indirect = TRUE)
)

head(sdt_moments(d))

# 2. From raw trials with sampling variances and standard errors
head(sdt_moments(vadillo_awareness,
                 subject_col      = "subj",
                 condition_col    = "condition",
                 condition_levels = c(signal = "old", noise = "new"),
                 response_col     = "judged.old",
                 response_levels  = c(signal = 1, noise = 0),
                 variances        = TRUE))

Parametric bootstrap intervals for hierarchical SDT models

Description

Simulates new datasets from a fitted model using lme4::bootMer(), refits the model to each replicate, and computes bootstrap confidence intervals for the three core hypotheses (H1, H2, H3). This is especially useful when asymptotic Wald intervals are unreliable due to singular or boundary fits.

Usage

usdt_boot(
  object,
  nsim = 1000,
  ncores = 1L,
  max_attempts = 2 * nsim,
  seed = NULL,
  progress = interactive(),
  level = 0.95,
  type = c("perc", "norm", "basic")
)

Arguments

object

An hsdt object fitted by hsdt().

nsim

Target number of successful replicates (at least 500).

ncores

Number of CPU cores for parallel processing. Values above 1 create a temporary cluster that works across Windows, macOS, and Linux, and automatically stops when finished.

max_attempts

Maximum number of refits to attempt. Defaults to 2 * nsim.

seed

Random seed for reproducibility. With the default NULL, no seed is set and the bootstrap continues the current random number stream.

progress

Logical. Display a progress bar during fitting (defaults to TRUE in interactive sessions).

level

Confidence level for intervals (default is 0.95).

type

Type of bootstrap interval: "perc" (percentile), "norm" (normal approximation with bias correction), or "basic" (empirical basic). For correlations, "norm" and "basic" operate on the Fisher-zz scale; if the sample correlation lies on the boundary (-1 or 1), these types return NA, whereas "perc" remains available.

Details

Replicates are dropped only if the model fails to fit or does not converge. Singular fits and boundary estimates are intentionally retained because discarding them artificially narrows intervals in constrained settings.

When an attempted run finishes with fewer than 500 usable replicates, the original Wald intervals are preserved, a warning is issued, and raw attempt diagnostics are stored in ⁠$boot⁠.

Point estimates remain identical to the original model fit. Two-sided bootstrap pp-values compare the observed test statistic against the centered bootstrap distribution using standard finite-sample adjustment ((k+1)/(B+1)(k + 1) / (B + 1)), ensuring pp-values never equal zero.

Value

An updated hsdt object where interval columns in ⁠$tests⁠ are replaced by bootstrap estimates. A new ⁠$boot⁠ element contains:

  • ⁠$t⁠: Matrix of replicates for the three hypotheses.

  • ⁠$variance⁠: Replicates of sensitivity variances.

  • ⁠$population⁠: Replicates of average criteria and sensitivities.

  • ⁠$subjects⁠: Replicates of individual-level parameters.

  • Run diagnostics and convergence counts (usable, attempted, retained, failures).

See Also

hsdt(), usdt_tests()

Examples

# Contextual cuing data from Vadillo et al. (2025)
d <- usdt_data_tasks(
  direct   = vadillo_awareness,
  indirect = vadillo_cuing,
  subject_col      = "subj",
  condition_col    = "condition",
  condition_levels = c(signal = "old", noise = "new"),
  response_col     = list(direct = "judged.old", indirect = "rt"),
  response_levels  = list(direct   = c(signal = 1, noise = 0),
                          indirect = c(signal = "faster", noise = "slower")),
  dichotomize      = list(direct = FALSE, indirect = TRUE)
)

m <- hsdt(d)


# Run parametric bootstrap with 500 replicates. Refitting this model 500
# times takes several minutes
b <- usdt_boot(m, nsim = 500, seed = 1)

# Inspect updated summary with bootstrap intervals and p-values
summary(b)

# Check fit diagnostics across bootstrap replicates
b$boot[c("usable", "attempted", "retained", "failures")]

Prepare data for hierarchical SDT models

Description

Formats direct and indirect task data into a standardized structure for hsdt(). Use usdt_data_tasks() when tasks are stored in separate data frames, or usdt_data_long() when both tasks are kept in a single data frame with a column that identifies each task.

Usage

usdt_data_tasks(
  direct,
  indirect,
  subject_col,
  condition_col = NULL,
  condition_levels = NULL,
  response_col = NULL,
  response_levels = NULL,
  successes_col = NULL,
  trials_col = NULL,
  successes_type = c("auto", "counts", "proportions"),
  sdt_cols = NULL,
  dichotomize = c("none", "indirect", "direct", "both"),
  ties = c("noise", "random"),
  coding = c("deviation", "treatment"),
  labels = c(direct = "Direct", indirect = "Indirect")
)

usdt_data_long(
  data,
  task_col,
  task_levels,
  subject_col,
  condition_col = NULL,
  condition_levels = NULL,
  response_col = NULL,
  response_levels = NULL,
  successes_col = NULL,
  trials_col = NULL,
  successes_type = c("auto", "counts", "proportions"),
  sdt_cols = NULL,
  dichotomize = c("none", "indirect", "direct", "both"),
  ties = c("noise", "random"),
  coding = c("deviation", "treatment"),
  labels = NULL
)

## S3 method for class 'usdt_data'
print(x, ...)

Arguments

direct, indirect

Data frames for each task (used in usdt_data_tasks()).

subject_col

Name of the column that identifies participants.

condition_col

Name of the column for signal and noise conditions. Not needed when using sdt_cols.

condition_levels

Named vector mapping condition labels, like c(signal = "old", noise = "new"). Required: which label is the signal and the noise.

response_col

Name of the column with responses. Can be binary choices or continuous values (like response times) to split at the median.

response_levels

Named vector mapping responses, like c(signal = 1, noise = 0). For a task named in dichotomize it names the side of the median instead, as c(signal = "faster", noise = "slower") or the reverse. Required in both cases.

successes_col, trials_col

Names of columns with pre-calculated counts or proportions of signal responses and total trials. Use these instead of response_col.

successes_type

Format of successes_col: "counts", "proportions", or "auto".

sdt_cols

Named vector for SDT table columns, like c(hit = "H", miss = "M", fa = "FA", cr = "CR").

dichotomize

Which tasks to split at the median using meyen_split(). Use "none", "direct", "indirect", "both", or a list like list(direct = FALSE, indirect = TRUE).

ties

How to handle trials that fall exactly on the median. See meyen_split().

coding

How condition is coded in the model: "deviation" (-0.5, 0.5) or "treatment" (0, 1). See Details.

labels

Optional names for the tasks in printed output.

data

A single data frame with both tasks (used in usdt_data_long()).

task_col

Name of the column that identifies the task in data.

task_levels

Named vector mapping task labels, like c(direct = "D", indirect = "I").

x

A usdt_data object.

...

Ignored.

Details

The functions count responses for each subject and condition, check that the same subjects appear in both tasks, and print a summary table so you can verify the column settings before fitting the model.

Value

An object of class usdt_data. The ⁠$agg⁠ table contains the counts used by hsdt(), and ⁠$meta⁠ contains setup details and summaries.

Settings per task

Arguments for columns and levels take either a single value (used for both tasks) or a list with separate settings for each task:

condition_col    = list(direct = "cond", indirect = "cue")
condition_levels = list(direct   = c(signal = "old", noise = "new"),
                        indirect = c(signal = "congruent", noise = "incongruent"))
dichotomize      = list(direct = FALSE, indirect = TRUE)

This works for all column and level arguments, so you can combine trial-level data in one task with summary tables in the other.

Condition coding

Under "deviation" coding (-0.5 vs. +0.5), the intercept is −c-c, the criterion measured from the point between the two distributions. Under "treatment" coding (0 vs. 1), the intercept is z(FAR)z(\mathrm{FAR}), the criterion measured from the noise distribution.

When a task is split at the median, deviation coding sets the group criterion to zero in balanced designs, so the model does not need to estimate it.

See Also

hsdt(), meyen_split(), sdt_moments()

Examples

# 1. Tasks in separate data frames
# Direct task: binary choices (old/new)
# Indirect task: response times (split at the median)
d_separate <- usdt_data_tasks(
  direct   = vadillo_awareness,
  indirect = vadillo_cuing,
  subject_col      = "subj",
  condition_col    = "condition",
  condition_levels = c(signal = "old", noise = "new"),
  response_col     = list(direct = "judged.old", indirect = "rt"),
  response_levels  = list(direct   = c(signal = 1, noise = 0),
                          indirect = c(signal = "faster", noise = "slower")),
  dichotomize      = list(direct = FALSE, indirect = TRUE)
)
d_separate

# 2. Tasks combined in a single long data frame
long <- rbind(
  data.frame(task      = "D",
             subj      = vadillo_awareness$subj,
             condition = vadillo_awareness$condition,
             response  = vadillo_awareness$judged.old),
  data.frame(task      = "I",
             subj      = vadillo_cuing$subj,
             condition = vadillo_cuing$condition,
             response  = vadillo_cuing$rt)
)

d_long <- usdt_data_long(
  long,
  task_col         = "task",
  task_levels      = c(direct = "D", indirect = "I"),
  subject_col      = "subj",
  condition_col    = "condition",
  condition_levels = c(signal = "old", noise = "new"),
  response_col     = "response",
  response_levels  = list(direct   = c(signal = 1, noise = 0),
                          indirect = c(signal = "faster", noise = "slower")),
  dichotomize      = list(direct = FALSE, indirect = TRUE)
)
d_long

Test the three core hypotheses of a hierarchical SDT model

Description

Evaluates the difference between average task sensitivities (H1), their correlation across subjects (H2), and the regression of indirect sensitivity on direct sensitivity (H3). usdt_tests() computes all three together, while individual functions compute them separately.

Usage

usdt_tests(fit, direct = "d_D", indirect = "d_I", level = 0.95)

sensitivity_diff(fit, direct = "d_D", indirect = "d_I", level = 0.95)

latent_cor(fit, direct = "d_D", indirect = "d_I", level = 0.95)

latent_regression(fit, direct = "d_D", indirect = "d_I", level = 0.95)

Arguments

fit

A fitted model: an hsdt object or a glmerMod from lme4::glmer().

direct, indirect

Character strings naming the sensitivity terms in the model. Defaults match the internal naming of hsdt(). For custom models, both terms must be fixed effects and share a common random-effects grouping by subject.

level

Confidence level for intervals (default is 0.95).

Details

These tests run automatically inside hsdt() and appear in its summary. Calling them directly is especially useful when fitting custom models with lme4::glmer(), allowing you to test these hypotheses while controlling for additional covariates (e.g., set size, experimental groups).

Value

A data frame with columns term, estimate, se, statistic, p.value, conf.low, conf.high, and ci_method. Columns status and reason flag unsupported estimates (e.g., singular fits). usdt_tests() includes an extra hypothesis column (H1, H2, H3).

The three hypotheses

  • H1 (Mean difference): Tests whether average sensitivity differs between the direct and indirect tasks.

  • H2 (Correlation): Tests the correlation between task sensitivities across participants using a Fisher-zz transformed interval.

  • H3 (Latent regression): Regresses indirect sensitivity onto direct sensitivity. The intercept represents expected indirect performance when direct sensitivity is zero (dDirect′=0d'_{\mathrm{Direct}} = 0), testing for unconscious processing.

Because both the correlation (H2) and regression slope (H3) are zero if and only if the covariance between sensitivities is zero, they evaluate the same association and share identical test statistics.

Custom models with covariates

To adjust tests for additional factors, specify the model directly using lme4::glmer(). As long as the two sensitivity terms are included as fixed effects and correlated across subjects via random slopes, usdt_tests() will compute the latent tests conditional on those covariates.

See Also

hsdt(), usdt_boot()

Examples

# 1. Standard model via hsdt()
d <- usdt_data_tasks(
  direct   = vadillo_awareness,
  indirect = vadillo_cuing,
  subject_col      = "subj",
  condition_col    = "condition",
  condition_levels = c(signal = "old", noise = "new"),
  response_col     = list(direct = "judged.old", indirect = "rt"),
  response_levels  = list(direct   = c(signal = 1, noise = 0),
                          indirect = c(signal = "faster", noise = "slower")),
  dichotomize      = list(direct = FALSE, indirect = TRUE)
)

m <- hsdt(d)

# All three tests at once
usdt_tests(m)

# Or one test at a time
sensitivity_diff(m)   # H1
latent_cor(m)         # H2
latent_regression(m)  # H3


# 2. Custom model with covariates via glmer()
# Controlling for display set size across both tasks
trials <- rbind(
  data.frame(vadillo_awareness[c("subj", "condition", "set.size")],
             task = "D", resp = vadillo_awareness$judged.old),
  data.frame(vadillo_cuing[c("subj", "condition", "set.size")],
             task = "I", resp = meyen_split(vadillo_cuing$rt,
                                            by = vadillo_cuing$subj))
)

# Deviation contrasts (-0.5 vs 0.5); `direct` flags the direct task
trials <- within(trials, {
  cond   <- ifelse(condition == "old", 0.5, -0.5)
  size   <- ifelse(set.size == "set size 16", 0.5, -0.5)
  direct <- as.integer(task == "D")
})

# Standard glmer formula: indirect criterion is omitted (fixed at 0
# by the median split). Random effects estimate the direct criterion
# and correlated task sensitivities across subjects.
fit <- lme4::glmer(
  resp ~ 0 + direct + task:size + task:cond +
    (0 + direct | subj) + (0 + task:cond | subj),
  data = trials, family = binomial("probit"),
  control = lme4::glmerControl(optimizer = "bobyqa")
)

# Check the names lme4 assigned to the sensitivity terms
names(lme4::fixef(fit))

# Evaluate hypotheses conditional on set size
usdt_tests(fit, direct = "taskD:cond", indirect = "taskI:cond")

Reliability of direct and indirect task measures

Description

Estimates the reliability of sensitivity (d′d') by separating true variance across participants from sampling noise caused by finite trial counts. Values close to 1 indicate that the measure reliably separates participants, whereas values near 0 indicate that observed differences are mostly measurement error.

Usage

usdt_reliability(object)

## S3 method for class 'usdt_reliability'
summary(object, ...)

## S3 method for class 'usdt_reliability'
print(x, ...)

Arguments

object

An hsdt object from hsdt(), which may also contain bootstrap results from usdt_boot().

...

Ignored.

x

A usdt_reliability object.

Details

For participant ii in task jj, reliability is defined as:

τj2τj2+vij\frac{\tau_j^2}{\tau_j^2 + v_{ij}}

where τj2\tau_j^2 is the true variance in sensitivity across participants from the model's random effects, and vijv_{ij} is the squared standard error of d′d' for that participant. This error variance reflects how precisely their trials determine sensitivity, accounting for trial count, performance level on the probit curve, and uncertainty in the criterion.

This variance is calculated using the large-sample Fisher information formula from Gourevitch and Galanter (1967). Unlike sdt_moments(), which evaluates that formula at raw empirical proportions (var_gg), usdt_reliability() evaluates it at the response probabilities predicted by the fitted hierarchical model.

Overall task reliability averages vijv_{ij} across participants, representing the expected proportion of true variance for a participant drawn at random from the sample.

When object includes bootstrap replicates from usdt_boot(), confidence intervals for reliability are computed automatically across all retained samples.

Value

An object of class usdt_reliability containing:

  • ⁠$tasks⁠: Overall reliability and variance components for each task.

  • ⁠$subjects⁠: Participant-level d′d', error variances, and individual reliabilities.

  • Bootstrap intervals for both components when available in object.

References

Gourevitch, V., & Galanter, E. (1967). A significance test for one parameter isosensitivity functions. Psychometrika, 32(1), 25–33. doi:10.1007/BF02289402

See Also

hsdt(), usdt_boot(), sdt_moments()

Examples

# Contextual cuing data from Vadillo et al. (2025)
d <- usdt_data_tasks(
  direct   = vadillo_awareness,
  indirect = vadillo_cuing,
  subject_col      = "subj",
  condition_col    = "condition",
  condition_levels = c(signal = "old", noise = "new"),
  response_col     = list(direct = "judged.old", indirect = "rt"),
  response_levels  = list(direct   = c(signal = 1, noise = 0),
                          indirect = c(signal = "faster", noise = "slower")),
  dichotomize      = list(direct = FALSE, indirect = TRUE)
)

r <- usdt_reliability(hsdt(d))
r

# Participant-level estimates (one row per subject and task)
head(r$subjects)

Awareness data from a probabilistic cuing experiment

Description

Trial-level direct-awareness data from Experiment 2 of Vadillo et al. (2025). The object reproduces the source CSV file without filtering or recoding and can be used as the direct input to usdt_data_tasks().

Usage

vadillo_awareness

Format

A data frame with 6,656 rows, 104 participants, and 10 variables:

subj

Participant identifier.

file

Original participant file name.

trial

Trial number.

pattId

Pattern identifier.

judgm

Awareness judgement on the original response scale.

judged.old

Whether the pattern was judged old (1) or new (0).

condition

Whether the pattern was old or new.

offset

Spatial-offset condition.

color

Colour condition.

set.size

Set-size condition.

Source

Vadillo, M. A., Malejka, S., & Shanks, D. R. (2025). Mapping the reliability multiverse of contextual cuing. Journal of Experimental Psychology: Learning, Memory, and Cognition. doi:10.1037/xlm0001410. Data retrieved from https://osf.io/jp3gx/.

Examples

data(vadillo_awareness)
str(vadillo_awareness)

Cuing data from a probabilistic cuing experiment

Description

Trial-level indirect-task data from Experiment 2 of Vadillo et al. (2025). The object reproduces the source CSV file without filtering or recoding and can be used as the indirect input to usdt_data_tasks().

Usage

vadillo_cuing

Format

A data frame with 39,936 rows, 104 participants, and 13 variables:

experiment

Experiment label.

subj

Participant identifier.

file

Original participant file name.

trial

Trial number.

block

Block number.

epoch

Epoch number.

pattId

Pattern identifier.

acc

Response accuracy (1 = correct, 0 = incorrect).

rt

Response time in milliseconds.

condition

Whether the pattern was old or new.

offset

Spatial-offset condition.

color

Colour condition.

set.size

Set-size condition.

Source

Vadillo, M. A., Malejka, S., & Shanks, D. R. (2025). Mapping the reliability multiverse of contextual cuing. Journal of Experimental Psychology: Learning, Memory, and Cognition. doi:10.1037/xlm0001410. Data retrieved from https://osf.io/jp3gx/.

Examples

data(vadillo_cuing)
str(vadillo_cuing)