OSCR

Dopaminergic processes predict temporal distortions in event memory.

Code ↔ Paper

9 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 9 matches · 2 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
  1. [1] § Methods › Eye-tracking methods › Eye-tracking ↔ DATA_AND_ANALYSIS/Blink_Code_and_Data/ET_RemoveBlinks_Algorithm.m, lines 108–227 · score 0.80 · FIR filter, Passband Frequency, Stopband Frequency, profiles, peak, trough
  2. [2] § Methods › Eye-tracking methods › Eye-tracking ↔ DATA_AND_ANALYSIS/Blink_Code_and_Data/EyeBrain_Blinks_1_Preprocess.m, the whole file · a weak match · score 0.64 · Passband Frequency, Stopband Frequency, peak, trough, artifacts, filter
  3. [3] § Methods › Eye-tracking methods › Eye-tracking ↔ DATA_AND_ANALYSIS/Blink_Code_and_Data/ET_RemoveBlinks_Algorithm.m, lines 108–227 · score 0.62 · Trough Threshold Factor, findpeaks, profiles, velocity, algorithm, artifacts
  4. [4] § Results › Event boundaries predicted a momentary increase in blinking ↔ DATA_AND_ANALYSIS/R_Code_and_Data/2026_01_DopaMinute_AnalysisCode.R, lines 602–646 · score 0.56 · tone onset, temporal distance ratings, post tone, VTA parameter, box, subset
  5. [5] § Results › Momentary increases in local boundary-evoked blinking behavior were not associated with later temporal distance ratings in memory ↔ DATA_AND_ANALYSIS/R_Code_and_Data/2026_01_DopaMinute_AnalysisCode.R, lines 958–1010 · score 0.56 · odds ratio, post tone blink, temporal distance ratings, interaction, CI, memory
  6. [6] § Results › Event boundaries reliably predicted BOLD activation in the VTA, and these brain responses predicted later time dilation effects in memory ↔ DATA_AND_ANALYSIS/R_Code_and_Data/2026_01_DopaMinute_AnalysisCode.R, lines 508–550 · score 0.56 · boundary related VTA, odds ratio, temporal distance ratings, CI
  7. [7] § Methods › Eye-tracking methods › Testing linear relations between the VTA, temporal memory, and blink patterns ↔ DATA_AND_ANALYSIS/R_Code_and_Data/2026_01_DopaMinute_AnalysisCode.R, lines 351–415 · score 0.53 · Distance memory ratings, temporal distance memory, ps, VTA parameter, Position, encoding
  8. [8] § Methods › fMRI acquisition and preprocessing › fMRI preprocessing ↔ DATA_AND_ANALYSIS/R_Code_and_Data/2026_01_DopaMinute_AnalysisCode.R, lines 864–909 · score 0.53 · excessive head motion, extreme, smoothing, unwarping, space, filter
  9. [9] § Methods › Eye-tracking methods › Eye-tracking ↔ DATA_AND_ANALYSIS/Blink_Code_and_Data/EyeBrain_Blinks_1_Preprocess.m, the whole file · a weak match · score 0.52 · Trough Threshold Factor, algorithm, peaks, artifacts, Eye, pupil

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

