OSCR

Histamine shapes the neurocomputational dynamics of human learning.

Code ↔ Paper

12 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 12 matches
  1. [1] § Methods › Behavioural and demographic data analysis ↔ Behavioural_Data/N_Back_fMRI/fMRI_nback_PreProcessing_and_Analysis.Rmd, lines 419–566 · score 0.79 · eta squared, log transformed, pre processing, bootstrapping, marginal, Holm
  2. [2] § Methods › MRI data acquisition, preprocessing, and analysis ↔ Behavioural_Data/Memory_Encoding_Task/Memory_Encoding_Behavioural_Prep_and_Analysis.Rmd, lines 469–586 · score 0.77 · basal forebrain, bilateral hippocampus, memory encoding task, mask, perirhinal, ROI
  3. [3] § Results › Histamine stabilises new learning signal persistence and leads to asymmetrical retrieval computations ↔ Behavioural_Data/Memory_Encoding_Task/Memory_Encoding_Behavioural_Prep_and_Analysis.Rmd, lines 1497–1536 · score 0.77 · encoding related activity, right hemisphere, entorhinal cortex, signal persistence, lateralised, decay
  4. [4] § Methods › MRI data acquisition, preprocessing, and analysis ↔ Behavioural_Data/Memory_Encoding_Task/Memory_Encoding_Behavioural_Prep_and_Analysis.Rmd, lines 469–586 · score 0.73 · basal forebrain, bilateral hippocampus, memory encoding task, mask, perirhinal, ROI
  5. [5] § Results › H3R blockade influences aversive computations during reinforcement learning ↔ Behavioural_Data/PILT_Reinforcement_Learning_Mod/PILT_comp_analysis.Rmd, lines 165–259 · score 0.72 · inverse decision temperature, reciprocal parameter, reinforcement learning, covary, inferential, Optimal
  6. [6] § Methods › Behavioural and demographic data analysis ↔ Behavioural_Data/Memory_Encoding_Task/Memory_Encoding_Behavioural_Prep_and_Analysis.Rmd, lines 866–951 · score 0.65 · eta squared, kurtosis, skewness, Variables, marginal, Holm
  7. [7] § Results › H3R blockade influences aversive computations during reinforcement learning ↔ Behavioural_Data/PILT_Reinforcement_Learning_Mod/PILT_comp_analysis.Rmd, lines 362–445 · score 0.62 · high probability stimulus, loss trials, win trials, Optimal, reinforcement, log
  8. [8] § Methods › MRI data acquisition, preprocessing, and analysis ↔ Behavioural_Data/Memory_Encoding_Task/Memory_Encoding_Behavioural_Prep_and_Analysis.Rmd, lines 590–697 · score 0.60 · memory encoding task, H3R weighting, unweighted, smoothing, squares, map
  9. [9] § Methods › fMRI memory and learning task paradigms ↔ Behavioural_Data/PILT_nonmodel/PILT_data preprocessing_and_analysis.Rmd, lines 501–602 · score 0.60 · optimal choices, loss trials, high probability, paradigms, behavioural
  10. [10] § Results › Histamine influences the neurocomputational signatures of working memory ↔ Behavioural_Data/Memory_Encoding_Task/Memory_Encoding_Behavioural_Prep_and_Analysis.Rmd, lines 2286–2383 · score 0.54 · memory recognition, working memory, drift rate, DDM, fit, behaviour
  11. [11] § Methods › fMRI memory and learning task paradigms ↔ Behavioural_Data/Memory_Encoding_Task/Memory_Encoding_Behavioural_Prep_and_Analysis.Rmd, lines 1111–1232 · score 0.54 · button press, encoding task, scanning, behavioural, memory, hippocampal
  12. [12] § Results › Histamine shapes offline temporal–hippocampal network dynamics ↔ Behavioural_Data/Memory_Encoding_Task/Memory_Encoding_Behavioural_Prep_and_Analysis.Rmd, lines 590–697 · score 0.52 · hippocampal encoding activity, bilateral hippocampal, mammillary zone, ROI, cluster, Scatterplot

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 Markdown · 2,383 lines · 82 KB · MPL-2.0 · 8 matches

  1. ---
  2. title: "Memory_Encoding_Analysis"
  3. author: "Michael Colwell"
  4. date: "2024-04-05"
  5. output: html_document
  6. ---
  7. #Memory encoding task (or 'Hippocampal task') behavioural and neuroimaging data preprocessing analysis scripts for the PEACE Study ('Pitolisant Effects on Affect and Cognition Exploratory Study') (NCT05849675).
  8. This script includes:
  9. - Preprocessing of raw behavioural files from the pre-scanner, in-scanner and post-scanner (recognition) tasks
  10. - Main behavioural analysis
  11. - DDM analysis
  12. - DDM parameter recovery
  13. - DDM posterior predictive checks
  14. - Signal persistence/encoding activity ~ connectivity analysis
  15. - Signal persistence ~ DDM parameters analysis
  16. - Signal persistence ~ encoding activity lateralisation analysis
  17. - RL parameters ~ DDM parameters analysis
  18. #Rmarkdown script by Michael Colwell ([email hidden]).
  19. ```{r setup, include=FALSE}
  20. knitr::opts_chunk$set(echo = TRUE)
  21. ```
  22. ## Library chunk
  23. ```{r cars}
  24. library(dplyr)
  25. library(tidyverse)
  26. library(gtools)
  27. library(knitr)
  28. library(data.table)
  29. library(ggplot2)
  30. library(car)
  31. library(ggbeeswarm)
  32. library(ggrepel)
  33. library(readxl)
  34. library(data.table)
  35. library(openxlsx)
  36. library(ggpubr)
  37. library(sdamr)
  38. library(rstatix)
  39. library("ez")
  40. library(ggsignif)
  41. library(RColorBrewer)
  42. library(emmeans)
  43. library(plotrix)
  44. library(sdamr)
  45. library(cowplot)
  46. library(psycho)
  47. library(ggridges)
  48. library(viridis)
  49. library(ggstance)
  50. library(ggdist)
  51. library(gghalves)
  52. library(ggpp)
  53. library(effectsize)
  54. library(lme4)
  55. library(lmerTest)
  56. library(brms)
  57. library(BayesFactor)
  58. library("ggExtra")
  59. library(purrr)
  60. library(broom)
  61. library(moments)
  62. library(gtools)
  63. library(stringr)
  64. library(ggExtra)
  65. ```
  66. ## Initial Preprocessing (Initial test & Final Test)
  67. ```{r pressure, echo=FALSE}
  68. ## Set directory; Create list of relevant files; Merge files
  69. # Set working directory
  70. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Memory_Encoding_Task/Results_Final")
  71. # Create an empty data frame to store the combined data
  72. combined_df <- data.frame()
  73. # Get a list of all .dat files in the directory
  74. dat_files <- list.files(pattern = glob2rx("*com*.log"))
  75. # Loop through each .dat file
  76. for (file in dat_files) {
  77. # Read the file using readLines()
  78. lines <- readLines(file)
  79. # Remove the first three lines
  80. lines <- lines[-(1:5)]
  81. # Extract the file name
  82. file_name <- sub("\\.log$", "", file)
  83. # Check if the file name contains P001, P002, etc.
  84. if (grepl("[Pp]\\d{3}", file_name)) {
  85. # Check if there are lines remaining
  86. if (length(lines) > 0) {
  87. # Replace blank spaces with NA in each line
  88. lines <- lapply(lines, function(line) {
  89. words <- strsplit(line, "\\s+")[[1]]
  90. words[words == ""] <- NA
  91. return(words)
  92. })
  93. # Find the maximum number of elements in a line
  94. max_elements <- max(sapply(lines, length))
  95. # Create a matrix to store the data
  96. data_matrix <- matrix(nrow = length(lines), ncol = max_elements)
  97. # Fill the matrix with the data from the lines
  98. for (i in seq_along(lines)) {
  99. row <- lines[[i]]
  100. data_matrix[i, 1:length(row)] <- row
  101. }
  102. # Convert the matrix to a data frame
  103. df <- as.data.frame(data_matrix, stringsAsFactors = FALSE) # Ensure strings are treated as characters
  104. # Add a column with the file name to the data frame
  105. df <- cbind(FileName = file_name, df)
  106. # Bind the data to the combined data frame
  107. combined_df <- bind_rows(combined_df, df)
  108. }
  109. }
  110. }
  111. # Assign column names
  112. col_names <- c("FileName", "Participant.ID", "Trial", "Event_Type", "Code_Raw", "Time", "TTime", "Uncertainty", "ResponseT", "Uncertainty_2", "ReqTime", "ReqDur", "Stim_Type", "Pair_Index") # Add your column names here
  113. colnames(combined_df) <- col_names
  114. # Prune 'Participant.ID' column to first few letters
  115. combined_df$Participant.ID <- str_sub(combined_df$Participant.ID, 1, 4)
  116. # Convert 'Participant.ID' column to uppercase
  117. combined_df$Participant.ID <- toupper(combined_df$Participant.ID)
  118. # Remove the "FileName" column
  119. combined_df <- combined_df[, !names(combined_df) %in% "FileName"]
  120. combined_df <- combined_df %>%
  121. filter(Event_Type == "Response")
  122. combined_df$Code <- ifelse(grepl("A", combined_df$Code_Raw), 1,
  123. ifelse(grepl("L", combined_df$Code_Raw), 2, NA)
  124. )
  125. # Remove the "Code_Raw" column
  126. combined_df <- combined_df[, !names(combined_df) %in% "Code_Raw"]
  127. # Only take the first instance of a button press (Presentation records all inputs) - you may want to change this
  128. combined_df <- combined_df %>%
  129. distinct(Participant.ID, Trial, .keep_all = TRUE)
  130. # score each trial
  131. combined_df <- combined_df %>%
  132. mutate(Correct = case_when(
  133. Trial == "1" & Code == "1" ~ "1",
  134. Trial == "2" & Code == "1" ~ "1",
  135. Trial == "3" & Code == "2" ~ "1",
  136. Trial == "4" & Code == "1" ~ "1",
  137. Trial == "5" & Code == "1" ~ "1",
  138. Trial == "6" & Code == "1" ~ "1",
  139. Trial == "7" & Code == "1" ~ "1",
  140. Trial == "8" & Code == "1" ~ "1",
  141. Trial == "9" & Code == "2" ~ "1",
  142. Trial == "10" & Code == "1" ~ "1",
  143. Trial == "11" & Code == "2" ~ "1",
  144. Trial == "12" & Code == "2" ~ "1",
  145. Trial == "13" & Code == "1" ~ "1",
  146. Trial == "14" & Code == "1" ~ "1",
  147. Trial == "15" & Code == "2" ~ "1",
  148. Trial == "16" & Code == "1" ~ "1",
  149. Trial == "17" & Code == "1" ~ "1",
  150. Trial == "18" & Code == "1" ~ "1",
  151. Trial == "19" & Code == "1" ~ "1",
  152. Trial == "20" & Code == "1" ~ "1",
  153. Trial == "21" & Code == "1" ~ "1",
  154. Trial == "22" & Code == "1" ~ "1",
  155. Trial == "23" & Code == "2" ~ "1",
  156. Trial == "24" & Code == "1" ~ "1",
  157. Trial == "25" & Code == "2" ~ "1",
  158. Trial == "26" & Code == "1" ~ "1",
  159. Trial == "27" & Code == "2" ~ "1",
  160. Trial == "28" & Code == "2" ~ "1",
  161. Trial == "29" & Code == "1" ~ "1",
  162. Trial == "30" & Code == "2" ~ "1",
  163. Trial == "31" & Code == "1" ~ "1",
  164. Trial == "32" & Code == "1" ~ "1",
  165. Trial == "33" & Code == "1" ~ "1",
  166. Trial == "34" & Code == "1" ~ "1",
  167. Trial == "35" & Code == "1" ~ "1",
  168. Trial == "36" & Code == "1" ~ "1",
  169. Trial == "37" & Code == "2" ~ "1",
  170. Trial == "38" & Code == "1" ~ "1",
  171. Trial == "39" & Code == "2" ~ "1",
  172. Trial == "40" & Code == "2" ~ "1",
  173. Trial == "41" & Code == "2" ~ "1",
  174. Trial == "42" & Code == "1" ~ "1",
  175. Trial == "43" & Code == "1" ~ "1",
  176. Trial == "44" & Code == "1" ~ "1",
  177. Trial == "45" & Code == "2" ~ "1",
  178. Trial == "46" & Code == "1" ~ "1",
  179. Trial == "47" & Code == "1" ~ "1",
  180. Trial == "48" & Code == "1" ~ "1",
  181. Trial == "49" & Code == "1" ~ "1",
  182. Trial == "50" & Code == "1" ~ "1",
  183. Trial == "51" & Code == "2" ~ "1",
  184. Trial == "52" & Code == "1" ~ "1",
  185. Trial == "53" & Code == "1" ~ "1",
  186. Trial == "54" & Code == "1" ~ "1",
  187. Trial == "55" & Code == "1" ~ "1",
  188. Trial == "56" & Code == "1" ~ "1",
  189. Trial == "57" & Code == "1" ~ "1",
  190. Trial == "58" & Code == "2" ~ "1",
  191. Trial == "59" & Code == "1" ~ "1",
  192. Trial == "60" & Code == "1" ~ "1",
  193. Trial == "61" & Code == "2" ~ "1",
  194. Trial == "62" & Code == "1" ~ "1",
  195. Trial == "63" & Code == "2" ~ "1",
  196. Trial == "64" & Code == "1" ~ "1",
  197. Trial == "65" & Code == "1" ~ "1",
  198. Trial == "66" & Code == "2" ~ "1",
  199. Trial == "67" & Code == "1" ~ "1",
  200. Trial == "68" & Code == "1" ~ "1",
  201. Trial == "69" & Code == "2" ~ "1",
  202. Trial == "70" & Code == "1" ~ "1",
  203. Trial == "71" & Code == "1" ~ "1",
  204. Trial == "72" & Code == "1" ~ "1",
  205. Trial == "73" & Code == "1" ~ "1",
  206. Trial == "74" & Code == "2" ~ "1",
  207. Trial == "75" & Code == "2" ~ "1",
  208. Trial == "76" & Code == "1" ~ "1",
  209. Trial == "77" & Code == "1" ~ "1",
  210. Trial == "78" & Code == "1" ~ "1",
  211. Trial == "79" & Code == "1" ~ "1",
  212. Trial == "80" & Code == "2" ~ "1",
  213. Trial == "81" & Code == "2" ~ "1",
  214. Trial == "82" & Code == "1" ~ "1",
  215. Trial == "83" & Code == "1" ~ "1",
  216. TRUE ~ "0"
  217. ))
  218. # Images #68 and #48 were corrected in this version of the script, which were previously labelled as distraction stimuli in error.
  219. # Creating a column to sort images into novel (seen in scanner), familiar (seen earlier in day and during scan), and distractors (seen only during final test [not encoded])
  220. combined_df <- combined_df %>%
  221. mutate(Trial_Type = case_when(
  222. Code == "2" ~ "Distractor",
  223. Trial == "10" & Code == "1" ~ "Familiar",
  224. Trial == "29" & Code == "1" ~ "Familiar",
  225. Trial == "36" & Code == "1" ~ "Familiar",
  226. Trial == "48" & Code == "1" ~ "Familiar",
  227. Trial == "50" & Code == "1" ~ "Familiar",
  228. Trial == "68" & Code == "1" ~ "Familiar",
  229. Trial == "78" & Code == "1" ~ "Familiar",
  230. Trial == "82" & Code == "1" ~ "Familiar",
  231. TRUE ~ "Novel"
  232. ))
  233. # Presentation records in tenths of milliseconds -- divide this value by 10 to get standard milliseconds
  234. combined_df$TTime <- as.numeric(combined_df$TTime)
  235. combined_df$Response.time <- combined_df$TTime / 10
  236. # Convert Correctness to numeric
  237. combined_df$Correct <- as.numeric(combined_df$Correct)
  238. # Remove extraneous columns
  239. Cleaned_Memory_Task <- subset(combined_df, select = -c(TTime, Event_Type, Uncertainty, ResponseT, ReqTime, ReqDur, Stim_Type, Pair_Index, Uncertainty_2))
  240. Cleaned_Memory_Task$Code <- recode_factor(Cleaned_Memory_Task$Code, "2" = "Unseen", "1" = "Seen")
  241. # Convert RT for correct responses only
  242. Cleaned_Memory_Task <- Cleaned_Memory_Task %>%
  243. transform(RT_Corr = ifelse(Correct == 1, Response.time, NA))
  244. Cleaned_Memory_Task <- Cleaned_Memory_Task %>%
  245. mutate(Hits = case_when(
  246. Correct == "1" & Trial_Type == "Novel" ~ "1",
  247. Correct == "1" & Trial_Type == "Familiar" ~ "1",
  248. Correct == "0" & Trial_Type == "Novel" ~ "0",
  249. Correct == "0" & Trial_Type == "Familiar" ~ "0",
  250. TRUE ~ NA
  251. ))
  252. Cleaned_Memory_Task <- Cleaned_Memory_Task %>%
  253. mutate(Misses = case_when(
  254. Correct == "0" & Trial_Type == "Novel" ~ "1",
  255. Correct == "0" & Trial_Type == "Familiar" ~ "1",
  256. Correct == "1" & Trial_Type == "Novel" ~ "0",
  257. Correct == "1" & Trial_Type == "Familiar" ~ "0",
  258. TRUE ~ NA
  259. ))
  260. Cleaned_Memory_Task <- Cleaned_Memory_Task %>%
  261. mutate(FAs = case_when(
  262. Correct == "1" & Trial_Type == "Distractor" ~ "0",
  263. Correct == "0" & Trial_Type == "Distractor" ~ "1",
  264. TRUE ~ NA
  265. ))
  266. Cleaned_Memory_Task <- Cleaned_Memory_Task %>%
  267. mutate(CRs = case_when(
  268. Correct == "0" & Trial_Type == "Distractor" ~ "0",
  269. Correct == "1" & Trial_Type == "Distractor" ~ "1",
  270. TRUE ~ NA
  271. ))
  272. ```
  273. ```{r pressure, echo=FALSE}
  274. # DDM Preprocessing Block (Optional)
  275. Cleaned_Memory_Task$rt <- Cleaned_Memory_Task$Response.time * 0.001
  276. DDM <- Cleaned_Memory_Task
  277. DDM <- Cleaned_Memory_Task
  278. DDM <- DDM %>%
  279. mutate(stim = case_when(
  280. Code == "Seen" ~ "1",
  281. Code == "Unseen" ~ "0",
  282. TRUE ~ NA
  283. ))
  284. DDM$correct <- DDM$Correct
  285. DDM$subj_idx <- DDM$Participant.ID
  286. DDM <- DDM %>%
  287. mutate(response = case_when(
  288. Correct == "1" & stim == "1" ~ "1",
  289. Correct == "0" & stim == "1" ~ "0",
  290. Correct == "1" & stim == "0" ~ "0",
  291. Correct == "0" & stim == "0" ~ "1",
  292. TRUE ~ NA
  293. ))
  294. DDM <- DDM %>% select(rt, response, subj_idx, correct, stim)
  295. write.csv(DDM, "C:/Users/micha/Desktop/Memory_Task_DDM.csv", row.names = TRUE)
  296. ```
  297. ```{r pressure, echo=FALSE}
  298. # Create summary file
  299. Cleaned_Memory_Task <- Cleaned_Memory_Task %>%
  300. mutate(
  301. Hits = as.numeric(Hits),
  302. FAs = as.numeric(FAs),
  303. Misses = as.numeric(Misses),
  304. CRs = as.numeric(CRs),
  305. Correct = as.numeric(Correct),
  306. RT_Corr = as.numeric(RT_Corr),
  307. Response.time = as.numeric(Response.time)
  308. )
  309. M_Encoding_Summary <- Cleaned_Memory_Task %>%
  310. group_by(Participant.ID, Trial_Type, Code) %>%
  311. summarize(
  312. Accuracy = sum(Correct, na.rm = TRUE),
  313. mean_RT_all = mean(Response.time, na.rm = TRUE),
  314. mean_RT_corr = mean(RT_Corr, na.rm = TRUE),
  315. Hits = sum(Hits, na.rm = TRUE),
  316. FAs = sum(FAs, na.rm = TRUE),
  317. Misses = sum(Misses, na.rm = TRUE),
  318. CRs = sum(CRs, na.rm = TRUE)
  319. )
  320. M_Encoding_Not <- Cleaned_Memory_Task %>%
  321. group_by(Participant.ID, ) %>%
  322. summarize(
  323. Accuracy = sum(Correct, na.rm = TRUE),
  324. mean_RT_all = mean(Response.time, na.rm = TRUE),
  325. mean_RT_corr = mean(RT_Corr, na.rm = TRUE),
  326. Hits = sum(Hits, na.rm = TRUE),
  327. FAs = sum(FAs, na.rm = TRUE),
  328. Misses = sum(Misses, na.rm = TRUE),
  329. CRs = sum(CRs, na.rm = TRUE)
  330. )
  331. # Convert Accuracy to Accuracy %
  332. # 25 Distractors, #58 Previously Encoded, 8 of which before the scanner.
  333. M_Encoding_Summary$Accuracy_Perc <- ifelse(M_Encoding_Summary$Trial_Type == "Novel",
  334. M_Encoding_Summary$Accuracy / 50 * 100,
  335. ifelse(M_Encoding_Summary$Trial_Type == "Familiar",
  336. M_Encoding_Summary$Accuracy / 8 * 100,
  337. ifelse(M_Encoding_Summary$Trial_Type == "Distractor",
  338. M_Encoding_Summary$Accuracy / 25 * 100,
  339. NA
  340. )
  341. )
  342. )
  343. ```
  344. ```{r pressure, echo=FALSE}
  345. # Quality checks
  346. # Function to detect outliers
  347. is_outlier <- function(x) {
  348. return(x < quantile(x, 0.25) - 3.0 * IQR(x) | x > quantile(x, 0.75) + 3.0 * IQR(x))
  349. }
  350. Accuracy_Plot <- ggplot(M_Encoding_Summary, aes(x = as.factor(Trial_Type), y = Accuracy_Perc)) +
  351. geom_boxplot(outlier.shape = NA) + # Hide outlier points in boxplot
  352. geom_point(data = M_Encoding_Summary[is_outlier(M_Encoding_Summary$Accuracy_Perc), ], aes(color = Participant.ID)) +
  353. geom_text_repel(data = M_Encoding_Summary[is_outlier(M_Encoding_Summary$Accuracy_Perc), ], aes(label = Participant.ID), color = "black", size = 3) + # Label outliers
  354. labs(
  355. title = "",
  356. y = "\nRecall Accuracy (%)\n",
  357. x = "\nTrial Type\n"
  358. ) +
  359. theme_minimal() +
  360. theme(text = element_text(size = 16))
  361. RT_Plot <- ggplot(M_Encoding_Summary, aes(x = as.factor(Trial_Type), y = mean_RT_corr)) +
  362. geom_boxplot(outlier.shape = NA) + # Hide outlier points in boxplot
  363. geom_point(data = M_Encoding_Summary[is_outlier(M_Encoding_Summary$mean_RT), ], aes(color = Participant.ID)) +
  364. geom_text_repel(data = M_Encoding_Summary[is_outlier(M_Encoding_Summary$mean_RT), ], aes(label = Participant.ID), color = "black", size = 3) + # Label outliers
  365. labs(
  366. title = "",
  367. y = "\nResponse Time (ms)\n",
  368. x = "\nTrial Type\n"
  369. ) +
  370. theme_minimal() +
  371. theme(text = element_text(size = 16))
  372. ```
  373. ```{r pressure, echo=FALSE}
  374. # Merging/Splitting files further; combining allocation information
  375. ROI_Values <- read.xlsx("C:/Users/micha/Desktop/PEACE_Data_and_Code/ROI_Data/Hip_encoding_sig_clusters_PE.xlsx")
  376. Mem_filtered <- M_Encoding_Summary[grepl("Novel", M_Encoding_Summary$Trial_Type), ]
  377. Mem_filtered_2 <- M_Encoding_Summary[grepl("Familiar", M_Encoding_Summary$Trial_Type), ]
  378. Merged_MemROI <- merge(Mem_filtered, ROI_Values, by = "Participant.ID")
  379. Merged_MemROI_2 <- merge(Mem_filtered_2, ROI_Values, by = "Participant.ID")
  380. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Allocation_and_Demographics")
  381. Allocation_and_Demographics <- read.csv("Allocation_And_Demo.csv")
  382. Allocation_and_Demographics$Participant.ID <- as.factor(Allocation_and_Demographics$Participant.ID)
  383. Merged_MemROI <- merge(Merged_MemROI, Allocation_and_Demographics, by = "Participant.ID")
  384. ````
  385. ```{r pressure, echo=FALSE}
  386. # Relationship between ROI values and task performance.
  387. # Full_Model_All_PEs
  388. # Create the scatterplot
  389. ## PE Boxplots
  390. ##
  391. Bil_Hip_Fig <- Merged_MemROI %>% ggplot(aes(x = Allocation, y = Bil_Hipp, fill = Allocation)) +
  392. stat_slab(
  393. side = "right", scale = 0.55, show.legend = F,
  394. position = position_dodge(width = .8), alpha = 0.5,
  395. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  396. ) +
  397. geom_boxplot(width = 0.2, outlier.shape = NA) +
  398. scale_fill_brewer(palette = "Set2") +
  399. scale_color_brewer(palette = "Set2") +
  400. labs(title = " ") +
  401. ylab("Cluster Mask β\n") +
  402. xlab("\nBilateral Hippocampus\n") +
  403. theme_minimal() +
  404. theme(
  405. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  406. panel.spacing = unit(-8, "lines")
  407. ) +
  408. stat_boxplot(
  409. geom = "errorbar",
  410. width = 0.15
  411. ) +
  412. geom_point(position = position_jitternudge(
  413. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  414. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.2, alpha = 0.5) +
  415. scale_shape_manual(values = c(19, 15))
  416. Basal_forebrain_fig <- Merged_MemROI %>% ggplot(aes(x = Allocation, y = Basal_forebrain, fill = Allocation)) +
  417. stat_slab(
  418. side = "right", scale = 0.55, show.legend = F,
  419. position = position_dodge(width = .8), alpha = 0.5,
  420. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  421. ) +
  422. geom_boxplot(width = 0.2, outlier.shape = NA) +
  423. scale_fill_brewer(palette = "Set2") +
  424. scale_color_brewer(palette = "Set2") +
  425. labs(title = " ") +
  426. ylab("Cluster Mask β\n") +
  427. xlab("\nBasal Forebrain\n") +
  428. theme_minimal() +
  429. theme(
  430. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title.y = element_blank(), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  431. panel.spacing = unit(-8, "lines")
  432. ) +
  433. stat_boxplot(
  434. geom = "errorbar",
  435. width = 0.15
  436. ) +
  437. geom_point(position = position_jitternudge(
  438. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  439. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.2, alpha = 0.5) +
  440. scale_shape_manual(values = c(19, 15))
  441. Bil_PRC_fig <- Merged_MemROI %>% ggplot(aes(x = Allocation, y = Perirhinal, fill = Allocation)) +
  442. stat_slab(
  443. side = "right", scale = 0.55, show.legend = F,
  444. position = position_dodge(width = .8), alpha = 0.5,
  445. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  446. ) +
  447. geom_boxplot(width = 0.2, outlier.shape = NA) +
  448. scale_fill_brewer(palette = "Set2") +
  449. scale_color_brewer(palette = "Set2") +
  450. labs(title = " ") +
  451. ylab("Cluster Mask β\n") +
  452. xlab("\nBilateral PRC\n") +
  453. theme_minimal() +
  454. theme(
  455. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title.y = element_blank(), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  456. panel.spacing = unit(-8, "lines")
  457. ) +
  458. stat_boxplot(
  459. geom = "errorbar",
  460. width = 0.15
  461. ) +
  462. geom_point(position = position_jitternudge(
  463. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  464. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.2, alpha = 0.5) +
  465. scale_shape_manual(values = c(19, 15))
  466. Bil_ETH_fig <- Merged_MemROI %>% ggplot(aes(x = Allocation, y = Entorhinal, fill = Allocation)) +
  467. stat_slab(
  468. side = "right", scale = 0.55, show.legend = F,
  469. position = position_dodge(width = .8), alpha = 0.5,
  470. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  471. ) +
  472. geom_boxplot(width = 0.2, outlier.shape = NA) +
  473. scale_fill_brewer(palette = "Set2") +
  474. scale_color_brewer(palette = "Set2") +
  475. labs(title = " ") +
  476. ylab("Cluster Mask β\n") +
  477. xlab("\nBilateral ETC\n") +
  478. theme_minimal() +
  479. theme(
  480. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title.y = element_blank(), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  481. panel.spacing = unit(-8, "lines")
  482. ) +
  483. stat_boxplot(
  484. geom = "errorbar",
  485. width = 0.15
  486. ) +
  487. geom_point(position = position_jitternudge(
  488. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  489. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.2, alpha = 0.5) +
  490. scale_shape_manual(values = c(19, 15))
  491. CombinedPlots <- plot_grid(Bil_Hip_Fig, Basal_forebrain_fig, Bil_PRC_fig, Bil_ETH_fig, align = "h", ncol = 4, labels = c(""))
  492. ```
  493. ```{r pressure, echo=FALSE}
  494. # Resting state edge strength analysis
  495. # Data merging/clean-up
  496. Edge_MamZ_Hipp <- read.csv("C:/Users/micha/Desktop/PEACE_Data_and_Code/ROI_Data/edge_strengths_Node1_Node2.csv")
  497. # Need to add in Participant.ID column to .csv - NTS.
  498. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Allocation_and_Demographics")
  499. Allocation_and_Demographics <- read.csv("Allocation_And_Demo.csv")
  500. EdgeS_in <- merge(Edge_MamZ_Hipp, Allocation_and_Demographics, by = "Participant.ID")
  501. EdgeS_R <- merge(EdgeS_in, Merged_MemROI_2, by = "Participant.ID")
  502. ##########################
  503. # Association between H3R weighted values for edge strengths (resting state) + Hippocampal encoding activity (novel > familiar, significant group cluster)
  504. LM_1 <- lm(Edge.Strengths ~ H3R_Hipp, data = EdgeS_R)
  505. summary(LM_1)
  506. eta_squared(LM_1, ci = 0.95, alternative = "two.sided")
  507. cor.test(EdgeS_R$Edge.Strengths, EdgeS_R$H3R_Hipp)
  508. # Fit regression within each sample
  509. regression_results <- EdgeS_R %>%
  510. group_by(Allocation) %>%
  511. group_map(~ tidy(lm(Edge.Strengths ~ H3R_Hipp, data = .x)))
  512. # Combine into one data frame
  513. regression_df <- bind_rows(regression_results, .id = "Participant.ID")
  514. # Summarize posterior over betas
  515. beta_summary <- regression_df %>%
  516. group_by(term) %>%
  517. summarise(
  518. mean = mean(estimate),
  519. lower = quantile(estimate, 0.025),
  520. upper = quantile(estimate, 0.975)
  521. )
  522. ##########################
  523. # Association between unweighted values for edge strengths (resting state) + Hippocampal encoding activity (novel > familiar, significant group cluster)
  524. LM_2 <- lm(Non.Weight ~ Bil_Hipp, data = EdgeS_R)
  525. summary(LM_2)
  526. eta_squared(LM_2, ci = 0.95, alternative = "two.sided")
  527. cor.test(EdgeS_R$Non.Weight, EdgeS_R$Bil_Hipp)
  528. # Fit regression within each sample
  529. regression_results <- EdgeS_R %>%
  530. group_by(Allocation) %>%
  531. group_map(~ tidy(lm(Non.Weight ~ Bil_Hipp, data = .x)))
  532. # Combine into one data frame
  533. regression_df <- bind_rows(regression_results, .id = "Participant.ID")
  534. # Summarize posterior over betas
  535. beta_summary <- regression_df %>%
  536. group_by(term) %>%
  537. summarise(
  538. mean = mean(estimate),
  539. lower = quantile(estimate, 0.025),
  540. upper = quantile(estimate, 0.975)
  541. )
  542. ##########################
  543. # Figures for publication
  544. # Compute correlation coefficient and p-value
  545. cor_result <- cor.test(EdgeS_R$Edge.Strengths, EdgeS_R$H3R_Hipp)
  546. # Create the scatterplot
  547. Edge_Encoding_Figure <- ggplot(data = EdgeS_R, aes(x = Edge.Strengths, y = H3R_Hipp)) +
  548. geom_smooth(method = "lm", se = TRUE, color = "black", fill = "lightgray", alpha = 0.3) + # Enable CI shading
  549. labs(
  550. x = "\nMammillary Zone ↔ Hippocampus Connectivity\n",
  551. y = "\nBilateral Hippocampus Activity (Novel > Familiar)\n"
  552. ) +
  553. annotate("text",
  554. x = Inf, y = -Inf, hjust = 1, vjust = -0.5, size = 5,
  555. label = paste(
  556. "r =", round(cor_result$estimate, 3),
  557. "\np =", ifelse(cor_result$p.value < 0.001, 0.001, format(cor_result$p.value, scientific = FALSE, digits = 3))
  558. )
  559. ) +
  560. geom_point(size = 3.25, color = "#2E5984", alpha = 0.75) +
  561. theme_minimal() +
  562. theme(
  563. axis.title.y = element_text(size = 16),
  564. axis.title.x = element_text(size = 16),
  565. axis.text.y = element_text(size = 15),
  566. axis.text.x = element_text(size = 15)
  567. )
  568. Edge_Encoding_Figure_Final <- ggMarginal(Edge_Encoding_Figure, type = "density", linetype = "blank", fill = "lightblue", color = "black", alpha = 0.8)
  569. ```
  570. ```{r pressure, echo=FALSE}
  571. # Edge Strengths Figure
  572. # Manually edited it to one * instead of two ** as this is this reflects the TFCE-corrected p-value:
  573. # Node 0 - 1: t = 2.91533; p = 0.9734
  574. Edge_Strengths <- EdgeS_in %>% ggplot(aes(x = Allocation, y = Edge.Strengths, fill = Allocation)) +
  575. stat_slab(
  576. side = "right", scale = 0.55, show.legend = F,
  577. position = position_dodge(width = .8), alpha = 0.5,
  578. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  579. ) +
  580. geom_boxplot(width = 0.2, outlier.shape = NA) +
  581. scale_fill_brewer(palette = "Set2") +
  582. scale_color_brewer(palette = "Set2") +
  583. geom_signif(
  584. comparisons = list(c("ACTIVE", "PLACEBO")),
  585. p.adjust.method = "holm",
  586. map_signif_level = c("***" = 0.001, "*" = 0.01, "*" = 0.05, " " = 0.20, " " = 2),
  587. margin_top = 0.05, textsize = 12
  588. ) +
  589. labs(title = " ") +
  590. ylab("Mammillary Zone ↔ Hippocampus Connectivity\n") +
  591. xlab("") +
  592. theme_minimal() +
  593. theme(
  594. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  595. panel.spacing = unit(-8, "lines")
  596. ) +
  597. stat_boxplot(
  598. geom = "errorbar",
  599. width = 0.15
  600. ) +
  601. geom_point(position = position_jitternudge(
  602. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  603. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.2, alpha = 0.5) +
  604. scale_shape_manual(values = c(19, 15))
  605. # Descriptive statistics
  606. EdgeS_in %>%
  607. group_by(Allocation) %>%
  608. get_summary_stats(Edge.Strengths, type = "mean_sd")
  609. EdgeS_in %>%
  610. group_by(Allocation) %>%
  611. get_summary_stats(Non.Weight, type = "mean_sd")
  612. ```
  613. ```{r pressure, echo=FALSE}
  614. # Removing excluded data & merging demographics file
  615. # P003, P011, P023, P034, P045, P051, & P059 were excluded from neuroimaging analysis due to technical and adherence issues identified in pre-unblinding data quality checks. The results remain significant with their inclusion.
  616. # During the memory recognition task, the task finished early for P044 due to glitch. For completeness, their data was included and analysed based on percentage correct, however, the findings remain significant with their data excluded from the analysis.
  617. removal_df <- subset(M_Encoding_Summary, Participant.ID != "P003" & Participant.ID != "P007" & Participant.ID != "P011" & Participant.ID != "P034" & Participant.ID != "P045" & Participant.ID != "P059")
  618. M_Encoding_Summary <- droplevels(removal_df)
  619. # Adding demographics file
  620. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Allocation_and_Demographics/")
  621. Allocation_and_Demographics <- read.csv("Allocation_And_Demo.csv")
  622. Allocation_and_Demographics$Participant.ID <- as.factor(Allocation_and_Demographics$Participant.ID)
  623. M_Encoding_Full <- merge(M_Encoding_Summary, Allocation_and_Demographics, by = "Participant.ID")
  624. M_Encoding_Full
  625. ```
  626. ```{r pressure, echo=FALSE}
  627. # Plots
  628. M_Encoding_Full$Trial_Type <- as.factor(M_Encoding_Full$Trial_Type)
  629. M_Encoding_Full$Trial_Type <- relevel(M_Encoding_Full$Trial_Type, ref = "Novel")
  630. M_Encoding_Seen <- M_Encoding_Full[M_Encoding_Full$Code == "Seen", ]
  631. M_Encoding_Unseen <- M_Encoding_Full[M_Encoding_Full$Code == "Unseen", ]
  632. M_Encoding_Full$Code <- factor(M_Encoding_Full$Code, levels = c("Seen", "Unseen"))
  633. # Overall DF
  634. # In the main paper, significance asterisks were altered to reflect EMM values.
  635. M_Encoding_Full <- M_Encoding_Full %>%
  636. mutate(Trial_Type = factor(Trial_Type, levels = c("Familiar", "Novel", "Distractor")))
  637. All_acc_Plot <- M_Encoding_Full %>% ggplot(aes(x = Allocation, y = Accuracy_Perc, fill = Allocation)) +
  638. facet_wrap(~Code) +
  639. stat_slab(
  640. side = "right", scale = 0.55, show.legend = F,
  641. position = position_dodge(width = .8), alpha = 0.5,
  642. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  643. ) +
  644. geom_boxplot(width = 0.2, outlier.shape = NA) +
  645. scale_fill_brewer(palette = "Set2") +
  646. scale_color_brewer(palette = "Set2") +
  647. geom_signif(
  648. comparisons = list(c("ACTIVE", "PLACEBO")),
  649. p.adjust.method = "holm",
  650. map_signif_level = c("***" = 0.001, "**" = 0.01, "*" = 0.05, " " = 0.20, " " = 2),
  651. margin_top = 0.05, textsize = 12
  652. ) +
  653. labs(title = " ") +
  654. ylab("Recognition accuracy (%)\n") +
  655. xlab("") +
  656. theme_minimal() +
  657. theme(
  658. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  659. panel.spacing = unit(-8, "lines")
  660. ) +
  661. stat_boxplot(
  662. geom = "errorbar",
  663. width = 0.15
  664. ) +
  665. geom_point(position = position_jitternudge(
  666. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  667. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.2, alpha = 0.5) +
  668. scale_shape_manual(values = c(19, 15))
  669. # Overall RT
  670. All_RT_Plot <- M_Encoding_Full %>% ggplot(aes(x = Allocation, y = mean_RT_corr, fill = Allocation)) +
  671. facet_wrap(~Code) +
  672. stat_slab(
  673. side = "right", scale = 0.55, show.legend = F,
  674. position = position_dodge(width = .8), alpha = 0.5,
  675. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  676. ) +
  677. geom_boxplot(width = 0.2, outlier.shape = NA) +
  678. scale_fill_brewer(palette = "Set2") +
  679. scale_color_brewer(palette = "Set2") +
  680. geom_signif(
  681. comparisons = list(c("ACTIVE", "PLACEBO")),
  682. p.adjust.method = "holm",
  683. map_signif_level = c("***" = 0.001, "**" = 0.01, "*" = 0.05, " " = 0.20, " " = 2),
  684. margin_top = 0.05, textsize = 12
  685. ) +
  686. labs(title = " ") +
  687. ylab("Time to choice (ms)\n") +
  688. xlab("") +
  689. theme_minimal() +
  690. theme(
  691. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  692. panel.spacing = unit(-8, "lines")
  693. ) +
  694. stat_boxplot(
  695. geom = "errorbar",
  696. width = 0.15
  697. ) +
  698. geom_point(position = position_jitternudge(
  699. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  700. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.2, alpha = 0.5) +
  701. scale_shape_manual(values = c(19, 15))
  702. Combined_plot <- plot_grid(All_acc_Plot, All_RT_Plot, ncol = 1)
  703. ```
  704. ```{r pressure, echo=FALSE}
  705. # Checking kurtosis values
  706. x <- M_Encoding_Full$Accuracy_Perc
  707. # skewness
  708. skew_val <- skewness(x, na.rm = TRUE)
  709. kurt_val <- kurtosis(x, na.rm = TRUE) # excess kurtosis by default
  710. c(skew_val = skew_val, kurt_val = kurt_val)
  711. # numeric vector (your variable of interest)
  712. y <- M_Encoding_Full$mean_RT_all
  713. # skewness
  714. skew_val <- skewness(y, na.rm = TRUE)
  715. kurt_val <- kurtosis(y, na.rm = TRUE) # excess kurtosis by default
  716. c(skew_val = skew_val, kurt_val = kurt_val)
  717. # Inferential analyses
  718. # Accuracy analysis
  719. Accuracy_Model <- aov(Accuracy_Perc ~ Allocation + Code + Allocation:Code + Error(Participant.ID), data = M_Encoding_Full)
  720. summary(Accuracy_Model)
  721. ###
  722. # Calculate estimated marginal means (EMMs) for Allocation*Condition interaction
  723. model_linear <- lmer(Accuracy_Perc ~ Allocation + Code + Allocation:Code + (1 | Participant.ID), data = M_Encoding_Full)
  724. eta_squared(model_linear, ci = 0.95, alternative = "two.sided")
  725. EMM_2 <- emmeans(model_linear, ~ Allocation | Code)
  726. # Calculate pairwise comparisons for the specified contrasts
  727. pairwise_comparisons <- pairs(EMM_2, adjust = "holm")
  728. summary(pairwise_comparisons)
  729. effect_size <- eff_size(EMM_2, sigma = sigma(model_linear), edf = df.residual(model_linear))
  730. summary(effect_size)
  731. M_Encoding_Full %>%
  732. group_by(Trial_Type, Allocation) %>%
  733. get_summary_stats(Accuracy_Perc, type = "mean_sd")
  734. # Response time analysis
  735. ###
  736. RT_Model <- aov(mean_RT_all ~ Allocation + Code + Allocation:Code + Error(Participant.ID), data = M_Encoding_Full)
  737. summary(RT_Model)
  738. ###
  739. RT_Model <- aov(mean_RT_corr ~ Allocation + Code + Allocation:Code + Gender + Digit.Span.Aggregate + Error(Participant.ID), data = M_Encoding_Full)
  740. summary(RT_Model)
  741. # Calculate estimated marginal means (EMMs) for Allocation*Condition interaction
  742. model_linear <- lmer(mean_RT_corr ~ Allocation + Code + Allocation:Code + (1 | Participant.ID), data = M_Encoding_Full)
  743. eta_squared(model_linear, ci = 0.95, alternative = "two.sided")
  744. EMM_2 <- emmeans(model_linear, ~ Allocation | Code)
  745. # Calculate pairwise comparisons for the specified contrasts
  746. pairwise_comparisons <- pairs(EMM_2, adjust = "holm")
  747. summary(pairwise_comparisons)
  748. effect_size <- eff_size(EMM_2, sigma = sigma(model_linear), edf = df.residual(model_linear))
  749. summary(effect_size)
  750. M_Encoding_Full %>%
  751. group_by(Trial_Type, Allocation) %>%
  752. get_summary_stats(Accuracy_Perc, type = "mean_sd")
  753. ```
  754. ```{r pressure, echo=FALSE}
  755. # Checking in-scanner engagement
  756. require("knitr")
  757. knitr::opts_knit$set(root.dir = "C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Memory_Encoding_Task/fmri_engagement/")
  758. ##### Set dir first!#########
  759. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Memory_Encoding_Task/fmri_engagement/")
  760. #############################
  761. # Create file list
  762. Hipp_Scan_Files <- list.files(pattern = glob2rx("*Hipp*.csv"))
  763. # Attach and detach plyr to avoid library conflicts
  764. library(plyr)
  765. # Merge files based on file list
  766. Hipp_Scan <- do.call(rbind.fill, lapply(Hipp_Scan_Files, function(x) read.csv(x, stringsAsFactors = FALSE)))
  767. detach("package:plyr", unload = TRUE)
  768. # Remove object to save space
  769. rm(Hipp_Scan_Files)
  770. Hipp_Scan_Clean <- Hipp_Scan %>% select(participant, im_type, im_familiarity, trialOrderFile, key_resp2.corr, key_resp2.rt)
  771. Hipp_Scan_Clean <- Hipp_Scan_Clean %>% rename(Participant.ID = participant)
  772. Hipp_Scan_Clean <- Hipp_Scan_Clean %>% drop_na(key_resp2.corr)
  773. library(stringr)
  774. Hipp_Scan_Clean <- Hipp_Scan_Clean %>%
  775. mutate(Participant.ID = str_replace_all(Participant.ID, "^p", "P") %>% # Convert lowercase 'p' to 'P' at the start
  776. str_replace("_real", "")) # Remove "_real"
  777. Hipp_Scan_Clean <- Hipp_Scan_Clean %>%
  778. mutate(trialOrderFile = str_replace_all(trialOrderFile, "scan_order|\\.xlsx", "")) %>%
  779. rename(Block = trialOrderFile)
  780. Hipp_Scan_Clean <- Hipp_Scan_Clean %>%
  781. rename(Trial_type = im_familiarity)
  782. Hipp_Scan_Clean <- Hipp_Scan_Clean %>%
  783. group_by(Participant.ID) %>% # Group by Participant.ID
  784. mutate(Trial_number = row_number()) %>% # Create sequential trial numbers within each group
  785. ungroup() # Remove grouping for further operations
  786. Hipp_Scan_Clean <- Hipp_Scan_Clean %>%
  787. rename(Accuracy = key_resp2.corr)
  788. Hipp_Scan_Summary <- Hipp_Scan_Clean %>%
  789. group_by(Participant.ID) %>%
  790. summarise(GoRTmean = mean(key_resp2.rt, na.rm = TRUE), GoRTsd = sd(key_resp2.rt, na.rm = TRUE), AccuratePress_Perc = sum(Accuracy) / 96 * 100, Accuracy_Full = sum(Accuracy))
  791. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Allocation_and_Demographics")
  792. Allocation_and_Demographics <- read.csv("Allocation_And_Demo.csv")
  793. Hipp_Scan_Summary_Full <- merge(Hipp_Scan_Summary, Allocation_and_Demographics, by = "Participant.ID")
  794. Hipp_Scan_Clean_Full <- merge(Hipp_Scan_Clean, Allocation_and_Demographics, by = "Participant.ID")
  795. ```
  796. ```{r pressure, echo=FALSE}
  797. # Analysis of engagement data
  798. Hipp_Scan_Summary_Full$Accuracylog <- log(Hipp_Scan_Summary_Full$Accuracy_Full)
  799. Hipp_Scan_Summary_Full$Participant.ID <- as.factor(Hipp_Scan_Summary_Full$Participant.ID)
  800. # Removal of excluded participants (see note above.)
  801. removal_df <- subset(Hipp_Scan_Summary_Full, Participant.ID != "P003" & Participant.ID != "P007" & Participant.ID != "P011" & Participant.ID != "P034" & Participant.ID != "P045" & Participant.ID != "P059")
  802. Hipp_Scan_Summary_Full <- droplevels(removal_df)
  803. Acc_Plot <- Hipp_Scan_Summary_Full %>% ggplot(aes(x = Allocation, y = AccuratePress_Perc, fill = Allocation)) +
  804. stat_slab(
  805. side = "right", scale = 0.55, show.legend = F,
  806. position = position_dodge(width = .8), alpha = 0.5,
  807. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  808. ) +
  809. geom_boxplot(width = 0.2, outlier.shape = NA) +
  810. scale_fill_brewer(palette = "Set2") +
  811. scale_color_brewer(palette = "Set2") +
  812. labs(title = " ") +
  813. ylab("Discrimination Accuracy (%)") +
  814. xlab("") +
  815. theme_minimal() +
  816. theme(
  817. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  818. panel.spacing = unit(-8, "lines")
  819. ) +
  820. stat_boxplot(
  821. geom = "errorbar",
  822. width = 0.15
  823. ) +
  824. geom_point(position = position_jitternudge(
  825. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  826. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.2, alpha = 0.5) +
  827. scale_shape_manual(values = c(19, 15))
  828. Hipp_Scan_Summary_Full$GoRTmean <- (Hipp_Scan_Summary_Full$GoRTmean) * 1000
  829. RT_Plot <- Hipp_Scan_Summary_Full %>% ggplot(aes(x = Allocation, y = GoRTmean, fill = Allocation)) +
  830. stat_slab(
  831. side = "right", scale = 0.55, show.legend = F,
  832. position = position_dodge(width = .8), alpha = 0.5,
  833. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  834. ) +
  835. geom_boxplot(width = 0.2, outlier.shape = NA) +
  836. scale_fill_brewer(palette = "Set2") +
  837. scale_color_brewer(palette = "Set2") +
  838. labs(title = " ") +
  839. ylab("Time to Response (ms)") +
  840. xlab("") +
  841. theme_minimal() +
  842. theme(
  843. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  844. panel.spacing = unit(-8, "lines")
  845. ) +
  846. stat_boxplot(
  847. geom = "errorbar",
  848. width = 0.15
  849. ) +
  850. geom_point(position = position_jitternudge(
  851. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  852. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.2, alpha = 0.5) +
  853. scale_shape_manual(values = c(19, 15))
  854. Combined_Plot <- plot_grid(Acc_Plot, RT_Plot)
  855. # numeric vector (your variable of interest)
  856. x <- Hipp_Scan_Summary_Full$AccuratePress_Perc
  857. # skewness
  858. skew_val <- skewness(x, na.rm = TRUE)
  859. kurt_val <- kurtosis(x, na.rm = TRUE) # excess kurtosis by default
  860. c(skew_val = skew_val, kurt_val = kurt_val)
  861. # Above skewness/Kurtosis threshold, so log transforming. Retaining the non-log transformed version for visual demonstration (see Methods).
  862. Hipp_Scan_Summary_Full$AccuratePress_Perc_log <- log(Hipp_Scan_Summary_Full$AccuratePress_Perc)
  863. Accuracy_Model <- aov(AccuratePress_Perc_log ~ Allocation + Error(Participant.ID), data = Hipp_Scan_Summary_Full)
  864. summary(Accuracy_Model)
  865. RT_Model <- aov(GoRTmean ~ Allocation + Error(Participant.ID), data = Hipp_Scan_Summary_Full)
  866. summary(RT_Model)
  867. ````
  868. ```{r pressure, echo=FALSE}
  869. # Checking pre-scanner engagement
  870. ## Set directory; Create list of relevant files; Merge files
  871. # Set working directory
  872. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Memory_Encoding_Task/Results_InitialTest")
  873. # Create an empty data frame to store the combined data
  874. combined_df <- data.frame()
  875. # Get a list of all .dat files in the directory
  876. dat_files <- list.files(pattern = glob2rx("*recpressce*.log"))
  877. # Loop through each .dat file
  878. for (file in dat_files) {
  879. # Read the file using readLines()
  880. lines <- readLines(file)
  881. # Remove the first three lines
  882. lines <- lines[-(1:5)]
  883. # Extract the file name
  884. file_name <- sub("\\.log$", "", file)
  885. # Check if the file name contains P001, P002, etc.
  886. if (grepl("[Pp]\\d{3}", file_name)) {
  887. # Check if there are lines remaining
  888. if (length(lines) > 0) {
  889. # Replace blank spaces with NA in each line
  890. lines <- lapply(lines, function(line) {
  891. words <- strsplit(line, "\\s+")[[1]]
  892. words[words == ""] <- NA
  893. return(words)
  894. })
  895. # Find the maximum number of elements in a line
  896. max_elements <- max(sapply(lines, length))
  897. # Create a matrix to store the data
  898. data_matrix <- matrix(nrow = length(lines), ncol = max_elements)
  899. # Fill the matrix with the data from the lines
  900. for (i in seq_along(lines)) {
  901. row <- lines[[i]]
  902. data_matrix[i, 1:length(row)] <- row
  903. }
  904. # Convert the matrix to a data frame
  905. df <- as.data.frame(data_matrix, stringsAsFactors = FALSE) # Ensure strings are treated as characters
  906. # Add a column with the file name to the data frame
  907. df <- cbind(FileName = file_name, df)
  908. # Bind the data to the combined data frame
  909. combined_df <- bind_rows(combined_df, df)
  910. }
  911. }
  912. }
  913. # Assign column names
  914. col_names <- c("FileName", "Participant.ID", "Trial", "Event_Type", "Code_Raw", "Time", "TTime", "Uncertainty", "ResponseT", "Uncertainty_2", "ReqTime", "ReqDur", "Stim_Type", "Pair_Index") # Add your column names here
  915. colnames(combined_df) <- col_names
  916. # Prune 'Participant.ID' column to first few letters
  917. combined_df$Participant.ID <- str_sub(combined_df$Participant.ID, 1, 4)
  918. # Convert 'Participant.ID' column to uppercase
  919. combined_df$Participant.ID <- toupper(combined_df$Participant.ID)
  920. # Remove the "FileName" column
  921. combined_df <- combined_df[, !names(combined_df) %in% "FileName"]
  922. combined_df <- combined_df %>%
  923. filter(Event_Type == "Response")
  924. combined_df$Code <- ifelse(grepl("A", combined_df$Code_Raw), 1,
  925. ifelse(grepl("L", combined_df$Code_Raw), 2, NA)
  926. )
  927. # Remove the "Code_Raw" column
  928. combined_df <- combined_df[, !names(combined_df) %in% "Code_Raw"]
  929. # Only take the first instance of a button press (Presentation records all inputs) - you may want to change this
  930. combined_df <- combined_df %>%
  931. distinct(Participant.ID, Trial, .keep_all = TRUE)
  932. combined_df <- combined_df %>%
  933. mutate(Correct = case_when(
  934. Trial == "1" & Code == "2" ~ "1",
  935. Trial == "2" & Code == "1" ~ "1",
  936. Trial == "3" & Code == "2" ~ "1",
  937. Trial == "4" & Code == "1" ~ "1",
  938. Trial == "5" & Code == "1" ~ "1",
  939. Trial == "6" & Code == "2" ~ "1",
  940. Trial == "7" & Code == "2" ~ "1",
  941. Trial == "8" & Code == "2" ~ "1",
  942. Trial == "9" & Code == "1" ~ "1",
  943. Trial == "10" & Code == "1" ~ "1",
  944. Trial == "11" & Code == "2" ~ "1",
  945. Trial == "12" & Code == "1" ~ "1",
  946. Trial == "13" & Code == "1" ~ "1",
  947. Trial == "14" & Code == "2" ~ "1",
  948. Trial == "15" & Code == "1" ~ "1",
  949. Trial == "16" & Code == "2" ~ "1",
  950. TRUE ~ "0"
  951. ))
  952. combined_df$Correct <- as.numeric(combined_df$Correct)
  953. Hipp_PreScan_Summary <- combined_df %>%
  954. group_by(Participant.ID) %>%
  955. summarise(AccuratePress_Perc = sum(Correct) / 16 * 100)
  956. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Allocation_and_Demographics")
  957. Allocation_and_Demographics <- read.csv("Allocation_And_Demo.csv")
  958. Hipp_PreScan_Summary_Full <- merge(Hipp_PreScan_Summary, Allocation_and_Demographics, by = "Participant.ID")
  959. ````
  960. ```{r pressure, echo=FALSE}
  961. # Analysis of engagement data
  962. Hipp_PreScan_Summary_Full$Participant.ID <- as.factor(Hipp_PreScan_Summary_Full$Participant.ID)
  963. removal_df <- subset(Hipp_PreScan_Summary_Full, Participant.ID != "P003" & Participant.ID != "P007" & Participant.ID != "P011" & Participant.ID != "P034" & Participant.ID != "P045" & Participant.ID != "P059" & Participant.ID != "P021" & Participant.ID != "P022")
  964. Hipp_PreScan_Summary_Full <- droplevels(removal_df)
  965. # Participants who were excluded from the fMRI analysis were excluded from this analysis. P021 and P022 self-reported misunderstanding initial task engagement tasks; their data was not included at this stage. Results remain non-significant with or without their inclusion.
  966. Hipp_PreScan_Summary_Full <- droplevels(removal_df)
  967. Accuracy_Model <- aov(AccuratePress_Perc ~ Allocation + Error(Participant.ID), data = Hipp_PreScan_Summary_Full)
  968. summary(Accuracy_Model)
  969. Hipp_PreScan_Summary_Full %>%
  970. get_summary_stats(AccuratePress_Perc, type = "mean_sd")
  971. ````
  972. ```{r pressure, echo=FALSE}
  973. # Signal persistence / FIR analysis
  974. # Importing FIR parameter estimate values and cleaning data
  975. Decay_df <- read.xlsx("C:/Users/micha/Desktop/PEACE_Data_and_Code/ROI_Data/Decay_PEs.xlsx")
  976. Decay_df_long_novel <- Decay_df %>%
  977. pivot_longer(
  978. cols = starts_with("Novel_"),
  979. names_to = "Time",
  980. values_to = "PEs"
  981. )
  982. Decay_df_long_novel <- Decay_df_long_novel %>%
  983. mutate(Time = sub("Novel_B_T", "", Time))
  984. Decay_df_long_novel <- Decay_df_long_novel %>%
  985. mutate(Time = dplyr::recode(as.character(Time),
  986. "Novel_R_T1" = "26",
  987. "Novel_R_T2" = "27",
  988. "Novel_R_T3" = "28",
  989. "Novel_R_T4" = "29",
  990. "Novel_R_T5" = "30",
  991. "Novel_R_T6" = "31",
  992. "Novel_R_T7" = "32",
  993. "Novel_R_T8" = "33",
  994. "Novel_R_T9" = "34",
  995. "Novel_R_T10" = "35",
  996. "Novel_R_T11" = "36",
  997. "Novel_R_T12" = "37",
  998. "Novel_R_T13" = "38",
  999. "Novel_R_T14" = "39",
  1000. "Novel_R_T15" = "40"
  1001. ))
  1002. Decay_df_long_familiar <- Decay_df %>%
  1003. pivot_longer(
  1004. cols = starts_with("Fam"),
  1005. names_to = "Time",
  1006. values_to = "PEs"
  1007. )
  1008. Decay_df_long_familiar <- Decay_df_long_familiar %>%
  1009. mutate(Time = sub("Familiar_B_T", "", Time))
  1010. Decay_df_long_familiar <- Decay_df_long_familiar %>%
  1011. mutate(Time = dplyr::recode(as.character(Time),
  1012. "Familar_R_T1" = "26",
  1013. "Familar_R_T2" = "27",
  1014. "Familar_R_T3" = "28",
  1015. "Familar_R_T4" = "29",
  1016. "Familar_R_T5" = "30",
  1017. "Familar_R_T6" = "31",
  1018. "Familar_R_T7" = "32",
  1019. "Familar_R_T8" = "33",
  1020. "Familar_R_T9" = "34",
  1021. "Familar_R_T10" = "35",
  1022. "Familar_R_T11" = "36",
  1023. "Familar_R_T12" = "37",
  1024. "Familar_R_T13" = "38",
  1025. "Familar_R_T14" = "39",
  1026. "Familar_R_T15" = "40"
  1027. ))
  1028. Decay_df_long_novel$Trial_Type <- "Novel"
  1029. Decay_df_long_familiar$Trial_Type <- "Familiar"
  1030. Decay_df_long_novel_sim <- Decay_df_long_novel %>%
  1031. select(Participant.ID, Time, Trial_Type, PEs)
  1032. Decay_df_long_familiar_sim <- Decay_df_long_familiar %>%
  1033. select(Participant.ID, Time, Trial_Type, PEs)
  1034. # Rename PEs columns before cbind
  1035. Decay_df_long_novel_sim <- Decay_df_long_novel_sim %>% rename(PEs_novel = PEs)
  1036. Decay_df_long_familiar_sim <- Decay_df_long_familiar_sim %>% rename(PEs_familiar = PEs)
  1037. # Now bind them side-by-side
  1038. merged_df <- cbind(Decay_df_long_novel_sim, PEs_familiar = Decay_df_long_familiar_sim$PEs_familiar)
  1039. # Subtract safely
  1040. merged_df$PE_diff <- merged_df$PEs_novel - merged_df$PEs_familiar
  1041. combined_decay_df <- bind_rows(Decay_df_long_novel_sim, Decay_df_long_familiar_sim)
  1042. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Allocation_and_Demographics")
  1043. Allocation_and_Demographics <- read.csv("Allocation_And_Demo.csv")
  1044. combined_decay_df <- merge(combined_decay_df, Allocation_and_Demographics, by = "Participant.ID")
  1045. merged_df <- merge(merged_df, Allocation_and_Demographics, by = "Participant.ID")
  1046. ````
  1047. ```{r pressure, echo=FALSE}
  1048. # FIR Analysis Figure (Main manuscript, Fig 2F-I)
  1049. merged_df <- merged_df %>%
  1050. filter(as.numeric(Time) >= 26)
  1051. merged_df <- merged_df %>%
  1052. mutate(Time = dplyr::recode(as.character(Time),
  1053. "26" = "1",
  1054. "27" = "2",
  1055. "28" = "3",
  1056. "29" = "4",
  1057. "30" = "5",
  1058. "31" = "6",
  1059. "32" = "7",
  1060. "33" = "8",
  1061. "34" = "9",
  1062. "35" = "10",
  1063. "36" = "11",
  1064. "37" = "12",
  1065. "38" = "13",
  1066. "39" = "14",
  1067. "40" = "15"
  1068. ))
  1069. avg_df <- merged_df %>%
  1070. group_by(Time, Allocation) %>%
  1071. summarise(PEs_novel = mean(PEs_novel, na.rm = TRUE), PEs_familiar = mean(PEs_familiar, na.rm = TRUE), .groups = "drop")
  1072. merged_df$Time <- factor(merged_df$Time, levels = mixedsort(unique(merged_df$Time)))
  1073. ####
  1074. ###
  1075. Decay_Beta_Df <- Decay_df %>%
  1076. select(Participant.ID, Decay.Beta, H3R.Decay)
  1077. Decay_Full_Df <- merge(Merged_MemROI, Decay_Beta_Df, by = "Participant.ID")
  1078. Decay_Full_Df_2 <- merge(Edge_MamZ_Hipp, Decay_Full_Df, by = "Participant.ID")
  1079. Decay_Full_Df_3 <- merge(M_Encoding_Not, Decay_Full_Df, by = "Participant.ID")
  1080. Decay_Full_Df_4 <- merge(Edge_MamZ_Hipp, Decay_Full_Df_3, by = "Participant.ID")
  1081. cor_result <- cor.test(Decay_Full_Df_2$Edge.Strengths, Decay_Full_Df_2$H3R.Decay)
  1082. cor_result <- cor.test(Decay_Full_Df_3$H3R.Decay, Decay_Full_Df_3$mean_RT_corr.x)
  1083. mean_se <- function(x) {
  1084. m <- mean(x)
  1085. se <- sd(x) / sqrt(length(x))
  1086. return(c(y = m, ymin = m - se, ymax = m + se))
  1087. }
  1088. merged_df$Time <- as.numeric(as.character(merged_df$Time))
  1089. glm_preds$Allocation <- factor(glm_preds$Allocation, levels = c("PLACEBO", "ACTIVE"))
  1090. # Figure 2G generation
  1091. Figure.2G <- ggplot(glm_preds, aes(x = Time, y = fit, color = Allocation, fill = Allocation, linetype = Allocation)) +
  1092. geom_ribbon(
  1093. aes(ymin = fit - se, ymax = fit + se),
  1094. fill = "grey70",
  1095. alpha = 0.15,
  1096. colour = NA
  1097. ) +
  1098. geom_line(size = 2.4) +
  1099. scale_color_manual(values = rev(RColorBrewer::brewer.pal(3, "Set2")[1:2])) +
  1100. scale_fill_manual(values = rev(RColorBrewer::brewer.pal(3, "Set2")[1:2])) +
  1101. scale_linetype_manual(values = rev(c("solid", "dashed"))) +
  1102. labs(
  1103. x = "Time (Bins)\n",
  1104. y = "Δ Signal Decay ETC Cluster\n"
  1105. ) +
  1106. theme_minimal() +
  1107. theme(
  1108. axis.text.x = element_text(angle = 45, hjust = 1, size = 16), # Increase tick text size
  1109. axis.text.y = element_text(size = 16), # Y-axis tick size
  1110. axis.title = element_text(size = 18), # Axis labels
  1111. plot.title = element_text(size = 18, face = "bold")
  1112. )
  1113. # Figure 2H generation
  1114. cor_result <- cor.test(Decay_Full_Df_4$Edge.Strengths, Decay_Full_Df_4$H3R_Hipp)
  1115. # Create the scatterplot
  1116. Scatterplot_check2 <- ggplot(data = Decay_Full_Df_4, aes(x = Edge.Strengths, y = H3R_Hipp)) +
  1117. geom_smooth(method = "lm", se = TRUE, color = "black", fill = "lightgray", alpha = 0.3) + # Enable CI shading
  1118. labs(
  1119. x = "\nΔ Signal Decay ETC Cluster\n",
  1120. y = "\nBilateral Hippocampus β - Novel Memory Encoding\n"
  1121. ) +
  1122. annotate("text",
  1123. x = Inf, y = -Inf, hjust = 1, vjust = -0.5, size = 5,
  1124. label = paste(
  1125. "r =", round(cor_result$estimate, 3),
  1126. "\np =", ifelse(cor_result$p.value < 0.001, 0.001, format(cor_result$p.value, scientific = FALSE, digits = 3))
  1127. )
  1128. ) +
  1129. geom_point(size = 3.25, color = "#2E5984", alpha = 0.75) +
  1130. theme_minimal() +
  1131. theme(
  1132. axis.title.y = element_text(size = 16),
  1133. axis.title.x = element_text(size = 16),
  1134. axis.text.y = element_text(size = 15),
  1135. axis.text.x = element_text(size = 15)
  1136. )
  1137. Figure.2H <- ggMarginal(Scatterplot_check2, type = "density", linetype = "blank", fill = "lightblue", color = "black", alpha = 0.8)
  1138. # Figure 2I
  1139. cor_result <- cor.test(Decay_Full_Df_4$Edge.Strengths, Decay_Full_Df_4$H3R.Decay)
  1140. # Create the scatterplot
  1141. Scatterplot_check2 <- ggplot(data = Decay_Full_Df_4, aes(x = Edge.Strengths, y = H3R.Decay)) +
  1142. geom_smooth(method = "lm", se = TRUE, color = "black", fill = "lightgray", alpha = 0.3) + # Enable CI shading
  1143. labs(
  1144. x = "\nMammillary Zone ↔ Hippocampus Connectivity\n",
  1145. y = "\nΔ Signal Decay ETC Cluster\n"
  1146. ) +
  1147. annotate("text",
  1148. x = Inf, y = -Inf, hjust = 1, vjust = -0.5, size = 5,
  1149. label = paste(
  1150. "r =", round(cor_result$estimate, 3),
  1151. "\np =", ifelse(cor_result$p.value < 0.001, 0.001, format(cor_result$p.value, scientific = FALSE, digits = 3))
  1152. )
  1153. ) +
  1154. geom_point(size = 3.25, color = "#2E5984", alpha = 0.75) +
  1155. theme_minimal() +
  1156. theme(
  1157. axis.title.y = element_text(size = 16),
  1158. axis.title.x = element_text(size = 16),
  1159. axis.text.y = element_text(size = 15),
  1160. axis.text.x = element_text(size = 15)
  1161. )
  1162. Figure.2I <- ggMarginal(Scatterplot_check2, type = "density", linetype = "blank", fill = "lightblue", color = "black", alpha = 0.8)
  1163. ```
  1164. ```{r pressure, echo=FALSE}
  1165. # DDM Analysis - Checking relationship between signal persistence and encoding-related activity (lateralised to check specificity).
  1166. # Left hemisphere - Entorhinal cortex (encoding)
  1167. med.fit <- lm(H3R.Decay ~ H3R_leftento, data = Decay_Full_Df_4)
  1168. cor_result <- cor.test(Decay_Full_Df_4$Decay.Beta, Decay_Full_Df_4$H3R_leftento)
  1169. summary(med.fit)
  1170. # Left hemisphere - Hippocampus (encoding)
  1171. med.fit <- lm(H3R.Decay ~ H3R_lefthipp, data = Decay_Full_Df_4)
  1172. summary(med.fit)
  1173. cor_result <- cor.test(Decay_Full_Df_4$Decay.Beta, Decay_Full_Df_4$H3R_lefthipp)
  1174. ## Right hemisphere - Entorhinal cortex (encoding)
  1175. med.fit <- lm(H3R.Decay ~ H3R_rightento, data = Decay_Full_Df_4)
  1176. cor_result <- cor.test(Decay_Full_Df_4$Decay.Beta, Decay_Full_Df_4$H3R_rightento)
  1177. summary(med.fit)
  1178. # Left hemisphere - Hippocampus (encoding)
  1179. med.fit <- lm(H3R.Decay ~ H3R_righthipp, data = Decay_Full_Df_4)
  1180. summary(med.fit)
  1181. cor_result <- cor.test(Decay_Full_Df_4$Decay.Beta, Decay_Full_Df_4$H3R_righthipp)
  1182. ##########################################################################
  1183. # DDM Analysis - Checking relationship between signal persistence and DDM params
  1184. # Persistence Analysis - Merging relevant files
  1185. ###########
  1186. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Memory_Encoding_Task")
  1187. ddm_df <- read.csv("pivoted_traces.csv")
  1188. #Decay_Full_Df_5 <- merge(ddm_df, Decay_Full_Df, by = "Participant.ID")
  1189. #Swap below and above depending on analysis (Correlation between params should have N=47 participants; between-groups analysis between params should have N=52 participants).
  1190. Decay_Full_Df_5 <- merge(ddm_df, Allocation_and_Demographics, by = "Participant.ID")
  1191. # Arcscin transform non-decision time to maintain consistency across analyses
  1192. Decay_Full_Df_5$t.a.0 <- asin(sqrt(Decay_Full_Df_5$t.0.))
  1193. Decay_Full_Df_5$t.a.1 <- asin(sqrt(Decay_Full_Df_5$t.1.))
  1194. # Log transform decision policy to maintain consistency across DDM analyses
  1195. Decay_Full_Df_5$a.0.log <- log(Decay_Full_Df_5$a.0)
  1196. Decay_Full_Df_5$a.1.log <- log(Decay_Full_Df_5$a.1)
  1197. Decay_Full_Df_5_long <- Decay_Full_Df_5 %>%
  1198. pivot_longer(
  1199. cols = matches("^(a|v|t|z_trans)\\.(?:0|1)\\.?$"),
  1200. names_to = c(".value", "Trial_type"),
  1201. names_pattern = "^(.*)\\.(\\d)\\.?$"
  1202. ) %>%
  1203. mutate(Trial_type = factor(Trial_type, levels = c("0", "1")))
  1204. #Decay_Full_Df_5_long$Trial_type <- recode_factor(Decay_Full_Df_5_long$Trial_type, "0" = "Unseen", "1" = "Seen")
  1205. # Legend: v [drift rate], a [decision policy], t [non-decision time], z_trans [initial choice bias]
  1206. # Parameter symbols ending in '.0' refer to distractor trials; '.1' refers to previously encoded trials
  1207. ############################################
  1208. #### Figures for publication
  1209. # Figure 3E
  1210. # Compute correlation coefficient and p-value
  1211. cor_result <- cor.test(Decay_Full_Df_5$v.1., Decay_Full_Df_5$H3R.Decay)
  1212. # Create the scatterplot
  1213. Scatterplot_check2 <- ggplot(data = Decay_Full_Df_5, aes(x = v.1., y = H3R.Decay)) +
  1214. geom_smooth(method = "lm", se = TRUE, color = "black", fill = "lightgray", alpha = 0.3) + # Enable CI shading
  1215. labs(
  1216. x = "\nDrift rate (v) - Previously encoded\n",
  1217. y = "\nΔ Signal Decay ETC Cluster\n"
  1218. ) +
  1219. annotate("text",
  1220. x = Inf, y = -Inf, hjust = 1, vjust = -0.5, size = 5,
  1221. label = paste(
  1222. "r =", round(cor_result$estimate, 3),
  1223. "\np =", ifelse(cor_result$p.value < 0.001, 0.001, format(cor_result$p.value, scientific = FALSE, digits = 3))
  1224. )
  1225. ) +
  1226. geom_point(size = 3.25, color = "#2E5984", alpha = 0.75) +
  1227. theme_minimal() +
  1228. theme(
  1229. axis.title.y = element_text(size = 16),
  1230. axis.title.x = element_text(size = 16),
  1231. axis.text.y = element_text(size = 15),
  1232. axis.text.x = element_text(size = 15)
  1233. )
  1234. Figure.3E <- ggMarginal(Scatterplot_check2, type = "density", linetype = "blank", fill = "lightblue", color = "black", alpha = 0.8)
  1235. # Figure 3F
  1236. # Compute correlation coefficient and p-value
  1237. cor_result <- cor.test(Decay_Full_Df_5$a.0., Decay_Full_Df_5$H3R.Decay)
  1238. # Create the scatterplot
  1239. Scatterplot_check2 <- ggplot(data = Decay_Full_Df_5, aes(x = a.0., y = H3R.Decay)) +
  1240. geom_smooth(method = "lm", se = TRUE, color = "black", fill = "lightgray", alpha = 0.3) + # Enable CI shading
  1241. labs(
  1242. x = "\nDecision Policy (a) - Unseen distractors\n",
  1243. y = "\nΔ Signal Decay ETC Cluster\n"
  1244. ) +
  1245. annotate("text",
  1246. x = Inf, y = -Inf, hjust = 1, vjust = -0.5, size = 5,
  1247. label = paste(
  1248. "r =", round(cor_result$estimate, 3),
  1249. "\np =", ifelse(cor_result$p.value < 0.001, 0.001, format(cor_result$p.value, scientific = FALSE, digits = 3))
  1250. )
  1251. ) +
  1252. geom_point(size = 3.25, color = "#2E5984", alpha = 0.75) +
  1253. theme_minimal() +
  1254. theme(
  1255. axis.title.y = element_text(size = 16),
  1256. axis.title.x = element_text(size = 16),
  1257. axis.text.y = element_text(size = 15),
  1258. axis.text.x = element_text(size = 15)
  1259. )
  1260. Figure.3F <- ggMarginal(Scatterplot_check2, type = "density", linetype = "blank", fill = "lightblue", color = "black", alpha = 0.8)
  1261. ######################################################
  1262. # Checking LMs for DDM parameters ~ Signal Decay
  1263. # Decision policy
  1264. med.fit <- lm(a.0.log ~ Decay.Beta, data = Decay_Full_Df_5)
  1265. summary(med.fit)
  1266. med.fit <- lm(a.1.log ~ Decay.Beta, data = Decay_Full_Df_5)
  1267. summary(med.fit)
  1268. # Fit regression within each sample
  1269. regression_results <- Decay_Full_Df_5_long %>%
  1270. group_by(Trial_type) %>%
  1271. group_map(~ tidy(lm(a ~ H3R.Decay + Allocation.y, data = .x)))
  1272. # Combine into one data frame
  1273. regression_df <- bind_rows(regression_results, .id = "Participant.ID")
  1274. # Summarize posterior over betas
  1275. beta_summary <- regression_df %>%
  1276. group_by(term) %>%
  1277. summarise(
  1278. mean = mean(estimate),
  1279. lower = quantile(estimate, 0.025),
  1280. upper = quantile(estimate, 0.975)
  1281. )
  1282. # Drift rate
  1283. med.fit <- lm(v.0. ~ Decay.Beta, data = Decay_Full_Df_5)
  1284. summary(med.fit)
  1285. med.fit <- lm(v.1. ~ Decay.Beta, data = Decay_Full_Df_5)
  1286. summary(med.fit)
  1287. # Fit regression within each sample
  1288. regression_results <- Decay_Full_Df_5_long %>%
  1289. group_by(Trial_type) %>%
  1290. group_map(~ tidy(lm(v ~ H3R.Decay + Allocation.y, data = .x)))
  1291. # Combine into one data frame
  1292. regression_df <- bind_rows(regression_results, .id = "Participant.ID")
  1293. # Summarize posterior over betas
  1294. beta_summary <- regression_df %>%
  1295. group_by(term) %>%
  1296. summarise(
  1297. mean = mean(estimate),
  1298. lower = quantile(estimate, 0.025),
  1299. upper = quantile(estimate, 0.975)
  1300. )
  1301. ######################################################
  1302. ````
  1303. ```{r pressure, echo=FALSE}
  1304. ########
  1305. ### Figures for publication
  1306. # Figure 3C
  1307. mean_se <- function(x) {
  1308. m <- mean(x)
  1309. se <- sd(x) / sqrt(length(x))
  1310. return(c(y = m, ymin = m - se, ymax = m + se))
  1311. }
  1312. # Plot to demonstrate LR interaction effect
  1313. Interaction_Graph <- ggplot(Decay_Full_Df_5_long, aes(x = Trial_type, y = v, color = Allocation, group = Allocation)) +
  1314. scale_fill_brewer(palette = "Set2") +
  1315. scale_color_brewer(palette = "Set2") +
  1316. # Left side (for 'Loss')
  1317. stat_slab(
  1318. data = subset(Decay_Full_Df_5_long, Trial_type == "Seen"), # Only data where Trial_type is 'Loss'
  1319. side = "left", scale = 0.5, show.legend = F, alpha = 0.5,
  1320. aes(fill = Allocation), # Color the slabs based on 'Allocation'
  1321. .width = c(.50, .95, 1), linetype = "blank", position = position_nudge(x = -0.15)
  1322. ) +
  1323. # Right side (for 'Win')
  1324. stat_slab(
  1325. data = subset(Decay_Full_Df_5_long, Trial_type == "Unseen"), # Only data where Trial_type is 'Win'
  1326. side = "right", scale = 0.5, show.legend = F, alpha = 0.5,
  1327. aes(fill = Allocation), # Color the slabs based on 'Allocation'
  1328. .width = c(.50, .95, 1), linetype = "blank", position = position_nudge(x = 0.15)
  1329. ) +
  1330. geom_line(aes(group = Participant.ID), linetype = "dashed", size = 0.175, alpha = 0.38) +
  1331. # Points and lines (jittered and connected by Participant.ID)
  1332. geom_point(position = position_jitternudge(
  1333. jitter.width = 0.2, jitter.height = -0.3, seed = 123
  1334. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.15, alpha = 0.55) +
  1335. # Lines connecting points for each Participant.ID (grouping)
  1336. # Labels and title
  1337. labs(
  1338. title = "",
  1339. x = "",
  1340. y = "\nDrift Rate (v)\n"
  1341. ) +
  1342. theme_minimal() +
  1343. scale_shape_manual(values = c(19, 15)) + # Custom shape for Allocation
  1344. # Confidence ribbon (mean ± SE)
  1345. stat_summary(
  1346. fun.data = mean_se,
  1347. geom = "ribbon",
  1348. aes(group = Allocation),
  1349. fill = "grey70", # or "lightgrey", "#CCCCCC", etc.
  1350. alpha = 0.25,
  1351. colour = NA # removes border
  1352. ) +
  1353. # Group mean line
  1354. stat_summary(
  1355. fun = mean,
  1356. geom = "line",
  1357. aes(group = Allocation, color = Allocation),
  1358. size = 1.9
  1359. )
  1360. # Figure 3D
  1361. # Plot to demonstrate LR interaction effect
  1362. Interaction_Graph <- ggplot(Decay_Full_Df_5_long, aes(x = Trial_type, y = a, color = Allocation, group = Allocation)) +
  1363. scale_fill_brewer(palette = "Set2") +
  1364. scale_color_brewer(palette = "Set2") +
  1365. # Left side (for 'Loss')
  1366. stat_slab(
  1367. data = subset(Decay_Full_Df_5_long, Trial_type == "Seen"), # Only data where Trial_type is 'Loss'
  1368. side = "left", scale = 0.5, show.legend = F, alpha = 0.5,
  1369. aes(fill = Allocation), # Color the slabs based on 'Allocation'
  1370. .width = c(.50, .95, 1), linetype = "blank", position = position_nudge(x = -0.15)
  1371. ) +
  1372. # Right side (for 'Win')
  1373. stat_slab(
  1374. data = subset(Decay_Full_Df_5_long, Trial_type == "Unseen"), # Only data where Trial_type is 'Win'
  1375. side = "right", scale = 0.5, show.legend = F, alpha = 0.5,
  1376. aes(fill = Allocation), # Color the slabs based on 'Allocation'
  1377. .width = c(.50, .95, 1), linetype = "blank", position = position_nudge(x = 0.15)
  1378. ) +
  1379. geom_line(aes(group = Participant.ID), linetype = "dashed", size = 0.175, alpha = 0.36) +
  1380. # Points and lines (jittered and connected by Participant.ID)
  1381. geom_point(position = position_jitternudge(
  1382. jitter.width = 0.2, jitter.height = -0.3, seed = 123
  1383. ), aes(color = Allocation, shape = Allocation), size = 4.4, stroke = 0.15, alpha = 0.55) +
  1384. # Lines connecting points for each Participant.ID (grouping)
  1385. # Labels and title
  1386. labs(
  1387. title = "",
  1388. x = "",
  1389. y = "\nLog Decision Policy (a)\n"
  1390. ) +
  1391. theme_minimal() +
  1392. scale_shape_manual(values = c(19, 15)) + # Custom shape for Allocation
  1393. # Confidence ribbon (mean ± SE)
  1394. stat_summary(
  1395. fun.data = mean_se,
  1396. geom = "ribbon",
  1397. aes(group = Allocation),
  1398. fill = "grey70", # or "lightgrey", "#CCCCCC", etc.
  1399. alpha = 0.2,
  1400. colour = NA # removes border
  1401. ) +
  1402. # Group mean line
  1403. stat_summary(
  1404. fun = mean,
  1405. geom = "line",
  1406. aes(group = Allocation, color = Allocation),
  1407. size = 1.9
  1408. )
  1409. ###
  1410. # Non-decision time plot (Supplementary Mats.)
  1411. Ter_plot <- Decay_Full_Df_5_long %>% ggplot(aes(x = Allocation.y, y = t, fill = Allocation.y)) +
  1412. facet_wrap(~Trial_type) +
  1413. stat_slab(
  1414. side = "right", scale = 0.55, show.legend = F,
  1415. position = position_dodge(width = .8), alpha = 0.5,
  1416. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1417. ) +
  1418. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1419. scale_fill_brewer(palette = "Set2") +
  1420. scale_color_brewer(palette = "Set2") +
  1421. geom_signif(
  1422. comparisons = list(c("ACTIVE", "PLACEBO")),
  1423. p.adjust.method = "holm",
  1424. map_signif_level = c("***" = 0.001, "**" = 0.01, "*" = 0.05, " " = 0.20, " " = 2),
  1425. margin_top = 0.05, textsize = 12
  1426. ) +
  1427. labs(title = " ") +
  1428. ylab("Non-decision time (Ter)\n") +
  1429. xlab("") +
  1430. theme_minimal() +
  1431. theme(
  1432. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  1433. panel.spacing = unit(-8, "lines")
  1434. ) +
  1435. stat_boxplot(
  1436. geom = "errorbar",
  1437. width = 0.15
  1438. ) +
  1439. geom_point(position = position_jitternudge(
  1440. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1441. ), aes(color = Allocation.y, shape = Allocation.y), size = 4.4, stroke = 0.2, alpha = 0.5) +
  1442. scale_shape_manual(values = c(19, 15))
  1443. Decay_Full_Df_5_long <- Decay_Full_Df_5 %>%
  1444. pivot_longer(
  1445. cols = c(z_trans.0., z_trans.1.),
  1446. names_to = "Trial_type",
  1447. names_prefix = "z",
  1448. values_to = "z"
  1449. )
  1450. # Initial choice bias plot (Supplementary Mats.)
  1451. bias_plot <- Decay_Full_Df_5_long %>% ggplot(aes(x = Allocation.y, y = z_trans, fill = Allocation.y)) +
  1452. facet_wrap(~Trial_type) +
  1453. stat_slab(
  1454. side = "right", scale = 0.55, show.legend = F,
  1455. position = position_dodge(width = .8), alpha = 0.5,
  1456. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1457. ) +
  1458. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1459. scale_fill_brewer(palette = "Set2") +
  1460. scale_color_brewer(palette = "Set2") +
  1461. geom_signif(
  1462. comparisons = list(c("ACTIVE", "PLACEBO")),
  1463. p.adjust.method = "holm",
  1464. map_signif_level = c("***" = 0.001, "**" = 0.01, "*" = 0.05, " " = 0.20, " " = 2),
  1465. margin_top = 0.05, textsize = 12
  1466. ) +
  1467. labs(title = " ") +
  1468. ylab("Initial Choice Bias (z)\n") +
  1469. xlab("") +
  1470. theme_minimal() +
  1471. theme(
  1472. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  1473. panel.spacing = unit(-8, "lines")
  1474. ) +
  1475. stat_boxplot(
  1476. geom = "errorbar",
  1477. width = 0.15
  1478. ) +
  1479. geom_point(position = position_jitternudge(
  1480. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1481. ), aes(color = Allocation.y, shape = Allocation.y), size = 4.4, stroke = 0.2, alpha = 0.5) +
  1482. scale_shape_manual(values = c(19, 15))
  1483. # Inter-trial variability in non-decision time plot (Supplementary Mats.)
  1484. st_plot <- Decay_Full_Df_5 %>% ggplot(aes(x = Allocation.y, y = st, fill = Allocation.y)) +
  1485. stat_slab(
  1486. side = "right", scale = 0.55, show.legend = F,
  1487. position = position_dodge(width = .8), alpha = 0.5,
  1488. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1489. ) +
  1490. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1491. scale_fill_brewer(palette = "Set2") +
  1492. scale_color_brewer(palette = "Set2") +
  1493. geom_signif(
  1494. comparisons = list(c("ACTIVE", "PLACEBO")),
  1495. p.adjust.method = "holm",
  1496. map_signif_level = c("***" = 0.001, "**" = 0.01, "*" = 0.05, " " = 0.20, " " = 2),
  1497. margin_top = 0.05, textsize = 12
  1498. ) +
  1499. labs(title = " ") +
  1500. ylab("Inter-trial variability - non-decision time (st)\n") +
  1501. xlab("") +
  1502. theme_minimal() +
  1503. theme(
  1504. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  1505. panel.spacing = unit(-8, "lines")
  1506. ) +
  1507. stat_boxplot(
  1508. geom = "errorbar",
  1509. width = 0.15
  1510. ) +
  1511. geom_point(position = position_jitternudge(
  1512. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1513. ), aes(color = Allocation.y, shape = Allocation.y), size = 4.4, stroke = 0.2, alpha = 0.5) +
  1514. scale_shape_manual(values = c(19, 15))
  1515. # Inter-trial variability in initial choice bias plot (Supplementary Mats.)
  1516. sz_plot <- Decay_Full_Df_5 %>% ggplot(aes(x = Allocation.y, y = sz, fill = Allocation.y)) +
  1517. stat_slab(
  1518. side = "right", scale = 0.55, show.legend = F,
  1519. position = position_dodge(width = .8), alpha = 0.5,
  1520. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1521. ) +
  1522. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1523. scale_fill_brewer(palette = "Set2") +
  1524. scale_color_brewer(palette = "Set2") +
  1525. geom_signif(
  1526. comparisons = list(c("ACTIVE", "PLACEBO")),
  1527. p.adjust.method = "holm",
  1528. map_signif_level = c("***" = 0.001, "**" = 0.01, "*" = 0.05, " " = 0.20, " " = 2),
  1529. margin_top = 0.05, textsize = 12
  1530. ) +
  1531. labs(title = " ") +
  1532. ylab("Inter-trial variability - initial choice bias (sz)\n") +
  1533. xlab("") +
  1534. theme_minimal() +
  1535. theme(
  1536. legend.position = "none", text = element_text(size = 14), axis.text.y = element_text(size = 14), axis.title = element_text(size = 20), axis.text.x = element_text(size = 14), strip.text = element_text(hjust = 0.41, vjust = 1, size = 14.5),
  1537. panel.spacing = unit(-8, "lines")
  1538. ) +
  1539. stat_boxplot(
  1540. geom = "errorbar",
  1541. width = 0.15
  1542. ) +
  1543. geom_point(position = position_jitternudge(
  1544. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1545. ), aes(color = Allocation.y, shape = Allocation.y), size = 4.4, stroke = 0.2, alpha = 0.5) +
  1546. scale_shape_manual(values = c(19, 15))
  1547. ````
  1548. ```{r pressure, echo=FALSE}
  1549. # Inferential analysis - DDM across allocation groups
  1550. removal_df <- subset(Decay_Full_Df_5_long, Participant.ID != "P003" & Participant.ID != "P007" & Participant.ID != "P011" & Participant.ID != "P034" & Participant.ID != "P045" & Participant.ID != "P059")
  1551. Decay_Full_Df_5_long <- droplevels(removal_df) #This dataset should have N=52 participants.
  1552. # Non-decision time
  1553. ANCOVA_Drift <- aov(t ~ Allocation.y * Trial_type + Error(Participant.ID), data = Decay_Full_Df_5_long)
  1554. summary(ANCOVA_Drift)
  1555. # Initial choice bias
  1556. ANCOVA_Drift <- aov(z_trans ~ Allocation.y * Trial_type + Error(Participant.ID), data = Decay_Full_Df_5_long)
  1557. summary(ANCOVA_Drift)
  1558. # Decision policy
  1559. ANCOVA_Drift <- aov(a ~ Allocation.y * Trial_type + Error(Participant.ID), data = Decay_Full_Df_5_long)
  1560. summary(ANCOVA_Drift)
  1561. # Significant
  1562. model_linear <- lmer(a ~ Allocation.y + Trial_type + Allocation.y:Trial_type + (1 | Participant.ID), data = Decay_Full_Df_5_long)
  1563. summary(model_linear)
  1564. anova(model_linear, type = 2) # Type III ANOVA-like table
  1565. eta_squared(model_linear, ci = 0.95, alternative = "two.sided")
  1566. EMM_2 <- emmeans(model_linear, ~ Allocation.y | Trial_type)
  1567. confint(model_linear, method = "Wald")
  1568. # Calculate pairwise comparisons for the specified contrasts
  1569. pairwise_comparisons <- pairs(EMM_2, adjust = "holm")
  1570. summary(pairwise_comparisons)
  1571. effect_size <- eff_size(EMM_2, sigma = sigma(model_linear), edf = df.residual(model_linear))
  1572. summary(effect_size)
  1573. #######
  1574. ANCOVA_Drift <- aov(v ~ Allocation.y * Trial_type + Error(Participant.ID), data = Decay_Full_Df_5_long)
  1575. summary(ANCOVA_Drift)
  1576. # Significant
  1577. model_linear <- lmer(v ~ Allocation.y + Trial_type + Allocation.y:Trial_type + (1 | Participant.ID), data = Decay_Full_Df_5_long)
  1578. summary(model_linear)
  1579. anova(model_linear, type = 2) # Type III ANOVA-like table
  1580. eta_squared(model_linear, ci = 0.95, alternative = "two.sided")
  1581. EMM_2 <- emmeans(model_linear, ~ Allocation.y | Trial_type)
  1582. confint(model_linear, method = "Wald")
  1583. # Calculate pairwise comparisons for the specified contrasts
  1584. pairwise_comparisons <- pairs(EMM_2, adjust = "holm")
  1585. summary(pairwise_comparisons)
  1586. effect_size <- eff_size(EMM_2, sigma = sigma(model_linear), edf = df.residual(model_linear))
  1587. summary(effect_size)
  1588. ````
  1589. ```{r pressure, echo=FALSE}
  1590. # DDM Param recovery
  1591. setwd("C:/Users/micha/Desktop/PEACE_Data_and_Code/Behavioural_Data/Memory_Encoding_Task/DDM/")
  1592. MasterDDM_sim <- read.csv("Param_recovery.csv", header = TRUE, stringsAsFactors = FALSE)
  1593. MasterDDM_sim$Blank <- "Blank"
  1594. BoundarySep <- MasterDDM_sim %>% ggplot(aes(x = Blank, y = log(a.0.), fill = Blank)) +
  1595. stat_slab(
  1596. side = "right", scale = 0.5, show.legend = F,
  1597. position = position_dodge(width = .8), alpha = 0.5,
  1598. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1599. ) +
  1600. scale_color_manual(values = c("#828283")) +
  1601. scale_fill_manual(values = c("#828283")) +
  1602. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1603. labs(title = " ") +
  1604. ylab("Log boundary separation (a)") +
  1605. xlab("") +
  1606. theme_minimal() +
  1607. theme(legend.position = "none", text = element_text(size = 14), axis.title.y = element_text(size = 17), strip.text = element_blank(), axis.text.x = element_blank()) +
  1608. stat_boxplot(
  1609. geom = "errorbar",
  1610. width = 0.15
  1611. ) +
  1612. geom_point(
  1613. position = position_jitternudge(
  1614. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1615. ), aes(color = Blank, shape = Blank),
  1616. size = 4.4, stroke = 0.2, alpha = 0.5
  1617. ) +
  1618. scale_shape_manual(values = c(19, 15)) +
  1619. geom_hline(yintercept = log(1.5), linetype = "dashed", color = "orange", size = 1)
  1620. DriftRate <- MasterDDM_sim %>% ggplot(aes(x = Blank, y = v.0., fill = Blank)) +
  1621. stat_slab(
  1622. side = "right", scale = 0.5, show.legend = F,
  1623. position = position_dodge(width = .8), alpha = 0.5,
  1624. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1625. ) +
  1626. scale_color_manual(values = c("#828283")) +
  1627. scale_fill_manual(values = c("#828283")) +
  1628. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1629. labs(title = " ") +
  1630. ylab("Drift rate (v)") +
  1631. xlab("") +
  1632. theme_minimal() +
  1633. theme(legend.position = "none", text = element_text(size = 14), axis.title.y = element_text(size = 17), strip.text = element_blank(), axis.text.x = element_blank()) +
  1634. stat_boxplot(
  1635. geom = "errorbar",
  1636. width = 0.15
  1637. ) +
  1638. geom_point(
  1639. position = position_jitternudge(
  1640. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1641. ), aes(color = Blank, shape = Blank),
  1642. size = 4.4, stroke = 0.2, alpha = 0.5
  1643. ) +
  1644. scale_shape_manual(values = c(19, 15)) +
  1645. geom_hline(yintercept = 0.5, linetype = "dashed", color = "orange", size = 1) +
  1646. ylim(NA, 2.9)
  1647. Dec <- MasterDDM_sim %>% ggplot(aes(x = Blank, y = asin(sqrt(MasterDDM_sim$t.0.)), fill = Blank)) +
  1648. stat_slab(
  1649. side = "right", scale = 0.5, show.legend = F,
  1650. position = position_dodge(width = .8), alpha = 0.5,
  1651. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1652. ) +
  1653. scale_color_manual(values = c("#828283")) +
  1654. scale_fill_manual(values = c("#828283")) +
  1655. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1656. labs(title = " ") +
  1657. ylab("Non-decision time (Ter)") +
  1658. xlab("") +
  1659. theme_minimal() +
  1660. theme(legend.position = "none", text = element_text(size = 14), axis.title.y = element_text(size = 17), strip.text = element_blank(), axis.text.x = element_blank()) +
  1661. stat_boxplot(
  1662. geom = "errorbar",
  1663. width = 0.15
  1664. ) +
  1665. geom_point(
  1666. position = position_jitternudge(
  1667. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1668. ), aes(color = Blank, shape = Blank),
  1669. size = 4.4, stroke = 0.2, alpha = 0.5
  1670. ) +
  1671. scale_shape_manual(values = c(19, 15)) +
  1672. geom_hline(yintercept = asin(sqrt(0.15)), linetype = "dashed", color = "orange", size = 1)
  1673. Non_Bias <- MasterDDM_sim %>% ggplot(aes(x = Blank, y = z_trans.0., fill = Blank)) +
  1674. stat_slab(
  1675. side = "right", scale = 0.5, show.legend = F,
  1676. position = position_dodge(width = .8), alpha = 0.5,
  1677. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1678. ) +
  1679. scale_color_manual(values = c("#828283")) +
  1680. scale_fill_manual(values = c("#828283")) +
  1681. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1682. labs(title = " ") +
  1683. ylab("Initial Choice Bias (z)") +
  1684. xlab("") +
  1685. theme_minimal() +
  1686. theme(legend.position = "none", text = element_text(size = 14), axis.title.y = element_text(size = 17), strip.text = element_blank(), axis.text.x = element_blank()) +
  1687. stat_boxplot(
  1688. geom = "errorbar",
  1689. width = 0.15
  1690. ) +
  1691. geom_point(
  1692. position = position_jitternudge(
  1693. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1694. ), aes(color = Blank, shape = Blank),
  1695. size = 4.4, stroke = 0.2, alpha = 0.5
  1696. ) +
  1697. scale_shape_manual(values = c(19, 15)) +
  1698. geom_hline(yintercept = 0.6681878, linetype = "dashed", color = "orange", size = 1)
  1699. var_v <- MasterDDM_sim %>% ggplot(aes(x = Blank, y = sz, fill = Blank)) +
  1700. stat_slab(
  1701. side = "right", scale = 0.5, show.legend = F,
  1702. position = position_dodge(width = .8), alpha = 0.5,
  1703. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1704. ) +
  1705. scale_color_manual(values = c("#828283")) +
  1706. scale_fill_manual(values = c("#828283")) +
  1707. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1708. labs(title = " ") +
  1709. ylab("Inter-trial bias variability (sz)") +
  1710. xlab("") +
  1711. theme_minimal() +
  1712. theme(legend.position = "none", text = element_text(size = 14), axis.title.y = element_text(size = 17), strip.text = element_blank(), axis.text.x = element_blank()) +
  1713. stat_boxplot(
  1714. geom = "errorbar",
  1715. width = 0.15
  1716. ) +
  1717. geom_point(
  1718. position = position_jitternudge(
  1719. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1720. ), aes(color = Blank, shape = Blank),
  1721. size = 4.4, stroke = 0.2, alpha = 0.5
  1722. ) +
  1723. scale_shape_manual(values = c(19, 15)) +
  1724. geom_hline(yintercept = 0.2, linetype = "dashed", color = "orange", size = 1)
  1725. var_ter <- MasterDDM_sim %>% ggplot(aes(x = Blank, y = st, fill = Blank)) +
  1726. stat_slab(
  1727. side = "right", scale = 0.5, show.legend = F,
  1728. position = position_dodge(width = .8), alpha = 0.5,
  1729. aes(fill_ramp = stat(level)), .width = c(.50, .95, 1)
  1730. ) +
  1731. scale_color_manual(values = c("#828283")) +
  1732. scale_fill_manual(values = c("#828283")) +
  1733. geom_boxplot(width = 0.2, outlier.shape = NA) +
  1734. labs(title = " ") +
  1735. ylab("Inter-trial non-decision time variability (st)") +
  1736. xlab("") +
  1737. theme_minimal() +
  1738. theme(legend.position = "none", text = element_text(size = 14), axis.title.y = element_text(size = 17), strip.text = element_blank(), axis.text.x = element_blank()) +
  1739. stat_boxplot(
  1740. geom = "errorbar",
  1741. width = 0.15
  1742. ) +
  1743. geom_point(
  1744. position = position_jitternudge(
  1745. jitter.width = 0.125, jitter.height = -0.3, nudge.x = -0.265, seed = 123
  1746. ), aes(color = Blank, shape = Blank),
  1747. size = 4.4, stroke = 0.2, alpha = 0.5
  1748. ) +
  1749. scale_shape_manual(values = c(19, 15)) +
  1750. geom_hline(yintercept = 0.2, linetype = "dashed", color = "orange", size = 1)
  1751. CombinedPlots2 <- plot_grid(BoundarySep, DriftRate, Dec, Non_Bias, var_v, var_ter, labels = c(""), label_size = 20)
  1752. ````
  1753. ```{r pressure, echo=FALSE}
  1754. ## Posterior predictive checks
  1755. setwd("C:/Users/micha/Desktop/Histamine_Learning_Data_and_Code/Behavioural_Data/Memory_Encoding_Task/DDM")
  1756. # Load and clean
  1757. real_data <- read_csv("Memory_Task_DDM.csv")
  1758. sim_data <- read_csv("posterior_predictive_simulation.csv")
  1759. # Label
  1760. real_data$Data_Type <- "Real"
  1761. sim_data$Data_Type <- "Simulated"
  1762. # Fix types
  1763. real_data <- real_data %>%
  1764. mutate(
  1765. correct = as.numeric(response == stim),
  1766. rt = as.numeric(rt),
  1767. stim = as.numeric(stim)
  1768. )
  1769. sim_data <- sim_data %>%
  1770. mutate(
  1771. correct = as.numeric(correct),
  1772. rt = as.numeric(rt),
  1773. stim = as.numeric(stim)
  1774. )
  1775. # Combine
  1776. all_data <- bind_rows(real_data, sim_data)
  1777. # Summarise per subject + stim
  1778. summary_data <- all_data %>%
  1779. group_by(subj_idx, stim, Data_Type) %>%
  1780. summarise(
  1781. mean_rt = mean(rt, na.rm = TRUE),
  1782. accuracy = mean(correct, na.rm = TRUE),
  1783. .groups = "drop"
  1784. )
  1785. # Plot
  1786. one <- ggplot(summary_data, aes(x = mean_rt, fill = Data_Type, linetype = Data_Type)) +
  1787. geom_density(alpha = 0.4) +
  1788. facet_wrap(~stim) +
  1789. xlab("\nTime to Choice (ms)\n") +
  1790. ylab("\nP(Density)\n") +
  1791. theme(legend.position = "none", text = element_text(size = 14), axis.title = element_text(size = 16)) +
  1792. theme_minimal()
  1793. two <- ggplot(summary_data, aes(x = accuracy, fill = Data_Type, linetype = Data_Type)) +
  1794. geom_density(alpha = 0.4) +
  1795. facet_wrap(~stim) +
  1796. xlab("\nOverall Accuracy\n") +
  1797. ylab("\nP(Density)\n") +
  1798. theme(legend.position = "none", text = element_text(size = 14), axis.title = element_text(size = 16)) +
  1799. theme_minimal()
  1800. combined <- plot_grid(one, two, cols = 1)
  1801. ````
  1802. ```{r b0, echo=FALSE, include=TRUE}
  1803. # Metachecks - checking RL task parameters and relationship with DDM parameters (see Supplementary Note 8, final paragraph).
  1804. setwd("C:/Users/micha/Desktop/Histamine_Learning_Data_and_Code/Behavioural_Data/Memory_Encoding_Task/DDM")
  1805. # Load and clean
  1806. RL_ddm <- read_csv("Meta_DDM_3.csv")
  1807. collapsed_df <- RL_ddm %>%
  1808. group_by(Participant.ID) %>%
  1809. summarise(across(c(LR_recipmodel, inv_recipmodel, Excl_LR, Excl_Inv), mean, na.rm = TRUE))
  1810. n_back_ddm <- read_csv("Meta_DDM_2.csv")
  1811. memory_ddm <- read_csv("Meta_DDM_1.csv")
  1812. Merged_1 <- merge(collapsed_df, n_back_ddm, by = "Participant.ID")
  1813. Merged_DDM_Meta <- merge(Merged_1, memory_ddm, by = "Participant.ID")
  1814. win_df <- RL_ddm %>%
  1815. filter(Trial_type == "Win") %>%
  1816. group_by(Participant.ID) %>%
  1817. summarise(across(c(LR_recipmodel, inv_recipmodel, Excl_LR, Excl_Inv), mean, na.rm = TRUE))
  1818. loss_df <- RL_ddm %>%
  1819. filter(Trial_type == "Loss") %>%
  1820. group_by(Participant.ID) %>%
  1821. summarise(across(c(LR_recipmodel, inv_recipmodel, Excl_LR, Excl_Inv), mean, na.rm = TRUE))
  1822. Merged_1 <- merge(win_df, n_back_ddm, by = "Participant.ID")
  1823. Merged_2 <- merge(loss_df, Merged_1, by = "Participant.ID")
  1824. Merged_DDM_Meta <- merge(Merged_2, memory_ddm, by = "Participant.ID")
  1825. ## LM analysis - working memory params
  1826. # Win trials - LR ~ working memory DDM
  1827. med.fit <- lm(LR_recipmodel.x ~ v_ddm, data = Merged_DDM_Meta)
  1828. summary(med.fit)
  1829. # Win trials - inv. decision temp ~ working memory drift rate
  1830. med.fit <- lm(inv_recipmodel.x ~ v_ddm, data = Merged_DDM_Meta)
  1831. summary(med.fit)
  1832. ###
  1833. # Loss trials - LR ~ working memory ddm
  1834. med.fit <- lm(LR_recipmodel.y ~ v_ddm, data = Merged_DDM_Meta)
  1835. summary(med.fit)
  1836. # Loss trials - inv. decision temp ~ working memory ddm
  1837. med.fit <- lm(inv_recipmodel.y ~ v_ddm, data = Merged_DDM_Meta)
  1838. summary(med.fit)
  1839. ####################
  1840. ## LM analysis - memory recognition drift rate
  1841. #Average v across unseen and distractor conditions to simplify analysis
  1842. Merged_DDM_Meta$avg_v <- (Merged_DDM_Meta$`v(0)` + Merged_DDM_Meta$`v(1)`) / 2
  1843. # Win trials - LR ~ v
  1844. med.fit <- lm(LR_recipmodel.x ~ avg_v, data = Merged_DDM_Meta)
  1845. summary(med.fit)
  1846. # Win trials - inv. decision temp ~ v
  1847. med.fit <- lm(inv_recipmodel.x ~ avg_v, data = Merged_DDM_Meta)
  1848. summary(med.fit)
  1849. ####
  1850. # Loss trials - LR ~ v
  1851. med.fit <- lm(LR_recipmodel.y ~ avg_v, data = Merged_DDM_Meta)
  1852. summary(med.fit)
  1853. # Loss trials - inv. decision temp ~ v
  1854. med.fit <- lm(inv_recipmodel.y ~ avg_v, data = Merged_DDM_Meta)
  1855. summary(med.fit)
  1856. ##################################################################
  1857. ````

Memory_Encoding_Behavioural_Prep_and_Analysis.Rmd at commit 9a45767, under MPL-2.0 · at the source

Overview

Authors: Michael J. Colwell1,2, Fin J. E. van Uum1,2, Philip J. Cowen1,2, Marieke A. G. Martens1,2, Michael Browning1,2, Helen C. Barron3,4,5, Catherine J. Harmer1,2, Susannah E. Murphy1,2
  1. University Department of Psychiatry, University of Oxford, Warneford Hospital,Oxford, UK
  2. Oxford Health NHS Foundation Trust, Warneford Hospital,Oxford, UK
  3. Brain Network Dynamics Unit, Nuffield Department of Clinical Neurosciences, University of Oxford,Oxford, UK
  4. Medical Research Council Centre of Research Excellence in Restorative Neural Dynamics, University of Oxford,Oxford, UK
  5. Oxford University Centre for Integrative Neuroimaging, FMRIB, Nuffield Department of Clinical Neurosciences, University of Oxford,Oxford, UK
Institutions: Warneford Hospital (United Kingdom); University of Oxford (United Kingdom)
Journal: Nature communications, volume 17, issue 1, article 7124
Dates: received 17 March 2026; accepted 15 May 2026; published online 2 June 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41467-026-73865-9 · PMID 42230645 · PMCID PMC13396361 · OpenAlex W7163278866
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: human (organism), cognitive (subfield)
Methods: Connectivity, Statistics, Smoothing, state filtering, decompositions, Machine learning, fMRI & imaging, Physiology & signal measures, Preprocessing
Keywords: Computational neuroscience, Cognitive neuroscience, Neurotransmitters, Learning and memory, Human behaviour
MeSH: Hippocampus*, Histamine*, Learning*, Adult, Female, Humans, Male, Memory, Short-Term, Piperidines (* major topic)
Topic: Mast cells and histamine (Immunology, Immunology and Microbiology), according to OpenAlex
Citations: not cited yet (Europe PMC); 179 references in the paper

Abstract

Histamine was the first canonical monoamine identified in the mammalian brain, yet arguably remains the least understood in its mechanistic contributions to human behaviour. Using a first-in-class causal probe (H3R inverse agonist pitolisant), we show how elevating histamine shapes offline and online temporal–hippocampal dynamics — sustaining episodic learning-related activity and polarising retrieval computations. Beyond this, histamine adaptively shifts neurocomputational strategy under high working memory load, while stabilising value updates during aversive reinforcement learning. These findings uncover a mechanistically grounded influence of this underexplored system on human neurocomputation, supporting its therapeutic potential in psychiatry.

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 12 matches between paragraphs and lines of code.

mjcolwell/n-back_oxford

License: MIT
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 8637a86cf4bfb0388db245767a14f23a3ca76ea1, 19 August 2025
Languages: Python (4), R (1)
Size: 87 files, 5 scripts
Software Heritage: archived
Found in: the text, “fMRI memory and learning task paradigms”
Holds: README, license file, 1 notebook
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: NumPy (2 files), PsychoPy (2 files), data.table (1 file), emmeans (1 file), ggpubr (1 file), pandas (1 file), rstatix (1 file), tidyverse (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
7 files

mjcolwell/Histamine_Learning_Data_and_Code

License: MPL-2.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 9a45767b9904cb3dc581afb503de2d1da68a7b3a, 5 June 2026
Languages: MATLAB (9), R (8), Jupyter (2), Python (1)
Size: 659 files, 20 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file, 10 notebooks
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: car (8 files), cowplot (8 files), data.table (8 files), easystats (8 files), emmeans (8 files), ggplot2 (8 files), ggpubr (8 files), lme4 (8 files), lmerTest (8 files), rstatix (8 files), tidyverse (8 files), BayesFactor (3 files), brms (3 files), broom (3 files), Matplotlib (3 files), NumPy (3 files), ArviZ (2 files), pandas (2 files), seaborn (2 files), FSL (1 file), metafor (1 file), SciPy (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
22 files

Zenodo 19861591

License: CC-BY-4.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: car (8 files), cowplot (8 files), data.table (8 files), easystats (8 files), emmeans (8 files), ggplot2 (8 files), ggpubr (8 files), lme4 (8 files), lmerTest (8 files), rstatix (8 files), tidyverse (8 files), BayesFactor (3 files), brms (3 files), broom (3 files), Matplotlib (3 files), NumPy (3 files), ArviZ (2 files), pandas (2 files), seaborn (2 files), FSL (1 file), metafor (1 file), SciPy (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
22 files
At the source:

Code availability

The code used to undertake preprocessing, network analysis, computational modelling and inferential modelling are available on Zenodo179 and Github: https://github.com/mjcolwell/Histamine_Learning_Data_and_Code.

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;
  • 45 scripts, each with its path and the digest of its content;
  • 12 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

The raw and modelled data generated for this study have been deposited on Zenodo179 and Github: https://github.com/mjcolwell/Histamine_Learning_Data_and_Code.

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 2, 28 September 2026

  • Funding: added UK Research and Innovation: MR/W008939/1; National Institute for Health and Care Research; University of Oxford

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 8 authors, 5 keywords, 9 MeSH terms, 174 references.

Cite

This paper

Colwell, M. J., van Uum, F. J. E., Cowen, P. J., Martens, M. A. G., Browning, M., Barron, H. C., Harmer, C. J., & Murphy, S. E. (2026). Histamine shapes the neurocomputational dynamics of human learning. Nature communications, 17(1), 7124. https://doi.org/10.1038/s41467-026-73865-9

BibTeX

@article{colwell2026histamine,
author = {Colwell, Michael J. and van Uum, Fin J. E. and Cowen, Philip J. and Martens, Marieke A. G. and Browning, Michael and Barron, Helen C. and Harmer, Catherine J. and Murphy, Susannah E.},
title = {{Histamine shapes the neurocomputational dynamics of human learning}},
journal = {Nature communications},
year = {2026},
month = jun,
volume = {17},
number = {1},
pages = {7124},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-73865-9},
url = {https://doi.org/10.1038/s41467-026-73865-9},
pmid = {42230645},
pmcid = {PMC13396361}
}

RIS

TY - JOUR
AU - Colwell, Michael J.
AU - van Uum, Fin J. E.
AU - Cowen, Philip J.
AU - Martens, Marieke A. G.
AU - Browning, Michael
AU - Barron, Helen C.
AU - Harmer, Catherine J.
AU - Murphy, Susannah E.
TI - Histamine shapes the neurocomputational dynamics of human learning
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/06/02
VL - 17
IS - 1
SP - 7124
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-73865-9
UR - https://doi.org/10.1038/s41467-026-73865-9
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-73865-9",
"type": "article-journal",
"title": "Histamine shapes the neurocomputational dynamics of human learning",
"container-title": "Nature communications",
"author": [
{
"family": "Colwell",
"given": "Michael J."
},
{
"family": "van Uum",
"given": "Fin J. E."
},
{
"family": "Cowen",
"given": "Philip J."
},
{
"family": "Martens",
"given": "Marieke A. G."
},
{
"family": "Browning",
"given": "Michael"
},
{
"family": "Barron",
"given": "Helen C."
},
{
"family": "Harmer",
"given": "Catherine J."
},
{
"family": "Murphy",
"given": "Susannah E."
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "7124",
"DOI": "10.1038/s41467-026-73865-9",
"PMID": "42230645",
"PMCID": "PMC13396361",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-73865-9",
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
2
]
]
}
}

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/s41398-026-04141-z [code]
Effects on hippocampal activity following novel 5-HT4 receptor agonism in unmedicated patients with depression: the RESTAND study.
Journal: Translational psychiatry
In common: rstatix, car, easystats, 6 other tools, 3 references, 2 authors
[2] doi:10.1523/eneuro.0076-26.2026 [code]
Exogenously Driven Neural Reactivation of Spatially Matching Visual Working-Memory Contents.
Journal: eNeuro
In common: BayesFactor, PsychoPy, brms, 13 other tools, cognitive
[3] doi:10.1073/pnas.2603114123 [code]
The human hippocampus can pattern separate memories by meaning.
Journal: Proceedings of the National Academy of Sciences of the United States of America
In common: PsychoPy, rstatix, easystats, 12 other tools, cognitive, 2 references
[4] doi:10.1192/bjp.2026.10664 [code]
Early effects of a novel 5-HT&lt;sub&gt;4&lt;/sub&gt;R agonist (PF-04995274) and the SSRI citalopram on emotional cognition in unmedicated depression: RESTAND study.
Journal: The British journal of psychiatry : the journal of mental science
In common: rstatix, car, easystats, 6 other tools, cognitive, 2 references, author Philip J Cowen
[5] doi:10.1093/nc/niag029 [code]
A data-driven approach to identifying and evaluating connectivity-based neural correlates of conscious visual perception.
Journal: Neuroscience of consciousness
In common: BayesFactor, car, easystats, 13 other tools, cognitive
[6] doi:10.1016/j.celrep.2026.117505 [code]
Impaired spatial coding and neuronal hyperactivity in the medial entorhinal cortex of aged APP knock-in mice.
Journal: Cell reports
In common: metafor, brms, car, 10 other tools
[7] doi:10.1093/bioinformatics/btag592 [code]
Network-based stratification of allele-specific expression reveals patient subgroups in Huntington's disease.
Journal: Bioinformatics (Oxford, England)
In common: rstatix, car, broom, 12 other tools
[8] doi:10.1162/imag.a.1321 [code]
Phase similarity between similar objects indicates representational merging across retrieval training but not sleep.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: rstatix, car, easystats, 11 other tools, cognitive
[9] doi:10.1038/s41467-026-74565-0 [code]
The functional neurobiology of dispositions towards negative emotions.
Journal: Nature communications
In common: metafor, BayesFactor, brms, 9 other tools, cognitive
[10] doi:10.1038/s41597-026-07377-y [code]
An open-access multi-site fMRI dataset for investigating conscious visual perception.
Journal: Scientific data
In common: BayesFactor, car, easystats, 10 other tools, 1 reference

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.