R · 1,569 lines · 73 KB · no license · 5 matches

  1. # Analysis Code
  2. # Manuscript title: Dopaminergic processes predict temporal distortions in event memory
  3. # Does not include analyses performed in supplementary material
  4. # Compiled by Erin Morrow
  5. # Last updated: 2/3/26
  6. # Set appropriate working directory
  7. # setwd()
  8. # Set contrasts for sum/deviation coding
  9. options(contrasts = rep("contr.sum", 2))
  10. # Install and load packages
  11. install.packages("gtable", dependencies = TRUE)
  12. install.packages("ggplot2")
  13. install.packages("lme4")
  14. install.packages("lmerTest")
  15. install.packages("pastecs")
  16. install.packages("dplyr")
  17. install.packages("tidyverse")
  18. install.packages("effsize")
  19. install.packages("lsr")
  20. install.packages("psychReport")
  21. install.packages("ggExtra")
  22. install.packages("rstatix")
  23. install.packages("car")
  24. install.packages("emmeans")
  25. install.packages("interactions")
  26. install.packages("lsmeans")
  27. install.packages("data.table")
  28. install.packages("effects")
  29. install.packages("tibble")
  30. install.packages("cowplot")
  31. install.packages("readr")
  32. install.packages("lavaan")
  33. install.packages("Hmisc")
  34. install.packages("plotrix")
  35. install.packages("ordinal")
  36. install.packages("svglite")
  37. install.packages("cocor")
  38. install.packages("insight")
  39. install.packages("effectsize")
  40. install.packages("report")
  41. library("gtable")
  42. library("ggplot2")
  43. library("lme4")
  44. library("lmerTest")
  45. library("pastecs")
  46. library("dplyr")
  47. library("tidyverse")
  48. library("effsize")
  49. library("lsr")
  50. library("psychReport")
  51. library("ggExtra")
  52. library("rstatix")
  53. library("car")
  54. library("emmeans")
  55. library("interactions")
  56. library("lsmeans")
  57. library("data.table")
  58. library("effects")
  59. library("tibble")
  60. library("cowplot")
  61. library("readr")
  62. library("lavaan")
  63. library("Hmisc")
  64. library("plotrix")
  65. library("ordinal")
  66. library("svglite")
  67. library("cocor")
  68. library("effectsize")
  69. library("report")
  70. #### WRITE DATA CLEANING FUNCTIONS ####
  71. # Create remove outliers function
  72. remove_outliers <- function(x, na.rm = TRUE, ...){
  73. qnt <- quantile(x, probs=c(.25,.75), na.rm = na.rm, ...) # calculate first and third quartiles
  74. H <- 1.5 * IQR(x, na.rm = na.rm) # define outlier bounds
  75. y <- x
  76. y[x < (qnt[1] - H)] <- NA # remove low outliers
  77. y[x > (qnt[2] + H)] <- NA # remove high outliers
  78. y}
  79. # Create centering function
  80. cent_function <- function(x) x - mean(x, na.rm = TRUE)
  81. # Create mean function
  82. mean_function <- function(x) mean(x, na.rm = TRUE)
  83. # Create raincloud plot function
  84. ## Source: Ben Marwick on Github (https://gist.github.com/benmarwick/2a1bb0133ff568cbe28d/)
  85. "%||%" <- function(a, b) {
  86. if (!is.null(a)) a else b
  87. }
  88. geom_flat_violin <- function(mapping = NULL, data = NULL, stat = "ydensity",
  89. position = "dodge", trim = TRUE, scale = "area",
  90. show.legend = NA, inherit.aes = TRUE, ...) {
  91. layer(
  92. data = data,
  93. mapping = mapping,
  94. stat = stat,
  95. geom = GeomFlatViolin,
  96. position = position,
  97. show.legend = show.legend,
  98. inherit.aes = inherit.aes,
  99. params = list(
  100. trim = trim,
  101. scale = scale,
  102. ...
  103. )
  104. )
  105. }
  106. #' @rdname ggplot2-ggproto
  107. #' @format NULL
  108. #' @usage NULL
  109. #' @export
  110. GeomFlatViolin <-
  111. ggproto("GeomFlatViolin", Geom,
  112. setup_data = function(data, params) {
  113. data$width <- data$width %||%
  114. params$width %||% (resolution(data$x, FALSE) * 0.9)
  115. # ymin, ymax, xmin, and xmax define the bounding rectangle for each group
  116. data %>%
  117. group_by(group) %>%
  118. mutate(
  119. ymin = min(y),
  120. ymax = max(y),
  121. xmin = x,
  122. xmax = x + width / 2
  123. )
  124. },
  125. draw_group = function(data, panel_scales, coord) {
  126. # Find the points for the line to go all the way around
  127. data <- transform(data,
  128. xminv = x,
  129. xmaxv = x + violinwidth * (xmax - x)
  130. )
  131. # Make sure it's sorted properly to draw the outline
  132. newdata <- rbind(
  133. plyr::arrange(transform(data, x = xminv), y),
  134. plyr::arrange(transform(data, x = xmaxv), -y)
  135. )
  136. # Close the polygon: set first and last point the same
  137. # Needed for coord_polar and such
  138. newdata <- rbind(newdata, newdata[1, ])
  139. ggplot2:::ggname("geom_flat_violin", GeomPolygon$draw_panel(newdata, panel_scales, coord))
  140. },
  141. draw_key = draw_key_polygon,
  142. default_aes = aes(
  143. weight = 1, colour = "grey20", fill = "white", linewidth = 0.5,
  144. alpha = NA, linetype = "solid"
  145. ),
  146. required_aes = c("x", "y")
  147. )
  148. #### FIGURE 1 (bottom right panel): Temporal distance memory test ####
  149. # Load csv
  150. memory <- read.csv("2026_01_DopaMinute_Main_SourceData_MEMORY.csv")
  151. # Should point to memory tab in main source data
  152. # Subset to relevant columns
  153. relevant <- c("Subject", # Participant ID
  154. "BlockName", # Block number (1-10)
  155. "FilterBlockIissue", # Identifies blocks with ISI timing error
  156. "ErrorAcrossTrials", # Identifies trials with incorrect tested item
  157. "RemSqueezeBall", # Identifies block during which participant triggered squeeze ball
  158. "ExcludeFirstPair", # Identifies trials with first item in sequence (boundary-like)
  159. "PositionAtEncoding", # Position of to-be-tested item pair at encoding (1-14)
  160. "Condition", # Boundary or same-context ("NB") pair
  161. "AccurateSide", # Side on which correct answer was displayed in temporal order memory test
  162. "ObjectFar", # First object in tested pair
  163. "ObjectNear", # Second (more recent) object in tested pair
  164. "RecencyAcc", # Accuracy on temporal order memory test (1 = correct)
  165. "DistanceRating", # Raw button box responses on temporal distance memory test
  166. "DistanceRatingConverted", # Categorical responses on temporal distance memory test
  167. "DistanceRatingDiscrete", # Numerical responses on temporal distance memory test
  168. "BoundaryItemBetween", # Item used as reference between each tested pair
  169. "PositionAtTest", # Position of to-be-tested item pair at retrieval (1-14)
  170. "UNWARP_HP_TONE_VTA_thr75", # Trial-level VTA parameter estimate
  171. "Tags") # Type of tested pair
  172. submemory <- memory[, relevant]
  173. # Perform exclusions
  174. submemory_excl <- subset(submemory, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  175. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  176. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  177. ExcludeFirstPair == "1") # Removes trials with first item in sequence (boundary-like)
  178. # Ensure Condition is a factor
  179. submemory_excl$Condition <- factor(submemory_excl$Condition)
  180. # Create separate ordinal variable for distance memory
  181. submemory_excl$ordinal_response <- factor(submemory_excl$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE)
  182. # Run cumulative rank model
  183. distance_model <- clmm(ordinal_response ~ Condition + (1|Subject), data = submemory_excl)
  184. summary(distance_model)
  185. exp(distance_model$beta) # odds ratio
  186. tab <- coef(summary(distance_model)) # derive Wald's CI
  187. beta <- tab["Condition1", "Estimate"]
  188. se <- tab["Condition1", "Std. Error"]
  189. z <- qnorm(0.975)
  190. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  191. exp(c(OR = beta, ci_logit))
  192. # Plot
  193. ## For plotting purposes, summarize distance memory (numerical) per subject & condition
  194. submemory_excl$DistanceRatingDiscrete <- as.numeric(submemory_excl$DistanceRatingDiscrete) # ensure distance rating is numerical
  195. distance_bysub <- submemory_excl %>% group_by(Subject, Condition) %>% dplyr::summarise(mean_Distance = mean(DistanceRatingDiscrete, na.rm = TRUE))
  196. ## Create plot
  197. distance_plot <- ggplot(distance_bysub, aes(x = Condition, y = mean_Distance, fill = Condition)) +
  198. geom_flat_violin(position = position_nudge(x=.25, y=0), color = NA) +
  199. geom_boxplot(width = .07, outlier.shape = NA, position = position_nudge(x=.25, y=0)) +
  200. geom_jitter(alpha = 0.5, width = .15, size = 4, aes(color = Condition)) +
  201. scale_fill_manual(values = c("Boundary" = "#f3e1a1ff", "NB" = "#c8b7e4ff")) +
  202. scale_color_manual(values = c("Boundary" = "#f3e1a1ff", "NB" = "#c8b7e4ff")) +
  203. scale_x_discrete(labels = c("Boundary" = "Boundary", "NB" = "Same-Context")) +
  204. labs(x = NULL, y = "Temporal Distance Rating") +
  205. theme_classic() +
  206. theme(text = element_text(size = 20), legend.position = "none") +
  207. scale_y_continuous(breaks = seq(2,3,1), labels = c("Close","Far")) +
  208. coord_cartesian(ylim= c(1.9,3))
  209. distance_plot
  210. ## Temporal distance memory ratings by item pair position during encoding (all pairs)
  211. ### Run cumulative rank model
  212. distance_byposition_model <- clmm(ordinal_response ~ PositionAtEncoding + (1|Subject), data = submemory_excl)
  213. summary(distance_byposition_model)
  214. exp(distance_byposition_model$beta) # odds ratio
  215. tab <- coef(summary(distance_byposition_model)) # derive Wald's CI
  216. beta <- tab["PositionAtEncoding", "Estimate"]
  217. se <- tab["PositionAtEncoding", "Std. Error"]
  218. z <- qnorm(0.975)
  219. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  220. exp(c(OR = beta, ci_logit))
  221. #### FIGURE 2: Event boundaries predicted greater VTA activation, and these responses predicted greater time dilation effects in memory. ####
  222. ####### FIGURE 2B: Main effect of tone type on VTA activation
  223. # Read csv
  224. encoding <- read.csv("2026_01_DopaMinute_Main_SourceData_ENCODING.csv")
  225. # Should point to encoding tab in main source data
  226. # Subset to relevant columns
  227. relevant <- c("Subject", # Participant ID
  228. "Block", # Block number (1-10)
  229. "RemSqueezeBall", # Identifies block during which participant triggered squeeze ball
  230. "ExtremeMotion1mm", # Identifies blocks with excessive head motion
  231. "TrialNumb", # Trial number (1-32)
  232. "EventPosition", # Position within 8-item event (1-8)
  233. "Condition", # Boundary or same-context ("NB") tone
  234. "UNWARP_HP_TONE_VTA_thr75", # Trial-level VTA parameter estimate
  235. "UNWARP_HP_TONE_LC_NM_THR11_AVG", # Trial-level LC parameter estimate
  236. "UNWARP_HP_TONE_Univariate_ACC") # Trial-level ACC parameter estimate
  237. subencoding <- encoding[, relevant]
  238. # Remove outliers
  239. subencoding_rem <- subencoding %>%
  240. group_by(Subject) %>%
  241. dplyr::mutate(across(starts_with("UNWARP_HP_TONE_VTA"), remove_outliers, .names = "Rem_VTA")) %>% # remove trial-level VTA estimate outliers
  242. dplyr::mutate(across(starts_with("UNWARP_HP_TONE_LC"), remove_outliers, .names = "Rem_LC")) %>% # remove trial-level LC estimate outliers
  243. dplyr::mutate(across(starts_with("UNWARP_HP_TONE_Univariate_ACC"), remove_outliers, .names = "Rem_ACC")) # remove trial-level ACC estimate outliers
  244. ## Check percentage of VTA outliers
  245. outliers <- sum(is.na(subencoding_rem$Rem_VTA)) # sum NAs
  246. total <- nrow(subencoding_rem) # sum number of rows
  247. percent_outliers <- outliers/total # percentage
  248. # Perform exclusions
  249. subencoding_excl <- subset(subencoding_rem, RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  250. TrialNumb != "1" & # Removes first trial (boundary-like)
  251. ExtremeMotion1mm == "1") # Removes blocks with excessive head motion
  252. # Run linear mixed model
  253. vta_model <- lmer(Rem_VTA ~ Condition + (1|Subject), data = subencoding_excl)
  254. summary(vta_model)
  255. report(vta_model)
  256. # Plot
  257. ## For plotting purposes, summarize VTA activation per subject & condition
  258. vta_bysub <- subencoding_excl %>% group_by(Subject, Condition) %>% dplyr::summarise(VTA = mean(Rem_VTA, na.rm = TRUE))
  259. ## Create plot
  260. vta_plot <- ggplot(vta_bysub, aes(x = Condition, y = VTA, fill = Condition)) +
  261. geom_flat_violin(position = position_nudge(x=.25, y=0), color = NA) +
  262. geom_boxplot(width = .07, outlier.shape = NA, position = position_nudge(x=.25, y=0)) +
  263. geom_jitter(alpha = 0.5, width = .15, size = 4, aes(color = Condition)) +
  264. scale_fill_manual(values = c("Boundary" = "#fec01fff", "NB" = "#674ea7ff")) +
  265. scale_color_manual(values = c("Boundary" = "#fec01fff", "NB" = "#674ea7ff")) +
  266. scale_x_discrete(labels = c("Boundary" = "Boundary", "NB" = "Same-Context")) +
  267. labs(x = NULL, y = "VTA Parameter Estimate") +
  268. theme_classic() +
  269. theme(text = element_text(size = 20), legend.position = "none")
  270. vta_plot
  271. ggplot_build(vta_plot)$data # get boxplot stats
  272. # Compare each condition to baseline (0)
  273. subencoding_excl_boundary <- subset(subencoding_excl, Condition == "Boundary") # create subsetted data frame for boundary condition
  274. subencoding_excl_samecont <- subset(subencoding_excl, Condition == "NB") # create subsetted data frame for same-context condition
  275. ## Boundary model
  276. vta_model_boundary <- lmer(Rem_VTA ~ 1 + (1 | Subject), data = subencoding_excl_boundary)
  277. summary(vta_model_boundary)
  278. report(vta_model_boundary)
  279. ## Same-context model
  280. vta_model_samecont <- lmer(Rem_VTA ~ 1 + (1 | Subject), data = subencoding_excl_samecont)
  281. summary(vta_model_samecont)
  282. report(vta_model_samecont)
  283. ####### FIGURE 2C: Plotting VTA activation by event position
  284. # Ensure event position is a factor
  285. subencoding_excl$EventPosition <- factor(subencoding_excl$EventPosition)
  286. # Summarize VTA activation per subject and event position
  287. vta_bysubposition <- subencoding_excl %>% group_by(Subject, EventPosition) %>% dplyr::summarise(VTA = mean(Rem_VTA, na.rm = TRUE))
  288. # Order event position levels
  289. levels(vta_bysubposition$EventPosition) <- c("Boundary", "2", "3", "4", "5", "6", "7", "8")
  290. # Create plot
  291. vta_subposition_plot <- ggplot(vta_bysubposition, aes(x = EventPosition, y = VTA, fill = EventPosition)) +
  292. geom_flat_violin(position = position_nudge(x=.25, y=0), color = NA) +
  293. geom_boxplot(width = .1, outlier.shape = NA, position = position_nudge(x=.25, y=0)) +
  294. geom_jitter(alpha = 0.5, width = .15, aes(color = EventPosition)) +
  295. scale_fill_manual(values = c("#fec01fff","#d2c5f4ff", "#c1b1eaff", "#b4a2e3ff", "#a28ed7ff", "#937ccdff", "#7f66bdff", "#674ea7ff")) +
  296. scale_color_manual(values = c("#fec01fff","#d2c5f4ff", "#c1b1eaff", "#b4a2e3ff", "#a28ed7ff", "#937ccdff", "#7f66bdff", "#674ea7ff")) +
  297. labs(x = "Event Position", y = "VTA Parameter Estimate") +
  298. theme_classic() +
  299. theme(text = element_text(size = 20), legend.position = "none")
  300. vta_subposition_plot
  301. ggplot_build(vta_subposition_plot)$data # get boxplot stats
  302. ####### FIGURE 2D & 2E: VTA activation vs. distance memory ratings (D: boundary | E: same-context )
  303. # Load csv
  304. memory <- read.csv("2026_01_DopaMinute_Main_SourceData_MEMORY.csv")
  305. # Should point to memory tab in main source data
  306. # Subset to relevant columns
  307. relevant <- c("Subject", # Participant ID
  308. "BlockName", # Block number (1-10)
  309. "FilterBlockIissue", # Identifies blocks with ISI timing error
  310. "ErrorAcrossTrials", # Identifies trials with incorrect tested item
  311. "RemSqueezeBall", # Identifies block during which participant triggered squeeze ball
  312. "ExcludeFirstPair", # Identifies trials with first item in sequence (boundary-like)
  313. "ExtremeMotion1mm", # Identifies blocks with excessive head motion
  314. "PositionAtEncoding", # Position of to-be-tested item pair at encoding (1-14)
  315. "Condition", # Boundary or same-context ("NB") pair
  316. "AccurateSide", # Side on which correct answer was displayed in temporal order memory test
  317. "ObjectFar", # First object in tested pair
  318. "ObjectNear", # Second (more recent) object in tested pair
  319. "RecencyAcc", # Accuracy on temporal order memory test (1 = correct)
  320. "DistanceRating", # Raw button box responses on temporal distance memory test
  321. "DistanceRatingConverted", # Categorical responses on temporal distance memory test
  322. "DistanceRatingDiscrete", # Numerical responses on temporal distance memory test
  323. "BoundaryItemBetween", # Item used as reference between each tested pair
  324. "PositionAtTest", # Position of to-be-tested item pair at retrieval (1-14)
  325. "Blink_Exc25", # Identifies windows with more than 25% invalid eye tracking samples
  326. "UNWARP_HP_TONE_VTA_thr75", # Trial-level VTA parameter estimate
  327. "UNWARP_HP_TONE_LC_NM_THR11_AVG", # Trial-level LC parameter estimate
  328. "Pairwise_PS_LEFT_DG", # Trial-level left DG pattern similarity
  329. "Pairwise_PS_RIGHT_DG", # Trial-level right DG pattern similarity
  330. "Pairwise_PS_LEFT_ca1", # Trial-level left CA1 pattern similarity
  331. "Pairwise_PS_RIGHT_ca1", # Trial-level right CA1 pattern similarity
  332. "Pairwise_PS_LEFT_ca23", # Trial-level left CA2/3 pattern similarity
  333. "Pairwise_PS_RIGHT_ca23") # Trial-level right CA2/3 pattern similarity
  334. submemory <- memory[, relevant]
  335. # Remove outliers
  336. submemory_rem <- submemory %>%
  337. group_by(Subject) %>%
  338. dplyr::mutate(across(starts_with("UNWARP_HP_TONE_VTA"), remove_outliers, .names = "Rem_VTA")) %>% # remove trial-level VTA estimate outliers
  339. dplyr::mutate(across(starts_with("UNWARP_HP_TONE_LC"), remove_outliers, .names = "Rem_LC")) # remove trial-level LC estimate outliers
  340. ## Check percentage of VTA outliers
  341. outliers <- sum(is.na(submemory_rem$Rem_VTA)) # sum NAs
  342. total <- nrow(submemory_rem) # sum number of rows
  343. percent_outliers <- outliers/total # percentage
  344. # Perform exclusions
  345. submemory_excl <- subset(submemory_rem, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  346. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  347. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  348. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  349. ExtremeMotion1mm == "1") # Removes trials with excessive head motion
  350. # Mean centering
  351. ## Overall data frame
  352. submemory_all <- submemory_excl %>%
  353. group_by(Subject) %>%
  354. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  355. ## Boundary data frame
  356. boundarypairs <- subset(submemory_excl, Condition == "Boundary") # Subset to boundary only
  357. submemory_boundary <- boundarypairs %>%
  358. group_by(Subject) %>%
  359. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  360. ## Same-context data frame
  361. samepairs <- subset(submemory_excl, Condition == "NB") # Subset to same-context only
  362. submemory_samecont <- samepairs %>%
  363. group_by(Subject) %>%
  364. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  365. # Create separate ordinal variables for distance memory
  366. submemory_all$ordinal_response <- factor(submemory_all$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # overall data frame
  367. submemory_boundary$ordinal_response <- factor(submemory_boundary$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # boundary only data frame
  368. submemory_samecont$ordinal_response <- factor(submemory_samecont$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # same context only data frame
  369. # Interaction model - without pair position as fixed effect
  370. vta_distance_model_all <- clmm(ordinal_response ~ scale(Cent_Rem_VTA)*Condition + (1|Subject), data = submemory_all)
  371. summary(vta_distance_model_all)
  372. # Boundary model - without pair position as fixed effect
  373. vta_distance_model_boundary <- clmm(ordinal_response ~ scale(Cent_Rem_VTA) + (1|Subject), data = submemory_boundary)
  374. summary(vta_distance_model_boundary)
  375. # Same context model - without pair position as fixed effect
  376. vta_distance_model_samecont <- clmm(ordinal_response ~ scale(Cent_Rem_VTA) + (1|Subject), data = submemory_samecont)
  377. summary(vta_distance_model_samecont)
  378. # Including pair position as a fixed effect in models
  379. ## Interaction model
  380. vta_distance_model_pp_all <- clmm(ordinal_response ~ scale(Cent_Rem_VTA)*Condition + PositionAtEncoding + (1|Subject), data = submemory_all)
  381. summary(vta_distance_model_pp_all)
  382. exp(vta_distance_model_pp_all$beta) # odds ratio
  383. tab <- coef(summary(vta_distance_model_pp_all)) # derive Wald's CI
  384. beta <- tab["scale(Cent_Rem_VTA):Condition1", "Estimate"]
  385. se <- tab["scale(Cent_Rem_VTA):Condition1", "Std. Error"]
  386. z <- qnorm(0.975)
  387. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  388. exp(c(OR = beta, ci_logit))
  389. ### Compare fit to model without pair position
  390. anova(vta_distance_model_all, vta_distance_model_pp_all)
  391. ## Boundary model
  392. vta_distance_model_pp_boundary <- clmm(ordinal_response ~ scale(Cent_Rem_VTA) + PositionAtEncoding + (1|Subject), data = submemory_boundary)
  393. summary(vta_distance_model_pp_boundary)
  394. exp(vta_distance_model_pp_boundary$beta) # odds ratio
  395. tab <- coef(summary(vta_distance_model_pp_boundary)) # derive Wald's CI
  396. beta <- tab["scale(Cent_Rem_VTA)", "Estimate"]
  397. se <- tab["scale(Cent_Rem_VTA)", "Std. Error"]
  398. z <- qnorm(0.975)
  399. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  400. exp(c(OR = beta, ci_logit))
  401. ### Compare fit to model without pair position
  402. anova(vta_distance_model_boundary, vta_distance_model_pp_boundary)
  403. ## Same context model
  404. vta_distance_model_pp_samecont <- clmm(ordinal_response ~ scale(Cent_Rem_VTA) + PositionAtEncoding + (1|Subject), data = submemory_samecont)
  405. summary(vta_distance_model_pp_samecont)
  406. exp(vta_distance_model_pp_samecont$beta) # odds ratio
  407. tab <- coef(summary(vta_distance_model_pp_samecont)) # derive Wald's CI
  408. beta <- tab["scale(Cent_Rem_VTA)", "Estimate"]
  409. se <- tab["scale(Cent_Rem_VTA)", "Std. Error"]
  410. z <- qnorm(0.975)
  411. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  412. exp(c(OR = beta, ci_logit))
  413. ### Compare fit to model without pair position
  414. anova(vta_distance_model_samecont, vta_distance_model_pp_samecont)
  415. # Create plots
  416. ## Boundary plot
  417. submemory_boundary$DistanceRatingDiscrete <- as.numeric(submemory_boundary$DistanceRatingDiscrete)
  418. vta_distance_plot <- ggplot(submemory_boundary) +
  419. aes(x = Cent_Rem_VTA, y = DistanceRatingDiscrete) +
  420. stat_smooth(aes(group=Subject), method = 'lm', formula = y ~ x, se = FALSE, color = "#fec01fff", lwd = 0.3, geom = "line", lineend="round") +
  421. stat_smooth(method = 'lm', formula = y ~ x, se = FALSE, color = rgb(0,0,0,1), lwd = 1, geom = "line", lineend="round") +
  422. xlab("Boundary-related VTA Parameter\nEstimate (mean-centered)") +
  423. ylab("Temporal Distance Rating") +
  424. theme(rect = element_rect(fill = "transparent", color = NA), # make background transparent
  425. plot.background = element_rect(color=NA), # removes white outline around the plot
  426. panel.background = element_blank(),
  427. panel.grid.major = element_blank(), # Remove gridlines
  428. panel.grid.minor = element_blank(),
  429. panel.spacing = unit(0, "lines"),
  430. axis.line = element_line(color = "black"),
  431. text = element_text(size=20),
  432. legend.position = 'none') +
  433. scale_y_continuous(breaks = seq(1,4,1), labels = c("Very\nClose","Close","Far","Very\nFar")) +
  434. coord_cartesian(ylim= c(1,4)) # this sets the axis limits WITHOUT clipping
  435. vta_distance_plot
  436. ## Same-context plot
  437. submemory_samecont$DistanceRatingDiscrete <- as.numeric(submemory_samecont$DistanceRatingDiscrete)
  438. vta_distance_samecont_plot <- ggplot(submemory_samecont) +
  439. aes(x = Cent_Rem_VTA, y = DistanceRatingDiscrete) +
  440. stat_smooth(aes(group=Subject), method = 'lm', formula = y ~ x, se = FALSE, color = "#674ea7ff", lwd = 0.3, geom = "line", lineend="round") +
  441. stat_smooth(method = 'lm', formula = y ~ x, se = FALSE, color = rgb(0,0,0,1), lwd = 1, geom = "line", lineend="round") +
  442. xlab("Same-context VTA Parameter\nEstimate (mean-centered)") +
  443. ylab("Temporal Distance Rating") +
  444. theme(rect = element_rect(fill = "transparent", color = NA), # make background transparent
  445. plot.background = element_rect(color=NA), # removes white outline around the plot
  446. panel.background = element_blank(),
  447. panel.grid.major = element_blank(), # Remove gridlines
  448. panel.grid.minor = element_blank(),
  449. panel.spacing = unit(0, "lines"),
  450. axis.line = element_line(color = "black"),
  451. text = element_text(size=20),
  452. legend.position = 'none') +
  453. scale_y_continuous(breaks = seq(1,4,1), labels = c("Very\nClose","Close","Far","Very\nFar")) +
  454. coord_cartesian(ylim= c(1,4)) # this sets the axis limits WITHOUT clipping
  455. vta_distance_samecont_plot
  456. #### PREPARE: Load in data for blinks ####
  457. # ENCODING: Read encoding csv
  458. encoding <- read.csv("2026_01_DopaMinute_Main_SourceData_ENCODING.csv")
  459. # Should point to encoding tab in main source data
  460. # Subset to relevant columns
  461. relevant <- c("Subject", # Participant ID
  462. "Block", # Block number (1-10)
  463. "RemSqueezeBall", # Identifies block during which participant triggered squeeze ball
  464. "ExtremeMotion1mm", # Identifies blocks with excessive head motion
  465. "TrialNumb", # Trial number (1-32)
  466. "EventPosition", # Position within 8-item event (1-8)
  467. "Condition", # Boundary or same-context ("NB") tone
  468. "UNWARP_HP_TONE_VTA_thr75", # Trial-level VTA parameter estimate
  469. "UNWARP_HP_TONE_LC_NM_THR11_AVG", # Trial-level LC parameter estimate
  470. "BlinkCount_Pre", # Blink count in 1.5s prior to tone
  471. "BlinkCount_Post", # Blink count in 1.5s after tone
  472. "Post_Include_25", # Identifies 1.5s post-tone intervals with more than 25% invalid samples
  473. "Pre_Include_25", # Identifies 1.5s pre-tone intervals with more than 25% invalid samples
  474. "TONEwindowduration", # Duration between each tone onset and end of post-tone ISI
  475. "BlinkCount_Tone", # Blink count after each tone (i.e., during above window)
  476. "Tone_Include_25") # Identifies tone windows with more than 25% invalid samples
  477. subencoding <- encoding[, relevant]
  478. # Ensure blink data is numerical
  479. subencoding <- subencoding %>%
  480. dplyr::mutate(across(starts_with("Blink"), as.numeric))
  481. # MEMORY: Read memory csv
  482. memory <- read.csv("2026_01_DopaMinute_Main_SourceData_MEMORY.csv")
  483. # Should point to memory tab in main source data
  484. # Subset to relevant columns
  485. relevant <- c("Subject", # Participant ID
  486. "BlockName", # Block number (1-10)
  487. "FilterBlockIissue", # Identifies blocks with ISI timing error
  488. "ErrorAcrossTrials", # Identifies trials with incorrect tested item
  489. "RemSqueezeBall", # Identifies block during which participant triggered squeeze ball
  490. "ExcludeFirstPair", # Identifies trials with first item in sequence (boundary-like)
  491. "ExtremeMotion1mm", # Identifies blocks with excessive head motion
  492. "PositionAtEncoding", # Position of to-be-tested item pair at encoding (1-14)
  493. "Condition", # Boundary or same-context ("NB") pair OR # Boundary or same-context ("NB") tone
  494. "AccurateSide", # Side on which correct answer was displayed in temporal order memory test
  495. "ObjectFar", # First object in tested pair
  496. "ObjectNear", # Second (more recent) object in tested pair
  497. "RecencyAcc", # Accuracy on temporal order memory test (1 = correct)
  498. "DistanceRating", # Raw button box responses on temporal distance memory test
  499. "DistanceRatingConverted", # Categorical responses on temporal distance memory test
  500. "DistanceRatingDiscrete", # Numerical responses on temporal distance memory test
  501. "BoundaryItemBetween", # Item used as reference between each tested pair
  502. "PositionAtTest", # Position of to-be-tested item pair at retrieval (1-14)
  503. "Ringo_BlinksCount", # Blink count between tested pair
  504. "Blink_Exc25", # Identifies windows with more than 25% invalid eye tracking samples
  505. "UNWARP_HP_TONE_VTA_thr75", # Trial-level VTA parameter estimate
  506. "UNWARP_HP_TONE_LC_NM_THR11_AVG", # Trial-level LC parameter estimate
  507. "BlinkCount_Pre", # Blink count in 1.5s prior to tone
  508. "BlinkCount_Post", # Blink count in 1.5s after tone
  509. "Post_Include_25", # Identifies 1.5s post-tone intervals with more than 25% invalid samples
  510. "Pre_Include_25", # Identifies 1.5s pre-tone intervals with more than 25% invalid samples
  511. "TONEwindowduration", # Duration between reference tone onset and end of post-tone ISI
  512. "BlinkCount_Tone", # Blink count after reference tone (i.e., during above window)
  513. "Tone_Include_25", # Identifies reference tone windows with more than 25% invalid samples
  514. "Tone_VTA_in_Pre_Average", # Average of all trial-level VTA parameter estimates in pre-reference window
  515. "Tone_VTA_in_Post_Average", # Average of all trial-level VTA parameter estimates in post-reference window
  516. "Tone_VTA_FullWindow_Average") # Average of all trial-level VTA parameter estimates between each tested pair
  517. submemory <- memory[, relevant]
  518. # Ensure blink is numerical
  519. submemory <- submemory %>%
  520. dplyr::mutate(across(starts_with("BlinkCount"), as.numeric)) %>% # blink count before and after tone
  521. dplyr::mutate(across(starts_with("Ringo"), as.numeric)) # blink count over entire window
  522. #### FIGURE 3: Relationships between local blinks, brain, and behavior ####
  523. ####### FIGURE 3C: Main effect of tone type on local count
  524. # Remove outliers for local blink
  525. subencoding_rem <- subencoding %>%
  526. group_by(Subject) %>%
  527. dplyr::mutate(across(starts_with("Blink"), remove_outliers, .names = "Rem_{.col}"))
  528. # Check percentage of blink outliers
  529. outliers <- sum(is.na(subencoding_rem$Rem_BlinkCount_Post)) # sum NAs
  530. total <- nrow(subencoding_rem) # sum number of rows
  531. percent_outliers <- outliers/total # percentage
  532. # Perform exclusions
  533. subencoding_excl <- subset(subencoding_rem, RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  534. TrialNumb != "1" & # Removes first trial (boundary-like)
  535. Post_Include_25 == "1") # Removes 1.5s post-tone intervals with more than 25% invalid samples
  536. ## Check percentage of blink intervals excluded for missing data
  537. missing <- sum(subencoding_rem$Post_Include_25 == ".") # sum number of intervals excluded for more than 25% invalid samples
  538. total <- nrow(subencoding_rem) # sum number of rows
  539. percent_missing <- missing/total # percentage
  540. ## Check percentage excluded for being outliers OR missing data
  541. either <- sum(is.na(subencoding_rem$Rem_BlinkCount_Post) | subencoding_rem$Post_Include_25 == ".") # sum outlier blink intervals (NA) and those identified as containing more than 25% invalid samples
  542. total <- nrow(subencoding_rem) # sum number of rows
  543. percent_either <- either/total # percentage
  544. ## Check percentage remaining for each participant after exclusions & calculate average
  545. either_by_participant <- subencoding_rem %>%
  546. group_by(Subject) %>%
  547. dplyr::summarise(ExclusionCount = sum(is.na(Rem_BlinkCount_Post) | Post_Include_25 == "."), # same conditions as above
  548. TotalCount = n(),
  549. RemainingCount = TotalCount - ExclusionCount,
  550. RemainingPercentage = RemainingCount / TotalCount)
  551. mean(either_by_participant$RemainingPercentage, na.rm = TRUE) # calculate mean across participants
  552. # Descriptive statistics
  553. mean(subencoding_excl$Rem_BlinkCount_Post, na.rm = TRUE)
  554. sd(subencoding_excl$Rem_BlinkCount_Post, na.rm = TRUE)
  555. # Main effect of Condition on post-tone blink count
  556. blink_main <- lmer(Rem_BlinkCount_Post~Condition + (1 | Subject), data = subencoding_excl)
  557. summary(blink_main)
  558. report(blink_main)
  559. # CONTROL ANALYSIS: PRE-tone blink count
  560. ## Perform exclusions
  561. subencoding_excl_pre <- subset(subencoding_rem, RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  562. TrialNumb != "1" & # Removes first trial (boundary-like)
  563. Pre_Include_25 == "1") # Removes 1.5s pre-tone intervals with more than 25% invalid samples
  564. ## Main effect of Condition on PRE-tone blink count
  565. blink_main_pre <- lmer(Rem_BlinkCount_Pre~Condition + (1 | Subject), data = subencoding_excl_pre)
  566. summary(blink_main_pre)
  567. report(blink_main_pre)
  568. # Plot
  569. ## For plotting purposes, group blink counts by tone type AND participant
  570. trialsummary_type <- subencoding_excl %>%
  571. group_by(Subject, Condition) %>%
  572. dplyr::summarize(
  573. MeanBlinkCount = mean(Rem_BlinkCount_Post, na.rm = TRUE))
  574. ## For plotting purposes, update levels of tone type to Boundary and Same-Context
  575. trialsummary_type <- trialsummary_type %>%
  576. mutate(Condition = dplyr::recode(as.character(Condition),
  577. "Boundary" = "Boundary",
  578. "NB" = "Same-Context"))
  579. ## Create plot
  580. maineffect2 <- ggplot(trialsummary_type, aes(x = Condition, y = MeanBlinkCount, fill = Condition)) +
  581. geom_flat_violin(position = position_nudge(x=.25, y=0), color = NA) +
  582. geom_boxplot(width = .07, outlier.shape = NA, position = position_nudge(x=.25, y=0)) +
  583. geom_jitter(alpha = 0.5, width = .15, size = 4, aes(color = Condition)) +
  584. scale_fill_manual(values = c("Boundary" = "#f3e1a1ff", "Same-Context" = "#c8b7e4ff")) +
  585. scale_color_manual(values = c("Boundary" = "#f3e1a1ff", "Same-Context" = "#c8b7e4ff")) +
  586. labs(x = NULL, y = "Post-Tone Blink Count") +
  587. theme_classic() +
  588. theme(text = element_text(size = 20), legend.position = "none")
  589. maineffect2
  590. ggplot_build(maineffect2)$data # get boxplot stats
  591. ####### FIGURE 3D: Plotting local blink count by event position
  592. # Remove outliers for local blink
  593. subencoding_rem <- subencoding %>%
  594. group_by(Subject) %>%
  595. dplyr::mutate(across(starts_with("Blink"), remove_outliers, .names = "Rem_{.col}"))
  596. ## Check percentage of blink outliers
  597. outliers <- sum(is.na(subencoding_rem$Rem_BlinkCount_Post)) # sum NAs
  598. total <- nrow(subencoding_rem) # sum number of rows
  599. percent_outliers <- outliers/total # percentage
  600. # Perform exclusions
  601. subencoding_excl <- subset(subencoding_rem, RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  602. TrialNumb != "1" & # Removes first trial (boundary-like)
  603. Post_Include_25 == "1") # Removes 1.5s post-tone intervals with more than 25% invalid samples
  604. ## Check percentage of blink intervals excluded for missing data
  605. missing <- sum(subencoding_rem$Post_Include_25 == ".") # sum NAs
  606. total <- nrow(subencoding_rem) # sum number of rows
  607. percent_missing <- missing/total # percentage
  608. # Plot
  609. ## For plotting purposes, group blink counts by trial number
  610. trialsummary <- subencoding_excl %>%
  611. group_by(TrialNumb) %>%
  612. dplyr::summarize(
  613. MeanBlinkCount = mean(Rem_BlinkCount_Post, na.rm = TRUE),
  614. SEM = sd(Rem_BlinkCount_Post, na.rm = TRUE) / sqrt(28))
  615. ## Identify boundary tone trials to highlight
  616. boundary_highlight <- c(9, 17, 25)
  617. trialsummary$Tone <- ifelse(trialsummary$TrialNumb %in% boundary_highlight, "Boundary", "Same-Context")
  618. ## Create plot
  619. highlight_plot <- ggplot(trialsummary, aes(x = TrialNumb, y = MeanBlinkCount, colour = Tone)) +
  620. scale_color_manual(values=c("#fec01fff", "#674ea7ff"), labels = c("Boundary", "Same-Context")) +
  621. geom_rect(aes(xmin = 1.5, xmax = 8.5, ymin = -Inf, ymax = Inf),
  622. fill = "#ffffffff", color = NA, alpha = 1) +
  623. geom_rect(aes(xmin = 8.5, xmax = 16.5, ymin = -Inf, ymax = Inf),
  624. fill = "#f7f7f7ff", color = NA, alpha = 1) +
  625. geom_rect(aes(xmin = 16.5, xmax = 24.5, ymin = -Inf, ymax = Inf),
  626. fill = "#f3f3f3ff", color = NA, alpha = 1) +
  627. geom_rect(aes(xmin = 24.5, xmax = 32.5, ymin = -Inf, ymax = Inf),
  628. fill = "#efefefff", color = NA, alpha = 1) +
  629. geom_point(aes(colour = Tone), size = 4) +
  630. geom_errorbar(aes(ymin = MeanBlinkCount - SEM, ymax = MeanBlinkCount + SEM), linewidth = 0.5, width = 0) +
  631. geom_vline(aes(xintercept = 8.5), color = "black", linetype = "longdash", linewidth = 0.2) +
  632. geom_vline(aes(xintercept = 16.5), color = "black", linetype = "longdash", linewidth = 0.2) +
  633. geom_vline(aes(xintercept = 24.5), color = "black", linetype = "longdash", linewidth = 0.2) +
  634. geom_hline(aes(yintercept = 1.85), color = "black", linewidth = 0.5) +
  635. annotate("text", x = 5, y = 1.98, label = "Event 1", size = 7, color = "black") +
  636. annotate("text", x = 12.5, y = 1.98, label = "Event 2", size = 7, color = "black") +
  637. annotate("text", x = 20.5, y = 1.98, label = "Event 3", size = 7, color = "black") +
  638. annotate("text", x = 28.5, y = 1.98, label = "Event 4", size = 7, color = "black") +
  639. labs(y = "Post-Tone Blink Count", x = "Item Position", color = "Tone") +
  640. scale_x_continuous(expand = c(0,0), breaks = c(9, 17, 25)) +
  641. scale_y_continuous(limits = c(0,2), breaks = seq(0,1.5, by = 0.5)) +
  642. theme_classic() +
  643. theme(text = element_text(size = 20), legend.position = "none")
  644. highlight_plot
  645. ####### FIGURE 3E: VTA activation vs. local blink count
  646. # Remove outliers
  647. ## Remove blink outliers
  648. subencoding_rem <- subencoding %>%
  649. group_by(Subject) %>%
  650. dplyr::mutate(across(starts_with("Blink"), remove_outliers, .names = "Rem_{.col}"))
  651. ## Remove brain outliers
  652. subencoding_rem2 <- subencoding_rem %>%
  653. group_by(Subject) %>%
  654. dplyr::mutate(across(starts_with("UNWARP"), remove_outliers, .names = "Rem_{.col}"))
  655. ## Check percentage of blink outliers
  656. outliers <- sum(is.na(subencoding_rem2$Rem_BlinkCount_Post)) # sum NAs
  657. total <- nrow(subencoding_rem2) # sum number of rows
  658. percent_outliers <- outliers/total # percentage
  659. ## Check percentage of VTA outliers
  660. outliers <- sum(is.na(subencoding_rem2$Rem_UNWARP_HP_TONE_VTA_thr75)) # sum NAs
  661. total <- nrow(subencoding_rem2) # sum number of rows
  662. percent_outliers <- outliers/total # percentage
  663. # Perform exclusions
  664. subencoding_excl <- subset(subencoding_rem2, RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  665. TrialNumb != "1" & # Removes first trial (boundary-like)
  666. Post_Include_25 == "1" & # Removes 1.5s post-tone intervals with more than 25% invalid samples
  667. ExtremeMotion1mm == "1") # Removes blocks with excessive head motion
  668. ## Check percentage of blink intervals excluded for missing data
  669. missing <- sum(subencoding_rem2$Post_Include_25 == ".") # sum NAs
  670. total <- nrow(subencoding_rem2) # sum number of rows
  671. percent_missing <- missing/total # percentage
  672. # Filter out NAs in blink counts
  673. subencoding_clean <- subencoding_excl %>%
  674. filter(!is.na(Rem_BlinkCount_Post))
  675. # Mean centering
  676. subencoding_clean_cent <- subencoding_clean %>%
  677. group_by(Subject) %>%
  678. dplyr::mutate(across(starts_with("Rem_UNWARP"), cent_function, .names = "Cent_{.col}")) # fMRI data
  679. # Test relationship between VTA activation and post-tone blink count
  680. blinkVTA <- lmer(Rem_BlinkCount_Post ~ Cent_Rem_UNWARP_HP_TONE_VTA_thr75*Condition + (1 | Subject), data = subencoding_clean_cent)
  681. summary(blinkVTA)
  682. report(blinkVTA)
  683. ####### CONTROL ANALYSIS: PRE-tone blink count
  684. # Perform exclusions
  685. subencoding_excl_pre <- subset(subencoding_rem2, RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  686. TrialNumb != "1" & # Removes first trial (boundary-like)
  687. Pre_Include_25 == "1" & # Removes 1.5s pre-tone intervals with more than 25% invalid samples
  688. ExtremeMotion1mm == "1") # Removes blocks with excessive head motion
  689. # Filter out NAs in blink counts
  690. subencoding_clean_pre <- subencoding_excl_pre %>%
  691. filter(!is.na(Rem_BlinkCount_Pre))
  692. # Mean centering
  693. subencoding_clean_cent_pre <- subencoding_clean_pre %>%
  694. group_by(Subject) %>%
  695. dplyr::mutate(across(starts_with("Rem_UNWARP"), cent_function, .names = "Cent_{.col}")) # fMRI data
  696. # Test relationship with pre-tone blink count
  697. blinkVTA_pre <- lmer(Rem_BlinkCount_Pre ~ Cent_Rem_UNWARP_HP_TONE_VTA_thr75*Condition + (1 | Subject), data = subencoding_clean_cent_pre)
  698. summary(blinkVTA_pre)
  699. report(blinkVTA_pre)
  700. # Create plot
  701. blinkvta_plot2 <- ggplot(subencoding_clean_cent) +
  702. aes(x = Cent_Rem_UNWARP_HP_TONE_VTA_thr75, y = Rem_BlinkCount_Post) +
  703. stat_smooth(aes(group=Subject), method = 'lm', formula = y ~ x, se = FALSE, color = "#999999ff", lwd = 0.3, geom = "line", lineend="round") +
  704. stat_smooth(method = 'lm', formula = y ~ x, se = FALSE, color = rgb(0,0,0,1), lwd = 1, geom = "line", lineend="round") +
  705. xlab("VTA Parameter Estimate (mean-centered)") +
  706. ylab("Post-Tone Blink Count") +
  707. theme(rect = element_rect(fill = "transparent", color = NA), # make background transparent
  708. plot.background = element_rect(color=NA), # removes white outline around the plot
  709. panel.background = element_blank(),
  710. panel.grid.major = element_blank(), # Remove gridlines
  711. panel.grid.minor = element_blank(),
  712. panel.spacing = unit(0, "lines"),
  713. axis.line = element_line(color = "black"),
  714. text = element_text(size=20),
  715. legend.position = 'none')
  716. blinkvta_plot2
  717. ####### FIGURE 3F: Local blink count vs. distance memory
  718. # Remove outliers for local blinks
  719. submemory_rem_count <- submemory %>%
  720. group_by(Subject) %>%
  721. dplyr::mutate(across(starts_with("BlinkCount"), remove_outliers, .names = "Rem_{.col}"))
  722. ## Check percentage of blink intervals excluded for being an outlier
  723. outliers <- sum(is.na(submemory_rem_count$Rem_BlinkCount_Post)) # sum NAs
  724. total <- nrow(submemory_rem_count) # sum number of rows
  725. percent_outliers <- outliers/total # percentage
  726. # Perform exclusions
  727. submemory_excl_count <- subset(submemory_rem_count, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  728. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  729. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  730. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  731. Post_Include_25 == "1") # Removes 1.5s post-tone intervals with more than 25% invalid samples
  732. ## Check percentage of blink intervals excluded for missing data
  733. missing <- sum(submemory_rem_count$Post_Include_25 == ".") # sum NAs
  734. total <- nrow(submemory_rem_count) # sum number of rows
  735. percent_missing <- missing/total # percentage
  736. ## Check percentage excluded for being outliers OR missing data
  737. either <- sum(is.na(submemory_rem_count$Rem_BlinkCount_Post) | submemory_rem_count$Post_Include_25 == ".") # sum outlier blink intervals (NA) and those identified as containing more than 25% invalid samples
  738. total <- nrow(submemory_rem_count) # sum number of rows
  739. percent_either <- either/total # percentage
  740. ### Check percentage remaining for each participant after exclusions & calculate average
  741. either_by_participant <- submemory_rem_count %>%
  742. group_by(Subject) %>%
  743. dplyr::summarise(ExclusionCount = sum(is.na(Rem_BlinkCount_Post) | Post_Include_25 == "."), # same conditions as above
  744. TotalCount = n(),
  745. RemainingCount = TotalCount - ExclusionCount,
  746. RemainingPercentage = RemainingCount / TotalCount)
  747. mean(either_by_participant$RemainingPercentage, na.rm = TRUE) # calculate mean across participants
  748. # Mean centering
  749. submemory_all_count <- submemory_excl_count %>%
  750. group_by(Subject) %>%
  751. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  752. # Create separate ordinal variable for distance memory
  753. submemory_all_count$ordinal_response <- factor(submemory_all_count$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE)
  754. # Interaction - cumulative rank model
  755. local_distance_model <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_Post*Condition + (1|Subject), data = submemory_all_count)
  756. summary(local_distance_model)
  757. exp(local_distance_model$beta) # odds ratios
  758. tab <- coef(summary(local_distance_model)) # derive Wald's CI for main effect
  759. beta <- tab["Cent_Rem_BlinkCount_Post", "Estimate"]
  760. se <- tab["Cent_Rem_BlinkCount_Post", "Std. Error"]
  761. z <- qnorm(0.975)
  762. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  763. exp(c(OR = beta, ci_logit))
  764. tab <- coef(summary(local_distance_model)) # derive Wald's CI for interaction effect
  765. beta <- tab["Cent_Rem_BlinkCount_Post:Condition1", "Estimate"]
  766. se <- tab["Cent_Rem_BlinkCount_Post:Condition1", "Std. Error"]
  767. z <- qnorm(0.975)
  768. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  769. exp(c(OR = beta, ci_logit))
  770. # Plot
  771. ## For plotting purposes, represent distance ratings as continuous
  772. submemory_all_count$DistanceRatingDiscrete <- as.numeric(submemory_all_count$DistanceRatingDiscrete)
  773. ## Create plot
  774. blinkcount_distance_plot <- ggplot(submemory_all_count) +
  775. aes(x = Cent_Rem_BlinkCount_Post, y = DistanceRatingDiscrete, fill = Condition, color = Condition) +
  776. stat_smooth(aes(group=Subject), method = 'lm', formula = y ~ x, se = FALSE, lwd = 0.3, geom = "line", lineend="round") +
  777. stat_smooth(method = 'lm', formula = y ~ x, se = FALSE, color = rgb(0,0,0,1), lwd = 1, geom = "line", lineend="round") +
  778. xlab("Post-Tone Blink Count (mean-centered)") +
  779. ylab("Temporal Distance Rating") +
  780. facet_wrap(~Condition, labeller = as_labeller(c("Boundary" = "Boundary", "NB" = "Same-Context"))) +
  781. theme(rect = element_rect(fill = "transparent", color = NA), # make background transparent
  782. plot.background = element_rect(color=NA), # removes white outline around the plot
  783. panel.background = element_blank(),
  784. panel.grid.major = element_blank(), # Remove gridlines
  785. panel.grid.minor = element_blank(),
  786. panel.spacing = unit(0, "lines"),
  787. axis.line = element_line(color = "black"),
  788. strip.text = element_text(size=20, color = rgb(0,0,0,1)),
  789. text = element_text(size=20),
  790. legend.position = 'none') +
  791. scale_fill_manual(values = c("#fec01fff","#674ea7ff")) +
  792. scale_color_manual(values = c("#fec01fff","#674ea7ff")) +
  793. scale_y_continuous(breaks = seq(1,4,1), labels = c("Very\nClose","Close","Far","Very\nFar")) +
  794. coord_cartesian(ylim= c(1,4)) # this sets the axis limits WITHOUT clipping
  795. blinkcount_distance_plot
  796. #### FIGURE 4: Relationships between extended blink count, brain, and behavior ####
  797. ####### FIGURE 4C: Main effect of pair type on extended blink count
  798. # Remove outliers for blink count
  799. submemory_rem <- submemory %>%
  800. group_by(Subject) %>%
  801. dplyr::mutate(across(starts_with("Ringo_BlinksCount"), remove_outliers, .names = "Rem_BlinkCount_Check")) # blink count
  802. # Perform exclusions
  803. submemory_excl <- subset(submemory_rem, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  804. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  805. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  806. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  807. Blink_Exc25 == "1") # Removes blink windows with more than 25% invalid samples
  808. ## Check percentage of blink windows excluded for being an outlier
  809. outliers <- sum(is.na(submemory_rem$Rem_BlinkCount_Check)) # sum NAs
  810. total <- nrow(submemory_rem) # sum number of rows
  811. percent_outliers <- outliers/total # percentage
  812. ## Check percentage of blink windows excluded for missing data
  813. missing <- sum(submemory_rem$Blink_Exc25 == ".") # sum windows marked as containing more than 25% invalid samples
  814. total <- nrow(submemory_rem) # sum number of rows
  815. percent_missing <- missing/total # percentage
  816. ## Check percentage excluded for being outliers OR missing data
  817. either <- sum(is.na(submemory_rem$Rem_BlinkCount_Check) | submemory_rem$Blink_Exc25 == ".") # sum outlier blink windows (NA) and those identified as containing more than 25% invalid samples
  818. total <- nrow(submemory_rem) # sum number of rows
  819. percent_either <- either/total # percentage
  820. ### Check percentage remaining for each participant after exclusions & calculate average
  821. either_by_participant <- submemory_rem %>%
  822. group_by(Subject) %>%
  823. dplyr::summarise(ExclusionCount = sum(is.na(Rem_BlinkCount_Check) | Blink_Exc25 == "."), # same conditions as above
  824. TotalCount = n(),
  825. RemainingCount = TotalCount - ExclusionCount,
  826. RemainingPercentage = RemainingCount / TotalCount)
  827. mean(either_by_participant$RemainingPercentage, na.rm = TRUE) # calculate mean across participants
  828. # Descriptive statistics
  829. mean(submemory_excl$Rem_BlinkCount_Check, na.rm = TRUE)
  830. sd(submemory_excl$Rem_BlinkCount_Check, na.rm = TRUE)
  831. # Main effect of Condition on uncorrected blink count
  832. blinkcount_check_main <- lmer(Rem_BlinkCount_Check~Condition + (1 | Subject), data = submemory_excl)
  833. summary(blinkcount_check_main)
  834. report(blinkcount_check_main)
  835. # Plot
  836. ## For plotting purposes, group extended blink count by Condition to display main effect
  837. grouped_count_main <- submemory_excl %>%
  838. group_by(Subject, Condition) %>%
  839. dplyr::summarize(
  840. MeanBlinkCount = mean(Rem_BlinkCount_Check, na.rm = TRUE))
  841. ## Create plot
  842. maineffect_blinkcount <- ggplot(grouped_count_main, aes(x = Condition, y = MeanBlinkCount, fill = Condition)) +
  843. geom_flat_violin(position = position_nudge(x=.25, y=0), color = NA) +
  844. geom_boxplot(width = .07, outlier.shape = NA, position = position_nudge(x=.25, y=0)) +
  845. geom_jitter(alpha = 0.5, width = .15, size = 4, aes(color = Condition)) +
  846. scale_fill_manual(values = c("Boundary" = "#f3e1a1ff", "NB" = "#c8b7e4ff")) +
  847. scale_color_manual(values = c("Boundary" = "#f3e1a1ff", "NB" = "#c8b7e4ff")) +
  848. scale_x_discrete(labels = c("Boundary" = "Boundary", "NB" = "Same-Context")) +
  849. labs(x = NULL, y = "Blink Count between Image Pair") +
  850. theme_classic() +
  851. theme(text = element_text(size = 20), legend.position = "none")
  852. maineffect_blinkcount
  853. ggplot_build(maineffect_blinkcount)$data # get boxplot stats
  854. ####### FIGURE 4D: Plotting extended blink count by pair position at encoding
  855. # Remove outliers for blink count
  856. submemory_rem <- submemory %>%
  857. group_by(Subject) %>%
  858. dplyr::mutate(across(starts_with("Ringo_BlinksCount"), remove_outliers, .names = "Rem_BlinkCount_Check")) # blink count
  859. # Perform exclusions
  860. submemory_excl <- subset(submemory_rem, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  861. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  862. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  863. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  864. Blink_Exc25 == "1") # Removes windows with more than 25% invalid samples
  865. ## Check percentage of blink windows excluded for being an outlier
  866. outliers <- sum(is.na(submemory_rem$Rem_BlinkCount_Check)) # sum NAs
  867. total <- nrow(submemory_rem) # sum number of rows
  868. percent_outliers <- outliers/total # percentage
  869. ## Check percentage of blink windows excluded for missing data
  870. missing <- sum(submemory_rem$Blink_Exc25 == ".") # sum windows marked as containing more than 25% invalid samples
  871. total <- nrow(submemory_rem) # sum number of rows
  872. percent_missing <- missing/total # percentage
  873. # Plot
  874. ## For plotting purposes, group extended blink count by Tested Pair
  875. testedpair_count <- submemory_excl %>%
  876. group_by(PositionAtEncoding, Condition) %>%
  877. dplyr::summarize(
  878. MeanBlinkCount = mean(Rem_BlinkCount_Check, na.rm = TRUE),
  879. SEM = sd(Rem_BlinkCount_Check, na.rm = TRUE) / sqrt(28))
  880. ## Create plot
  881. window_count_plot <- ggplot(testedpair_count, aes(x = PositionAtEncoding, y = MeanBlinkCount, colour = Condition)) +
  882. scale_color_manual(values=c("#fec01fff", "#674ea7ff"), labels = c("Boundary", "Same-Context")) +
  883. geom_point(aes(colour = Condition), size = 4, shape = 17) +
  884. geom_errorbar(aes(ymin = MeanBlinkCount - SEM, ymax = MeanBlinkCount + SEM), linewidth = 0.5, width = 0) +
  885. labs(y = "Blink Count between Image Pair", x = "Position of Image Pair at Encoding", color = "Pair Type") +
  886. scale_x_continuous(breaks = seq(0, 14, by = 1)) +
  887. scale_y_continuous(limits = c(16,30)) +
  888. theme_classic() +
  889. theme(text = element_text(size = 20), legend.position = "none")
  890. window_count_plot
  891. ####### FIGURE 4E: VTA activation vs. extended blink count
  892. # Remove outliers
  893. submemory_rem <- submemory %>%
  894. group_by(Subject) %>%
  895. dplyr::mutate(across(starts_with("UNWARP_HP_TONE_VTA"), remove_outliers, .names = "Rem_VTA")) %>% # VTA data for single tone
  896. dplyr::mutate(across(starts_with("Tone_VTA_in_Pre_Average"), remove_outliers, .names = "Rem_VTA_Pre_Average")) %>% # VTA data for all tones across pre window
  897. dplyr::mutate(across(starts_with("Tone_VTA_in_Post_Average"), remove_outliers, .names = "Rem_VTA_Post_Average")) %>% # VTA data for all tones across post window
  898. dplyr::mutate(across(starts_with("Tone_VTA_FullWindow_Average"), remove_outliers, .names = "Rem_VTA_Average")) %>% # VTA data for all tones across window
  899. dplyr::mutate(across(starts_with("UNWARP_HP_TONE_LC"), remove_outliers, .names = "Rem_LC")) # LC data
  900. submemory_rem <- submemory_rem %>%
  901. group_by(Subject) %>%
  902. dplyr::mutate(across(starts_with("Ringo_BlinksCount"), remove_outliers, .names = "Rem_BlinkCount_Check")) # blink count
  903. # Perform exclusions
  904. submemory_excl <- subset(submemory_rem, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  905. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  906. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  907. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  908. Blink_Exc25 == "1" & # Removes windows containing more than 25% invalid samples
  909. ExtremeMotion1mm == "1") # Removes blocks with excessive head motion
  910. ## Check percentage of blink windows excluded for being an outlier
  911. outliers <- sum(is.na(submemory_rem$Rem_BlinkCount_Check)) # sum NAs
  912. total <- nrow(submemory_rem) # sum number of rows
  913. percent_outliers <- outliers/total # percentage
  914. ## Check percentage of VTA outliers
  915. outliers <- sum(is.na(submemory_rem$Rem_VTA)) # sum NAs
  916. total <- nrow(submemory_rem) # sum number of rows
  917. percent_outliers <- outliers/total # percentage
  918. ## Check percentage of blink windows excluded for missing data
  919. missing <- sum(submemory_rem$Blink_Exc25 == ".") # sum windows marked as containing more than 25% invalid samples
  920. total <- nrow(submemory_rem) # sum number of rows
  921. percent_missing <- missing/total # percentage
  922. # Mean centering
  923. submemory_all <- submemory_excl %>%
  924. group_by(Subject) %>%
  925. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  926. # Test relationship between VTA activation and extended blink count
  927. blinkcount_check_VTA <- lmer(Rem_BlinkCount_Check ~ Cent_Rem_VTA*Condition + (1 | Subject), data = submemory_all)
  928. summary(blinkcount_check_VTA)
  929. report(blinkcount_check_VTA)
  930. # Plot
  931. blinkvta_count_plot2 <- ggplot(submemory_all) +
  932. aes(x = Cent_Rem_VTA, y = Rem_BlinkCount_Check) +
  933. stat_smooth(aes(group=Subject), method = 'lm', formula = y ~ x, se = FALSE, color = "#999999ff", lwd = 0.3, geom = "line", lineend="round") +
  934. stat_smooth(method = 'lm', formula = y ~ x, se = FALSE, color = rgb(0,0,0,1), lwd = 1, geom = "line", lineend="round") +
  935. xlab("VTA Parameter Estimate (mean-centered)") +
  936. ylab("Blink Count between Image Pair") +
  937. theme(rect = element_rect(fill = "transparent", color = NA), # make background transparent
  938. plot.background = element_rect(color=NA), # removes white outline around the plot
  939. panel.background = element_blank(),
  940. panel.grid.major = element_blank(), # Remove gridlines
  941. panel.grid.minor = element_blank(),
  942. panel.spacing = unit(0, "lines"),
  943. axis.line = element_line(color = "black"),
  944. text = element_text(size=20),
  945. legend.position = 'none')
  946. blinkvta_count_plot2
  947. ####### FIGURE 4F: Extended blink count vs. distance memory
  948. # Remove outliers
  949. submemory_rem <- submemory %>%
  950. group_by(Subject) %>%
  951. dplyr::mutate(across(starts_with("Ringo_BlinksCount"), remove_outliers, .names = "Rem_BlinkCount_Check")) # blink count
  952. # Perform exclusions
  953. submemory_excl <- subset(submemory_rem, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  954. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  955. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  956. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  957. Blink_Exc25 == "1") # Removes windows containing more than 25% invalid samples
  958. ## Check percentage of blink windows excluded for being an outlier
  959. outliers <- sum(is.na(submemory_rem$Rem_BlinkCount_Check)) # sum NAs
  960. total <- nrow(submemory_rem) # sum number of rows
  961. percent_outliers <- outliers/total # percentage
  962. ## Check percentage of blink windows excluded for missing data
  963. missing <- sum(submemory_rem$Blink_Exc25 == ".") # sum windows marked as containing more than 25% invalid samples
  964. total <- nrow(submemory_rem) # sum number of rows
  965. percent_missing <- missing/total # percentage
  966. # Mean centering
  967. ## Overall
  968. submemory_all <- submemory_excl %>%
  969. group_by(Subject) %>%
  970. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  971. ## Boundary
  972. boundarypairs <- subset(submemory_excl, Condition == "Boundary") # subset to boundary only
  973. submemory_boundary <- boundarypairs %>%
  974. group_by(Subject) %>%
  975. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  976. ## Same-context
  977. samepairs <- subset(submemory_excl, Condition == "NB") # subset to same context only
  978. submemory_samecont <- samepairs %>%
  979. group_by(Subject) %>%
  980. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  981. # Create separate ordinal variable for distance memory
  982. submemory_all$ordinal_response <- factor(submemory_all$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # overall data frame
  983. submemory_boundary$ordinal_response <- factor(submemory_boundary$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # boundary data frame
  984. submemory_samecont$ordinal_response <- factor(submemory_samecont$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # same context data frame
  985. # Interaction - cumulative rank model
  986. blinkcount_check_distance_model_all <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_Check*Condition + (1|Subject), data = submemory_all)
  987. summary(blinkcount_check_distance_model_all)
  988. exp(blinkcount_check_distance_model_all$beta) # odds ratio
  989. tab <- coef(summary(blinkcount_check_distance_model_all)) # derive Wald's CI for interaction effect
  990. beta <- tab["Cent_Rem_BlinkCount_Check:Condition1", "Estimate"]
  991. se <- tab["Cent_Rem_BlinkCount_Check:Condition1", "Std. Error"]
  992. z <- qnorm(0.975)
  993. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  994. exp(c(OR = beta, ci_logit))
  995. # Boundary alone - cumulative rank model
  996. blinkcount_check_distance_model_boundary <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_Check + (1|Subject), data = submemory_boundary)
  997. summary(blinkcount_check_distance_model_boundary)
  998. exp(blinkcount_check_distance_model_boundary$beta) # odds ratio
  999. tab <- coef(summary(blinkcount_check_distance_model_boundary)) # derive Wald's CI for interaction effect
  1000. beta <- tab["Cent_Rem_BlinkCount_Check", "Estimate"]
  1001. se <- tab["Cent_Rem_BlinkCount_Check", "Std. Error"]
  1002. z <- qnorm(0.975)
  1003. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  1004. exp(c(OR = beta, ci_logit))
  1005. ## Same context alone - cumulative rank model
  1006. blinkcount_check_distance_model_samecont <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_Check + (1|Subject), data = submemory_samecont)
  1007. summary(blinkcount_check_distance_model_samecont)
  1008. exp(blinkcount_check_distance_model_samecont$beta) # odds ratio
  1009. tab <- coef(summary(blinkcount_check_distance_model_samecont)) # derive Wald's CI for interaction effect
  1010. beta <- tab["Cent_Rem_BlinkCount_Check", "Estimate"]
  1011. se <- tab["Cent_Rem_BlinkCount_Check", "Std. Error"]
  1012. z <- qnorm(0.975)
  1013. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  1014. exp(c(OR = beta, ci_logit))
  1015. # Plot
  1016. ## For plotting purposes, represent distance ratings as continuous
  1017. submemory_all$DistanceRatingDiscrete <- as.numeric(submemory_all$DistanceRatingDiscrete)
  1018. ## Create plot
  1019. blink_count_distance_plot <- ggplot(submemory_all) +
  1020. aes(x = Cent_Rem_BlinkCount_Check, y = DistanceRatingDiscrete, fill = Condition, color = Condition) +
  1021. stat_smooth(aes(group=Subject), method = 'lm', formula = y ~ x, se = FALSE, lwd = 0.3, geom = "line", lineend="round") +
  1022. stat_smooth(method = 'lm', formula = y ~ x, se = FALSE, color = rgb(0,0,0,1), lwd = 1, geom = "line", lineend="round") +
  1023. xlab("Blink Count between Image Pair (mean-centered)") +
  1024. ylab("Temporal Distance Rating") +
  1025. facet_wrap(~Condition, labeller = as_labeller(c("Boundary" = "Boundary", "NB" = "Same-Context"))) +
  1026. theme(rect = element_rect(fill = "transparent", color = NA), # make background transparent
  1027. plot.background = element_rect(color=NA), # removes white outline around the plot
  1028. panel.background = element_blank(),
  1029. panel.grid.major = element_blank(), # Remove gridlines
  1030. panel.grid.minor = element_blank(),
  1031. panel.spacing = unit(0, "lines"),
  1032. axis.line = element_line(color = "black"),
  1033. strip.text = element_text(size=20, color = rgb(0,0,0,1)),
  1034. text = element_text(size=20),
  1035. legend.position = 'none') +
  1036. scale_fill_manual(values = c("#fec01fff","#674ea7ff")) +
  1037. scale_color_manual(values = c("#fec01fff","#674ea7ff")) +
  1038. scale_y_continuous(breaks = seq(1,4,1), labels = c("Very\nClose","Close","Far","Very\nFar")) +
  1039. coord_cartesian(ylim= c(1,4))
  1040. blink_count_distance_plot
  1041. #### Identifying which blink periods and stimuli predicted subsequent temporal distortions in memory ####
  1042. # Load memory sheet
  1043. memory_extra <- read.csv("2026_01_DopaMinute_Main_SourceData_MEMORY.csv")
  1044. # Should point to memory tab in main source data
  1045. # Ensure blink counts are numerical
  1046. memory_extra$BlinkCount_PreRef <- as.numeric(memory_extra$BlinkCount_PreRef)
  1047. memory_extra$BlinkCount_PostRef <- as.numeric(memory_extra$BlinkCount_PostRef)
  1048. # Remove outliers for blink counts
  1049. memory_extra_rem <- memory_extra %>%
  1050. group_by(Subject) %>%
  1051. dplyr::mutate(across(starts_with("BlinkCount_PreRef"), remove_outliers, .names = "Rem_BlinkCount_PreRef")) %>%
  1052. dplyr::mutate(across(starts_with("BlinkCount_PostRef"), remove_outliers, .names = "Rem_BlinkCount_PostRef"))
  1053. # PRE-REFERENCE INTERVAL
  1054. ## Perform exclusions - pre-reference interval
  1055. memory_extra_excl_preref <- subset(memory_extra_rem, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  1056. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  1057. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  1058. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  1059. PreRef_Include_25 == "1") # Removes windows with more than 25% invalid samples
  1060. #### Mean-centering
  1061. #### Overall
  1062. memory_extra_preref_all <- memory_extra_excl_preref %>%
  1063. group_by(Subject) %>%
  1064. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1065. #### Boundary
  1066. boundarypairs_preref <- subset(memory_extra_excl_preref, Condition == "Boundary") # subset to boundary only
  1067. memory_extra_preref_boundary <- boundarypairs_preref %>%
  1068. group_by(Subject) %>%
  1069. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1070. #### Same-context
  1071. samepairs_preref <- subset(memory_extra_excl_preref, Condition == "NB") # subset to same context only
  1072. memory_extra_preref_samecont <- samepairs_preref %>%
  1073. group_by(Subject) %>%
  1074. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1075. ### Create separate ordinal variable for distance memory
  1076. memory_extra_preref_all$ordinal_response <- factor(memory_extra_preref_all$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # overall data frame
  1077. memory_extra_preref_boundary$ordinal_response <- factor(memory_extra_preref_boundary$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # boundary data frame
  1078. memory_extra_preref_samecont$ordinal_response <- factor(memory_extra_preref_samecont$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # same context data frame
  1079. ### Interaction - cumulative rank model
  1080. blink_extra_distance_model_preref <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_PreRef*Condition + (1|Subject), data = memory_extra_preref_all)
  1081. summary(blink_extra_distance_model_preref)
  1082. ### Boundary alone - cumulative rank model
  1083. blink_extra_distance_model_boundary_preref <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_PreRef + (1|Subject), data = memory_extra_preref_boundary)
  1084. summary(blink_extra_distance_model_boundary_preref)
  1085. ### Same context alone - cumulative rank model
  1086. blink_extra_distance_model_samecont_preref <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_PreRef + (1|Subject), data = memory_extra_preref_samecont)
  1087. summary(blink_extra_distance_model_samecont_preref)
  1088. # POST-REFERENCE INTERVAL
  1089. ## Perform exclusions - post-reference interval
  1090. memory_extra_excl_postref <- subset(memory_extra_rem, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  1091. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  1092. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  1093. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  1094. PostRef_Include_25 == "1") #Removes windows with more than 25% invalid samples
  1095. #### Mean-centering
  1096. #### Overall
  1097. memory_extra_postref_all <- memory_extra_excl_postref %>%
  1098. group_by(Subject) %>%
  1099. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1100. #### Boundary
  1101. boundarypairs_postref <- subset(memory_extra_excl_postref, Condition == "Boundary") # subset to boundary only
  1102. memory_extra_postref_boundary <- boundarypairs_postref %>%
  1103. group_by(Subject) %>%
  1104. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1105. #### Same-context
  1106. samepairs_postref <- subset(memory_extra_excl_postref, Condition == "NB") # subset to same context only
  1107. memory_extra_postref_samecont <- samepairs_postref %>%
  1108. group_by(Subject) %>%
  1109. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1110. ### Create separate ordinal variable for distance memory
  1111. memory_extra_postref_all$ordinal_response <- factor(memory_extra_postref_all$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # overall data frame
  1112. memory_extra_postref_boundary$ordinal_response <- factor(memory_extra_postref_boundary$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # boundary data frame
  1113. memory_extra_postref_samecont$ordinal_response <- factor(memory_extra_postref_samecont$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # same context data frame
  1114. ### Interaction - cumulative rank model
  1115. blink_extra_distance_model_postref <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_PostRef*Condition + (1|Subject), data = memory_extra_postref_all)
  1116. summary(blink_extra_distance_model_postref)
  1117. ### Boundary alone - cumulative rank model
  1118. blink_extra_distance_model_boundary_postref <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_PostRef + (1|Subject), data = memory_extra_postref_boundary)
  1119. summary(blink_extra_distance_model_boundary_postref)
  1120. ### Same context alone - cumulative rank model
  1121. blink_extra_distance_model_samecont_postref <- clmm(ordinal_response ~ Cent_Rem_BlinkCount_PostRef + (1|Subject), data = memory_extra_postref_samecont)
  1122. summary(blink_extra_distance_model_samecont_postref)
  1123. # POST-REFERENCE INTERVAL: TONES AND IMAGES
  1124. ## Remove outliers for blink count
  1125. memory_specific_rem <- memory_extra %>%
  1126. group_by(Subject) %>%
  1127. dplyr::mutate(across(starts_with("ToneSum_in_Post"), remove_outliers, .names = "Rem_ToneSum_in_Post")) %>%
  1128. dplyr::mutate(across(starts_with("ImageSum_in_Post"), remove_outliers, .names = "Rem_ImageSum_in_Post"))
  1129. ### IMAGES
  1130. #### Perform exclusions - images in post-reference interval
  1131. memory_extra_images_excl <- subset(memory_specific_rem, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  1132. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  1133. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  1134. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  1135. !grepl("\\.", ImageSum_Post_Include_25)) # Removes windows with more than 25% invalid samples
  1136. #### Mean-centering
  1137. #### Overall
  1138. memory_extra_images_all <- memory_extra_images_excl %>%
  1139. group_by(Subject) %>%
  1140. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1141. ### Create separate ordinal variable for distance memory
  1142. memory_extra_images_all$ordinal_response <- factor(memory_extra_images_all$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # overall data frame
  1143. ### Interaction - cumulative rank model
  1144. blink_extra_distance_model_images <- clmm(ordinal_response ~ Cent_Rem_ImageSum_in_Post*Condition + (1|Subject), data = memory_extra_images_all)
  1145. summary(blink_extra_distance_model_images)
  1146. ### TONES
  1147. #### Perform exclusions - tones in post-reference interval
  1148. memory_extra_tones_excl <- subset(memory_specific_rem, ErrorAcrossTrials == "1" & # Removes trials with incorrect tested item
  1149. FilterBlockIissue == "1" & # Removes blocks with ISI timing error
  1150. RemSqueezeBall == "1" & # Removes block during which participant triggered squeeze ball
  1151. ExcludeFirstPair == "1" & # Removes trials with first item in sequence (boundary-like)
  1152. !grepl("\\.", ToneSum_Post_Include_25)) # Removes windows with more than 25% invalid samples
  1153. #### Mean-centering
  1154. #### Overall
  1155. memory_extra_tones_all <- memory_extra_tones_excl %>%
  1156. group_by(Subject) %>%
  1157. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1158. #### Boundary
  1159. boundarypairs_tones <- subset(memory_extra_tones_excl, Condition == "Boundary") # subset to boundary only
  1160. memory_extra_tones_boundary <- boundarypairs_tones %>%
  1161. group_by(Subject) %>%
  1162. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1163. #### Same-context
  1164. samepairs_tones <- subset(memory_extra_tones_excl, Condition == "NB") # subset to same context only
  1165. memory_extra_tones_samecont <- samepairs_tones %>%
  1166. group_by(Subject) %>%
  1167. dplyr::mutate(across(starts_with("Rem_"), cent_function, .names = "Cent_{.col}"))
  1168. ### Create separate ordinal variable for distance memory
  1169. memory_extra_tones_all$ordinal_response <- factor(memory_extra_tones_all$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # overall data frame
  1170. memory_extra_tones_boundary$ordinal_response <- factor(memory_extra_tones_boundary$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # boundary data frame
  1171. memory_extra_tones_samecont$ordinal_response <- factor(memory_extra_tones_samecont$DistanceRatingConverted, levels = c("VeryClose", "Close", "Far","VeryFar"), ordered = TRUE) # same-context data frame
  1172. ### Interaction - cumulative rank model
  1173. blink_extra_distance_model_tones <- clmm(ordinal_response ~ Cent_Rem_ToneSum_in_Post*Condition + (1|Subject), data = memory_extra_tones_all)
  1174. summary(blink_extra_distance_model_tones)
  1175. exp(blink_extra_distance_model_tones$beta) # odds ratio
  1176. tab <- coef(summary(blink_extra_distance_model_tones)) # derive Wald's CI for interaction effect
  1177. beta <- tab["Cent_Rem_ToneSum_in_Post:Condition1", "Estimate"]
  1178. se <- tab["Cent_Rem_ToneSum_in_Post:Condition1", "Std. Error"]
  1179. z <- qnorm(0.975)
  1180. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  1181. exp(c(OR = beta, ci_logit))
  1182. ### Boundary alone - cumulative rank model
  1183. blink_extra_distance_model_boundary_tones <- clmm(ordinal_response ~ Cent_Rem_ToneSum_in_Post + (1|Subject), data = memory_extra_tones_boundary)
  1184. summary(blink_extra_distance_model_boundary_tones)
  1185. exp(blink_extra_distance_model_boundary_tones$beta) # odds ratios
  1186. tab <- coef(summary(blink_extra_distance_model_boundary_tones)) # derive Wald's CI for interaction effect
  1187. beta <- tab["Cent_Rem_ToneSum_in_Post", "Estimate"]
  1188. se <- tab["Cent_Rem_ToneSum_in_Post", "Std. Error"]
  1189. z <- qnorm(0.975)
  1190. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  1191. exp(c(OR = beta, ci_logit))
  1192. ### Same context alone - cumulative rank model
  1193. blink_extra_distance_model_samecont_tones <- clmm(ordinal_response ~ Cent_Rem_ToneSum_in_Post + (1|Subject), data = memory_extra_tones_samecont)
  1194. summary(blink_extra_distance_model_samecont_tones)
  1195. exp(blink_extra_distance_model_samecont_tones$beta) # odds ratios
  1196. tab <- coef(summary(blink_extra_distance_model_samecont_tones)) # derive Wald's CI for interaction effect
  1197. beta <- tab["Cent_Rem_ToneSum_in_Post", "Estimate"]
  1198. se <- tab["Cent_Rem_ToneSum_in_Post", "Std. Error"]
  1199. z <- qnorm(0.975)
  1200. ci_logit <- c(lower = beta - z *se, upper = beta + z * se)
  1201. exp(c(OR = beta, ci_logit))

2026_01_DopaMinute_AnalysisCode.R, no license · at the source

Overview

Authors: Erin Morrow1, Ringo Huang1, David Clewett1
  1. Department of Psychology, University of California, Los Angeles, CA USA
Institutions: University of California, Los Angeles (United States)
Journal: Nature communications, volume 17, issue 1, article 3971
Dates: received 22 May 2025; accepted 12 February 2026; published online 14 March 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41467-026-69950-8 · PMID 41832137 · PMCID PMC13133266 · OpenAlex W7135407626
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: human (organism), cognitive (subfield)
Methods: Smoothing, state filtering, decompositions, Preprocessing, Statistics, fMRI & imaging, Single-unit activity, calcium imaging, Physiology & signal measures
Keywords: Cognitive neuroscience, Long-term memory
MeSH: Dopamine*, Memory*, Memory, Episodic*, Time Perception*, Ventral Tegmental Area*, Blinking, Brain Mapping, Eye-Tracking Technology, Female, Humans, Magnetic Resonance Imaging, Male, Young Adult (* major topic)
Topic: Memory Processes and Influences (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: NIMH NIH HHS (F32 MH114536, R01 MH074692)
Citations: cited by 1 paper (Europe PMC); 76 references in the paper

Abstract

Our memories do not simply keep time — they distort it, stretching and compressing the past to reflect the structure of experience. Here, we combined functional magnetic resonance imaging (fMRI; n = 32) with eye-tracking (n = 28) to test whether activation of the dopaminergic system, known to influence encoding and time perception, expands mnemonic representations of time between contextually distinct events. Participants encoded item sequences while listening to tones that typically repeated over time, but occasionally changed, creating salient event boundaries. We found that tone switches significantly activated the ventral tegmental area (VTA), and the magnitude of these responses predicted greater time dilation between item pairs spanning those switches. At a longer timescale, increased blinking also predicted greater time dilation in memory, but only for boundary-spanning item pairs. Together, these findings suggest that dopaminergic processes are sensitive to event structure and contribute to distortions of remembered time that may help segment continuous experience into distinct episodic memories.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

Its files are read in the Code ↔ Paper reader above, with 9 matches between paragraphs and lines of code.

OSF yt6hm

License: none: the authors keep all their rights
State: the link answers, verified on 30 September 2026
Evidence: the link answers
Software Heritage: not checked
Found in: “Code and data accessibility”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
  • 30 September 2026: the link answers (HTTP 200)
At the source: osf.io/yt6hm/

d.docs.live.net/69e036cd301315ff/documents

License: none: the authors keep all their rights
State: the link is dead, verified on 30 September 2026
Evidence: found in the paper
Software Heritage: not checked
Found in: “Code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 30 September 2026: the link is dead (HTTP 404)
  • 30 September 2026: the link is dead (HTTP 404)

OSF 8y7hr

License: none: the authors keep all their rights
State: the link answers, verified on 30 September 2026
Evidence: files inventoried
Languages: MATLAB (5), R (1)
Size: 257 files, 6 scripts
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: car (1 file), cowplot (1 file), data.table (1 file), easystats (1 file), emmeans (1 file), ggplot2 (1 file), lavaan (1 file), lme4 (1 file), lmerTest (1 file), Signal Processing Toolbox (1 file), rstatix (1 file), tidyverse (1 file)
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
  • 30 September 2026: the link answers (HTTP 200)
6 files
At the source:

Code availability

The code for this experiment is publicly available on the OSF account of Erin Morrow at the following link: osf.io/yt6hm (https://d.docs.live.net/69e036cd301315ff/Documents/ACME LAB/DopaMinute/osf.io/yt6hm)76.

Reproduced under the paper's license (CC BY), from the paper cited above.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 6 scripts, each with its path and the digest of its content;
  • 9 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability

Source data are provided with this paper. The processed data are also publicly available on the OSF account of Erin Morrow at the following link: osf.io/yt6hm (https://d.docs.live.net/69e036cd301315ff/Documents/ACME LAB/DopaMinute/osf.io/yt6hm). Source data are provided with this paper.

Reproduced under the paper's license (CC BY), from the paper cited above.

Data Availability Statement

The code, experiment materials, and data for this study are publicly available on the OSF account of E.M. (osf.io/yt6hm).

Source data are provided with this paper. The processed data are also publicly available on the OSF account of Erin Morrow at the following link: osf.io/yt6hm (https://d.docs.live.net/69e036cd301315ff/Documents/ACME LAB/DopaMinute/osf.io/yt6hm). Source data are provided with this paper.

The code for this experiment is publicly available on the OSF account of Erin Morrow at the following link: osf.io/yt6hm (https://d.docs.live.net/69e036cd301315ff/Documents/ACME LAB/DopaMinute/osf.io/yt6hm)76.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 30 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 3 authors, 2 keywords, 13 MeSH terms, 1 funder, 64 references.

Cite

This paper

Morrow, E., Huang, R., & Clewett, D. (2026). Dopaminergic processes predict temporal distortions in event memory. Nature communications, 17(1), 3971. https://doi.org/10.1038/s41467-026-69950-8

BibTeX

@article{morrow2026dopaminergic,
author = {Morrow, Erin and Huang, Ringo and Clewett, David},
title = {{Dopaminergic processes predict temporal distortions in event memory}},
journal = {Nature communications},
year = {2026},
month = mar,
volume = {17},
number = {1},
pages = {3971},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-69950-8},
url = {https://doi.org/10.1038/s41467-026-69950-8},
pmid = {41832137},
pmcid = {PMC13133266}
}

RIS

TY - JOUR
AU - Morrow, Erin
AU - Huang, Ringo
AU - Clewett, David
TI - Dopaminergic processes predict temporal distortions in event memory
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/03/14
VL - 17
IS - 1
SP - 3971
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-69950-8
UR - https://doi.org/10.1038/s41467-026-69950-8
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-69950-8",
"type": "article-journal",
"title": "Dopaminergic processes predict temporal distortions in event memory",
"container-title": "Nature communications",
"author": [
{
"family": "Morrow",
"given": "Erin"
},
{
"family": "Huang",
"given": "Ringo"
},
{
"family": "Clewett",
"given": "David"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "3971",
"DOI": "10.1038/s41467-026-69950-8",
"PMID": "41832137",
"PMCID": "PMC13133266",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-69950-8",
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
14
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1038/s44271-026-00524-6 [code]
Emergent blink rate in early childhood is associated with neural origins of executive function.
Journal: Communications psychology
In common: rstatix, easystats, emmeans, 4 other tools, cognitive, 8 references
[2] doi:10.1038/s41467-026-73865-9 [code]
Histamine shapes the neurocomputational dynamics of human learning.
Journal: Nature communications
In common: rstatix, easystats, car, 7 other tools, cognitive
[3] doi:10.1038/s41398-026-04010-9 [code]
Bullying victimization and brain development: a longitudinal structural magnetic resonance imaging study from adolescence to early adulthood.
Journal: Translational psychiatry
In common: lavaan, rstatix, easystats, 6 other tools
[4] doi:10.1016/j.neuroimage.2026.122115 [code]
Midfrontal theta power relates to response speeding following frustrative nonreward.
Journal: NeuroImage
In common: rstatix, easystats, car, 6 other tools, cognitive
[5] doi:10.1111/psyp.70265 [code]
Neurocognitive Dynamics of Translating Information From a Spatial Map Into Action.
Journal: Psychophysiology
In common: easystats, car, emmeans, 6 other tools, cognitive
[6] doi:10.1126/sciadv.aeb8106 [code]
A thyroid hormone-mediated opsin switch initiates metamorphosis in a proto-vertebrate.
Journal: Science advances
In common: rstatix, easystats, car, 6 other tools
[7] doi:10.1038/s41467-026-74753-y [code]
A human-specific microRNA controls the timing of excitatory synaptogenesis.
Journal: Nature communications
In common: rstatix, easystats, emmeans, 6 other tools
[8] doi:10.1073/pnas.2606871123 [code]
Oxytocin modulates the neurocomputational mechanisms engaged in learning rank relationships in social networks.
Journal: Proceedings of the National Academy of Sciences of the United States of America
In common: easystats, car, emmeans, 6 other tools
[9] doi:10.1016/j.isci.2026.116601 [code]
Random auditory stimulation during sleep disturbs traveling slow waves and declarative memory.
Journal: iScience
In common: lavaan, rstatix, car, 5 other tools, cognitive
[10] doi:10.1126/sciadv.aec9291 [code]
Computational mechanisms of perception in autism revealed using games inspired by rodent operant tasks.
Journal: Science advances
In common: rstatix, easystats, car, 5 other tools, cognitive

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.