The human hippocampus can pattern separate memories by meaning.
The 9 matches
- [1] § Behavioral Methods › Materials. › Covariate assessments. ↔ scripts/smst2_bids_participants_maker.py, lines 191–215 · score 0.70 · WAIS IV, Digit Symbol, subtests, Vocabulary, covariate, words
- [2] § Behavioral Methods › MRI Methods. › Hippocampal subfield segmentation. ↔ scripts/smst_mr1_HCmask_snapshot.sh, lines 1–50 · score 0.64 · coronal slices, template T1, brain, masks, SI
- [3] § Behavioral Methods › Materials. › Main task (sMST). › Stimuli. ↔ scripts/smst2_bids_tsv_maker.py, lines 303–386 · score 0.63 · Hungarian National Corpus, imageability, metric, arousal, concreteness, fillers
- [4] § Behavioral Methods › MRI Methods. › Analysis. ↔ scripts/smst_mr1_analysis.Rmd, lines 156–247 · score 0.61 · close lure, distant lure, lure correct, incorrect, hits, foil
- [5] § Results › RS Sensitive Clusters in the Hippocampal Head Differentially Activate for Exact Repeats and Modified Repeats During Encoding. ↔ scripts/smst_mr1_analysis.Rmd, lines 2190–2332 · score 0.61 · DG CA3, right hemisphere, left hemisphere, CA12, ROI, Facets
- [6] § Results › Neural Response Is Increased for Semantically Close Modified Phrases Compared to Exact Repetitions, with No Further Difference between Semantic Similarity Bins. ↔ scripts/smst_mr1_analysis.Rmd, lines 2190–2332 · score 0.54 · DG CA3, distant repeats, CA1, anatomically, ANOVA, head
- [7] § Behavioral Methods › Analysis. ↔ scripts/smst_mr1_analysis.Rmd, lines 398–440 · score 0.54 · Wald, confint, intercept, arousal, concreteness, GLMEMs
- [8] § Results › RS Sensitive Clusters in the Hippocampal Head Differentially Activate for Exact Repeats and Modified Repeats During Encoding. ↔ scripts/smst_mr1_analysis.Rmd, lines 442–540 · score 0.53 · Post hoc, covariate, clusters, encoding
- [9] § Results › Clusters Sensitive to Repetition at Encoding Do Not Track Mnemonic Discrimination Success within Lures but Differentiate Correctly Rejected Lures from Correctly Rejected Foils During Recogni ↔ scripts/smst_mr1_analysis.Rmd, lines 3552–3596 · score 0.50 · lure correct rejections, target hits, modified repeat, baseline, clusters
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 · 5,188 lines · 155 KB · no license · 6 matches
- ---
- title: "Analysis pipeline for the behavioral and functional MRI data from the semantic Mnemonic Similarity Task"
- output: html_document
- editor_options:
- chunk_output_type: console
- ---
- # Glossary & packages
- ENC = Encoding task phase
- REC = Recognition task phase
- RS = repetition suppression (first presentation - repeat)
- PS = pattern separation (hippocampal operation)
- MD = mnemonic discrimination (behavioural correlate)
- LDI = lure discrimination index (proxy of MD)
- ```{r}
- knitr::opts_chunk$set(echo = TRUE)
- library(ppcor)
- library(tidyverse)
- library(tidytuesdayR)
- library(readxl)
- library(tidyr)
- library(scales)
- library(ggplot2)
- library(psycho)
- library(ggpubr)
- library(rstatix)
- library(afex)
- library(MuMIn)
- library(lme4)
- library(lmerTest)
- library(ggstatsplot)
- library(sjPlot)
- library(smplot2)
- library(openxlsx)
- library(stats)
- library(performance)
- library(emmeans)
- library(purrr)
- library(broom)
- library(ggpattern)
- library(ggtext)
- library(dplyr)
- library(ppcor)
- library(readr)
- library(stringr)
- library(grid)
- library(gridExtra)
- library(gtable)
- library(patchwork)
- theme_set(theme_light())
- custom_theme = theme(
- plot.title = element_text(color="black", size=30, face="bold", hjust = 0, vjust = 3), #30 for covariate plots
- axis.text.x = element_text(vjust = 0.5, hjust=0.5, size = 20, face="bold"), #was 16 for other plots besides rec resp rate
- axis.text.y = element_text(vjust = 0.5, hjust=0.5, size = 20, face="bold"),
- axis.title.x = element_text(vjust = -2, hjust=0.5, size = 26, face="bold"),
- axis.title.y = element_text(vjust = 3, hjust=0.5, size = 26, face="bold"),
- legend.text = element_text(vjust = 0.5, hjust=0.5, size = 22, face="bold"),
- legend.title = element_text(vjust = 0.5, hjust=0.5, size = 24, face="bold"),
- strip.text = element_text(vjust = 0.5, hjust=0.5, size = 22, face="bold"),
- plot.margin = margin(30, 30, 30, 30),
- panel.grid.major = element_blank(),
- panel.grid.minor = element_blank(),
- panel.background = element_blank(),
- axis.line = element_line(colour = "black")
- )
- ```
- # Data handling
- ## Read-in MR
- ```{r}
- semmst_mr_data = read.xlsx("./data/fmri/ses-01/subfield_data_featquery_2025.xlsx")
- ```
- ## Preprocess MR
- ```{r}
- semmst_mr_data_filtered = semmst_mr_data %>%
- dplyr::select(-c(cope_num, query_type, groupanalysis_type)) %>%
- dplyr::rename(ID = subject) %>%
- mutate(
- ID = as.factor(ID),
- space_type = as.factor(space_type),
- task = as.factor(task),
- cope_name = as.factor(cope_name),
- hemisphere = as.factor(hemisphere),
- roi = as.factor(roi),
- mask_type = as.factor(mask_type),
- contrast = as.factor(contrast),
- cluster = as.factor(cluster),
- estimate = as.numeric(estimate),
- )
- ```
- ## Read-in behavior
- ```{r}
- semmst_behav_data <- read_xlsx("./data/behavioural/smst/smst_mr_behvaioural_grand.xlsx")
- ```
- ## Preprocess behavior
- ```{r}
- # Clean and factorize
- semmst_behav_data_filtered <- semmst_behav_data %>%
- dplyr::rename(ID = participant_id) %>%
- mutate(ID = factor(str_c("sub-", ID)),
- task = factor(task, levels = c("enc", "rec")),
- run = factor(run),
- trial_type = factor(trial_type),
- stim_file = factor(stim_file),
- itemno = factor(itemno),
- order = factor(order),
- response = tolower(response),
- sex = factor(sex, levels = c("male", "female")),
- handedness = factor(handedness, levels = "R"),
- response_time = as.numeric(response_time),
- onset = as.numeric(onset),
- correctness = factor(correctness)) %>%
- filter(ID %in% semmst_mr_data_filtered$ID)
- semmst_mr_behav_data_enc <- semmst_behav_data_filtered %>%
- filter(task == "enc",
- trial_type != "FILLER") %>%
- mutate(former_type = ifelse(trial_type=="REPEAT", "TARGET", "LURE")) %>%
- dplyr::select(ID, noun, former_type) %>%
- distinct()
- semmst_mr_behav_data_rec <- semmst_behav_data_filtered %>%
- filter(task == "rec",
- !is.na(response)) %>%
- left_join(semmst_mr_behav_data_enc, by = c("ID", "noun") ) %>%
- mutate(response = factor(response, levels=c("old", "new"))) %>%
- mutate(trial_type = factor(trial_type)) %>%
- mutate(former_type = factor(former_type)) %>%
- mutate(correctness = factor(correctness, levels=c(0,1)))
- ```
- ### LDI
- ```{r}
- semmst_behav_data_rec_filtered = semmst_mr_behav_data_rec %>%
- filter(task == "rec") %>%
- filter(response != "None") %>%
- mutate(response = as.factor(response))
- semmst_behav_data_rec_wide_dprime = semmst_behav_data_rec_filtered %>%
- dplyr::count(ID, trial_type, response) %>%
- unite("trial_resp", c("trial_type", "response"), sep = "_") %>%
- spread(trial_resp, n) %>%
- mutate_at(vars(matches("_")), ~ifelse(is.na(.), 0, .)) %>%
- mutate(targ_n = TARGET_new + TARGET_old) %>%
- mutate(close_n = CLOSE_new + CLOSE_old) %>%
- mutate(distant_n = DISTANT_new + DISTANT_old) %>%
- mutate(foil_n = FOIL_new + FOIL_old) %>%
- mutate(LURE_old = CLOSE_old + DISTANT_old) %>%
- mutate(LURE_new = CLOSE_new + DISTANT_new) %>%
- mutate(lure_n = LURE_new + LURE_old)
- # Simple recognition - TARG vs FOIL
- rec_dprime <- psycho::dprime(
- n_hit = semmst_behav_data_rec_wide_dprime$TARGET_old,
- n_fa = semmst_behav_data_rec_wide_dprime$FOIL_old,
- n_miss = semmst_behav_data_rec_wide_dprime$TARGET_new,
- n_cr = semmst_behav_data_rec_wide_dprime$FOIL_new,
- n_targets = semmst_behav_data_rec_wide_dprime$targ_n,
- n_distractors = semmst_behav_data_rec_wide_dprime$foil_n,
- adjusted = TRUE
- )
- # Close lure discrimination - TARG vs CLOSE
- close_dprime <- psycho::dprime(
- n_hit = semmst_behav_data_rec_wide_dprime$TARGET_old,
- n_fa = semmst_behav_data_rec_wide_dprime$CLOSE_old,
- n_miss = semmst_behav_data_rec_wide_dprime$TARGET_new,
- n_cr = semmst_behav_data_rec_wide_dprime$CLOSE_new,
- n_targets = semmst_behav_data_rec_wide_dprime$targ_n,
- n_distractors = semmst_behav_data_rec_wide_dprime$close_n,
- adjusted = TRUE
- )
- # Distant lure discrimination - TARG vs DISTANT
- dist_dprime <- psycho::dprime(
- n_hit = semmst_behav_data_rec_wide_dprime$TARGET_old,
- n_fa = semmst_behav_data_rec_wide_dprime$DISTANT_old,
- n_miss = semmst_behav_data_rec_wide_dprime$TARGET_new,
- n_cr = semmst_behav_data_rec_wide_dprime$DISTANT_new,
- n_targets = semmst_behav_data_rec_wide_dprime$targ_n,
- n_distractors = semmst_behav_data_rec_wide_dprime$distant_n,
- adjusted = TRUE
- )
- # All lure discrimination - TARG vs LURE
- lure_dprime <- psycho::dprime(
- n_hit = semmst_behav_data_rec_wide_dprime$TARGET_old,
- n_fa = semmst_behav_data_rec_wide_dprime$LURE_old,
- n_miss = semmst_behav_data_rec_wide_dprime$TARGET_new,
- n_cr = semmst_behav_data_rec_wide_dprime$LURE_new,
- n_targets = semmst_behav_data_rec_wide_dprime$targ_n,
- n_distractors = semmst_behav_data_rec_wide_dprime$lure_n,
- adjusted = TRUE
- )
- semmst_behav_data_rec_summary <- semmst_behav_data_rec_wide_dprime %>%
- transmute(
- ID,
- # Recognition
- rec_dprime = rec_dprime$dprime,
- rec_correct = (TARGET_old) / (targ_n),
- rec_incorrect = (TARGET_new) / (targ_n),
- # Close LDI
- close_dprime = close_dprime$dprime,
- close_correct = (CLOSE_new) / (close_n),
- close_incorrect= (CLOSE_old) / (close_n),
- # Distant LDI
- distant_dprime = dist_dprime$dprime,
- distant_correct = (DISTANT_new) / (distant_n),
- distant_incorrect= (DISTANT_old) / (distant_n),
- # Lure LDI
- lure_dprime = lure_dprime$dprime,
- lure_correct = (LURE_new) / (lure_n),
- lure_incorrect= (LURE_old) / (lure_n),
- )
- ```
- ## Merge
- ```{r}
- semmst_merged_data <- semmst_mr_data_filtered %>%
- left_join(
- semmst_behav_data_filtered %>%
- dplyr::select(ID, sex:GRO_score_SES02) %>%
- distinct(ID, .keep_all = TRUE),
- by = "ID"
- ) %>%
- left_join(semmst_behav_data_rec_summary, by = "ID") %>%
- droplevels()
- ```
- ## FILTER for HYPOTHESIS TESTING
- ```{r}
- # REPETITION SENSTIVITY
- semmst_merged_data_filtered = semmst_merged_data %>%
- filter(contrast %in% c("ENC_ERP_ALLRS")) %>%
- filter(space_type == "standard") %>%
- filter(voxels > 50) %>%
- filter(as.numeric(as.character(cluster)) < 140) %>%
- mutate(roi_cluster = paste(hemisphere, roi, cluster, sep = "_")) %>%
- mutate(roi_hemisphere = paste(hemisphere, roi, sep = "_")) %>%
- mutate(Vocabulary_scale = scale(Vocabulary)) %>%
- mutate(Digit_Symbol_scale = scale(Digit_Symbol)) %>%
- mutate(NonWord_sum_scale = scale(NonWord_sum))
- # ANATOMY CONTROL
- semmst_merged_data_filtered_anat = semmst_merged_data %>%
- filter(contrast %in% c("anatHC")) %>%
- mutate(roi_cluster = paste(hemisphere, roi, cluster, sep = "_")) %>%
- mutate(roi_hemisphere = paste(hemisphere, roi, sep = "_")) %>%
- mutate(Vocabulary_scale = scale(Vocabulary)) %>%
- mutate(Digit_Symbol_scale = scale(Digit_Symbol)) %>%
- mutate(NonWord_sum_scale = scale(NonWord_sum))
- ```
- # Revision data handling - read-in, filter and merge
- ```{r}
- # Read in
- semmst_mr_data_supplement = read.xlsx("./data/fmri/ses-01/subfield_data_featquery_supplement.xlsx")
- # Filter
- semmst_mr_data_supplement_filtered = semmst_mr_data_supplement %>%
- dplyr::select(-any_of(c("cope_num", "query_type", "groupanalysis_type"))) %>%
- dplyr::rename(ID = subject) %>%
- mutate(
- ID = as.factor(ID),
- space_type = as.factor(space_type),
- task = as.factor(task),
- cope_name = as.factor(cope_name),
- hemisphere = as.factor(hemisphere),
- roi = as.factor(roi),
- mask_type = as.factor(mask_type),
- contrast = as.factor(contrast),
- cluster = as.factor(cluster),
- estimate = as.numeric(estimate)
- )
- # Merge
- semmst_merged_data_supplement <- semmst_mr_data_supplement_filtered %>%
- left_join(
- semmst_behav_data_filtered %>%
- dplyr::select(ID, sex:GRO_score_SES02) %>%
- distinct(ID, .keep_all = TRUE),
- by = "ID"
- ) %>%
- left_join(semmst_behav_data_rec_summary, by = "ID") %>%
- droplevels()
- ```
- ## CLEAN
- ```{r}
- semmst_merged_data_supplement_filtered = semmst_merged_data_supplement %>%
- mutate(roi_cluster = paste(hemisphere, roi, cluster, sep = "_")) %>%
- mutate(roi_hemisphere = paste(hemisphere, roi, sep = "_")) %>%
- mutate(Vocabulary_scale = scale(Vocabulary)) %>%
- mutate(Digit_Symbol_scale = scale(Digit_Symbol)) %>%
- mutate(NonWord_sum_scale = scale(NonWord_sum))
- ```
- # Results
- ## Analysis 1 - Behavioural
- ### ANOVA on LDI
- ```{r}
- semmst_behav_data_rec_LDI_ANCOVA = semmst_behav_data_rec_LDI_ANOVA %>%
- left_join(semmst_behav_data_rec_filtered %>% dplyr::select(ID, age, sex, education, Vocabulary, Digit_Symbol, NonWord_sum) %>% distinct(), by="ID") %>%
- mutate(Vocabulary_scale = scale(Vocabulary)) %>%
- mutate(Digit_Symbol_scale = scale(Digit_Symbol)) %>%
- mutate(NonWord_sum_scale = scale(NonWord_sum)) %>% drop_na()
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_behav_data_rec_LDI_ANCOVA %>%
- group_by(dprime_type) %>%
- identify_outliers(dprime_value)
- ##NORMALITY
- semmst_behav_data_rec_LDI_ANCOVA %>%
- group_by(dprime_type) %>%
- shapiro_test(dprime_value) %>% print(n=40)
- ggqqplot(semmst_behav_data_rec_LDI_ANCOVA, "dprime_value", ggtheme = theme_bw()) +
- facet_grid(. ~ dprime_type, labeller = "label_both")
- # ANCOVA
- ANCOVA_behav_data_rec_LDI = semmst_behav_data_rec_LDI_ANCOVA %>%
- anova_test(dv = dprime_value, wid = ID, within = c(dprime_type), covariate = c(sex, age, Vocabulary_scale, Digit_Symbol_scale, NonWord_sum_scale))
- get_anova_table(ANCOVA_behav_data_rec_LDI)
- # POST-HOC
- semmst_behav_data_rec_LDI_ANCOVA_PWC = semmst_behav_data_rec_LDI_ANCOVA %>%
- pairwise_t_test(
- dprime_value ~ dprime_type,
- paired = TRUE,
- detailed = TRUE
- ) %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_behav_data_rec_LDI_ANCOVA_PWC %>%
- dplyr::select(-c(alternative, method, .y.)) %>%
- print(n = 50)
- # REPORT
- ## dprime_type 174.597 <0.001 *** 0.582000
- ## NonWord_sum_scale 8.346 0.008 ** 0.229000
- ## Digit_Symbol_scale:dprime_type 3.593 0.035 * 0.028000
- ```
- ### GLMEM: semantic similarity ~ response
- ```{r}
- semmst_behav_data_rec_filtered_GLMEM <- semmst_behav_data_rec_filtered %>%
- mutate(across(all_of(c("Vocabulary", "Digit_Symbol", "NonWord_sum", "arousal", "concreteness", "imageability", "meaningfulness")),
- ~ as.numeric(scale(.x)), # drop scale() attributes
- .names = "{.col}_scale")) %>%
- drop_na(Vocabulary) %>%
- mutate(response = relevel(response, ref = "new"))
- semmst_behav_data_rec_filtered_GLMEM_lure = semmst_behav_data_rec_filtered_GLMEM %>%
- filter(trial_type %in% c("CLOSE", "DISTANT"))
- model_simple_cont = glmer(response ~ cosine * trial_type * former_type +
- (1|ID) +
- (1|itemno),
- family = binomial("probit"),
- data = semmst_behav_data_rec_filtered_GLMEM_lure,
- control = glmerControl(optimizer ='bobyqa', optCtrl=list(maxfun = 20000)), nAGQ=0)
- model_complex_cont = glmer(response ~ cosine * trial_type * former_type +
- age + sex + education + Vocabulary_scale + Digit_Symbol_scale +
- NonWord_sum_scale + arousal_scale + meaningfulness_scale + concreteness_scale +
- (1|ID) +
- (1|itemno),
- family = binomial("probit"),
- data = semmst_behav_data_rec_filtered_GLMEM_lure,
- control = glmerControl(optimizer ='bobyqa', optCtrl=list(maxfun = 20000)), nAGQ=0)
- anova(model_simple_cont, model_complex_cont)
- summary(model_complex_cont)
- confint(model_complex_cont, parm="beta_", method="Wald")
- # REPORT Estimate Std. Error z value Pr(>|z|) 2.5 % 97.5 % (Intercept)
- ## cosine 5.131681 1.806091 2.841 0.00449 ** -7.444086424 -0.35150302
- ## NonWord_sum_scale -0.213690 0.069192 -3.088 0.00201 ** -0.349304360 -0.07807487
- ## meaningfulness_scale 0.145144 0.073066 1.986 0.04698 * 0.001936827 0.28835127
- ## trial_typeDISTANT 2.011234 1.931225 1.041 0.29768
- ## former_typeTARGET -1.376078 1.970692 -0.698 0.48501
- ```
- ## Analysis 2 - ENC RS
- ### ANOVA - REPEAT vs. LURE
- ```{r}
- # FILTER DATA
- semmst_merged_data_H1 = semmst_merged_data_filtered %>%
- filter(task == "Encoding") %>%
- filter(cope_name %in% c("LureFirst", "ExactFirst", "LureRepeat", "ExactRepeat")) %>%
- extract(
- col = cope_name,
- into = c("stim_type", "order"),
- regex = "([A-Za-z]+?)(First|Repeat)$"
- ) %>%
- mutate(
- stim_type = as.factor(stim_type),
- order = as.factor(order)
- ) %>%
- mutate(stim_type = factor(stim_type, levels = c("Exact", "Lure")))
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_merged_data_H1 %>%
- group_by(stim_type, order, roi_cluster) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, is.outlier, is.extreme) %>%
- filter(is.extreme==TRUE)
- semmst_merged_data_H1_nooutlier = semmst_merged_data_H1 %>%
- group_by(stim_type, order, roi_cluster) %>%
- filter(! ID %in% c("sub-434971")) %>% #, " sub-012421", "sub-632012", "sub-800472")) %>% # c("sub-434971", "sub-982347")) %>%
- drop_na(NonWord_sum_scale) %>%
- ungroup()
- ##NORMALITY
- semmst_merged_data_H1_nooutlier %>%
- group_by(stim_type, order) %>%
- shapiro_test(estimate)
- # ANOVA
- semmst_merged_data_H1_nooutlier_AOV = semmst_merged_data_H1_nooutlier %>%
- anova_test(dv = estimate, wid = ID, within = c(stim_type, order, roi_cluster), covariate = c(NonWord_sum_scale, Digit_Symbol_scale))
- get_anova_table(semmst_merged_data_H1_nooutlier_AOV)
- # REPORT Effect DFn DFd F p p<.05 ges
- ## 3 stim_type 1 25 16.271 4.54e-04 * 4.50e-02
- ## 4 order 1 25 50.948 1.76e-07 * 1.41e-01
- ## 4 stim_type:order 1 25 12.810 1.00e-03 * 3.20e-02
- ## 6 order:roi_cluster 1 25 5.677 2.50e-02 * 6.00e-03
- # COVARIATES
- ## 16 Digit_Symbol_scale:stim_type:order 1 25 6.123 2.00e-02 * 1.60e-02
- ## 19 NonWord_sum_scale:order:roi_cluster 1 25 9.266 5.00e-03 * 1.00e-02
- # POST-HOC
- # pairwise comparisons - stim_type * order
- semmst_merged_data_H1_nooutlier_PWC = semmst_merged_data_H1_nooutlier %>%
- drop_na(Digit_Symbol) %>%
- group_by(stim_type) %>%
- pairwise_t_test(
- estimate ~ order,
- paired = TRUE,
- detailed = TRUE,
- ) %>%
- ungroup() %>%
- # group_by(stim_type) %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_data_H1_nooutlier_PWC
- # REPORT estimate .y. group1 group2 n1 n2 statistic p df conf.low conf.high method alternative p.adj p.adj.signif label
- ## Exact 0.190 estimate First Repeat 56 56 8.86 3.52e-12 55 0.147 0.232 T-test two.sided 7.04e-12 **** p=7.04e-12
- ## Lure 0.0720 estimate First Repeat 56 56 3.44 1 e- 3 55 0.0301 0.114 T-test two.sided 2 e- 3 ** p=0.002
- # pairwise comparisons - order * roi_cluster
- semmst_merged_data_H1_nooutlier_PWC = semmst_merged_data_H1_nooutlier %>%
- drop_na(Digit_Symbol) %>%
- group_by(order) %>%
- pairwise_t_test(
- estimate ~ stim_type,
- paired = TRUE,
- detailed = TRUE,
- ) %>%
- ungroup() %>%
- # group_by(stim_type) %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_data_H1_nooutlier_PWC
- # REPORT estimate .y. group1 group2 n1 n2 statistic p df conf.low conf.high method alternative p.adj p.adj.signif labe
- ## First -0.0114 estimate Exact Lure 56 56 -0.734 0.466 55 -0.0427 0.0198 T-test two.sided 0.932 ns p=0.932
- ## Repeat -0.129 estimate Exact Lure 56 56 -5.45 0.00000124 55 -0.176 -0.0815 T-test two.sided 0.00000248 **** p=2.48e-06
- ```
- ### ANOVA - REPEAT vs. LURE and CORRECT vs. INCORRECT
- For subsequent correctness we use those models, where only those runs were included, where non-zero amount of trials were in each bin.
- ```{r}
- semmst_merged_data_filtered_subseq = semmst_merged_data_filtered %>%
- dplyr::filter(task %in% c("EncodingSubseq", "EncodingSubseq_limited")) %>%
- dplyr::group_by(ID) %>%
- dplyr::filter(
- task == "EncodingSubseq" &
- !any(task == "EncodingSubseq_limited")
- ) %>%
- dplyr::ungroup()
- semmst_merged_data_HE = semmst_merged_data_filtered_subseq %>%
- filter(cope_name %in% c("CorrectExactRepeat", "CorrectExactFirst", "CorrectLureRepeat", "CorrectLureFirst", "IncorrectExactFirst", "IncorrectExactRepeat", "IncorrectLureFirst", "IncorrectLureRepeat"))
- ```
- ```{r}
- # STANDARD
- semmst_merged_data_HE_test = semmst_merged_data_HE %>%
- extract(col = cope_name,
- into = c("correctness", "stim_type", "order"),
- regex = "^(Correct|Incorrect)(Exact|Lure)(First|Repeat)$") %>%
- mutate(
- stim_type = as.factor(stim_type),
- order = as.factor(order)
- ) %>%
- mutate(stim_type = factor(stim_type, levels = c("Exact", "Lure"))) %>%
- mutate(correctness = factor(correctness, levels = c("Correct", "Incorrect"))) %>%
- droplevels()
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_merged_data_HE_test %>%
- group_by(order, correctness, roi_cluster) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, roi_cluster, stim_type, order, correctness, is.outlier, is.extreme) %>%
- filter(is.extreme == TRUE)
- semmst_merged_data_HE_test_nooutlier = semmst_merged_data_HE_test %>%
- #filter(!ID %in% c("sub-434971")) %>% #, "sub-124846")) %>% #c("sub-434971", "sub-632012", "sub-680997")) %>% #, "sub-193800")) %>%
- ungroup()
- ##NORMALITY
- semmst_merged_data_HE_test_nooutlier %>%
- group_by(stim_type, order, correctness, roi, hemisphere) %>%
- shapiro_test(estimate) %>% print(n=100)
- # ANOVA
- semmst_merged_data_HE_test_AOV = semmst_merged_data_HE_test_nooutlier %>%
- anova_test(dv = estimate, wid = ID, within = c(stim_type, correctness, order, roi_cluster))#, covariate = c(NonWord_sum_scale))
- get_anova_table(semmst_merged_data_HE_test_AOV)
- # REPORT
- ## 1 stim_type 1 28 13.459000 1.00e-03 * 1.80e-02
- ## 3 order 1 28 43.614000 3.66e-07 * 4.60e-02
- ## 6 stim_type:order 1 28 7.165000 1.20e-02 * 1.50e-02
- ## 7 correctness:order 1 28 0.048000 8.28e-01 1.18e-04
- ## 11 stim_type:correctness:order 1 28 0.277000 6.03e-01 4.92e-04
- # POST-HOC
- # pairwise comparisons
- semmst_merged_data_HE_test_nooutlier_PWC = semmst_merged_data_HE_test_nooutlier %>%
- group_by(stim_type) %>%
- pairwise_t_test(
- estimate ~ order,
- paired = TRUE,
- detailed = TRUE,
- ) %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_data_HE_test_nooutlier_PWC %>% dplyr::select(-c(alternative, method, .y., )) %>% print(n=50)
- # REPORT stim_type estimate group1 group2 n1 n2 statistic p df conf.low conf.high p.adj p.adj.signif label
- ## 1 Exact 0.164 First Repeat 116 116 6.32 0.00000000513 115 0.112 0.215 0.0000000103 **** p=1.03e-08
- ## 2 Lure 0.0454 First Repeat 116 116 1.72 0.088 115 -0.00681 0.0975 0.176 ns p=0.176
- ```
- ## Revision Analysis 3 - Exact, close, distant
- ```{r}
- # FILTER DATA
- semmst_merged_data_H1_clodis = semmst_merged_data_filtered %>%
- filter(task == "EncodingFirst") %>%
- filter(cope_name %in% c("ExactRepeat", "CloseRepeat", "DistantRepeat")) %>%
- mutate(
- roi_cluster = paste(hemisphere, roi, cluster, sep = "_"),
- roi_hemisphere = paste(hemisphere, roi, sep = "_"),
- condition = recode(
- cope_name,
- "ExactRepeat" = "Exact",
- "CloseRepeat" = "Close",
- "DistantRepeat" = "Distant"
- )
- ) %>%
- mutate(
- condition = factor(condition, levels = c("Exact", "Close", "Distant")),
- roi_cluster = factor(roi_cluster)
- )
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_merged_data_H1_clodis %>%
- group_by(condition, roi_cluster) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, condition, roi_cluster, is.outlier, is.extreme) %>%
- filter(is.extreme == TRUE)
- # REMOVE OUTLIERS IF NEEDED
- semmst_merged_data_H1_clodis_nooutlier = semmst_merged_data_H1_clodis %>%
- drop_na(estimate, NonWord_sum_scale, Digit_Symbol_scale) %>%
- ungroup()
- ## NORMALITY
- semmst_merged_data_H1_clodis_nooutlier %>%
- group_by(condition, roi_cluster) %>%
- shapiro_test(estimate)
- # ANOVA
- semmst_merged_data_H1_clodis_AOV = semmst_merged_data_H1_clodis_nooutlier %>%
- anova_test(
- dv = estimate,
- wid = ID,
- within = c(condition, roi_cluster),
- )
- get_anova_table(semmst_merged_data_H1_clodis_AOV)
- # POST-HOC
- # pairwise comparisons - condition within each ROI
- semmst_merged_data_H1_clodis_PWC = semmst_merged_data_H1_clodis_nooutlier %>%
- group_by(roi_cluster) %>%
- pairwise_t_test(
- estimate ~ condition,
- paired = TRUE,
- detailed = TRUE,
- p.adjust.method = "none"
- ) %>%
- ungroup() %>%
- add_significance("p") %>%
- mutate(
- label = case_when(
- p < .001 ~ "p < .001",
- p < .01 ~ "p < .01",
- p < .05 ~ paste0("p = ", sub("^0", "", sprintf("%.3f", p))),
- TRUE ~ paste0("p = ", sub("^0", "", sprintf("%.2f", p)))
- )
- )
- semmst_merged_data_H1_clodis_PWC
- ```
- ## Analysis 4 - ENC RS ~ LDI
- ### Prepare bias scores
- ```{r}
- group_vars_H3 <- c("ID", "mask_type", "space_type", "contrast", "roi_cluster")
- # baseline
- semmst_merged_data_H3_neural_ps = semmst_merged_data_filtered %>%
- filter(task %in% c("Encoding")) %>%
- filter(cope_name %in% c("ExactFirst", "ExactRepeat", "LureFirst","LureRepeat", "CloseFirst", "CloseRepeat", "DistantFirst", "DistantRepeat")) %>%
- dplyr::select(ID, space_type, cope_name, hemisphere, roi, mask_type, cluster, voxels, contrast, task, roi_cluster, roi_hemisphere, estimate, NonWord_sum_scale, Digit_Symbol_scale, rec_dprime:lure_incorrect) %>%
- group_by(across(all_of(group_vars_H3))) %>%
- pivot_wider(names_from = cope_name, values_from = estimate, values_fill = NA_real_) %>%
- mutate(
- # --- Non-RS bias scores (Exact denominator) ---
- LureBiasScore = LureRepeat - ExactRepeat,
- CloseBiasScore = CloseRepeat - ExactRepeat,
- DistantBiasScore = DistantRepeat - ExactRepeat
- ) %>%
- ungroup()
- ```
- ### Correlation - LURES
- ```{r}
- # 1) Filter / define roi_group
- df_corr_input_all <- semmst_merged_data_H3_neural_ps %>%
- mutate(roi_group = roi_cluster) %>%
- dplyr::select(
- ID, roi_group, roi, hemisphere, cluster, voxels,
- LureBiasScore, lure_dprime,
- NonWord_sum_scale, Digit_Symbol_scale
- ) %>%
- ungroup()
- # 2) Mahalanobis outlier detection (per ROI)
- alpha <- 0.99 # cutoff for chi-square (df=2)
- md_tbl_all <- df_corr_input_all %>%
- dplyr::group_by(roi_group) %>%
- dplyr::group_modify(~{
- d <- .x %>% dplyr::select(ID, LureBiasScore, lure_dprime) %>% tidyr::drop_na()
- if (nrow(d) < 3) {
- return(tibble::tibble(ID = character(), MD = numeric(), p = numeric(),
- cutoff = numeric(), is_outlier = logical()))
- }
- X <- as.matrix(d[, c("LureBiasScore", "lure_dprime")])
- center <- colMeans(X)
- covmat <- stats::cov(X)
- md <- stats::mahalanobis(X, center = center, cov = covmat)
- tibble::tibble(
- ID = d$ID,
- MD = md,
- p = 1 - stats::pchisq(md, df = 2),
- cutoff = stats::qchisq(alpha, df = 2),
- is_outlier = md > stats::qchisq(alpha, df = 2)
- )
- }) %>%
- ungroup()
- md_outliers_all <- md_tbl_all %>% dplyr::filter(is_outlier)
- md_multi_all <- md_outliers_all %>% dplyr::count(ID, sort = TRUE) %>% dplyr::filter(n > 1)
- md_tbl_all
- md_outliers_all
- md_multi_all
- # 3) Remove outlier ID
- df_corr_input_all_nooutlier <- df_corr_input_all %>%
- dplyr::filter(ID != "sub-434971") %>%
- droplevels() %>%
- ungroup()
- # 4) Fisher-z CI for Pearson r (95% hard-coded)
- pearson_ci <- function(r, n) {
- z <- atanh(r)
- se <- 1 / sqrt(n - 3)
- zcrit <- stats::qnorm(1 - (1 - 0.95) / 2)
- c(low = tanh(z - zcrit * se), high = tanh(z + zcrit * se))
- }
- # 5) SIMPLE correlations only (Pearson) per ROI + Bonferroni
- H3_corr_lure_simple <- df_corr_input_all_nooutlier %>%
- dplyr::group_by(roi_group) %>%
- dplyr::group_modify(~{
- d <- .x %>% dplyr::select(LureBiasScore, lure_dprime) %>% tidyr::drop_na()
- ct <- stats::cor.test(d$LureBiasScore, d$lure_dprime, method = "pearson")
- r <- unname(ct$estimate)
- p <- ct$p.value
- n <- nrow(d)
- ci <- pearson_ci(r, n)
- tibble::tibble(
- n = n,
- r = r,
- p = p,
- ci = sprintf("[%.3f, %.3f]", ci["low"], ci["high"])
- )
- }) %>%
- ungroup() %>%
- mutate(
- p_adj = p.adjust(p, method = "bonferroni")
- ) %>%
- arrange(p_adj)
- H3_corr_lure_simple
- ```
- ### Compare correlations
- ```{r}
- # --- A) Build subject-level wide table (bias per ROI, plus lure_dprime per ID)
- wide_bias <- df_corr_input_all_nooutlier %>%
- group_by(ID, roi_group) %>%
- summarise(
- bias = mean(LureBiasScore, na.rm = TRUE),
- lure_dprime = first(lure_dprime),
- .groups = "drop"
- ) %>%
- tidyr::pivot_wider(
- names_from = roi_group,
- values_from = bias,
- names_repair = "minimal"
- )
- roi_cols <- setdiff(names(wide_bias), c("ID", "lure_dprime"))
- # --- B) Pairwise dependent-correlation tests:
- # compares r(lure_dprime, ROI1_bias) vs r(lure_dprime, ROI2_bias)
- H3_pairwise_roi_corrdiff <- combn(roi_cols, 2, simplify = FALSE) %>%
- purrr::map_dfr(function(pair){
- roi1 <- pair[1]
- roi2 <- pair[2]
- d <- wide_bias %>%
- select(lure_dprime, all_of(roi1), all_of(roi2)) %>%
- drop_na()
- n <- nrow(d)
- r1 <- cor(d$lure_dprime, d[[roi1]], method = "pearson")
- r2 <- cor(d$lure_dprime, d[[roi2]], method = "pearson")
- r12 <- cor(d[[roi1]], d[[roi2]], method = "pearson")
- # Williams/Steiger-style test for two dependent correlations sharing one variable
- tst <- psych::r.test(n = n, r12 = r1, r13 = r2, r23 = r12)
- tibble(
- roi1 = roi1,
- roi2 = roi2,
- n = n,
- r_roi1 = r1,
- r_roi2 = r2,
- r_roi1_roi2 = r12,
- t = unname(tst$t),
- p = unname(tst$p)
- )
- }) %>%
- mutate(p_adj_bonf = p.adjust(p, method = "bonferroni")) %>%
- arrange(p_adj_bonf, p)
- H3_pairwise_roi_corrdiff
- ```
- ## Analysis 5 - REC MD
- ### ANOVA #1 - LureMD
- ```{r}
- ### FILTERING FR AT LEAST 5 items per condition per run
- run_status <- semmst_behav_data_rec_filtered %>%
- select(ID, run, trial_type, correctness) %>%
- filter(trial_type %in% c("CLOSE", "DISTANT")) %>%
- mutate(run = as.integer(str_extract(as.character(run), "\\d+"))) %>%
- count(ID, run, correctness, name = "n") %>%
- group_by(ID, run) %>%
- complete(correctness, fill = list(n = 0)) %>%
- summarise(
- min_n = min(n),
- run_ok = (min_n >= 3),
- .groups = "drop"
- ) %>%
- select(ID, run, run_ok) %>%
- tidyr::pivot_wider(
- names_from = run,
- values_from = run_ok,
- names_prefix = "run",
- values_fill = FALSE
- ) %>%
- mutate(
- group = case_when(
- run1 & run2 ~ "both_ok",
- !run1 & run2 ~ "run1_low_only",
- run1 & !run2 ~ "run2_low_only",
- TRUE ~ "both_low"
- )
- )
- # We use both runs only if both have n > 5 items in all bins, otherwise only 1 run or exclude
- ids_both_ok <- run_status %>% filter(group == "both_ok") %>% pull(ID)
- ids_run1_lowonly <- run_status %>% filter(group == "run1_low_only") %>% pull(ID)
- ids_run2_lowonly <- run_status %>% filter(group == "run2_low_only") %>% pull(ID)
- semmst_merged_data_filtered_lures = semmst_merged_data_filtered
- df_LureCR_all <- semmst_merged_data_filtered_lures %>%
- filter(task == "RecognitionRespAll", cope_name == "LureCR")
- df_LureFA_both_ok <- semmst_merged_data_filtered_lures %>%
- filter(task == "RecognitionRespAll", cope_name == "LureFA") %>%
- semi_join(tibble(ID = ids_both_ok), by = "ID")
- df_LureFA_use_run2 <- semmst_merged_data_filtered_lures %>%
- filter(task == "RecognitionRespAllRun2", cope_name == "LureFA") %>%
- semi_join(tibble(ID = ids_run1_lowonly), by = "ID")
- df_LureFA_use_run1 <- semmst_merged_data_filtered_lures %>%
- filter(task == "RecognitionRespAllRun1", cope_name == "LureFA") %>%
- semi_join(tibble(ID = ids_run2_lowonly), by = "ID")
- # Merge for testing
- df_LureFA_all <- bind_rows(
- df_LureFA_both_ok,
- df_LureFA_use_run2,
- df_LureFA_use_run1
- )
- semmst_merged_data_H4_lureFACR <- bind_rows(df_LureCR_all, df_LureFA_all)
- keep_ids <- semmst_merged_data_H4_lureFACR %>%
- group_by(ID, roi_cluster) %>%
- summarise(
- has_LureCR = any(cope_name == "LureCR"),
- has_LureFA = any(cope_name == "LureFA"),
- .groups = "drop"
- ) %>%
- filter(has_LureCR & has_LureFA) %>% count(ID) %>%
- filter(n > 1) %>%
- pull(ID)
- semmst_merged_data_H4_lureFACR <- semmst_merged_data_H4_lureFACR %>%
- filter(ID %in% keep_ids) %>%
- droplevels()
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_merged_data_H4_lureFACR %>%
- group_by(cope_name, roi_cluster, task) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, roi_cluster, cope_name, is.outlier, is.extreme) %>%
- filter(is.extreme==TRUE)
- semmst_merged_data_H4_lureFACR_nooutlier = semmst_merged_data_H4_lureFACR %>%
- #filter(ID != "sub-632012") %>%
- ungroup()
- semmst_merged_H4_AOV = semmst_merged_data_H4_lureFACR_nooutlier %>%
- droplevels() %>%
- anova_test(dv = estimate, wid = ID, within = c(cope_name, roi_cluster))#, covariate = c(NonWord_sum_scale))
- get_anova_table(semmst_merged_H4_AOV)
- # REPORT Effect DFn DFd F p p<.05 ges
- ## 1 cope_name 1 23 1.621 0.216 0.013
- ## 2 roi_cluster 1 23 0.584 0.453 0.005
- ## 3 cope_name:roi_cluster 1 23 1.079 0.310 0.006
- # POST-HOC
- # pairwise comparisons - stim_type * order
- semmst_merged_H4_REC_lureFACR_PWC = semmst_merged_data_H4_lureFACR_nooutlier %>%
- group_by(roi_cluster) %>%
- pairwise_t_test(
- estimate ~ cope_name,
- paired = TRUE,
- detailed = TRUE,
- ) %>%
- ungroup() %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_H4_REC_lureFACR_PWC
- ```
- ### ANOVA #2 - REC CONDITIONS
- ```{r}
- # Control analysis for CR only on the total sample
- semmst_merged_data_filtered_H4_REC_conditions = semmst_merged_data_filtered %>%
- filter(task == "RecognitionRespAll") %>%
- filter(cope_name %in% c("LureCR", "FoilCR", "TargetHIT"))
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_merged_data_filtered_H4_REC_conditions %>%
- group_by(cope_name, roi_cluster) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, roi_cluster, cope_name, is.outlier, is.extreme) %>%
- filter(is.extreme==TRUE)
- semmst_merged_data_filtered_H4_REC_conditions_nooutlier = semmst_merged_data_filtered_H4_REC_conditions %>%
- ungroup()
- semmst_merged_H4_REC_conditions_AOV = semmst_merged_data_filtered_H4_REC_conditions_nooutlier %>%
- droplevels() %>%
- anova_test(dv = estimate, wid = ID, within = c(cope_name, roi_cluster))#, covariate = c(NonWord_sum_scale))
- get_anova_table(semmst_merged_H4_REC_conditions_AOV)
- # Effect DFn DFd F p p<.05 ges
- ## 1 cope_name 2 58 6.967 0.002 * 0.040
- ## 2 roi_cluster 1 29 2.018 0.166 0.015
- ## 3 cope_name:roi_cluster 2 58 0.508 0.604 0.002
- # POST-HOC
- # pairwise comparisons - stim_type * order
- semmst_merged_H4_REC_conditions_PWC = semmst_merged_data_filtered_H4_REC_conditions_nooutlier %>%
- group_by(task) %>%
- pairwise_t_test(
- estimate ~ cope_name,
- paired = TRUE,
- detailed = TRUE,
- ) %>%
- ungroup() %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_H4_REC_conditions_PWC
- ## roi_cluster estimate .y. group1 group2 n1 n2 statistic p df conf.low conf.high method alternative p.adj
- ## 1 L_HEAD_DGCA23_HEAD_SUB_14 0.138 estimate FoilCR LureCR 30 30 3.43 0.002 29 0.0558 0.221 T-test two.sided 0.012 *
- ## 4 R_HEAD_DGCA23_HEAD_SUB_15 0.103 estimate FoilCR LureCR 30 30 3.05 0.005 29 0.0341 0.173 T-test two.sided 0.03 *
- # AGAINTS ZERO BASLEINE
- semmst_merged_H4_REC_FoilLure_vs0 <- semmst_merged_data_filtered_H4_REC_conditions_nooutlier %>%
- filter(cope_name %in% c("FoilCR", "LureCR")) %>%
- group_by(cope_name) %>%
- t_test(
- estimate ~ 1,
- mu = 0,
- detailed = TRUE
- ) %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance("p.adj") %>%
- mutate(label = paste0("p=", signif(p.adj, 3))) %>%
- ungroup()
- semmst_merged_H4_REC_FoilLure_vs0
- ### cope_name estimate .y. group1 group2 n statistic p df conf.low conf.high method alternative p.adj p.adj.signif label
- ## 1 FoilCR 0.0298 estimate 1 null model 60 0.976 0.333 59 -0.0313 0.0909 T-test two.sided 0.666 ns p=0.666
- ## 2 LureCR -0.0911 estimate 1 null model 60 -2.77 0.00758 59 -0.157 -0.0252 T-test two.sided 0.0152 * p=0.0152
- ```
- # Figures
- ## Figure 1 - Behavioral figures (response, LDI)
- ### Figure 1A - response ratio
- ```{r}
- knitr::opts_chunk$set(
- fig.width = 11, # same as ggsave width
- fig.height = 16, # same as ggsave height
- dpi = 300,
- fig.retina = 2, # crisp in HTML
- out.width = "45%", # display smaller, but proportions/text scale together
- dev = "ragg_png"
- )
- dodge <- 0.7
- trial_order <- c("TARGET", "CLOSE", "DISTANT", "FOIL")
- # 1) Build per-ID percentages so the two responses sum to 100% within each ID × trial_type
- figA_base <- semmst_behav_data_rec_filtered %>%
- filter(!is.na(ID), !is.na(trial_type), !is.na(response)) %>%
- mutate(
- trial_type = factor(trial_type, levels = trial_order),
- response = factor(response)
- )
- resp_lvls <- levels(figA_base$response)
- figA_pct <- figA_base %>%
- dplyr::count(ID, trial_type, response, name = "n") %>%
- tidyr::complete(response = factor(resp_lvls, levels = resp_lvls), fill = list(n = 0)) %>%
- dplyr::mutate(
- percent_response = 100 * n / sum(n),
- .by = c(ID, trial_type)
- )
- # 2) Within-subject SE across ID for each (trial_type × response)
- figA_barsum <- Rmisc::summarySEwithin(
- data = figA_pct,
- measurevar = "percent_response",
- withinvars = c("trial_type", "response"),
- idvar = "ID",
- na.rm = TRUE
- )
- # Paul Tol "Light" (pastel, print-friendly): light blue / light orange
- fill_vals <- setNames(c("#EE8866", "#77AADD"), levels(figA_barsum$response))
- behav_fig_A <- ggplot(figA_barsum, aes(
- x = trial_type, y = percent_response,
- fill = response, group = response
- )) +
- geom_col(position = position_dodge(width = dodge), width = 0.70) +
- geom_errorbar(
- aes(ymin = percent_response - se, ymax = percent_response + se),
- position = position_dodge(width = dodge), width = 0.2, size = 1.4
- ) +
- scale_fill_manual(values = fill_vals) +
- scale_y_continuous(limits = c(0, 100), expand = expansion(mult = c(0.01, 0.06))) +
- scale_x_discrete(
- drop = FALSE,
- labels = c(
- "TARGET" = "TARGET",
- "CLOSE" = "CLOSE\nLURE",
- "DISTANT" = "DISTANT\nLURE",
- "FOIL" = "FOIL"
- )
- ) +
- labs(
- x = "Trial type",
- y = "Response percentages",
- fill = "Response"
- ) +
- theme_classic(base_size = 16) +
- theme(
- legend.position = c(0.15, 0.95),
- )
- behav_fig_A
- ```
- ```{r}
- text_base_export=40
- behav_fig_A_export <- behav_fig_A +
- theme_classic(base_size = text_base_export) +
- theme(
- legend.position = c(0.18, 0.95),
- legend.title = element_text(size = text_base_export * 0.95),
- legend.text = element_text(size = text_base_export * 0.90),
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05)
- )
- ggsave(
- "derivatives/figures/Figure1A.png",
- plot = behav_fig_A_export,
- width = 18, height = 13, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- ### Figure 1 D - D-primes
- ```{r}
- # 1) Prep & adjustment (remove linear effects of covariates)
- figD_plot_base <- semmst_behav_data_rec_LDI_ANCOVA %>%
- filter(!is.na(ID), !is.na(dprime_type), !is.na(dprime_value)) %>%
- mutate(
- dprime_type = factor(dprime_type),
- sex = factor(sex)
- )
- # order as: Close, Distant, Target
- figD_contrast_order <- c("close_dprime", "distant_dprime", "rec_dprime")
- figD_plot_base <- figD_plot_base %>%
- mutate(dprime_type = fct_relevel(dprime_type, figD_contrast_order))
- # covariate-only model for adjustment
- figD_mod_cov <- lm(dprime_value ~ sex + age + Vocabulary_scale + Digit_Symbol_scale + NonWord_sum_scale,
- data = figD_plot_base)
- figD_plot_base <- figD_plot_base %>%
- mutate(dprime_adj = dprime_value - predict(figD_mod_cov, newdata = figD_plot_base) + mean(dprime_value, na.rm = TRUE))
- # 2) Labels & colors
- figD_x_lab_map <- c(
- "close_dprime" = "CLOSE\nLURE",
- "distant_dprime" = "DISTANT\nLURE",
- "rec_dprime" = "FOIL"
- )
- # Paul Tol (muted): blue / yellow / red — CVD-safe, good in print & grayscale
- figD_fill_vals <- c("close_dprime"="#4477AA", "distant_dprime"="#DDCC77", "rec_dprime"="#117733")
- # 3) Plot
- behav_fig_D <- ggplot(figD_plot_base, aes(x = dprime_type, y = dprime_adj, fill = dprime_type)) +
- geom_boxplot(width = 0.6, outlier.alpha = 0.4, linewidth = 1.8, color = "black") +
- stat_summary(fun = mean, geom = "point", shape = 21, size = 2.2, fill = "white", color = "black") +
- scale_x_discrete(labels = figD_x_lab_map, drop = FALSE) +
- scale_fill_manual(values = figD_fill_vals, guide = "none") +
- labs(
- x = "Discriminability contrasts",
- y = "Covariate-adjusted d'\n [p(\"old\"|target) - p(\"old\"|condition)]"
- ) +
- theme_classic(base_size = 14)
- behav_fig_D
- ```
- ```{r}
- behav_fig_D_export <- behav_fig_D +
- theme_classic(base_size = 40) +
- theme(
- axis.title = element_text(size = 42),
- axis.text = element_text(size = 34)
- ) + labs(x = NULL)
- ggsave(
- "derivatives/figures/Figure1D.png",
- plot = behav_fig_D_export,
- width = 9, height = 16, units = "in",
- dpi = 300,
- bg = "white",
- device = "png" # base png
- )
- ```
- ### Figure 1 E - continous GLMEM
- ```{r}
- # In this plot, we predict p|old by cosine similarity
- # Base data: binary outcome + keep CLOSE & DISTANT only
- semmst_behav_data_rec_filtered_GLMEM_plot <- semmst_behav_data_rec_filtered_GLMEM %>%
- mutate(response = as.integer(response == "old")) %>%
- filter(trial_type %in% c("CLOSE", "DISTANT"))
- # If your column is 'trial_type', replace 'trial_type' with 'trial_type' above.
- # Build a facetting variable: Overall, DISTANT-only, CLOSE-only
- semmst_behav_data_rec_filtered_GLMEM_plot_facet <- bind_rows(
- semmst_behav_data_rec_filtered_GLMEM_plot %>% mutate(panel = "ALL LURE"),
- semmst_behav_data_rec_filtered_GLMEM_plot %>% filter(trial_type == "DISTANT") %>% mutate(panel = "DISTANT LURE"),
- semmst_behav_data_rec_filtered_GLMEM_plot %>% filter(trial_type == "CLOSE") %>% mutate(panel = "CLOSE LURE")
- ) %>%
- mutate(panel = factor(panel, levels = c("ALL LURE", "DISTANT LURE", "CLOSE LURE")))
- # Okabe–Ito (CVD-safe): purple, yellow, blue
- figE_cols <- c("ALL LURE" = "#CC79A7", "DISTANT LURE" = "#DDCC77", "CLOSE LURE" = "#4477AA")
- behav_fig_E <- ggplot(semmst_behav_data_rec_filtered_GLMEM_plot_facet,
- aes(x = cosine, y = response, color = panel, fill = panel)) +
- geom_smooth(
- method = "glm", method.args = list(family = "binomial"),
- linewidth = 2, se = TRUE, alpha = 0.25
- ) +
- facet_wrap(~ panel, nrow = 1, scales = "free_x") +
- scale_x_continuous(
- breaks = function(lims) round(lims[1] + c(0.1, 0.5, 0.9) * (lims[2] - lims[1]), 2),
- labels = function(x) sprintf("%.2f", x)
- ) +
- scale_y_continuous(labels = scales::percent, limits = c(0, 1)) +
- scale_color_manual(values = figE_cols, guide = "none") +
- scale_fill_manual(values = figE_cols, guide = "none") +
- labs(x = "Cosine similarity", y = "Percentage of 'old' responses") +
- theme_classic(base_size = 14) +
- theme(
- panel.grid.minor = element_blank(),
- strip.text = element_text(face = "bold")
- )
- behav_fig_E
- ```
- ```{r}
- behav_fig_E_export <- behav_fig_E +
- theme_classic(base_size = 40) +
- theme(
- axis.title = element_text(size = 42),
- axis.text = element_text(size = 32)
- )
- ggsave(
- "derivatives/figures/Figure1E.png",
- plot = behav_fig_E_export,
- width = 16, height = 16, units = "in",
- dpi = 300,
- bg = "white",
- device = "png" # base png
- )
- ```
- ### Figure 1 C - Lure cosine similarities
- ```{r}
- figC_plot_base <- semmst_behav_data_rec_filtered %>%
- filter(trial_type %in% c("CLOSE", "DISTANT")) %>%
- mutate(trial_type = factor(trial_type,
- levels = c("CLOSE", "DISTANT"),
- labels = c("CLOSE LURE", "DISTANT LURE"))) %>%
- dplyr::select(trial_type, noun, cosine) %>%
- unique()
- # Paul Tol (muted): blue / yellow / red — CVD-safe, good in print & grayscale
- figC_fill_vals <- c("CLOSE LURE"="#4477AA", "DISTANT LURE"="#DDCC77")
- # 3) Plot
- behav_fig_C_hists <- ggplot(figC_plot_base, aes(x = cosine, fill = trial_type)) +
- geom_histogram(
- bins = 20, # tweak bins/binwidth as you like
- color = "black",
- linewidth = 1.0
- ) +
- facet_wrap(~ trial_type, ncol = 1) + # <-- vertically stacked (2 panels if 2 trial types)
- scale_fill_manual(values = figC_fill_vals, guide = "none") +
- labs(
- x = "Cosine similarity [1.0 = identical]",
- y = "Number of items in 20 equally spaced bins"
- ) +
- theme_classic(base_size = 14) +
- theme(
- strip.background = element_blank(),
- strip.text = element_text(face = "bold"),
- panel.spacing = unit(0.7, "lines")
- )
- behav_fig_C_hists
- ```
- ```{r}
- behav_fig_C_export <- behav_fig_C_hists +
- theme_classic(base_size = 40) +
- theme(
- axis.title = element_text(size = 38),
- axis.text = element_text(size = 34)
- )
- ggsave(
- "derivatives/figures/Figure1C.png",
- plot = behav_fig_C_export,
- width = 12, height = 19, units = "in",
- dpi = 300,
- bg = "white",
- device = "png" # base png
- )
- ```
- ## Figure 2 - ENC RS specificity
- ```{r}
- # BARPLOT
- fig2_dodge <- 0.8
- fig2_barsum <- Rmisc::summarySEwithin(
- data = semmst_merged_data_H1_nooutlier,
- measurevar = "estimate",
- withinvars = c("stim_type","order", "roi_cluster"),
- idvar = "ID",
- na.rm = TRUE
- ) %>%
- mutate(stim_type = factor(as.character(stim_type),
- levels = c("Exact","Lure"),
- labels = c("Exact","Modified")))
- fig2_roi_lab <- semmst_merged_data_H1_nooutlier %>%
- dplyr::distinct(roi_cluster, hemisphere, roi, cluster, voxels) %>%
- dplyr::mutate(
- roi_label = dplyr::case_when(
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "R" ~ "Right hippocampal head cluster",
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "L" ~ "Left hippocampal head cluster"
- )
- ) %>%
- dplyr::select(roi_cluster, roi_label)
- # ------------------------------------------------------------
- # NEW: paired tests of stim_type (Exact vs Modified) WITHIN each order,
- # collapsed across roi_cluster (same p-values in both facets)
- # ------------------------------------------------------------
- fig2_stat.test <- semmst_merged_data_H1_nooutlier %>%
- mutate(stim_type = factor(as.character(stim_type),
- levels = c("Exact","Lure"),
- labels = c("Exact","Modified"))) %>%
- group_by(ID, order, stim_type) %>%
- summarise(estimate = mean(estimate, na.rm = TRUE), .groups = "drop") %>%
- group_by(order) %>%
- rstatix::t_test(estimate ~ stim_type, paired = TRUE) %>%
- ungroup() %>%
- rstatix::adjust_pvalue(method = "bonferroni") %>%
- rstatix::add_significance("p.adj") %>%
- mutate(
- label = dplyr::case_when(
- p.adj < 0.001 ~ "p < .001",
- p.adj < .01 ~ "p < .01",
- TRUE ~ paste0("p = ", sub("^0", "", sprintf("%.2f", p.adj)))
- )
- )
- # 1) Attach ROI labels to barsum
- fig2_barsum <- fig2_barsum %>% dplyr::left_join(fig2_roi_lab, by = "roi_cluster")
- # 2) replicate the same stats into both facets and set y.position per facet+order
- fig2_stat.test <- fig2_stat.test %>%
- tidyr::crossing(fig2_barsum %>% dplyr::distinct(roi_label)) %>%
- dplyr::left_join(
- fig2_barsum %>%
- dplyr::group_by(order, roi_label) %>%
- dplyr::summarise(y.position = max(estimate + se, na.rm = TRUE) * 1.08, .groups = "drop"),
- by = c("order", "roi_label")
- )
- # 3) compute xmin/xmax to connect Exact ↔ Modified within each ORDER (dodge offset)
- fig2_stim_lvls <- levels(factor(fig2_barsum$stim_type)) # should be c("Exact","Modified")
- exact_idx <- which(fig2_stim_lvls == "Exact")
- mod_idx <- which(fig2_stim_lvls == "Modified")
- fig2_stat.test <- fig2_stat.test %>%
- mutate(
- order = factor(order, levels = c("First", "Repeat")),
- offset = if_else(order == "First", -fig2_dodge/2, +fig2_dodge/2),
- xmin = exact_idx + offset,
- xmax = mod_idx + offset
- )
- # --- bar plot (fill by stim_type color, opacity by order), same dodging ---
- fig2_plot <- ggplot(fig2_barsum, aes(
- x = stim_type, y = estimate,
- fill = stim_type, # color by stim type
- group = `order` # ensures side-by-side bars per stim_type
- )) +
- geom_col(aes(alpha = order), position = position_dodge(width = fig2_dodge), width = 0.65) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = fig2_dodge), width = 0.15, size=1.2
- ) +
- facet_wrap(~ roi_label) +
- theme_classic(base_size = 13) +
- labs(x = "Condition during encoding", y = "Mean % signal change", fill = "Stimulus", alpha = "Order") +
- # accessible, pleasant green & violet
- scale_fill_manual(values = c(
- "Exact" = "#66BB6A", # soft green
- "Modified" = "#9575CD" # soft violet
- )) +
- # subtle opacity difference for First vs Repeat
- scale_alpha_manual(values = c(
- "First" = 0.95,
- "Repeat" = 0.55
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.14))) +
- custom_theme + guides(fill = "none") +
- theme(
- legend.position = c(0.88, 0.93) # a bit up
- )
- # --- add bracket + p (Exact vs Modified within each order; same in both facets) ---
- fig2_plot +
- ggpubr::stat_pvalue_manual(
- fig2_stat.test,
- label = "label",
- xmin = "xmin",
- xmax = "xmax",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.shorten=1.2,
- size = 5.4,
- bracket.size = 1.0
- )
- ```
- ```{r}
- text_base_export=40
- p_text_size_mm <- text_base_export * 0.20 # ~points → mm-ish (tweak 0.30–0.45)
- p_bracket_mm <- p_text_size_mm * 0.15 # bracket thickness relative to text
- fig2_plot_export <- fig2_plot +
- theme_classic(base_size = text_base_export) +
- theme(
- legend.position = c(0.88, 0.88),
- legend.title = element_text(size = text_base_export * 0.88),
- legend.text = element_text(size = text_base_export * 0.90),
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05),
- strip.text = element_blank(),
- panel.spacing.x = unit(4, "in")
- )
- ggsave(
- "derivatives/figures/Figure2B.png",
- plot = fig2_plot_export,
- width = 26, height = 13, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- ## Revised Figure 3 - exact, close, distant
- ```{r}
- # BARPLOT SUMMARY
- fig3_barsum <- Rmisc::summarySEwithin(
- data = semmst_merged_data_H1_clodis_nooutlier,
- measurevar = "estimate",
- withinvars = c("condition", "roi_cluster"),
- idvar = "ID",
- na.rm = TRUE
- ) %>%
- mutate(
- condition = factor(as.character(condition), levels = c("Exact", "Close", "Distant"))
- )
- # ROI LABELS
- fig3_roi_lab <- semmst_merged_data_H1_clodis_nooutlier %>%
- dplyr::distinct(roi_cluster, hemisphere, roi, cluster, voxels) %>%
- dplyr::mutate(
- roi_label = dplyr::case_when(
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "R" ~ "Right hippocampal head cluster",
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "L" ~ "Left hippocampal head cluster",
- TRUE ~ as.character(roi_cluster)
- )
- ) %>%
- dplyr::select(roi_cluster, roi_label)
- # ATTACH ROI LABELS
- fig3_barsum <- fig3_barsum %>%
- dplyr::left_join(fig3_roi_lab, by = "roi_cluster")
- # SIGNIFICANT PAIRWISE BRACKETS
- fig3_stat.test <- semmst_merged_data_H1_clodis_PWC %>%
- dplyr::filter(p < .05) %>%
- dplyr::left_join(fig3_roi_lab, by = "roi_cluster")
- # BRACKET HEIGHTS
- fig3_ypos <- fig3_barsum %>%
- dplyr::group_by(roi_label) %>%
- dplyr::summarise(
- y_max = max(estimate + se, na.rm = TRUE),
- y_min = min(estimate - se, na.rm = TRUE),
- y_span = y_max - y_min,
- .groups = "drop"
- ) %>%
- dplyr::mutate(
- y_span = if_else(y_span == 0 | is.na(y_span), 0.1, y_span),
- y_base = y_max + 0.10 * y_span,
- y_step = 0.12 * y_span
- )
- # STACK BRACKETS WITHIN EACH ROI
- fig3_stat.test <- fig3_stat.test %>%
- dplyr::left_join(fig3_ypos, by = "roi_label") %>%
- dplyr::group_by(roi_label) %>%
- dplyr::arrange(group1, group2, .by_group = TRUE) %>%
- dplyr::mutate(y.position = y_base + (dplyr::row_number() - 1) * y_step) %>%
- dplyr::ungroup()
- # BASE FIGURE
- fig3_plot <- ggplot(fig3_barsum, aes(x = condition, y = estimate, fill = condition)) +
- geom_col(width = 0.68) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- width = 0.12,
- size = 1.2
- ) +
- ggpubr::stat_pvalue_manual(
- fig3_stat.test,
- label = "label",
- xmin = "group1",
- xmax = "group2",
- y.position = "y.position",
- tip.length = 0.015,
- hide.ns = FALSE,
- inherit.aes = FALSE,
- bracket.shorten = 0.03,
- size = 6.6,
- bracket.size = 1.35
- ) +
- facet_wrap(~ roi_label, ncol = 2) +
- labs(
- x = "Conditions of repeats during encoding",
- y = "Mean % signal change"
- ) +
- scale_fill_manual(values = c(
- "Exact" = "#66BB6A",
- "Close" = "#4477AA",
- "Distant" = "#DDCC77"
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.03, 0.22))) +
- theme_classic(base_size = 18) +
- custom_theme +
- guides(fill = "none")
- fig3_plot
- ```
- ```{r}
- # EXPORT
- text_base_export = 40
- fig3_plot_export <- ggplot(fig3_barsum, aes(x = condition, y = estimate, fill = condition)) +
- geom_col(width = 0.68) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- width = 0.12,
- linewidth = 1.8
- ) +
- ggpubr::stat_pvalue_manual(
- fig3_stat.test,
- label = "label",
- xmin = "group1",
- xmax = "group2",
- y.position = "y.position",
- tip.length = 0.015,
- hide.ns = FALSE,
- inherit.aes = FALSE,
- bracket.shorten = 0.03,
- size = 10.5,
- bracket.size = 2.1
- ) +
- facet_wrap(~ roi_label, ncol = 2) +
- labs(
- x = "Conditions of repeats during encoding",
- y = "Mean % signal change"
- ) +
- scale_fill_manual(values = c(
- "Exact" = "#66BB6A",
- "Close" = "#4477AA",
- "Distant" = "#DDCC77"
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.03, 0.22))) +
- theme_classic(base_size = text_base_export) +
- custom_theme +
- guides(fill = "none") +
- theme(
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.95),
- axis.title.x = element_text(size = text_base_export * 1.05, face = "plain"),
- axis.title.y = element_text(size = text_base_export * 1.25, face = "plain"),
- strip.text = element_text(size = text_base_export * 0.95, face = "plain"),
- strip.background = element_rect(fill = "white", color = "black", linewidth = 2.2)
- )
- ggsave(
- "derivatives/figures/Figure3.png",
- plot = fig3_plot_export,
- width = 22, height = 12.5, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- ## Figure 4 - RS ~ LDI
- ```{r}
- # 1) Long table (ALL trials only)
- figure4_df <- df_corr_input_all_nooutlier %>%
- dplyr::select(ID, roi_group, roi, hemisphere, bias = LureBiasScore, lure_dprime) %>%
- tidyr::drop_na(bias, lure_dprime) %>%
- dplyr::mutate(
- facet_lab = dplyr::case_when(
- roi_group == "L_HEAD_DGCA23_HEAD_SUB_14" ~ "Left hippocampal head cluster",
- roi_group == "R_HEAD_DGCA23_HEAD_SUB_15" ~ "Right hippocampal head cluster",
- TRUE ~ as.character(roi_group)
- )
- )
- # 2) Per-ROI correlation + Bonferroni + label text
- figure4_labs <- figure4_df %>%
- dplyr::group_by(roi_group, facet_lab) %>%
- dplyr::summarise(
- n = dplyr::n(),
- r = unname(stats::cor(bias, lure_dprime, method = "pearson")),
- p = stats::cor.test(bias, lure_dprime, method = "pearson")$p.value,
- .groups = "drop"
- ) %>%
- dplyr::mutate(
- p_adj = p.adjust(p, method = "bonferroni"),
- stars = dplyr::case_when(
- p_adj < .001 ~ "***",
- p_adj < .01 ~ "**",
- p_adj < .05 ~ "*",
- TRUE ~ ""
- ),
- sig = if_else(p_adj < .05, "sig", "ns"),
- ann = dplyr::case_when(
- is.na(p_adj) ~ sprintf("r = %.2f, p = NA", r),
- p_adj < .001 ~ sprintf("r = %.2f, p < .001%s", r, stars),
- TRUE ~ sprintf("r = %.2f, p = %.3f%s", r, p_adj, stars)
- )
- )
- figure4_full <- figure4_df %>%
- left_join(figure4_labs %>% select(roi_group, sig), by = "roi_group")
- # 3) Plot
- fig4 = ggplot(figure4_full, aes(bias, lure_dprime)) +
- geom_point(alpha = 0.7, size = 4.5) +
- scale_color_manual(values = c(ns = "grey30", sig = "red"), guide = "none") +
- facet_wrap(~ roi_group, scales = "free",
- labeller = labeller(roi_group = setNames(figure4_labs$facet_lab, figure4_labs$roi_group))) +
- labs(
- x = "Neural pattern separation\nModified repeat - exact repeat\n(% signal change)",
- y = "Behavioral mnemonic discrimination\nd' (lures vs targets)"
- ) +
- theme_classic(base_size = 18) +
- custom_theme
- fig4 +
- geom_smooth(aes(color = sig), method = "lm", se = FALSE, linewidth = 1.1) +
- geom_text(
- data = figure4_labs,
- aes(x = -Inf, y = Inf, label = ann, color = sig),
- inherit.aes = FALSE,
- hjust = -0.05, vjust = 1.2, size = 5.5
- )
- ```
- ```{r}
- text_base_export=40
- fig4_export <- fig4 +
- geom_smooth(aes(color = sig), method = "lm", se = FALSE, linewidth = 2.6) +
- geom_text(
- data = figure4_labs,
- aes(x = -Inf, y = Inf, label = ann, color = sig),
- inherit.aes = FALSE,
- hjust = -0.05, vjust = 1.2, size = 10.5
- ) +
- theme_classic(base_size = text_base_export) +
- theme(
- legend.title = element_text(size = text_base_export * 0.95),
- legend.text = element_text(size = text_base_export * 0.90),
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05)
- )
- ggsave(
- "derivatives/figures/Figure4.png",
- plot = fig4_export,
- width = 20, height = 12, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- ## Figure 5 - ENC RS mask -> REC conditions
- ```{r}
- fig5_dodge <- 0.8
- level_map <- c("FoilCR", "LureCR", "TargetHIT")
- level_lab <- c("Foil", "Lure", "Target")
- # 1) Within-subject summary
- fig5_barsum <- Rmisc::summarySEwithin(
- data = semmst_merged_data_filtered_H4_REC_conditions_nooutlier,
- measurevar = "estimate",
- withinvars = c("cope_name", "roi_cluster"),
- idvar = "ID",
- na.rm = TRUE
- )
- fig5_roi_lab <- semmst_merged_data_filtered_H4_REC_conditions_nooutlier %>%
- distinct(roi_cluster, hemisphere, roi, cluster, voxels) %>%
- mutate(
- roi_label = case_when(
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "R" ~ "Right hippocampal head cluster",
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "L" ~ "Left hippocampal head cluster",
- TRUE ~ NA_character_
- )
- ) %>%
- select(roi_cluster, roi_label)
- fig5_barsum <- fig5_barsum %>%
- mutate(cope_name = factor(cope_name, levels = level_map, labels = level_lab)) %>%
- left_join(fig5_roi_lab, by = "roi_cluster")
- # 2) Base plot (no stats)
- fig5_plot <- ggplot(fig5_barsum, aes(x = cope_name, y = estimate, fill = cope_name)) +
- geom_col(position = position_dodge(width = fig5_dodge), width = 0.65) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = fig5_dodge),
- width = 0.15,
- size = 1.2
- ) +
- facet_wrap(~ roi_label) +
- theme_classic(base_size = 13) +
- labs(x = "Condition during recognition", y = "Mean % signal change") +
- scale_fill_manual(values = c(
- "Target" = "#66BB6A",
- "Lure" = "#9575CD",
- "Foil" = "#EE8866"
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.12))) +
- custom_theme +
- guides(fill = "none")
- # 3) Global paired pairwise stats (collapsed across ROI)
- fig5_stats_global <- semmst_merged_data_filtered_H4_REC_conditions_nooutlier %>%
- mutate(cope_name = factor(cope_name, levels = level_map, labels = level_lab)) %>%
- group_by(ID, cope_name) %>%
- summarise(estimate = mean(estimate, na.rm = TRUE), .groups = "drop") %>%
- pairwise_t_test(
- estimate ~ cope_name,
- paired = TRUE,
- p.adjust.method = "bonferroni"
- ) %>%
- mutate(
- label = case_when(
- p.adj < 0.001 ~ "p < .001",
- p.adj < 0.01 ~ "p < .01",
- p.adj < 0.05 ~ "p < .05",
- TRUE ~ paste0("p = ", sub("^0", "", sprintf("%.3f", p.adj)))
- )
- )
- # Global ymax across BOTH facets (shared bracket height)
- ymax_global <- fig5_barsum %>%
- summarise(ymax = max(estimate + se, na.rm = TRUE)) %>%
- pull(ymax)
- # Replicate the same stats into each facet; same y.position levels everywhere
- fig5_stats_for_facets <- fig5_barsum %>%
- distinct(roi_label) %>%
- tidyr::crossing(fig5_stats_global) %>%
- group_by(roi_label) %>%
- arrange(group1, group2, .by_group = TRUE) %>%
- mutate(
- y.position = ymax_global * 1.08 + (row_number() - 1) * (0.10 * ymax_global)
- ) %>%
- ungroup()
- # 4) In-window plot WITH stats
- fig5_plot_with_stats_global <- fig5_plot +
- stat_pvalue_manual(
- fig5_stats_for_facets,
- label = "label",
- xmin = "group1",
- xmax = "group2",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.size = 1.0,
- size = 5.0
- ) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.18)))
- fig5_plot_with_stats_global
- ```
- ```{r}
- text_base_export <- 40
- p_text_export <- text_base_export * 0.28 # bigger p text on export only
- fig5_plot_export <- fig5_plot +
- stat_pvalue_manual(
- fig5_stats_for_facets,
- label = "label",
- xmin = "group1",
- xmax = "group2",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.size = 1.3,
- size = p_text_export
- ) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.18))) +
- theme_classic(base_size = text_base_export) +
- theme(
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05),
- strip.text = element_text(size = text_base_export * 0.95)
- )
- ggsave(
- "derivatives/figures/Figure5.png",
- plot = fig5_plot_export,
- width = 22, height = 14, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- # Supplementary Results
- ### Supplementary Results 1 - covariate effects
- #### Behavioural GLMEM covariates
- ```{r}
- model_complex_cont = glmer(response ~ cosine * trial_type * former_type +
- age + sex + education + Vocabulary_scale + Digit_Symbol_scale +
- NonWord_sum_scale + arousal_scale + meaningfulness_scale + concreteness_scale +
- (1|ID) +
- (1|itemno),
- family = binomial("probit"),
- data = semmst_behav_data_rec_filtered_GLMEM_lure,
- control = glmerControl(optimizer ='bobyqa', optCtrl=list(maxfun = 20000)), nAGQ=0)
- ```
- ##### Supplementary Figure 2AB.
- ```{r}
- # 1) Marginal (averaged-over-covariates) predictions
- pred_nonword <- ggeffects::ggaverage(
- model_complex_cont,
- terms = "NonWord_sum_scale [n=100]" # smooth grid
- ) %>%
- as.data.frame() %>%
- mutate(effect = "Phonological awareness of participants")
- pred_meaning <- ggeffects::ggaverage(
- model_complex_cont,
- terms = "meaningfulness_scale [n=100]"
- ) %>%
- as.data.frame() %>%
- mutate(effect = "Meaningfulness of items")
- preds_2ABSI <- bind_rows(pred_nonword, pred_meaning)
- # 2) Plot (2 facets next to each other)
- fig_ABSI_behav <- ggplot(preds_2ABSI, aes(x = x, y = predicted)) +
- geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = 0.18, fill="#4C72B0") +
- geom_line(size = 1.2, colour="#4C72B0") +
- facet_wrap(~ effect, nrow = 1, scales = "free_x") +
- theme_classic(base_size = 13) +
- labs(
- x = NULL,
- y = "p(response 'old'|lure)"
- ) +
- scale_y_continuous(limits = c(0, 0.5), expand = expansion(mult = c(0.02, 0.06))) +
- custom_theme
- fig_ABSI_behav
- ```
- ```{r}
- # 3) Export (matches your Figure2B export approach)
- text_base_export <- 40
- fig_ABSI_export <- fig_ABSI_behav +
- theme_classic(base_size = text_base_export) +
- theme(
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05)
- )
- ggsave(
- "derivatives/figures/SI_figures/Figure2ABSI.png",
- plot = fig_ABSI_export,
- width = 21, height = 11, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- #### Encoding ANCOVA MEDIAN SPLIT (Digit-Symbol)
- ```{r}
- df <- semmst_merged_data_H1_nooutlier %>%
- drop_na(Digit_Symbol) %>%
- mutate(Digit_Symbol_scale = scale(Digit_Symbol))
- df_E1 <- df %>%
- mutate(
- digit_group = if_else(Digit_Symbol_scale >= median(Digit_Symbol_scale, na.rm = TRUE), "High", "Low"),
- digit_group = factor(digit_group, levels = c("Low", "High"))
- )
- semmst_merged_data_E1_digit_median_split = df_E1 %>%
- group_by(stim_type, digit_group) %>%
- pairwise_t_test(
- estimate ~ order,
- paired = TRUE,
- detailed = TRUE,
- ) %>%
- ungroup() %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_data_E1_digit_median_split
- # stim_type digit_group estimate .y. group1 group2 n1 n2 statistic p df conf.low conf.high method alternative p.adj
- ## 1 Exact Low 0.221 estimate First Repeat 28 28 8.04 1.22e-8 27 0.164 0.277 T-test two.sided 4.88e-8 ****
- ## 2 Exact High 0.158 estimate First Repeat 28 28 4.92 3.82e-5 27 0.0923 0.225 T-test two.sided 1.53e-4 ***
- ## 3 Lure Low 0.0490 estimate First Repeat 28 28 1.54 1.36e-1 27 -0.0165 0.115 T-test two.sided 5.44e-1 ns
- ## 4 Lure High 0.0949 estimate First Repeat 28 28 3.53 2 e-3 27 0.0397 0.150 T-test two.sided 8 e-3 **
- ```
- ##### Supplementary Figure 2C.
- ```{r}
- fig_mediansplit_CSI_dodge <- 0.8
- # OPTIONAL but recommended if you have multiple rows per ID/condition (e.g., ROI clusters):
- # collapse to one value per ID × stim_type × order × digit_group
- df_E1_collapsed <- df_E1 %>%
- group_by(ID, stim_type, order, digit_group) %>%
- mutate(stim_type = factor(as.character(stim_type),
- levels = c("Exact", "Lure"),
- labels = c("Exact", "Modified"))) %>%
- mutate(digit_group = factor(as.character(digit_group),
- levels = c("Low", "High"),
- labels = c("Low processing speed", "High processing speed")))
- # --- summary for bars (within-subject correction for stim_type+order, between = digit_group) ---
- fig_mediansplit_CSI_barsum <- Rmisc::summarySEwithin(
- data = df_E1_collapsed,
- measurevar = "estimate",
- withinvars = c("stim_type", "order"),
- betweenvars = "digit_group",
- idvar = "ID",
- na.rm = TRUE
- )
- # --- paired tests: First vs Repeat within each stim_type × digit_group ---
- fig_mediansplit_CSI_stat.test <- df_E1_collapsed %>%
- group_by(stim_type, digit_group) %>%
- pairwise_t_test(
- estimate ~ order,
- paired = TRUE,
- detailed = TRUE
- ) %>%
- ungroup() %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance("p.adj") %>%
- mutate(
- label = case_when(
- p.adj < 0.001 ~ "p < .001",
- p.adj < 0.01 ~ "p < .01",
- p.adj < 0.05 ~ "p < .05",
- TRUE ~ paste0("p = ", sub("^0", "", sprintf("%.2f", p.adj)))
- )
- )
- # y positions per facet + stim_type
- fig_mediansplit_CSI_stat.test <- fig_mediansplit_CSI_stat.test %>%
- left_join(
- fig_mediansplit_CSI_barsum %>%
- group_by(stim_type, digit_group) %>%
- summarise(y.position = max(estimate + se, na.rm = TRUE) * 1.08, .groups = "drop"),
- by = c("stim_type", "digit_group")
- ) %>%
- mutate(
- stim_idx = as.numeric(stim_type),
- xmin = stim_idx - fig_mediansplit_CSI_dodge/2,
- xmax = stim_idx + fig_mediansplit_CSI_dodge/2
- )
- # --- plot ---
- fig_mediansplit_CSI_plot <- ggplot(
- fig_mediansplit_CSI_barsum,
- aes(x = stim_type, y = estimate, fill = stim_type, group = order)
- ) +
- geom_col(
- aes(alpha = order),
- position = position_dodge(width = fig_mediansplit_CSI_dodge),
- width = 0.65
- ) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = fig_mediansplit_CSI_dodge),
- width = 0.15, size = 1.2
- ) +
- facet_wrap(~ digit_group) +
- theme_classic(base_size = 13) +
- labs(
- x = "Condition during encoding",
- y = "Mean % signal change",
- fill = "Stimulus",
- alpha = "Order"
- ) +
- scale_fill_manual(values = c(
- "Exact" = "#66BB6A",
- "Modified" = "#9575CD"
- )) +
- scale_alpha_manual(values = c(
- "First" = 0.95,
- "Repeat" = 0.55
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.14))) +
- custom_theme +
- guides(fill = "none") +
- theme(
- legend.position = c(0.88, 0.13)
- )
- fig_mediansplit_CSI_plot +
- ggpubr::stat_pvalue_manual(
- fig_mediansplit_CSI_stat.test,
- label = "label",
- xmin = "xmin",
- xmax = "xmax",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.shorten = 1.2,
- size = 5.4,
- bracket.size = 1.0
- )
- ```
- ```{r}
- text_base_export <- 40
- fig_mediansplit_CSI_plot_export <- fig_mediansplit_CSI_plot +
- ggpubr::stat_pvalue_manual(
- fig_mediansplit_CSI_stat.test,
- label = "label",
- xmin = "xmin",
- xmax = "xmax",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.shorten = 1.2,
- size = 8.4,
- bracket.size = 1.4
- ) +
- theme_classic(base_size = text_base_export) +
- theme(
- legend.position = c(0.88, 0.12),
- legend.title = element_text(size = text_base_export * 0.88),
- legend.text = element_text(size = text_base_export * 0.90),
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05)
- )
- ggsave(
- "derivatives/figures/SI_figures/Figure2CSI.png",
- plot = fig_mediansplit_CSI_plot_export,
- width = 21, height = 13, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- ### Revised Supplementary Results 2 - Exact, close, distant
- ```{r}
- # HELPERS
- parse_roi_clean_anat <- function(roi_string) {
- roi_string <- as.character(roi_string)
- dplyr::case_when(
- str_detect(roi_string, regex("CA12|CA1/2|CA1_2|CA1-2|CA1", ignore_case = TRUE)) ~ "CA12",
- str_detect(roi_string, regex("DGCA3|DGCA23|DG-CA3|DG-CA23|DG", ignore_case = TRUE)) ~ "DGCA3",
- str_detect(roi_string, regex("SUB", ignore_case = TRUE)) ~ "SUB",
- TRUE ~ NA_character_
- )
- }
- # BODY DATA FROM ORIGINAL ANATOMICAL TABLE
- H1_clodis_anat_body <- semmst_merged_data_filtered_anat %>%
- filter(task == "EncodingFirst") %>%
- filter(cope_name %in% c("ExactRepeat", "CloseRepeat", "DistantRepeat")) %>%
- mutate(
- roi_cluster = paste(hemisphere, roi, sep = "_"),
- roi_type = if_else(str_detect(roi_cluster, "HEAD"), "head", "body")
- ) %>%
- filter(roi_type == "body") %>%
- mutate(
- condition = recode(
- cope_name,
- "ExactRepeat" = "Exact",
- "CloseRepeat" = "Close",
- "DistantRepeat" = "Distant"
- ),
- hemi_lab = case_when(
- hemisphere == "L" ~ "Left hemisphere",
- hemisphere == "R" ~ "Right hemisphere",
- TRUE ~ as.character(hemisphere)
- ),
- roi_clean = parse_roi_clean_anat(roi_cluster)
- ) %>%
- dplyr::select(
- ID, task, cope_name, condition, estimate,
- hemisphere, hemi_lab, roi, roi_clean, roi_cluster, roi_type,
- everything()
- )
- # HEAD DATA FROM SUPPLEMENTARY ANATOMICAL TABLE
- H1_clodis_anat_head <- semmst_merged_data_supplement_filtered %>%
- filter(contrast == "anatHC_berron") %>%
- filter(task == "EncodingFirst") %>%
- filter(cope_name %in% c("ExactRepeat", "CloseRepeat", "DistantRepeat")) %>%
- mutate(
- roi = str_remove(roi, "^_"),
- roi = str_remove(roi, "^HEAD"),
- roi = str_remove(roi, "^_"),
- roi_type = "head",
- roi_cluster = paste(hemisphere, roi, sep = "_")
- ) %>%
- mutate(
- condition = recode(
- cope_name,
- "ExactRepeat" = "Exact",
- "CloseRepeat" = "Close",
- "DistantRepeat" = "Distant"
- ),
- hemi_lab = case_when(
- hemisphere == "L" ~ "Left hemisphere",
- hemisphere == "R" ~ "Right hemisphere",
- TRUE ~ as.character(hemisphere)
- ),
- roi_clean = parse_roi_clean_anat(roi_cluster)
- ) %>%
- dplyr::select(
- ID, task, cope_name, condition, estimate,
- hemisphere, hemi_lab, roi, roi_clean, roi_cluster, roi_type,
- everything()
- )
- # MERGE HEAD AND BODY
- H1_clodis_anat <- bind_rows(
- H1_clodis_anat_head,
- H1_clodis_anat_body
- ) %>%
- mutate(
- condition = factor(condition, levels = c("Exact", "Close", "Distant")),
- roi_type = factor(roi_type, levels = c("head", "body")),
- hemi_lab = factor(hemi_lab, levels = c("Left hemisphere", "Right hemisphere")),
- roi_clean = factor(roi_clean, levels = c("CA12", "DGCA3", "SUB"))
- )
- # ASSUMPTION CHECKS
- ## OUTLIER
- H1_clodis_anat %>%
- group_by(roi_type, hemi_lab, roi_clean, condition) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, roi_type, hemi_lab, roi_clean, condition, is.outlier, is.extreme) %>%
- filter(is.extreme == TRUE)
- # REMOVE OUTLIERS IF NEEDED
- H1_clodis_anat_nooutlier <- H1_clodis_anat %>%
- filter(! ID %in% c("sub-632012", "sub-499854")) %>%
- drop_na(estimate) %>%
- ungroup()
- ## NORMALITY
- H1_clodis_anat_nooutlier %>%
- group_by(roi_type, hemi_lab, roi_clean, condition) %>%
- shapiro_test(estimate)
- # ANOVA
- # condition effect is tested separately within each anatomical facet
- H1_clodis_anat_AOV = H1_clodis_anat_nooutlier %>%
- anova_test(
- dv = estimate,
- wid = ID,
- within = c(condition, roi_type, hemi_lab, roi_clean),
- )
- get_anova_table(H1_clodis_anat_AOV)
- # POST-HOC
- # pairwise comparisons - FWE correction across conditions only within each facet
- H1_clodis_anat_PWC <- H1_clodis_anat_nooutlier %>%
- group_by(roi_type, hemi_lab, roi_clean) %>%
- pairwise_t_test(
- estimate ~ condition,
- paired = TRUE,
- detailed = TRUE,
- p.adjust.method = "holm"
- ) %>%
- ungroup() %>%
- add_significance("p") %>%
- mutate(
- label = case_when(
- p < .001 ~ "p < .001",
- p < .01 ~ "p < .01",
- p < .05 ~ paste0("p = ", sub("^0", "", sprintf("%.3f", p))),
- TRUE ~ paste0("p = ", sub("^0", "", sprintf("%.2f", p)))
- )
- )
- H1_clodis_anat_PWC %>% print(n=40)
- ```
- ##### Revised Supplementary Figure 3
- ```{r}
- # BARPLOT SUMMARY
- fig_anat_barsum <- Rmisc::summarySEwithin(
- data = H1_clodis_anat_nooutlier,
- measurevar = "estimate",
- withinvars = c("condition", "roi_type", "hemi_lab", "roi_clean"),
- idvar = "ID",
- na.rm = TRUE
- ) %>%
- mutate(
- condition = factor(as.character(condition), levels = c("Exact", "Close", "Distant")),
- roi_type = factor(roi_type, levels = c("head", "body")),
- hemi_lab = factor(hemi_lab, levels = c("Left hemisphere", "Right hemisphere")),
- roi_clean = factor(roi_clean, levels = c("CA12", "DGCA3", "SUB"))
- )
- # SIGNIFICANT FWE-CORRECTED PAIRWISE BRACKETS
- fig_anat_stat.test <- H1_clodis_anat_PWC %>%
- dplyr::filter(p < .05) %>%
- mutate(
- roi_type = factor(roi_type, levels = c("head", "body")),
- hemi_lab = factor(hemi_lab, levels = c("Left hemisphere", "Right hemisphere")),
- roi_clean = factor(roi_clean, levels = c("CA12", "DGCA3", "SUB")),
- label = case_when(
- p < .001 ~ "p < .001",
- p < .01 ~ "p < .01",
- p < .05 ~ paste0("p = ", sub("^0", "", sprintf("%.3f", p))),
- TRUE ~ paste0("p = ", sub("^0", "", sprintf("%.2f", p)))
- )
- )
- # BRACKET HEIGHTS
- fig_anat_ypos <- fig_anat_barsum %>%
- dplyr::group_by(roi_type, hemi_lab, roi_clean) %>%
- dplyr::summarise(
- y_max = max(estimate + se, na.rm = TRUE),
- y_min = min(estimate - se, na.rm = TRUE),
- y_span = y_max - y_min,
- .groups = "drop"
- ) %>%
- dplyr::mutate(
- y_span = if_else(y_span == 0 | is.na(y_span), 0.1, y_span),
- y_base = y_max + 0.10 * y_span,
- y_step = 0.12 * y_span
- )
- # STACK BRACKETS WITHIN EACH FACET
- fig_anat_stat.test <- fig_anat_stat.test %>%
- dplyr::left_join(fig_anat_ypos, by = c("roi_type", "hemi_lab", "roi_clean")) %>%
- dplyr::group_by(roi_type, hemi_lab, roi_clean) %>%
- dplyr::arrange(group1, group2, .by_group = TRUE) %>%
- dplyr::mutate(y.position = y_base + (dplyr::row_number() - 1) * y_step) %>%
- dplyr::ungroup()
- # PANEL FUNCTION
- make_anat_panel <- function(which_type, title_txt,
- base_size = 14,
- bar_width = 0.68,
- err_width = 0.12,
- err_size = 1.1,
- p_size = 4.2,
- p_bracket = 0.9) {
- p_dat <- fig_anat_barsum %>%
- dplyr::filter(roi_type == which_type)
- p_sig <- fig_anat_stat.test %>%
- dplyr::filter(roi_type == which_type)
- p <- ggplot(
- p_dat,
- aes(x = condition, y = estimate, fill = condition)
- ) +
- geom_col(width = bar_width) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- width = err_width,
- linewidth = err_size
- ) +
- facet_grid(rows = vars(roi_clean), cols = vars(hemi_lab), scales = "free_y") +
- scale_fill_manual(values = c(
- "Exact" = "#66BB6A",
- "Close" = "#4477AA",
- "Distant" = "#DDCC77"
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.03, 0.22))) +
- coord_cartesian(clip = "off") +
- labs(
- x = "Conditions of repeats during encoding",
- y = "Mean % signal change",
- title = title_txt
- ) +
- theme_classic(base_size = base_size) +
- custom_theme +
- guides(fill = "none") +
- theme(
- plot.title = element_text(hjust = 0.5, face = "bold"),
- strip.background = element_blank(),
- strip.text = element_text(face = "bold"),
- panel.spacing.x = unit(1.25, "lines"),
- panel.spacing.y = unit(0.6, "lines")
- )
- # ADD BRACKETS ONLY IF SIGNIFICANT TESTS EXIST
- if (nrow(p_sig) > 0) {
- p <- p +
- ggpubr::stat_pvalue_manual(
- p_sig,
- label = "label",
- xmin = "group1",
- xmax = "group2",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = FALSE,
- inherit.aes = FALSE,
- bracket.shorten = 0.05,
- size = p_size,
- bracket.size = p_bracket
- )
- }
- p
- }
- # VIEW
- p_head_view <- make_anat_panel(
- "head", "Hippocampal head",
- base_size = 14,
- bar_width = 0.68,
- err_width = 0.12,
- err_size = 1.1,
- p_size = 4.2,
- p_bracket = 0.9
- )
- p_body_view <- make_anat_panel(
- "body", "Hippocampal body",
- base_size = 14,
- bar_width = 0.68,
- err_width = 0.12,
- err_size = 1.1,
- p_size = 4.2,
- p_bracket = 0.9
- )
- supp_fig_anat_bars <- p_head_view | p_body_view
- supp_fig_anat_bars
- ```
- ```{r}
- # EXPORT
- text_base_export <- 24
- FigureSI3_export_theme <- theme_classic(base_size = text_base_export) +
- theme(
- axis.text.x = element_text(size = text_base_export * 0.80, margin = margin(t = 6)),
- axis.text.y = element_text(size = text_base_export * 0.80),
- axis.title.x = element_text(size = text_base_export * 0.95, margin = margin(t = 10)),
- axis.title.y = element_text(size = text_base_export * 0.95, margin = margin(r = 10)),
- # more visible square facet boxes
- strip.background = element_rect(
- fill = "white",
- colour = "black",
- linewidth = 1.0
- ),
- strip.text = element_text(
- size = text_base_export * 0.76,
- face = "bold",
- margin = margin(4, 8, 4, 8)
- ),
- plot.title = element_text(size = text_base_export * 1.00, face = "bold", hjust = 0.5),
- legend.position = "none",
- panel.spacing.x = unit(0.9, "lines"),
- panel.spacing.y = unit(0.9, "lines"),
- panel.grid.major = element_blank(),
- panel.grid.minor = element_blank(),
- panel.border = element_blank(),
- axis.line = element_line(linewidth = 0.5)
- )
- p_head_export <- make_anat_panel(
- "head", "Hippocampal head",
- base_size = text_base_export,
- bar_width = 0.65,
- err_width = 0.15,
- err_size = 1.1,
- # slightly smaller p labels/brackets
- p_size = 5.8,
- p_bracket = 0.65
- ) +
- FigureSI3_export_theme +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.16)))
- p_body_export <- make_anat_panel(
- "body", "Hippocampal body",
- base_size = text_base_export,
- bar_width = 0.65,
- err_width = 0.15,
- err_size = 1.1,
- # slightly smaller p labels/brackets
- p_size = 5.8,
- p_bracket = 0.65
- ) +
- FigureSI3_export_theme +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.16)))
- supp_fig_anat_bars_export <- p_head_export | p_body_export
- ggsave(
- "derivatives/figures/SI_figures/Figure3SI.png",
- plot = supp_fig_anat_bars_export,
- width = 23, height = 12, units = "in",
- dpi = 300,
- bg = "white",
- device = ragg::agg_png
- )
- ```
- ### Revised Supplementary Results 3 - anatomical masks
- ```{r}
- # BODY ROIs from the original anatomical dataset
- revision_results3_body_from_anat <- semmst_merged_data_filtered_anat %>%
- filter(task == "Encoding") %>%
- filter(cope_name %in% c("LureFirst", "ExactFirst", "LureRepeat", "ExactRepeat")) %>%
- filter(!str_detect(roi, "HEAD")) %>%
- extract(
- col = cope_name,
- into = c("stim_type", "order"),
- regex = "([A-Za-z]+?)(First|Repeat)$"
- ) %>%
- mutate(
- stim_type = as.factor(stim_type),
- order = as.factor(order)
- ) %>%
- mutate(
- stim_type = factor(stim_type, levels = c("Exact", "Lure")),
- order = factor(order),
- roi_type = "body"
- )
- # HEAD/other supplement anatomical data
- revision_results3_supplement_anat <- semmst_merged_data_supplement_filtered %>%
- filter(contrast == "anatHC_berron") %>%
- filter(task == "Encoding") %>%
- filter(cope_name %in% c("LureFirst", "ExactFirst", "LureRepeat", "ExactRepeat")) %>%
- extract(
- col = cope_name,
- into = c("stim_type", "order"),
- regex = "([A-Za-z]+?)(First|Repeat)$"
- ) %>%
- mutate(
- stim_type = as.factor(stim_type),
- order = as.factor(order),
- roi = str_remove(roi, "^_"),
- roi = str_remove(roi, "^HEAD"),
- roi = str_remove(roi, "^_"),
- roi_type = if_else(str_detect(roi_cluster, "HEAD") | str_detect(roi, "^SUB|^CA1|^DGCA23"), "head", "body")
- ) %>%
- mutate(
- stim_type = factor(stim_type, levels = c("Exact", "Lure")),
- order = factor(order)
- )
- # MERGE body anat + supplement anat
- semmst_merged_data_supplement_filtered_revision_results3 = bind_rows(
- revision_results3_body_from_anat,
- revision_results3_supplement_anat
- ) %>%
- mutate(
- roi_type = factor(roi_type, levels = c("head", "body"))
- )
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_merged_data_supplement_filtered_revision_results3 %>%
- group_by(stim_type, order, roi_type, roi, hemisphere) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, roi_type, roi, hemisphere, is.outlier, is.extreme) %>%
- filter(is.extreme == TRUE)
- semmst_merged_data_supplement_filtered_revision_results3_nooutlier = semmst_merged_data_supplement_filtered_revision_results3 %>%
- group_by(stim_type, order, roi_type, roi, hemisphere) %>%
- filter(!ID %in% c("sub-499854", "sub-982347")) %>%
- ungroup()
- ## NORMALITY
- semmst_merged_data_supplement_filtered_revision_results3_nooutlier %>%
- group_by(stim_type, order, roi_type) %>%
- shapiro_test(estimate)
- # ANOVA
- semmst_merged_data_supplement_filtered_revision_results3_nooutlier_AOV = semmst_merged_data_supplement_filtered_revision_results3_nooutlier %>%
- anova_test(
- dv = estimate,
- wid = ID,
- within = c(stim_type, order, roi_type, roi, hemisphere)
- )
- get_anova_table(semmst_merged_data_supplement_filtered_revision_results3_nooutlier_AOV)
- # REPORT Effect DFn DFd F p p<.05 ges
- ## 2 order 1.00 27.00 10.116 4.00e-03 * 1.70e-02
- ## 7 stim_type:roi_type 1.00 27.00 5.878 2.20e-02 * 2.00e-03
- ## 8 order:roi_type 1.00 27.00 28.916 1.11e-05 * 1.90e-02
- ## 9 stim_type:roi 2.00 54.00 4.116 2.20e-02 * 2.00e-03
- ## 10 order:roi 1.61 43.44 4.124 3.00e-02 * 2.00e-03
- ## 11 roi_type:roi 2.00 54.00 13.740 1.50e-05 * 2.70e-02
- ## 13 order:hemisphere 1.00 27.00 6.667 1.60e-02 * 2.00e-03
- ## 18 stim_type:roi_type:roi 2.00 54.00 3.655 3.20e-02 * 9.16e-04
- ## 25 roi_type:roi:hemisphere 2.00 54.00 3.282 4.50e-02 * 3.00e-03
- ## 29 stim_type:roi_type:roi:hemisphere 2.00 54.00 5.885 5.00e-03 * 1.00e-03
- ```
- ##### Revised Supplementary Figure 4.
- ```{r}
- FigureR3_dodge <- 0.8
- # within-subject summary per stim_type × order × roi_type × roi × hemisphere
- FigureR3_barsum <- Rmisc::summarySEwithin(
- data = semmst_merged_data_supplement_filtered_revision_results3_nooutlier,
- measurevar = "estimate",
- withinvars = c("stim_type", "order", "roi_type", "roi", "hemisphere"),
- idvar = "ID",
- na.rm = TRUE
- ) %>%
- mutate(
- stim_type = factor(stim_type, levels = c("Exact", "Lure")),
- order = factor(order, levels = c("First", "Repeat")),
- roi_type = factor(roi_type, levels = c("head", "body")),
- roi = factor(roi),
- hemisphere = factor(
- hemisphere,
- levels = c("L", "R"),
- labels = c("Left hemisphere", "Right hemisphere")
- )
- ) %>%
- mutate(
- stim_type = factor(
- as.character(stim_type),
- levels = c("Exact", "Lure"),
- labels = c("Exact", "Modified")
- )
- )
- FigureR3_cols <- c(
- "Exact" = "#66BB6A",
- "Modified" = "#9575CD"
- )
- FigureR3_make_panel <- function(df) {
- ggplot(
- df,
- aes(
- x = stim_type,
- y = estimate,
- fill = stim_type,
- alpha = order,
- group = order
- )
- ) +
- geom_col(
- position = position_dodge(width = FigureR3_dodge),
- width = 0.65
- ) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = FigureR3_dodge),
- width = 0.15,
- linewidth = 1.1
- ) +
- facet_grid(rows = vars(roi), cols = vars(hemisphere)) +
- theme_classic(base_size = 13) +
- labs(
- x = "Condition during encoding",
- y = "Mean % signal change",
- alpha = "Order"
- ) +
- scale_fill_manual(values = FigureR3_cols) +
- scale_alpha_manual(values = c("First" = 0.95, "Repeat" = 0.55)) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.12))) +
- guides(
- fill = "none",
- alpha = guide_legend(title = "Order")
- ) +
- theme(
- strip.background = element_blank(),
- strip.text = element_text(face = "bold"),
- panel.spacing = unit(0.6, "lines")
- )
- }
- # Left panel (head): no legend
- FigureR3_head_plot <- FigureR3_barsum %>%
- filter(roi_type == "head") %>%
- FigureR3_make_panel() +
- ggtitle("Hippocampal head") +
- theme(
- plot.title = element_text(hjust = 0.5, face = "bold"),
- legend.position = "none"
- )
- # Right panel (body): legend inset top-right
- FigureR3_body_plot <- FigureR3_barsum %>%
- filter(roi_type == "body") %>%
- FigureR3_make_panel() +
- ggtitle("Hippocampal body") +
- theme(
- plot.title = element_text(hjust = 0.5, face = "bold"),
- legend.position = c(0.98, 0.98),
- legend.justification = c(1, 1),
- legend.background = element_rect(fill = alpha("white", 0.75), colour = NA),
- legend.key = element_blank()
- )
- # Combine as two columns
- FigureR3_plot <- (FigureR3_head_plot | FigureR3_body_plot)
- FigureR3_plot
- ```
- ```{r}
- text_base_export <- 24 # 20–28 usually looks best for this many facets
- # IMPORTANT: do NOT set legend.position in the export theme
- FigureR3_export_theme <- theme_classic(base_size = text_base_export) +
- theme(
- axis.text.x = element_text(size = text_base_export * 0.80, margin = margin(t = 6)),
- axis.text.y = element_text(size = text_base_export * 0.80),
- axis.title.x = element_text(size = text_base_export * 0.95, margin = margin(t = 10)),
- axis.title.y = element_text(size = text_base_export * 0.95, margin = margin(r = 10)),
- strip.text = element_text(size = text_base_export * 0.85, face = "bold"),
- plot.title = element_text(size = text_base_export * 1.05, face = "bold", hjust = 0.5),
- legend.title = element_text(size = text_base_export * 0.85),
- legend.text = element_text(size = text_base_export * 0.80),
- panel.spacing = unit(0.8, "lines")
- )
- # Apply export theme per panel + enforce legend behavior
- FigureR3_head_export <- FigureR3_head_plot &
- FigureR3_export_theme &
- theme(legend.position = "none")
- FigureR3_body_export <- FigureR3_body_plot &
- FigureR3_export_theme &
- theme(
- legend.position = c(0.98, 0.98), # inside top-right of RIGHT panel
- legend.justification = c(1, 1),
- legend.background = element_rect(fill = alpha("white", 0.75), colour = NA),
- legend.key = element_blank()
- )
- FigureR3_plot_export <- FigureR3_head_export | FigureR3_body_export
- ggsave(
- "derivatives/figures/SI_figures/Figure4SI.png",
- plot = FigureR3_plot_export,
- width = 23, height = 12, units = "in",
- dpi = 300, bg = "white", device = ragg::agg_png
- )
- ```
- ### Supplementary Results 4 - close vs distant REC
- ```{r}
- semmst_merged_data_filtered_H4b_REC_clodis = semmst_merged_data_filtered %>%
- filter(task == "RecognitionRespCloDis") %>%
- filter(cope_name %in% c("DistantCR", "CloseCR"))
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_merged_data_filtered_H4b_REC_clodis %>%
- group_by(cope_name, roi_cluster) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, roi_cluster, cope_name, is.outlier, is.extreme) %>%
- filter(is.extreme==TRUE)
- semmst_merged_data_filtered_H4b_REC_clodis_nooutlier = semmst_merged_data_filtered_H4b_REC_clodis %>%
- ungroup()
- semmst_merged_H4b_REC_clodis_PWC = semmst_merged_data_filtered_H4b_REC_clodis_nooutlier %>%
- group_by(roi_cluster) %>%
- pairwise_t_test(
- estimate ~ cope_name,
- paired = TRUE,
- detailed = TRUE,
- ) %>%
- ungroup() %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_H4b_REC_clodis_PWC
- # REP roi_cluster estimate .y. group1 group2 n1 n2 statistic p df conf.low conf.high method alternative p.adj
- ## 1 L_HEAD_DGCA23_HEAD_SUB_14 -0.110 estimate CloseCR Distan… 30 30 -1.55 0.133 29 -0.255 0.0355 T-test two.sided 0.266 ns
- ## 2 R_HEAD_DGCA23_HEAD_SUB_15 -0.0498 estimate CloseCR Distan… 30 30 -1.07 0.294 29 -0.145 0.0455 T-test two.sided 0.588 ns
- ```
- #### Supplementary Figure 5.
- ```{r}
- # BARPLOT
- figSI_clodisREC_dodge <- 0.8
- figSI_clodisREC_barsum <- Rmisc::summarySEwithin(
- data = semmst_merged_data_filtered_H4b_REC_clodis,
- measurevar = "estimate",
- withinvars = c("cope_name", "roi_cluster"),
- idvar = "ID",
- na.rm = TRUE
- )
- figSI_clodisREC_roi_lab <- semmst_merged_data_filtered_H4_REC_conditions_nooutlier %>%
- distinct(roi_cluster, hemisphere, roi, cluster, voxels) %>%
- mutate(
- roi_label = case_when(
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "R" ~ "Right hippocampal head cluster",
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "L" ~ "Left hippocampal head cluser",
- TRUE ~ NA_character_
- )
- ) %>%
- select(roi_cluster, roi_label)
- figSI_clodisREC_level_map <- c("CloseCR", "DistantCR")
- figSI_clodisREC_level_lab <- c("Close lure", "Distant lure")
- figSI_clodisREC_barsum <- figSI_clodisREC_barsum %>%
- mutate(cope_name = factor(cope_name, levels = figSI_clodisREC_level_map, labels = figSI_clodisREC_level_lab)) %>%
- left_join(figSI_clodisREC_roi_lab, by = "roi_cluster")
- figSI_clodisREC_plot <- ggplot(figSI_clodisREC_barsum, aes(x = cope_name, y = estimate, fill = cope_name)) +
- geom_col(position = position_dodge(width = figSI_clodisREC_dodge), width = 0.65) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = figSI_clodisREC_dodge),
- width = 0.15,
- size = 1.2
- ) +
- facet_wrap(~ roi_label) +
- theme_classic(base_size = 13) +
- labs(x = "Condition during recognition", y = "Mean % signal change") +
- scale_fill_manual(values = c(
- "Close lure" = "#4477AA",
- "Distant lure" = "#DDCC77"
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.12))) +
- custom_theme +
- guides(fill = "none")
- figSI_clodisREC_plot
- ```
- ```{r}
- text_base_export=40
- figSI_clodisREC_plot_export <- figSI_clodisREC_plot +
- theme_classic(base_size = text_base_export) +
- theme(
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05),
- strip.text = element_text(size = text_base_export * 0.95)
- )
- ggsave(
- "derivatives/figures/SI_figures/Figure5SI.png",
- plot = figSI_clodisREC_plot_export,
- width = 22, height = 14, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- ### Supplementary Results 5 - Behaviour wo. covariates and outlier
- ```{r}
- semmst_behav_data_rec_LDI_ANOVA = semmst_behav_data_rec_summary %>%
- dplyr::select(ID, rec_dprime, close_dprime, distant_dprime) %>%
- gather("dprime_type", "dprime_value", rec_dprime:distant_dprime) %>%
- mutate(dprime_type = factor(dprime_type, levels = c("close_dprime", "rec_dprime", "distant_dprime"))) %>%
- left_join(semmst_behav_data_rec_filtered %>% dplyr::select(ID, age, sex, education, Vocabulary, Digit_Symbol, NonWord_sum) %>% distinct(), by="ID")
- semmst_behav_data_rec_LDI_ANCOVA = semmst_behav_data_rec_LDI_ANOVA %>%
- left_join(semmst_behav_data_rec_filtered %>% dplyr::select(ID, age, sex, education, Vocabulary, Digit_Symbol, NonWord_sum) %>% distinct(), by="ID") %>%
- mutate(Vocabulary_scale = scale(Vocabulary)) %>%
- mutate(Digit_Symbol_scale = scale(Digit_Symbol)) %>%
- mutate(NonWord_sum_scale = scale(NonWord_sum)) %>% drop_na()
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_behav_data_rec_LDI_ANOVA %>%
- group_by(dprime_type) %>%
- identify_outliers(dprime_value)
- ##NORMALITY
- semmst_behav_data_rec_LDI_ANOVA %>%
- group_by(dprime_type) %>%
- shapiro_test(dprime_value) %>% print(n=40)
- ggqqplot(semmst_behav_data_rec_LDI_ANOVA, "dprime_value", ggtheme = theme_bw()) +
- facet_grid(. ~ dprime_type, labeller = "label_both")
- # ANOVA
- ANOVA_behav_data_rec_LDI = semmst_behav_data_rec_LDI_ANOVA %>%
- anova_test(dv = dprime_value, wid = ID, within = c(dprime_type), covariate = c(sex, age))
- get_anova_table(ANOVA_behav_data_rec_LDI)
- # REPORT
- ## dprime_type 2 54 159.192 2.28e-23 * 0.493
- ```
- #### Supplementary Figure 6.
- ```{r}
- # 1) Prep & adjustment (remove linear effects of covariates)
- figSI_outlier_plot_base <- semmst_behav_data_rec_LDI_ANOVA %>%
- filter(!is.na(ID), !is.na(dprime_type), !is.na(dprime_value)) %>%
- mutate(
- dprime_type = factor(dprime_type),
- sex = factor(sex)
- )
- # order as: Close, Distant, Target
- figSI_outlier_contrast_order <- c("close_dprime", "distant_dprime", "rec_dprime")
- # order as: Close, Distant, Target
- figSI_outlier_contrast_order <- c("close_dprime", "distant_dprime", "rec_dprime")
- figSI_outlier_plot_base <- figSI_outlier_plot_base %>%
- mutate(dprime_type = fct_relevel(dprime_type, figSI_outlier_contrast_order))
- # covariate-only model for adjustment
- figSI_outlier_mod_cov <- lm(dprime_value ~ sex + age,
- data = figSI_outlier_plot_base)
- figSI_outlier_plot_base <- figSI_outlier_plot_base %>%
- mutate(dprime_adj = dprime_value - predict(figSI_outlier_mod_cov, newdata = figSI_outlier_plot_base) + mean(dprime_value, na.rm = TRUE))
- # 2) Labels & colors
- figSI_outlier_x_lab_map <- c(
- "close_dprime" = "Close\nlure",
- "distant_dprime" = "Distant\nlure",
- "rec_dprime" = "Foil"
- )
- # Paul Tol (muted): blue / yellow / red — CVD-safe, good in print & grayscale
- figSI_outlier_fill_vals <- c("close_dprime"="#4477AA", "distant_dprime"="#DDCC77", "rec_dprime"="#117733")
- # 3) Plot
- behav_figSI_outlier <- ggplot(figSI_outlier_plot_base, aes(x = dprime_type, y = dprime_adj, fill = dprime_type)) +
- geom_boxplot(width = 0.6, outlier.alpha = 0.4, linewidth = 1.8, color = "black") +
- stat_summary(fun = mean, geom = "point", shape = 21, size = 2.2, fill = "white", color = "black") +
- scale_x_discrete(labels = figSI_outlier_x_lab_map, drop = FALSE) +
- scale_fill_manual(values = figSI_outlier_fill_vals, guide = "none") +
- labs(
- x = "Discriminability contrasts",
- y = "Covariate-adjusted d'\n [p(\"old\"|target) - p(\"old\"|condition)]"
- ) +
- theme_classic(base_size = 14)
- behav_figSI_outlier
- ```
- ```{r}
- behav_figSI_outlier_export <- behav_figSI_outlier +
- theme_classic(base_size = 40) +
- theme(
- axis.title = element_text(size = 42),
- axis.text = element_text(size = 34)
- ) + labs(x = NULL)
- ggsave(
- "derivatives/figures/SI_figures/Figure6SI.png",
- plot = behav_figSI_outlier_export,
- width = 16, height = 12, units = "in",
- dpi = 300,
- bg = "white",
- device = "png" # base png
- )
- ```
- ### Supplementary Results 6 - Encoding wo. covariates and outlier
- #### ANOVA
- ```{r}
- # FILTER DATA
- semmst_merged_data_H1 = semmst_merged_data_filtered %>%
- filter(task == "Encoding") %>%
- filter(cope_name %in% c("LureFirst", "ExactFirst", "LureRepeat", "ExactRepeat")) %>%
- extract(
- col = cope_name,
- into = c("stim_type", "order"),
- regex = "([A-Za-z]+?)(First|Repeat)$"
- ) %>%
- mutate(
- stim_type = as.factor(stim_type),
- order = as.factor(order)
- ) %>%
- mutate(stim_type = factor(stim_type, levels = c("Exact", "Lure")))
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_merged_data_H1 %>%
- group_by(stim_type, order, roi_cluster) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, is.outlier, is.extreme) %>%
- filter(is.extreme==TRUE)
- semmst_merged_data_H1SI_nooutlier = semmst_merged_data_H1 %>%
- group_by(stim_type, order, roi_cluster) %>%
- #filter(! ID %in% c("sub-434971")) %>% #, " sub-012421", "sub-632012", "sub-800472")) %>% # c("sub-434971", "sub-982347")) %>%
- ungroup()
- ##NORMALITY
- semmst_merged_data_H1SI_nooutlier %>%
- group_by(stim_type, order) %>%
- shapiro_test(estimate)
- # ANOVA
- semmst_merged_data_H1SI_nooutlier_AOV = semmst_merged_data_H1SI_nooutlier %>%
- anova_test(dv = estimate, wid = ID, within = c(stim_type, order, roi_cluster))#, covariate = c(NonWord_sum_scale, Digit_Symbol_scale))
- get_anova_table(semmst_merged_data_H1SI_nooutlier_AOV)
- # REPORT Effect DFn DFd F p p<.05 ges
- ## 1 stim_type 1 29 16.545 3.33e-04 * 3.30e-02
- ## 2 order 1 29 54.775 3.73e-08 * 1.07e-01
- ## 4 stim_type:order 1 29 4.123 5.20e-02 1.60e-02
- ```
- #### Correlation
- ```{r}
- group_vars_H3SI <- c("ID", "mask_type", "space_type", "contrast", "roi_cluster")
- # baseline
- semmst_merged_data_H3SI_neural_ps = semmst_merged_data_filtered %>%
- filter(task %in% c("Encoding")) %>%
- filter(cope_name %in% c("ExactFirst", "ExactRepeat", "LureFirst","LureRepeat", "CloseFirst", "CloseRepeat", "DistantFirst", "DistantRepeat")) %>%
- dplyr::select(ID, space_type, cope_name, hemisphere, roi, mask_type, cluster, voxels, contrast, task, roi_cluster, roi_hemisphere, estimate, NonWord_sum_scale, Digit_Symbol_scale, rec_dprime:lure_incorrect) %>%
- group_by(across(all_of(group_vars_H3SI))) %>%
- pivot_wider(names_from = cope_name, values_from = estimate, values_fill = NA_real_) %>%
- mutate(
- # --- Non-RS bias scores (Exact denominator) ---
- LureBiasScore = LureRepeat - ExactRepeat,
- CloseBiasScore = CloseRepeat - ExactRepeat,
- DistantBiasScore = DistantRepeat - ExactRepeat
- ) %>%
- ungroup()
- # 1) Filter to the Exact subset and define roi_group
- df_corr_input_all_SI <- semmst_merged_data_H3SI_neural_ps %>%
- mutate(roi_group = roi_cluster) %>%
- dplyr::select(ID, roi_group, roi, hemisphere, cluster, voxels, LureBiasScore, lure_dprime, NonWord_sum_scale, Digit_Symbol_scale) %>%
- ungroup()
- df_corr_input_all_SI_nooutlier <- df_corr_input_all_SI %>%
- droplevels() %>%
- ungroup()
- # Fisher-z CI for Pearson r (95% hard-coded)
- pearson_ci <- function(r, n) {
- z <- atanh(r)
- se <- 1 / sqrt(n - 3)
- zcrit <- qnorm(1 - (1 - 0.95) / 2)
- c(low = tanh(z - zcrit * se), high = tanh(z + zcrit * se))
- }
- H3SI_corr_lure_simple <- df_corr_input_all_SI_nooutlier %>%
- group_by(roi_group) %>%
- group_modify(~{
- d_all <- .x
- # Pearson
- d_s <- d_all %>% dplyr::select(LureBiasScore, lure_dprime) %>% tidyr::drop_na()
- ct_s <- cor.test(d_s$LureBiasScore, d_s$lure_dprime, method = "pearson")
- r_s <- unname(ct_s$estimate)
- p_s <- ct_s$p.value
- n_s <- nrow(d_s)
- ci_s <- pearson_ci(r_s, n_s)
- tibble::tibble(
- n = n_s,
- r = r_s,
- p = p_s,
- ci = sprintf("[%.3f, %.3f]", ci_s["low"], ci_s["high"])
- )
- }) %>%
- ungroup() %>%
- mutate(
- p_adj = p.adjust(p, method = "bonferroni")
- ) %>%
- arrange(p_adj, p)
- H3SI_corr_lure_simple
- ```
- #### Supplementary Figure 7B
- ```{r}
- fig_corroutlier_BSI_dodge <- 0.8
- fig_corroutlier_BSI_barsum <- Rmisc::summarySEwithin(
- data = semmst_merged_data_H1SI_nooutlier,
- measurevar = "estimate",
- withinvars = c("stim_type","order","roi_cluster"),
- idvar = "ID",
- na.rm = TRUE
- ) %>%
- mutate(stim_type = factor(as.character(stim_type),
- levels = c("Exact","Lure"),
- labels = c("Exact","Modified")))
- fig_corroutlier_BSI_roi_lab <- semmst_merged_data_H1SI_nooutlier %>%
- distinct(roi_cluster, hemisphere, roi, cluster, voxels) %>%
- mutate(
- roi_label = case_when(
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "R" ~ "Right DG-CA2/3-SUB cluster",
- roi == "HEAD_DGCA23_HEAD_SUB" & hemisphere == "L" ~ "Left DG-CA2/3-SUB cluster",
- TRUE ~ as.character(roi_cluster)
- )
- ) %>%
- select(roi_cluster, roi_label)
- fig_corroutlier_BSI_barsum <- fig_corroutlier_BSI_barsum %>%
- left_join(fig_corroutlier_BSI_roi_lab, by = "roi_cluster")
- # bar plot
- fig_corroutlier_BSI <- ggplot(fig_corroutlier_BSI_barsum, aes(
- x = stim_type, y = estimate,
- fill = stim_type,
- group = order
- )) +
- geom_col(aes(alpha = order),
- position = position_dodge(width = fig_corroutlier_BSI_dodge),
- width = 0.65) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = fig_corroutlier_BSI_dodge),
- width = 0.15,
- size = 1.2
- ) +
- facet_wrap(~ roi_label) +
- theme_classic(base_size = 13) +
- labs(x = "Condition during encoding", y = "Mean % signal change", fill = "Stimulus", alpha = "Order") +
- scale_fill_manual(values = c(
- "Exact" = "#66BB6A",
- "Modified" = "#9575CD"
- )) +
- scale_alpha_manual(values = c(
- "First" = 0.95,
- "Repeat" = 0.55
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.12))) +
- custom_theme +
- guides(fill = "none")
- fig_corroutlier_BSI
- ```
- ```{r}
- text_base_export <- 40
- fig_corroutlier_BSI_export <- fig_corroutlier_BSI +
- theme_classic(base_size = text_base_export) +
- theme(
- legend.position = c(0.88, 0.88),
- legend.title = element_text(size = text_base_export * 0.88),
- legend.text = element_text(size = text_base_export * 0.90),
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05),
- strip.text = element_blank(),
- panel.spacing.x = unit(4, "in")
- )
- ggsave(
- "derivatives/figures/SI_figures/Figure7BSI.png",
- plot = fig_corroutlier_BSI_export,
- width = 26, height = 13, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- #### Supplementary Figure 7A
- ```{r}
- ID_HI <- "sub-434971"
- semmst_merged_data_H1SI_nooutlier_data <- semmst_merged_data_H1SI_nooutlier %>%
- filter(!is.na(estimate)) %>%
- mutate(
- highlight = (ID == ID_HI),
- # Column labels you asked for
- stim_col = case_when(
- stim_type == "Exact" ~ "Exact repeat",
- TRUE ~ "Modified repeat" # e.g., Lure -> Modified
- ),
- # Row labels you asked for
- roi_row = case_when(
- str_detect(roi_cluster, "^L$|L") ~ "Left DG-CA2/3-Subiculum",
- str_detect(roi_cluster, "^R$|R") ~ "Right DG-CA2/3-Subiculum",
- TRUE ~ as.character(roi_cluster)
- ),
- order_row = case_when(
- order == "First" ~ "First presentation",
- order == "Repeat" ~ "Repeat",
- TRUE ~ as.character(order)
- )
- ) %>%
- mutate(
- stim_col = factor(stim_col, levels = c("Exact repeat", "Modified repeat")),
- roi_row = factor(roi_row, levels = c("Left DG-CA2/3-Subiculum", "Right DG-CA2/3-Subiculum")),
- order_row = factor(order_row, levels = c("First presentation", "Repeat"))
- )
- # compute QQ points per facet (roi_row × order_row × stim_col) ---
- semmst_merged_data_H1SI_nooutlier_qq <- semmst_merged_data_H1SI_nooutlier_data %>%
- group_by(roi_row, order_row, stim_col) %>%
- arrange(estimate, .by_group = TRUE) %>%
- mutate(theoretical = qnorm(ppoints(n()))) %>%
- ungroup()
- # compute qqline (like R's qqline: through 25% and 75%) per facet ---
- semmst_merged_data_H1SI_nooutlier_lines <- semmst_merged_data_H1SI_nooutlier_qq %>%
- group_by(roi_row, order_row, stim_col) %>%
- summarise(
- y25 = quantile(estimate, 0.25, na.rm = TRUE),
- y75 = quantile(estimate, 0.75, na.rm = TRUE),
- x25 = qnorm(0.25),
- x75 = qnorm(0.75),
- slope = (y75 - y25) / (x75 - x25),
- intercept = y25 - slope * x25,
- .groups = "drop"
- )
- # plot (thin line, correct highlight, correct labels) ---
- fig_corroutlier_SIA_figure = ggplot(semmst_merged_data_H1SI_nooutlier_qq, aes(x = theoretical, y = estimate)) +
- geom_point(size = 2.4, alpha = 0.75, colour = "black") +
- geom_point(
- data = dplyr::filter(semmst_merged_data_H1SI_nooutlier_qq, highlight),
- size = 2.6, alpha = 0.95, colour = "red"
- ) +
- geom_abline(
- data = semmst_merged_data_H1SI_nooutlier_lines,
- aes(slope = slope, intercept = intercept),
- linewidth = 1.2,
- colour = "black"
- ) +
- facet_grid(roi_row + order_row ~ stim_col, labeller = label_value) +
- labs(
- x = "Theoretical quantiles",
- y = "Sample quantiles (% signal change)"
- ) +
- theme_bw()
- fig_corroutlier_SIA_figure
- ```
- ```{r}
- text_base_export <- 34 # tweak (28–40); 34 usually good for dense facet grids
- fig_corroutlier_SIA_export <- fig_corroutlier_SIA_figure +
- # bump dot sizes (both black + highlighted red)
- geom_point(size = 7.1, alpha = 0.75, colour = "black") +
- geom_point(
- data = dplyr::filter(semmst_merged_data_H1SI_nooutlier_qq, highlight),
- size = 10.3, alpha = 0.95, colour = "red"
- ) +
- # thicker qqline
- geom_abline(
- data = semmst_merged_data_H1SI_nooutlier_lines,
- aes(slope = slope, intercept = intercept),
- linewidth = 1.6,
- colour = "black"
- ) +
- theme_bw(base_size = text_base_export) +
- theme(
- axis.text.x = element_text(size = text_base_export * 0.85, margin = margin(t = 6)),
- axis.text.y = element_text(size = text_base_export * 0.85),
- axis.title.x = element_text(size = text_base_export * 0.95, margin = margin(t = 10)),
- axis.title.y = element_text(size = text_base_export * 0.95, margin = margin(r = 10)),
- strip.text = element_text(size = text_base_export * 0.80, face = "bold"),
- panel.spacing = unit(0.65, "lines"),
- plot.margin = margin(12, 12, 12, 12)
- )
- # install.packages("ragg")
- ggsave(
- "derivatives/figures/SI_figures/Figure7ASI.png",
- plot = fig_corroutlier_SIA_export,
- width = 16, height = 26, units = "in",
- dpi = 300, bg = "white", device = ragg::agg_png
- )
- ```
- #### Supplementary Figure 7C
- ```{r}
- ID_HI <- "sub-434971"
- # 1) Long table (ALL trials only)
- fig_corroutlierCSI_df <- df_corr_input_all_SI_nooutlier %>%
- dplyr::select(ID, roi_group, roi, hemisphere, bias = LureBiasScore, lure_dprime) %>%
- tidyr::drop_na(bias, lure_dprime) %>%
- dplyr::mutate(
- hemi_lab = dplyr::recode(hemisphere, L = "Left", R = "Right"),
- roi_clean = roi %>%
- gsub("HEAD_", "", .) %>%
- gsub("_", "-", .) %>%
- gsub("2", "", .),
- facet_lab = paste(hemi_lab, roi_clean)
- )
- # 2) Facet labels (no stats)
- fig_corroutlierCSI_labs <- fig_corroutlierCSI_df %>%
- dplyr::distinct(roi_group, facet_lab)
- # 3) Plot (base)
- fig_corroutlierCSI <- ggplot(
- fig_corroutlierCSI_df %>% mutate(highlight = (ID == ID_HI)),
- aes(bias, lure_dprime)
- ) +
- # all points
- geom_point(
- data = \(d) d %>% filter(!highlight),
- alpha = 0.7, size = 4.5, colour = "grey20"
- ) +
- # highlighted point on top
- geom_point(
- data = \(d) d %>% filter(highlight),
- alpha = 1, size = 6.2, colour = "red"
- ) +
- # regression line (single neutral colour)
- geom_smooth(method = "lm", se = FALSE, linewidth = 1.1, colour = "grey20") +
- facet_wrap(
- ~ roi_group, scales = "free",
- labeller = labeller(roi_group = setNames(fig_corroutlierCSI_labs$facet_lab, fig_corroutlierCSI_labs$roi_group))
- ) +
- labs(
- x = "Modified repeat - exact repeat estimates",
- y = "d' (lures vs targets)"
- ) +
- theme_classic(base_size = 18) +
- custom_theme +
- theme(
- panel.spacing = unit(4, "in") # big gap like your 6A; reduce if too much
- )
- fig_corroutlierCSI
- ```
- ```{r}
- text_base_export <- 40
- fig_corroutlierCSI_export <- fig_corroutlierCSI +
- theme_classic(base_size = text_base_export) +
- theme(
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05),
- panel.spacing = unit(4, "in"),
- strip.text = element_blank()
- ) +
- # make the line thicker for export (optional)
- geom_smooth(method = "lm", se = FALSE, linewidth = 2.6, colour = "grey20")
- ggsave(
- "derivatives/figures/SI_figures/Figure7CSI.png",
- plot = fig_corroutlierCSI_export,
- width = 26, height = 12, units = "in",
- dpi = 300, bg = "white", device = "png"
- )
- ```
- ### Supplementary Results 7 - Recognition per encoding status
- ```{r}
- # FoilCR baseline per ID x roi_cluster
- foil_baseline_df <- semmst_merged_data_filtered %>%
- filter(task == "RecognitionRespAll",
- cope_name == "FoilCR") %>%
- select(ID, roi_cluster, foil_baseline = estimate)
- # Target conditions + baseline correction
- semmst_merged_data_filtered_supp4_REC_conditions_bc <- semmst_merged_data_supplement_filtered %>%
- filter(task %in% c("RecognitionRespAllEncRepeat", "RecognitionRespAllEncSimilar"),
- cope_name %in% c("LureCR", "TargetHIT")) %>%
- left_join(foil_baseline_df, by = c("ID", "roi_cluster")) %>%
- mutate(estimate_bc = estimate - foil_baseline)
- # ASSUMPTION CHECKS
- ## OUTLIER
- semmst_merged_data_filtered_supp4_REC_conditions_bc %>%
- group_by(cope_name, task, roi_cluster) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, roi_cluster, cope_name, is.outlier, is.extreme) %>%
- filter(is.extreme==TRUE)
- semmst_merged_data_filtered_supp4_REC_conditions_bc_nooutlier = semmst_merged_data_filtered_supp4_REC_conditions_bc %>%
- #filter(!ID %in% c("sub-526930", "sub-468051")) %>%
- ungroup()
- semmst_merged_supp4_REC_conditions_bc_AOV = semmst_merged_data_filtered_supp4_REC_conditions_bc_nooutlier %>%
- droplevels() %>%
- anova_test(dv = estimate, wid = ID, within = c(cope_name, task, roi_cluster))#, covariate = c(NonWord_sum_scale))
- get_anova_table(semmst_merged_supp4_REC_conditions_bc_AOV)
- # Effect DFn DFd F p p<.05 ges
- ## 1 cope_name 1 29 2.597 0.118 8.00e-03
- ## 2 task 1 29 0.236 0.631 5.39e-04
- ## 4 cope_name:task 1 29 4.762 0.037 * 2.50e-02
- semmst_merged_data_filtered_supp4_REC_conditions_bc_nooutlier %>%
- ggplot(aes(x=cope_name, fill=task, y=estimate)) +
- geom_boxplot(position = position_dodge2()) +
- facet_wrap(~roi_cluster)
- # POST-HOC
- # pairwise comparisons - stim_type * order
- semmst_merged_supp4_REC_conditions_bc_PWC = semmst_merged_data_filtered_supp4_REC_conditions_bc_nooutlier %>%
- group_by(task) %>%
- pairwise_t_test(
- estimate ~ cope_name,
- paired = TRUE,
- detailed = TRUE,
- ) %>%
- ungroup() %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_supp4_REC_conditions_bc_PWC
- ## roi_cluster estimate .y. group1 group2 n1 n2 statistic p df conf.low conf.high method alternative p.adj
- ## 1 L_HEAD_DGCA23_HEAD_SUB_14 0.138 estimate FoilCR LureCR 30 30 3.43 0.002 29 0.0558 0.221 T-test two.sided 0.012 *
- ## 4 R_HEAD_DGCA23_HEAD_SUB_15 0.103 estimate FoilCR LureCR 30 30 3.05 0.005 29 0.0341 0.173 T-test two.sided 0.03 *
- # pairwise comparisons - stim_type * order
- semmst_merged_supp4_REC_conditions_bc_PWC = semmst_merged_data_filtered_supp4_REC_conditions_bc_nooutlier %>%
- group_by(cope_name) %>%
- mutate(task = forcats::fct_rev(task)) %>%
- pairwise_t_test(
- estimate ~ task,
- paired = TRUE,
- detailed = TRUE,
- ) %>%
- ungroup() %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- ungroup() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_supp4_REC_conditions_bc_PWC
- ```
- #### Revision Figure 4 - REC status
- ```{r}
- #### Revision Figure 4 - REC conditions, baseline-corrected, collapsed across ROI ----
- figR4_dodge <- 0.8
- Figure4_revision_rec_bc_nofacet_level_map_task <- c(
- "RecognitionRespAllEncRepeat",
- "RecognitionRespAllEncSimilar"
- )
- Figure4_revision_rec_bc_nofacet_level_lab_task <- c(
- "Exact repeat",
- "Modified repeat"
- )
- Figure4_revision_rec_bc_nofacet_level_map_cope <- c(
- "TargetHIT",
- "LureCR"
- )
- Figure4_revision_rec_bc_nofacet_level_lab_cope <- c(
- "Target hit",
- "Lure correct rejection"
- )
- # 1) Base plotting data
- Figure4_revision_rec_bc_nofacet_base <- semmst_merged_data_filtered_supp4_REC_conditions_bc_nooutlier %>%
- filter(
- task %in% Figure4_revision_rec_bc_nofacet_level_map_task,
- cope_name %in% Figure4_revision_rec_bc_nofacet_level_map_cope,
- roi_cluster %in% c("L_HEAD_DGCA23_HEAD_SUB_14", "R_HEAD_DGCA23_HEAD_SUB_15")
- ) %>%
- mutate(
- task = factor(
- task,
- levels = Figure4_revision_rec_bc_nofacet_level_map_task,
- labels = Figure4_revision_rec_bc_nofacet_level_lab_task
- ),
- cope_name = factor(
- cope_name,
- levels = Figure4_revision_rec_bc_nofacet_level_map_cope,
- labels = Figure4_revision_rec_bc_nofacet_level_lab_cope
- )
- )
- # 2) Collapse across ROI within participant
- Figure4_revision_rec_bc_nofacet_idmean <- Figure4_revision_rec_bc_nofacet_base %>%
- group_by(ID, task, cope_name) %>%
- summarise(
- estimate = mean(estimate, na.rm = TRUE),
- .groups = "drop"
- )
- # 3) Within-subject summary for bar plot + SE
- Figure4_revision_rec_bc_nofacet_barsum <- Rmisc::summarySEwithin(
- data = Figure4_revision_rec_bc_nofacet_idmean,
- measurevar = "estimate",
- withinvars = c("task", "cope_name"),
- idvar = "ID",
- na.rm = TRUE
- )
- # 4A) Stats: Target vs Lure within each encoding condition
- Figure4_revision_rec_bc_nofacet_stats_recwithinenc <- Figure4_revision_rec_bc_nofacet_idmean %>%
- group_by(task) %>%
- pairwise_t_test(
- estimate ~ cope_name,
- paired = TRUE,
- p.adjust.method = "bonferroni"
- ) %>%
- ungroup() %>%
- mutate(
- label = case_when(
- p.adj < 0.001 ~ "p < .001",
- p.adj < 0.01 ~ "p < .01",
- p.adj < 0.05 ~ "p < .05",
- TRUE ~ paste0("p = ", sub("^0", "", sprintf("%.3f", p.adj)))
- ),
- x_num = case_when(
- task == "Exact repeat" ~ 1,
- task == "Modified repeat" ~ 2
- )
- )
- Figure4_revision_rec_bc_nofacet_ypos_task <- Figure4_revision_rec_bc_nofacet_barsum %>%
- group_by(task) %>%
- summarise(
- y_base = max(estimate + se, na.rm = TRUE),
- .groups = "drop"
- )
- Figure4_revision_rec_bc_nofacet_stats_recwithinenc <- Figure4_revision_rec_bc_nofacet_stats_recwithinenc %>%
- left_join(Figure4_revision_rec_bc_nofacet_ypos_task, by = "task") %>%
- mutate(
- xmin = x_num - 0.20,
- xmax = x_num + 0.20,
- y.position = y_base + 0.030
- )
- # 4B) Reverse stats: Repeat vs Similar within each recognition condition
- Figure4_revision_rec_bc_nofacet_stats_encwithinrec <- Figure4_revision_rec_bc_nofacet_idmean %>%
- group_by(cope_name) %>%
- pairwise_t_test(
- estimate ~ task,
- paired = TRUE,
- p.adjust.method = "bonferroni"
- ) %>%
- ungroup() %>%
- mutate(
- label = case_when(
- p.adj < 0.001 ~ "p < .001",
- p.adj < 0.01 ~ "p < .01",
- p.adj < 0.05 ~ "p < .05",
- TRUE ~ paste0("p = ", sub("^0", "", sprintf("%.3f", p.adj)))
- )
- )
- Figure4_revision_rec_bc_nofacet_ypos_cope <- Figure4_revision_rec_bc_nofacet_barsum %>%
- group_by(cope_name) %>%
- summarise(
- y_base = max(estimate + se, na.rm = TRUE),
- .groups = "drop"
- )
- Figure4_revision_rec_bc_nofacet_stats_encwithinrec <- Figure4_revision_rec_bc_nofacet_stats_encwithinrec %>%
- left_join(Figure4_revision_rec_bc_nofacet_ypos_cope, by = "cope_name") %>%
- mutate(
- xmin = case_when(
- cope_name == "Target hit" ~ 1 - 0.20,
- cope_name == "Lure correct rejection" ~ 1 + 0.20
- ),
- xmax = case_when(
- cope_name == "Target hit" ~ 2 - 0.20,
- cope_name == "Lure correct rejection" ~ 2 + 0.20
- ),
- y.position = case_when(
- cope_name == "Target hit" ~ y_base + 0.090,
- cope_name == "Lure correct rejection" ~ y_base + 0.140
- )
- )
- # 5) Plot
- Figure4_revision_rec_bc_nofacet_plot <- ggplot(
- Figure4_revision_rec_bc_nofacet_barsum,
- aes(x = task, y = estimate, fill = cope_name)
- ) +
- geom_col(
- position = position_dodge(width = figR4_dodge),
- width = 0.65
- ) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = figR4_dodge),
- width = 0.15,
- linewidth = 1.2
- ) +
- stat_pvalue_manual(
- Figure4_revision_rec_bc_nofacet_stats_recwithinenc,
- label = "label",
- xmin = "xmin",
- xmax = "xmax",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.size = 1.0,
- size = 5.0
- ) +
- stat_pvalue_manual(
- Figure4_revision_rec_bc_nofacet_stats_encwithinrec,
- label = "label",
- xmin = "xmin",
- xmax = "xmax",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.size = 1.0,
- size = 5.0
- ) +
- scale_fill_manual(values = c(
- "Target hit" = "#66BB6A",
- "Lure correct rejection" = "#9575CD"
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.28))) +
- labs(
- x = "Encoding condition",
- y = "Baseline-corrected mean % signal change",
- fill = "Recognition condition"
- ) +
- theme_classic(base_size = 13) +
- theme(
- panel.grid.minor = element_blank()
- )
- Figure4_revision_rec_bc_nofacet_plot
- ```
- EXPORT
- ```{r}
- text_base_export <- 40
- p_text_export <- text_base_export * 0.28
- Figure4_revision_rec_bc_nofacet_plot_export <- ggplot(
- Figure4_revision_rec_bc_nofacet_barsum,
- aes(x = task, y = estimate, fill = cope_name)
- ) +
- geom_col(
- position = position_dodge(width = figR4_dodge),
- width = 0.65
- ) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = figR4_dodge),
- width = 0.15,
- linewidth = 2.0
- ) +
- stat_pvalue_manual(
- Figure4_revision_rec_bc_nofacet_stats_recwithinenc,
- label = "label",
- xmin = "xmin",
- xmax = "xmax",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.size = 1.3,
- size = p_text_export
- ) +
- stat_pvalue_manual(
- Figure4_revision_rec_bc_nofacet_stats_encwithinrec,
- label = "label",
- xmin = "xmin",
- xmax = "xmax",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.size = 1.3,
- size = p_text_export
- ) +
- scale_fill_manual(values = c(
- "Target hit" = "#66BB6A",
- "Lure correct rejection" = "#9575CD"
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.32))) +
- labs(
- x = "Encoding condition",
- y = "Mean % signal change\nduring recognition",
- fill = "Recognition condition"
- ) +
- theme_classic(base_size = text_base_export) +
- theme(
- axis.text.x = element_text(size = 34, margin = margin(t = 4)),
- axis.text.y = element_text(size = 30),
- axis.title.x = element_text(size = 38, margin = margin(t = 12)),
- axis.title.y = element_text(size = 34, margin = margin(r = 18)),
- legend.position = c(0.82, 0.96),
- legend.justification = c(0.5, 1),
- legend.title = element_text(size = 30),
- legend.text = element_text(size = 26),
- legend.background = element_rect(fill = scales::alpha("white", 0), color = NA),
- plot.margin = margin(t = 24, r = 20, b = 20, l = 70)
- )
- ggsave(
- "derivatives/figures/SI_figures/Figure8SI.png",
- plot = Figure4_revision_rec_bc_nofacet_plot_export,
- width = 16, height = 12, units = "in",
- dpi = 300,
- bg = "white",
- device = "png"
- )
- ```
- ### Revised Supplementary Figure 9 - Lure CR vs Lure FA
- ```{r}
- ## Figure H4 - Recognition specificity (Lure CR vs Lure FA)
- # 1) Within-subject summary
- FigureH4_barsum <- Rmisc::summarySEwithin(
- data = semmst_merged_data_H4_lureFACR_nooutlier,
- measurevar = "estimate",
- withinvars = c("cope_name", "roi_cluster"),
- idvar = "ID",
- na.rm = TRUE
- ) %>%
- mutate(
- cope_name = factor(
- as.character(cope_name),
- levels = c("LureCR", "LureFA"),
- labels = c("Correct rejection", "False alarm")
- )
- )
- # 2) ROI labels
- FigureH4_roi_lab <- semmst_merged_data_H4_lureFACR_nooutlier %>%
- dplyr::distinct(roi_cluster) %>%
- dplyr::mutate(
- roi_label = dplyr::case_when(
- roi_cluster == "L_HEAD_DGCA23_HEAD_SUB_14" ~ "Left hippocampal head cluster",
- roi_cluster == "R_HEAD_DGCA23_HEAD_SUB_15" ~ "Right hippocampal head cluster",
- TRUE ~ as.character(roi_cluster)
- )
- )
- FigureH4_barsum <- FigureH4_barsum %>%
- dplyr::left_join(FigureH4_roi_lab, by = "roi_cluster")
- # 3) Plot
- FigureH4_lure_col <- "#9575CD"
- FigureH4_plot <- ggplot(
- FigureH4_barsum,
- aes(x = cope_name, y = estimate, alpha = cope_name)
- ) +
- geom_col(
- fill = FigureH4_lure_col,
- width = 0.65,
- show.legend = FALSE
- ) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- width = 0.15,
- linewidth = 1.2
- ) +
- facet_wrap(~ roi_label) +
- theme_classic(base_size = 13) +
- labs(
- x = "Response during recognition",
- y = "Mean % signal change"
- ) +
- scale_alpha_manual(values = c(
- "Correct rejection" = 0.95,
- "False alarm" = 0.55
- )) +
- scale_y_continuous(expand = expansion(mult = c(0.02, 0.02))) +
- custom_theme +
- guides(alpha = "none")
- FigureH4_plot
- ```
- EXPORT
- ```{r}
- text_base_export <- 40
- FigureH4_plot_export <- FigureH4_plot +
- theme_classic(base_size = text_base_export) +
- theme(
- axis.text.x = element_text(size = text_base_export * 0.82, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05),
- strip.text = element_text(size = text_base_export * 0.82, face = "bold"),
- panel.spacing.x = unit(0.8, "lines")
- )
- ggsave(
- "derivatives/figures/SI_figures/Figure9SI.png",
- plot = FigureH4_plot_export,
- width = 20, height = 12, units = "in",
- dpi = 300,
- bg = "white",
- device = "png"
- )
- ```
- # Revision Results
- ### Revision Results 1 - Encoding trial-wise RS (Response to reviewers)
- ```{r}
- # 1) Neural data: keep all EncodingLSA* tasks, extract itemno from cope_name
- semmst_merged_data_supplement_filtered_results3 = semmst_merged_data_supplement_filtered %>%
- filter(stringr::str_detect(task, "^EncodingLSA")) %>%
- mutate(
- itemno = stringr::str_extract(as.character(cope_name), "\\d+"),
- itemno = as.character(itemno)
- ) %>%
- filter(!is.na(itemno)) %>%
- dplyr::select(ID, task, roi_cluster, estimate, itemno) %>%
- distinct(ID, roi_cluster, itemno, .keep_all = TRUE)
- # 2) Encoding item-level behavioral data: only order == 2
- semmst_behav_data_enc_itemwise_GLMEM <- semmst_behav_data_filtered %>%
- filter(task == "enc") %>%
- filter(trial_type != "FILLER") %>%
- mutate(
- across(
- all_of(c("Vocabulary", "Digit_Symbol", "NonWord_sum",
- "arousal", "concreteness", "imageability", "meaningfulness")),
- ~ as.numeric(scale(.x)),
- .names = "{.col}_scale"
- ),
- itemno = as.character(itemno),
- order = as.character(order),
- trial_type = factor(trial_type)
- ) %>%
- filter(order == "2") %>%
- drop_na(Vocabulary, itemno, cosine, trial_type) %>%
- distinct(ID, itemno, .keep_all = TRUE)
- # 3) Merge neural + encoding behavior by ID and itemno
- semmst_merged_data_supplement_filtered_results3_glmem <- semmst_merged_data_supplement_filtered_results3 %>%
- left_join(
- semmst_behav_data_enc_itemwise_GLMEM %>%
- dplyr::select(
- ID, itemno,
- noun, trial_type, cosine, order,
- age, sex, education,
- Vocabulary_scale, Digit_Symbol_scale, NonWord_sum_scale,
- arousal_scale, meaningfulness_scale, concreteness_scale
- ),
- by = c("ID", "itemno")
- ) %>%
- drop_na(estimate, trial_type, cosine)
- # quick checks
- semmst_merged_data_supplement_filtered_results3_glmem %>%
- count(roi_cluster, trial_type)
- semmst_merged_data_supplement_filtered_results3_glmem %>%
- dplyr::select(ID, itemno, task, roi_cluster, estimate, noun, trial_type, cosine, order) %>%
- print()
- ```
- Models
- ```{r}
- model_simple_cosine_results3 <- lmer(
- estimate ~ cosine * roi_cluster * trial_type +
- (1 | ID) +
- (1 | itemno),
- data = semmst_merged_data_supplement_filtered_results3_glmem
- )
- model_complex_cosine_results3 <- lmer(
- estimate ~ cosine * trial_type * roi_cluster +
- Vocabulary_scale + Digit_Symbol_scale + NonWord_sum_scale +
- arousal_scale + meaningfulness_scale + concreteness_scale +
- (1 | ID) +
- (1 | itemno),
- data = semmst_merged_data_supplement_filtered_results3_glmem,
- REML = FALSE,
- control = lmerControl(
- optimizer = "bobyqa",
- optCtrl = list(maxfun = 20000)
- )
- )
- anova(model_simple_cosine_results3, model_complex_cosine_results3)
- summary(model_simple_cosine_results3)
- ```
- #### Revision Figure 1
- ```{r}
- # In this plot, we predict estimate by cosine similarity
- FigureR1A_continuous_scatter_roi_base <- semmst_merged_data_supplement_filtered_results3_glmem %>%
- filter(
- roi_cluster %in% c("L_HEAD_DGCA23_HEAD_SUB_14", "R_HEAD_DGCA23_HEAD_SUB_15"),
- trial_type %in% c("CLOSE", "DISTANT"),
- !is.na(cosine),
- !is.na(estimate)
- ) %>%
- mutate(
- trial_type = factor(trial_type, levels = c("CLOSE", "DISTANT")),
- roi_label = case_when(
- roi_cluster == "L_HEAD_DGCA23_HEAD_SUB_14" ~ "Left HC head cluster",
- roi_cluster == "R_HEAD_DGCA23_HEAD_SUB_15" ~ "Right HC head cluster",
- TRUE ~ as.character(roi_cluster)
- ),
- roi_label = factor(
- roi_label,
- levels = c("Left HC head cluster", "Right HC head cluster")
- )
- )
- # Okabe–Ito (CVD-safe): blue, yellow
- FigureR1A_continuous_scatter_roi_cols <- c(
- "CLOSE" = "#4477AA",
- "DISTANT" = "#DDCC77"
- )
- FigureR1A_continuous_scatter_roi_plot <- ggplot(
- FigureR1A_continuous_scatter_roi_base,
- aes(x = cosine, y = estimate, color = trial_type, fill = trial_type)
- ) +
- geom_point(
- alpha = 0.30,
- size = 1.8
- ) +
- geom_smooth(
- aes(group = trial_type),
- method = "lm",
- linewidth = 2,
- se = TRUE,
- alpha = 0.20
- ) +
- facet_wrap(~ roi_label, ncol = 1) +
- scale_x_continuous(
- breaks = function(lims) round(lims[1] + c(0.1, 0.5, 0.9) * (lims[2] - lims[1]), 2),
- labels = function(x) sprintf("%.2f", x)
- ) +
- scale_color_manual(values = FigureR1A_continuous_scatter_roi_cols) +
- scale_fill_manual(values = FigureR1A_continuous_scatter_roi_cols) +
- labs(
- x = "Cosine similarity",
- y = "Mean % signal change",
- color = "Encoding trial type",
- fill = "Encoding trial type"
- ) +
- theme_classic(base_size = 14) +
- theme(
- panel.grid.minor = element_blank(),
- strip.text = element_text(face = "bold"),
- legend.position = c(0.87, 0.88)
- )
- FigureR1A_continuous_scatter_roi_plot
- ```
- ##### EXPORT
- ```{r}
- FigureR1A_continuous_scatter_roi_plot_export <- ggplot(
- FigureR1A_continuous_scatter_roi_base,
- aes(x = cosine, y = estimate, color = trial_type, fill = trial_type)
- ) +
- geom_point(
- alpha = 0.30,
- size = 3.8
- ) +
- geom_smooth(
- aes(group = trial_type),
- method = "lm",
- linewidth = 3.2,
- se = TRUE,
- alpha = 0.20
- ) +
- facet_wrap(~ roi_label, ncol = 1) +
- scale_x_continuous(
- breaks = function(lims) round(lims[1] + c(0.1, 0.5, 0.9) * (lims[2] - lims[1]), 2),
- labels = function(x) sprintf("%.2f", x)
- ) +
- scale_color_manual(values = FigureR1A_continuous_scatter_roi_cols) +
- scale_fill_manual(values = FigureR1A_continuous_scatter_roi_cols) +
- labs(
- x = "Cosine similarity",
- y = "Mean % signal change"
- ) +
- theme_classic(base_size = 32) +
- theme(
- axis.title = element_text(size = 34),
- axis.text = element_text(size = 24),
- strip.text = element_text(size = 24, face = "bold"),
- legend.position = "none"
- )
- ggsave(
- "derivatives/figures/revision_figures/FigureR1A.png",
- plot = FigureR1A_continuous_scatter_roi_plot_export,
- width = 12, height = 18, units = "in",
- dpi = 300,
- bg = "white",
- device = "png"
- )
- ```
- #### Revision Figure 1B
- ```{r}
- FigureR1B_itemwise_base <- semmst_merged_data_supplement_filtered_results3_glmem %>%
- filter(
- roi_cluster %in% c("L_HEAD_DGCA23_HEAD_SUB_14", "R_HEAD_DGCA23_HEAD_SUB_15"),
- trial_type %in% c("CLOSE", "DISTANT"),
- !is.na(itemno),
- !is.na(trial_type),
- !is.na(cosine),
- !is.na(estimate)
- ) %>%
- mutate(
- trial_type = factor(trial_type, levels = c("CLOSE", "DISTANT")),
- roi_label = case_when(
- roi_cluster == "L_HEAD_DGCA23_HEAD_SUB_14" ~ "Left HC head cluster",
- roi_cluster == "R_HEAD_DGCA23_HEAD_SUB_15" ~ "Right HC head cluster",
- TRUE ~ as.character(roi_cluster)
- ),
- roi_label = factor(
- roi_label,
- levels = c("Left HC head cluster", "Right HC head cluster")
- ),
- # Treat CLOSE and DISTANT versions of the same item separately
- item_trial = paste(itemno, trial_type, sep = "_")
- )
- # Order x-axis categories by mean cosine similarity
- FigureR1B_item_order <- FigureR1B_itemwise_base %>%
- group_by(itemno, trial_type, item_trial) %>%
- summarise(
- mean_cosine = mean(cosine, na.rm = TRUE),
- .groups = "drop"
- ) %>%
- arrange(mean_cosine, itemno, trial_type) %>%
- pull(item_trial)
- FigureR1B_itemwise_base <- FigureR1B_itemwise_base %>%
- mutate(
- item_trial = factor(item_trial, levels = FigureR1B_item_order)
- )
- # Colors
- FigureR1B_itemwise_cols <- c(
- "CLOSE" = "#4477AA",
- "DISTANT" = "#DDCC77"
- )
- ## PLOT
- FigureR1B_itemwise_plot <- ggplot(
- FigureR1B_itemwise_base,
- aes(x = item_trial, y = estimate, fill = trial_type, color = trial_type)
- ) +
- geom_boxplot(
- width = 0.70,
- alpha = 0.45,
- outlier.shape = NA
- ) +
- geom_point(
- aes(group = item_trial),
- position = position_jitter(width = 0.16, height = 0),
- alpha = 0.65,
- size = 1.6
- ) +
- facet_wrap(~ roi_label, ncol = 1) +
- scale_fill_manual(values = FigureR1B_itemwise_cols) +
- scale_color_manual(values = FigureR1B_itemwise_cols) +
- labs(
- x = "Items in ascending order of cosine similarity",
- y = "Mean % signal change",
- fill = "Encoding trial type",
- color = "Encoding trial type"
- ) +
- theme_classic(base_size = 14) +
- theme(
- panel.grid.minor = element_blank(),
- strip.text = element_text(face = "bold"),
- axis.text.x = element_blank(),
- axis.ticks.x = element_blank(),
- legend.position = "top"
- )
- FigureR1B_itemwise_plot
- ```
- ```{r}
- FigureR1B_itemwise_plot_export <- ggplot(
- FigureR1B_itemwise_base,
- aes(x = item_trial, y = estimate, fill = trial_type, color = trial_type)
- ) +
- geom_boxplot(
- width = 0.72,
- alpha = 0.45,
- outlier.shape = NA,
- linewidth = 1.1
- ) +
- geom_point(
- aes(group = item_trial),
- position = position_jitter(width = 0.16, height = 0),
- alpha = 0.70,
- size = 2.8
- ) +
- facet_wrap(~ roi_label, ncol = 1) +
- scale_fill_manual(values = FigureR1B_itemwise_cols) +
- scale_color_manual(values = FigureR1B_itemwise_cols) +
- labs(
- x = "Items in ascending order of cosine similarity",
- y = "Mean % signal change"
- ) +
- theme_classic(base_size = 32) +
- theme(
- axis.title = element_text(size = 34),
- axis.text.x = element_blank(),
- axis.ticks.x = element_blank(),
- axis.text.y = element_text(size = 24),
- strip.text = element_text(size = 24, face = "bold"),
- legend.position = "none"
- )
- ggsave(
- "derivatives/figures/revision_figures/FigureR1B.png",
- plot = FigureR1B_itemwise_plot_export,
- width = 16, height = 18, units = "in",
- dpi = 300,
- bg = "white",
- device = "png"
- )
- ```
- ### Revision Results 2 - yes vs no (Response to reviewers)
- #### Behavioural yes-no results
- ```{r}
- # Behaviour
- semmst_behav_data_filtered_revision_results2A = semmst_behav_data_filtered %>%
- filter(task == "enc") %>%
- filter(trial_type != "FILLER") %>%
- drop_na(response, order) %>%
- mutate(
- trial_type = case_when(
- trial_type %in% c("CLOSE", "DISTANT") ~ "LURE",
- TRUE ~ as.character(trial_type)
- ),
- trial_type = factor(trial_type, levels = c("REPEAT", "LURE")),
- response = tolower(as.character(response))
- ) %>%
- filter(response %in% c("no-good", "good")) %>%
- mutate(
- response = factor(response, levels = c("no-good", "good")),
- order = factor(order, levels = c(1, 2))
- ) %>%
- droplevels()
- # Percent response
- semmst_behav_data_filtered_revision_results2A_good = semmst_behav_data_filtered_revision_results2A %>%
- count(ID, trial_type, order, response, name = "n") %>%
- tidyr::complete(ID, trial_type, order, response, fill = list(n = 0)) %>%
- group_by(ID, trial_type, order) %>%
- mutate(
- percent_response = 100 * n / sum(n)
- ) %>%
- ungroup() %>%
- filter(response == "good") %>%
- droplevels()
- # OUTLIERS
- semmst_behav_data_filtered_revision_results2A_good %>%
- group_by(trial_type, order) %>%
- identify_outliers(percent_response) %>%
- dplyr::select(ID, trial_type, order, is.outlier, is.extreme) %>%
- filter(is.extreme == TRUE)
- # NORMALITY
- semmst_behav_data_filtered_revision_results2A_good %>%
- group_by(trial_type, order) %>%
- shapiro_test(percent_response)
- ## ANOVA
- semmst_behav_data_filtered_revision_results2A_AOV = semmst_behav_data_filtered_revision_results2A_good %>%
- anova_test(
- dv = percent_response,
- wid = ID,
- within = c(trial_type, order)
- )
- get_anova_table(semmst_behav_data_filtered_revision_results2A_AOV)
- ## POST-HOC
- semmst_behav_data_filtered_revision_results2A_PWC_response = semmst_behav_data_filtered_revision_results2A_good %>%
- group_by(trial_type) %>%
- pairwise_t_test(
- percent_response ~ order,
- paired = TRUE,
- detailed = TRUE
- ) %>%
- ungroup() %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_behav_data_filtered_revision_results2A_PWC_response
- ```
- #### Neural results
- ```{r}
- # Prepare data
- semmst_merged_data_revision_results2B = semmst_merged_data_supplement_filtered %>%
- filter(task == "EncodingResp") %>%
- filter(cope_name %in% c("YesFirst", "NoFirst", "YesRepeat", "NoRepeat")) %>%
- filter(roi_cluster %in% c("L_HEAD_DGCA23_HEAD_SUB_14", "R_HEAD_DGCA23_HEAD_SUB_15")) %>%
- filter(estimate != 0) %>%
- extract(
- col = cope_name,
- into = c("response_type", "order"),
- regex = "^(Yes|No)(First|Repeat)$"
- ) %>%
- mutate(
- response_type = factor(response_type, levels = c("No", "Yes")),
- order = factor(order, levels = c("First", "Repeat"))
- ) %>%
- droplevels()
- # Keep only IDs with complete 2 x 2 x 2 cells
- complete_ids_revision_results2B <- semmst_merged_data_revision_results2B %>%
- count(ID, response_type, order, roi_cluster) %>%
- tidyr::complete(
- ID,
- response_type = levels(semmst_merged_data_revision_results2B$response_type),
- order = levels(semmst_merged_data_revision_results2B$order),
- roi_cluster = unique(semmst_merged_data_revision_results2B$roi_cluster),
- fill = list(n = 0)
- ) %>%
- group_by(ID) %>%
- summarise(all_cells_present = all(n > 0), .groups = "drop") %>%
- filter(all_cells_present) %>%
- pull(ID)
- semmst_merged_data_revision_results2B = semmst_merged_data_revision_results2B %>%
- filter(ID %in% complete_ids_revision_results2B) %>%
- droplevels()
- # OUTLIER
- semmst_merged_data_revision_results2B %>%
- group_by(response_type, order, roi_cluster) %>%
- identify_outliers(estimate) %>%
- dplyr::select(ID, roi_cluster, response_type, order, is.outlier, is.extreme) %>%
- filter(is.extreme == TRUE)
- # Exclude outliers
- semmst_merged_data_revision_results2B_nooutlier = semmst_merged_data_revision_results2B %>%
- filter(!ID %in% c("sub-434971")) %>%
- ungroup()
- # NORMALITY
- semmst_merged_data_revision_results2B_nooutlier %>%
- group_by(response_type, order, roi_cluster) %>%
- shapiro_test(estimate) %>%
- print(n = 100)
- ## ANOVA
- semmst_merged_data_revision_results2B_AOV = semmst_merged_data_revision_results2B_nooutlier %>%
- anova_test(
- dv = estimate,
- wid = ID,
- within = c(response_type, order, roi_cluster)
- )
- get_anova_table(semmst_merged_data_revision_results2B_AOV)
- ## POST-HOC
- semmst_merged_data_revision_results2B_PWC = semmst_merged_data_revision_results2B_nooutlier %>%
- group_by(ID, order, response_type) %>%
- summarise(
- estimate = mean(estimate, na.rm = TRUE),
- .groups = "drop"
- ) %>%
- tidyr::pivot_wider(
- names_from = response_type,
- values_from = estimate
- ) %>%
- drop_na(No, Yes) %>%
- tidyr::pivot_longer(
- cols = c(No, Yes),
- names_to = "response_type",
- values_to = "estimate"
- ) %>%
- mutate(response_type = factor(response_type, levels = c("No", "Yes"))) %>%
- group_by(response_type) %>%
- pairwise_t_test(
- estimate ~ order,
- paired = TRUE,
- detailed = TRUE
- ) %>%
- ungroup() %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- mutate(label = paste0("p=", signif(p.adj, 3)))
- semmst_merged_data_revision_results2B_PWC
- ```
- #### Neural - behavioural correlation
- ```{r}
- # Participant-specific "yes" rate for LURE, second presentation
- revision_results2C_behav_lure_yesrate <- semmst_behav_data_filtered_revision_results2A_good %>%
- filter(
- trial_type == "LURE",
- order == 2
- ) %>%
- transmute(
- ID,
- lure_yes_rate = percent_response
- ) %>%
- droplevels()
- ### Correlation - LURE second presentation
- # 1) Filter / define roi_group
- revision_results2C_corr_input_all <- semmst_merged_data_H3_neural_ps %>%
- mutate(roi_group = roi_cluster) %>%
- dplyr::select(
- ID, roi_group, roi, hemisphere, cluster, voxels,
- LureRepeat,
- NonWord_sum_scale, Digit_Symbol_scale
- ) %>%
- left_join(revision_results2C_behav_lure_yesrate, by = "ID") %>%
- dplyr::select(
- ID, roi_group, roi, hemisphere, cluster, voxels,
- LureRepeat, lure_yes_rate,
- NonWord_sum_scale, Digit_Symbol_scale
- ) %>%
- ungroup()
- # 2) Mahalanobis outlier detection (per ROI)
- alpha <- 0.99 # cutoff for chi-square (df=2)
- revision_results2C_md_tbl_all <- revision_results2C_corr_input_all %>%
- dplyr::group_by(roi_group) %>%
- dplyr::group_modify(~{
- d <- .x %>%
- dplyr::select(ID, LureRepeat, lure_yes_rate) %>%
- tidyr::drop_na()
- if (nrow(d) < 3) {
- return(tibble::tibble(
- ID = character(),
- MD = numeric(),
- p = numeric(),
- cutoff = numeric(),
- is_outlier = logical()
- ))
- }
- X <- as.matrix(d[, c("LureRepeat", "lure_yes_rate")])
- center <- colMeans(X)
- covmat <- stats::cov(X)
- md <- stats::mahalanobis(X, center = center, cov = covmat)
- tibble::tibble(
- ID = d$ID,
- MD = md,
- p = 1 - stats::pchisq(md, df = 2),
- cutoff = stats::qchisq(alpha, df = 2),
- is_outlier = md > stats::qchisq(alpha, df = 2)
- )
- }) %>%
- ungroup()
- revision_results2C_md_outliers_all <- revision_results2C_md_tbl_all %>%
- dplyr::filter(is_outlier)
- revision_results2C_md_multi_all <- revision_results2C_md_outliers_all %>%
- dplyr::count(ID, sort = TRUE) %>%
- dplyr::filter(n > 1)
- revision_results2C_md_tbl_all
- revision_results2C_md_outliers_all
- revision_results2C_md_multi_all
- # 3) Remove outlier ID
- revision_results2C_corr_input_all_nooutlier <- revision_results2C_corr_input_all %>%
- dplyr::filter(ID != "sub-434971") %>%
- droplevels() %>%
- ungroup()
- # 4) Fisher-z CI for Pearson r (95% hard-coded)
- pearson_ci <- function(r, n) {
- z <- atanh(r)
- se <- 1 / sqrt(n - 3)
- zcrit <- stats::qnorm(1 - (1 - 0.95) / 2)
- c(low = tanh(z - zcrit * se), high = tanh(z + zcrit * se))
- }
- # 5) SIMPLE correlations only (Pearson) per ROI + Bonferroni
- revision_results2C_corr_lure_yesrate_simple <- revision_results2C_corr_input_all_nooutlier %>%
- dplyr::group_by(roi_group) %>%
- dplyr::group_modify(~{
- d <- .x %>%
- dplyr::select(LureRepeat, lure_yes_rate) %>%
- tidyr::drop_na()
- ct <- stats::cor.test(d$LureRepeat, d$lure_yes_rate, method = "pearson")
- r <- unname(ct$estimate)
- p <- ct$p.value
- n <- nrow(d)
- ci <- pearson_ci(r, n)
- tibble::tibble(
- n = n,
- r = r,
- p = p,
- ci = sprintf("[%.3f, %.3f]", ci["low"], ci["high"])
- )
- }) %>%
- ungroup() %>%
- mutate(
- p_adj = p.adjust(p, method = "bonferroni")
- ) %>%
- arrange(p_adj)
- revision_results2C_corr_lure_yesrate_simple
- ```
- #### Revision Figure 2A - Behavioural revision
- ```{r}
- ## BEHAVIOURAL FIGURE ------------------------------------------------------------
- FigureR2A_dodge <- 0.8
- # 1) Within-subject summary
- FigureR2A_barsum <- Rmisc::summarySEwithin(
- data = semmst_behav_data_filtered_revision_results2A_good,
- measurevar = "percent_response",
- withinvars = c("trial_type", "order"),
- idvar = "ID",
- na.rm = TRUE
- ) %>%
- mutate(
- trial_type = factor(
- as.character(trial_type),
- levels = c("REPEAT", "LURE"),
- labels = c("Exact repeat", "Modified repeat")
- ),
- order = factor(
- as.character(order),
- levels = c("1", "2"),
- labels = c("First", "Repeat")
- )
- )
- # 2) Only theoretically matched pairwise post-hocs
- FigureR2A_stats_all <- semmst_behav_data_filtered_revision_results2A_good %>%
- mutate(
- cond = factor(
- paste(as.character(trial_type), as.character(order), sep = "_"),
- levels = c("REPEAT_1", "REPEAT_2", "LURE_1", "LURE_2")
- )
- ) %>%
- pairwise_t_test(
- percent_response ~ cond,
- paired = TRUE,
- detailed = TRUE
- ) %>%
- adjust_pvalue(method = "bonferroni") %>%
- add_significance() %>%
- mutate(
- comparison = paste(as.character(group1), as.character(group2), sep = "__"),
- label = case_when(
- p.adj < 0.001 ~ "p < .001",
- p.adj < 0.05 ~ paste0("p = ", sub("^0", "", sprintf("%.3f", p.adj))),
- TRUE ~ NA_character_
- )
- ) %>%
- filter(comparison %in% c(
- "REPEAT_1__REPEAT_2",
- "LURE_1__LURE_2",
- "REPEAT_1__LURE_1",
- "REPEAT_2__LURE_2"
- ))
- # 3) Map comparisons onto dodged bar centers
- FigureR2A_xpos <- c(
- "REPEAT_1" = 1 - FigureR2A_dodge / 4,
- "REPEAT_2" = 1 + FigureR2A_dodge / 4,
- "LURE_1" = 2 - FigureR2A_dodge / 4,
- "LURE_2" = 2 + FigureR2A_dodge / 4
- )
- FigureR2A_y_base <- max(
- FigureR2A_barsum$percent_response + FigureR2A_barsum$se,
- na.rm = TRUE
- )
- FigureR2A_y_step <- 6
- FigureR2A_stats_all <- FigureR2A_stats_all %>%
- mutate(
- xmin_plot = unname(FigureR2A_xpos[as.character(group1)]),
- xmax_plot = unname(FigureR2A_xpos[as.character(group2)]),
- y.position = case_when(
- comparison == "REPEAT_1__REPEAT_2" ~ FigureR2A_y_base + FigureR2A_y_step * 1,
- comparison == "LURE_1__LURE_2" ~ FigureR2A_y_base + FigureR2A_y_step * 2,
- comparison == "REPEAT_1__LURE_1" ~ FigureR2A_y_base + FigureR2A_y_step * 3,
- comparison == "REPEAT_2__LURE_2" ~ FigureR2A_y_base + FigureR2A_y_step * 4
- )
- ) %>%
- ungroup()
- # only draw significant matched comparisons
- FigureR2A_stats_draw <- FigureR2A_stats_all %>%
- filter(!is.na(label), p.adj < 0.05) %>%
- as.data.frame()
- # 4) y-axis upper limit for brackets, but only label up to 100
- FigureR2A_y_top <- max(
- 105,
- FigureR2A_stats_draw$y.position,
- na.rm = TRUE
- )
- # 5) Base plot
- FigureR2A_plot <- ggplot(
- FigureR2A_barsum,
- aes(
- x = trial_type,
- y = percent_response,
- fill = trial_type,
- group = order
- )
- ) +
- geom_col(
- aes(alpha = order),
- position = position_dodge(width = FigureR2A_dodge),
- width = 0.65
- ) +
- geom_errorbar(
- aes(ymin = percent_response - se, ymax = percent_response + se),
- position = position_dodge(width = FigureR2A_dodge),
- width = 0.15,
- linewidth = 1.2
- ) +
- ggpubr::stat_pvalue_manual(
- FigureR2A_stats_draw,
- label = "label",
- xmin = "xmin_plot",
- xmax = "xmax_plot",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.shorten = 0,
- bracket.size = 1.0,
- size = 5.0,
- step.increase = 0
- ) +
- theme_classic(base_size = 13) +
- labs(
- x = "Condition during encoding",
- y = "Percentage of 'accept' responses",
- fill = "Trial type",
- alpha = "Order"
- ) +
- scale_fill_manual(values = c(
- "Exact repeat" = "#66BB6A",
- "Modified repeat" = "#9575CD"
- )) +
- scale_alpha_manual(values = c(
- "First" = 0.95,
- "Repeat" = 0.55
- )) +
- scale_y_continuous(
- limits = c(0, FigureR2A_y_top),
- breaks = c(0, 25, 50, 75, 100),
- labels = c("0", "25", "50", "75", "100"),
- expand = expansion(mult = c(0.02, 0))
- ) +
- custom_theme +
- guides(fill = "none") +
- theme(
- legend.position = c(0.05, 0.98),
- legend.justification = c(0, 1),
- legend.background = element_rect(fill = scales::alpha("white", 0), color = NA)
- )
- FigureR2A_plot
- ```
- ```{r}
- # 6) Export
- text_base_export <- 40
- FigureR2A_plot_export <- ggplot(
- FigureR2A_barsum,
- aes(
- x = trial_type,
- y = percent_response,
- fill = trial_type,
- group = order
- )
- ) +
- geom_col(
- aes(alpha = order),
- position = position_dodge(width = FigureR2A_dodge),
- width = 0.65
- ) +
- geom_errorbar(
- aes(ymin = percent_response - se, ymax = percent_response + se),
- position = position_dodge(width = FigureR2A_dodge),
- width = 0.15,
- linewidth = 2.0
- ) +
- ggpubr::stat_pvalue_manual(
- FigureR2A_stats_draw,
- label = "label",
- xmin = "xmin_plot",
- xmax = "xmax_plot",
- y.position = "y.position",
- tip.length = 0.015,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.shorten = 0,
- bracket.size = 1.8,
- size = text_base_export * 0.24,
- step.increase = 0
- ) +
- labs(
- x = "Condition during encoding",
- y = "Percentage of 'accept' responses",
- fill = "Trial type",
- alpha = "Order"
- ) +
- scale_fill_manual(values = c(
- "Exact repeat" = "#66BB6A",
- "Modified repeat" = "#9575CD"
- )) +
- scale_alpha_manual(values = c(
- "First" = 0.95,
- "Repeat" = 0.55
- )) +
- scale_y_continuous(
- limits = c(0, FigureR2A_y_top),
- breaks = c(0, 25, 50, 75, 100),
- labels = c("0", "25", "50", "75", "100"),
- expand = expansion(mult = c(0.02, 0))
- ) +
- custom_theme +
- guides(fill = "none") +
- theme_classic(base_size = text_base_export) +
- theme(
- legend.position = c(0.05, 0.98),
- legend.justification = c(0, 1),
- legend.background = element_rect(fill = scales::alpha("white", 0), color = NA),
- legend.title = element_text(size = text_base_export * 0.82),
- legend.text = element_text(size = text_base_export * 0.78),
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05)
- )
- ggsave(
- "derivatives/figures/revision_figures/FigureR2A.png",
- plot = FigureR2A_plot_export,
- width = 16, height = 12, units = "in",
- dpi = 300,
- bg = "white",
- device = "png"
- )
- ```
- #### Revision Figure 2B - Nerual results
- ```{r}
- ## NEURAL FIGURE ----------------------------------------------------------------
- FigureR2B_dodge <- 0.8
- # 1) Collapse across the two HC head clusters (to match the post-hoc tests)
- FigureR2B_plotdata <- semmst_merged_data_revision_results2B_nooutlier %>%
- group_by(ID, response_type, order) %>%
- summarise(
- estimate = mean(estimate, na.rm = TRUE),
- .groups = "drop"
- ) %>%
- mutate(
- response_type = factor(
- as.character(response_type),
- levels = c("No", "Yes"),
- labels = c("Not accept", "Accept")
- ),
- order = factor(
- as.character(order),
- levels = c("First", "Repeat"),
- labels = c("First", "Repeat")
- )
- )
- # 2) Within-subject summary
- FigureR2B_barsum <- Rmisc::summarySEwithin(
- data = FigureR2B_plotdata,
- measurevar = "estimate",
- withinvars = c("response_type", "order"),
- idvar = "ID",
- na.rm = TRUE
- )
- # 3) Planned comparison: Not accept vs Accept during FIRST presentation only
- FigureR2B_first_comp <- FigureR2B_plotdata %>%
- filter(order == "First") %>%
- tidyr::pivot_wider(
- names_from = response_type,
- values_from = estimate
- ) %>%
- drop_na(`Not accept`, Accept)
- FigureR2B_first_ttest <- t.test(
- FigureR2B_first_comp$`Not accept`,
- FigureR2B_first_comp$Accept,
- paired = TRUE
- )
- FigureR2B_first_p <- FigureR2B_first_ttest$p.value
- # 4) Bracket coordinates
- FigureR2B_xpos <- c(
- "Not accept_First" = 1 - FigureR2B_dodge / 4,
- "Not accept_Repeat" = 1 + FigureR2B_dodge / 4,
- "Accept_First" = 2 - FigureR2B_dodge / 4,
- "Accept_Repeat" = 2 + FigureR2B_dodge / 4
- )
- FigureR2B_y_base <- max(
- FigureR2B_barsum$estimate + FigureR2B_barsum$se,
- na.rm = TRUE
- )
- FigureR2B_y_step <- 0.025
- FigureR2B_stats_draw <- tibble::tibble(
- group1 = "Not accept_First",
- group2 = "Accept_First",
- xmin_plot = unname(FigureR2B_xpos["Not accept_First"]),
- xmax_plot = unname(FigureR2B_xpos["Accept_First"]),
- y.position = FigureR2B_y_base + FigureR2B_y_step,
- label = case_when(
- FigureR2B_first_p < 0.001 ~ "p < .001",
- FigureR2B_first_p < 0.1 ~ paste0("p = ", sub("^0", "", sprintf("%.3f", FigureR2B_first_p))),
- TRUE ~ NA_character_
- )
- ) %>%
- filter(!is.na(label))
- # 5) y-axis upper limit for bracket
- FigureR2B_y_top <- max(
- c(
- FigureR2B_barsum$estimate + FigureR2B_barsum$se,
- FigureR2B_stats_draw$y.position
- ),
- na.rm = TRUE
- ) + 0.01
- # 6) Base plot
- FigureR2B_plot <- ggplot(
- FigureR2B_barsum,
- aes(
- x = response_type,
- y = estimate,
- fill = response_type,
- group = order
- )
- ) +
- geom_col(
- aes(alpha = order),
- position = position_dodge(width = FigureR2B_dodge),
- width = 0.65
- ) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = FigureR2B_dodge),
- width = 0.15,
- linewidth = 1.2
- ) +
- theme_classic(base_size = 13) +
- labs(
- x = "Response during encoding",
- y = "Mean % signal change",
- fill = "Response type",
- alpha = "Order"
- ) +
- scale_fill_manual(values = c(
- "Accept" = "#4477AA",
- "Not accept" = "#CC6677"
- )) +
- scale_alpha_manual(values = c(
- "First" = 0.95,
- "Repeat" = 0.55
- )) +
- scale_y_continuous(
- limits = c(
- min(0, min(FigureR2B_barsum$estimate - FigureR2B_barsum$se, na.rm = TRUE)),
- FigureR2B_y_top
- ),
- expand = expansion(mult = c(0.02, 0))
- ) +
- custom_theme +
- guides(fill = "none") +
- theme(
- legend.position = c(0.75, 0.98),
- legend.justification = c(0, 1),
- legend.background = element_rect(fill = scales::alpha("white", 0), color = NA)
- )
- # Add the single planned bracket only if p < .1
- if (nrow(FigureR2B_stats_draw) > 0) {
- FigureR2B_plot <- FigureR2B_plot +
- ggpubr::stat_pvalue_manual(
- FigureR2B_stats_draw,
- label = "label",
- xmin = "xmin_plot",
- xmax = "xmax_plot",
- y.position = "y.position",
- tip.length = 0.01,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.shorten = 0,
- bracket.size = 1.0,
- size = 5.0
- )
- }
- FigureR2B_plot
- ```
- ```{r}
- # 7) Export
- text_base_export <- 40
- FigureR2B_plot_export <- ggplot(
- FigureR2B_barsum,
- aes(
- x = response_type,
- y = estimate,
- fill = response_type,
- group = order
- )
- ) +
- geom_col(
- aes(alpha = order),
- position = position_dodge(width = FigureR2B_dodge),
- width = 0.65
- ) +
- geom_errorbar(
- aes(ymin = estimate - se, ymax = estimate + se),
- position = position_dodge(width = FigureR2B_dodge),
- width = 0.15,
- linewidth = 2.0
- ) +
- labs(
- x = "Response during encoding",
- y = "Mean % signal change",
- fill = "Response type",
- alpha = "Order"
- ) +
- scale_fill_manual(values = c(
- "Accept" = "#4477AA",
- "Not accept" = "#CC6677"
- )) +
- scale_alpha_manual(values = c(
- "First" = 0.95,
- "Repeat" = 0.55
- )) +
- scale_y_continuous(
- limits = c(
- min(0, min(FigureR2B_barsum$estimate - FigureR2B_barsum$se, na.rm = TRUE)),
- FigureR2B_y_top
- ),
- expand = expansion(mult = c(0.02, 0))
- ) +
- custom_theme +
- guides(fill = "none") +
- theme_classic(base_size = text_base_export) +
- theme(
- legend.position = c(0.75, 0.98),
- legend.justification = c(0, 1),
- legend.background = element_rect(fill = scales::alpha("white", 0), color = NA),
- legend.title = element_text(size = text_base_export * 0.82),
- legend.text = element_text(size = text_base_export * 0.78),
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05)
- )
- # Add the single planned bracket only if p < .1
- if (nrow(FigureR2B_stats_draw) > 0) {
- FigureR2B_plot_export <- FigureR2B_plot_export +
- ggpubr::stat_pvalue_manual(
- FigureR2B_stats_draw,
- label = "label",
- xmin = "xmin_plot",
- xmax = "xmax_plot",
- y.position = "y.position",
- tip.length = 0.015,
- hide.ns = TRUE,
- inherit.aes = FALSE,
- bracket.shorten = 0,
- bracket.size = 1.8,
- size = text_base_export * 0.24
- )
- }
- ggsave(
- "derivatives/figures/revision_figures/FigureR2B.png",
- plot = FigureR2B_plot_export,
- width = 16, height = 12, units = "in",
- dpi = 300,
- bg = "white",
- device = "png"
- )
- ```
- #### Revision Figure 2C - Behavioural - neural correlation
- ```{r}
- ## Figure R2C - Neural response ~ behavioural "accept" rate
- # 1) Long table
- FigureR2C_df <- revision_results2C_corr_input_all_nooutlier %>%
- dplyr::select(ID, roi_group, LureRepeat, lure_yes_rate) %>%
- tidyr::drop_na(LureRepeat, lure_yes_rate) %>%
- dplyr::mutate(
- facet_lab = dplyr::case_when(
- roi_group == "L_HEAD_DGCA23_HEAD_SUB_14" ~ "Left HC head cluster",
- roi_group == "R_HEAD_DGCA23_HEAD_SUB_15" ~ "Right HC head cluster",
- TRUE ~ as.character(roi_group)
- )
- )
- # 2) Per-ROI correlation + Bonferroni + label text
- FigureR2C_labs <- FigureR2C_df %>%
- dplyr::group_by(roi_group, facet_lab) %>%
- dplyr::summarise(
- n = dplyr::n(),
- r = unname(stats::cor(LureRepeat, lure_yes_rate, method = "pearson")),
- p = stats::cor.test(LureRepeat, lure_yes_rate, method = "pearson")$p.value,
- .groups = "drop"
- ) %>%
- dplyr::mutate(
- p_adj = p.adjust(p, method = "bonferroni"),
- stars = dplyr::case_when(
- p_adj < .001 ~ "***",
- p_adj < .01 ~ "**",
- p_adj < .05 ~ "*",
- TRUE ~ ""
- ),
- sig = if_else(p_adj < .05, "sig", "ns"),
- ann = dplyr::case_when(
- is.na(p_adj) ~ sprintf("r = %.2f, p = NA", r),
- p_adj < .001 ~ sprintf("r = %.2f, p < .001%s", r, stars),
- TRUE ~ sprintf("r = %.2f, p = %.3f%s", r, p_adj, stars)
- )
- )
- FigureR2C_full <- FigureR2C_df %>%
- left_join(FigureR2C_labs %>% dplyr::select(roi_group, sig), by = "roi_group")
- # 3) Plot
- FigureR2C_plot_base <- ggplot(FigureR2C_full, aes(LureRepeat, lure_yes_rate)) +
- geom_point(alpha = 0.7, size = 4.5) +
- scale_color_manual(values = c(ns = "grey30", sig = "red"), guide = "none") +
- facet_wrap(
- ~ roi_group,
- scales = "free",
- labeller = labeller(roi_group = setNames(FigureR2C_labs$facet_lab, FigureR2C_labs$roi_group))
- ) +
- labs(
- x = "Neural % signal change to modified repeats",
- y = "Percent rate of 'accept' responses\nfor modified repeats"
- ) +
- theme_classic(base_size = 18) +
- custom_theme
- FigureR2C_plot <- FigureR2C_plot_base +
- geom_smooth(aes(color = sig), method = "lm", se = FALSE, linewidth = 1.1) +
- geom_text(
- data = FigureR2C_labs,
- aes(x = -Inf, y = Inf, label = ann, color = sig),
- inherit.aes = FALSE,
- hjust = -0.05, vjust = 1.2, size = 5.5
- )
- FigureR2C_plot
- ```
- EXPORT
- ```{r}
- text_base_export <- 40
- FigureR2C_plot_export <- FigureR2C_plot_base +
- geom_smooth(aes(color = sig), method = "lm", se = FALSE, linewidth = 2.6) +
- geom_text(
- data = FigureR2C_labs,
- aes(x = -Inf, y = Inf, label = ann, color = sig),
- inherit.aes = FALSE,
- hjust = -0.05, vjust = 1.2, size = 10.5
- ) +
- theme_classic(base_size = text_base_export) +
- theme(
- legend.title = element_text(size = text_base_export * 0.95),
- legend.text = element_text(size = text_base_export * 0.90),
- axis.text.x = element_text(size = text_base_export * 0.90, margin = margin(t = 2)),
- axis.text.y = element_text(size = text_base_export * 0.90),
- axis.title = element_text(size = text_base_export * 1.05)
- )
- ggsave(
- "derivatives/figures/revision_figures/FigureR2C.png",
- plot = FigureR2C_plot_export,
- width = 20, height = 12, units = "in",
- dpi = 300,
- bg = "white",
- device = "png"
- )
- ```
smst_mr1_analysis.Rmd at commit b1f8280, no license · at the source
Overview
- Doctoral School of Psychology, Eötvös Loránd University, Budapest 1075, Hungary
- Brain Imaging Centre, Hungarian Research Network, Research Centre for Natural Sciences, Budapest 1117, Hungary
- Institute of Psychology, Eötvös Loránd University, Budapest 1064, Hungary
- Mental Health Sciences Division, Doctoral School, Semmelweis University, Budapest 1085, Hungary
- Konkoly Observatory, Hungarian Research Network, Research Centre for Astronomy and Earth Sciences, Budapest 1121, Hungary
- Wigner Data Center, Hungarian Research Network, Wigner Research Centre for Physics, Budapest 1121, Hungary
- Hungarian Academy of Sciences Centre of Excellence, Hungarian Research Network, Research Centre for Astronomy and Earth Sciences, Budapest 1121, Hungary
- Max Planck Partner Group of the Max Planck Institute for Human Development, Hippocampal Circuit and Code for Cognition Lab, Budapest 1117, Hungary
Abstract
The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.
Repositories
Its files are read in the Code ↔ Paper reader above, with 9 matches between paragraphs and lines of code.
Zenodo 18395407
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
- 27 September 2026: the link answers (HTTP 200)
10 files
- scripts/
smst2_bids_participants_ , Python, 216 linesmaker.py - scripts/
smst2_bids_tsv_maker.py , Python, 529 lines - scripts/
smst2_bids_tsv_maker_ses , Python, 359 lines02.py - scripts/
smst2_mr_summarize_ses01 , Python, 65 lines.py - sem_mst_2_mr.py, Python, 4,024 lines
- sem_mst_2_mr_enc_lastrun
.py , Python, 2,712 lines - sem_mst_2_mr_lastrun.py, Python, 3,876 lines
- sem_mst_2_mr_rec_lastrun
.py , Python, 2,814 lines - sem_mst_2_mr_session2_ma
pping_lastrun.py , Python, 2,883 lines - README.md, Text, 35 lines
Zenodo 20090797
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
- 27 September 2026: the link answers (HTTP 200)
6 files
- scripts/
smst_mr1_HCmask_snapshot , Shell, 169 lines.sh - scripts/
smst_mr1_MNIcoordinates. , Python, 479 linespy - scripts/
smst_mr1_analysis.Rmd , R, 5,188 lines - scripts/
smst_mr1_powerfunction.m , MATLAB, 192 lines - scripts/
smst_mr1_powerfunction_a , MATLAB, 192 linesnat.m - README.md, Text, 19 lines
ilyesalex/smst2_mr_experiment
c73d841427fd9ac13d6434ad2bf9b971ab5c2e56, 27 January 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
10 files
- scripts/
smst2_bids_participants_ , Python, 216 lines, 1 matchmaker.py - scripts/
smst2_bids_tsv_maker.py , Python, 529 lines, 1 match - scripts/
smst2_bids_tsv_maker_ses , Python, 359 lines02.py - scripts/
smst2_mr_summarize_ses01 , Python, 65 lines.py - sem_mst_2_mr.py, Python, 4,024 lines
- sem_mst_2_mr_enc_lastrun
.py , Python, 2,712 lines - sem_mst_2_mr_lastrun.py, Python, 3,876 lines
- sem_mst_2_mr_rec_lastrun
.py , Python, 2,814 lines - sem_mst_2_mr_session2_ma
pping_lastrun.py , Python, 2,883 lines - README.md, Text, 35 lines
ilyesalex/smst2_mr_analysis
b1f8280750fbe099b86224e616a30e5db4c0f85a, 8 May 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
6 files
- scripts/
smst_mr1_HCmask_snapshot , Shell, 169 lines, 1 match.sh - scripts/
smst_mr1_MNIcoordinates. , Python, 479 linespy - scripts/
smst_mr1_analysis.Rmd , R, 5,188 lines, 6 matches - scripts/
smst_mr1_powerfunction.m , MATLAB, 192 lines - scripts/
smst_mr1_powerfunction_a , MATLAB, 192 linesnat.m - README.md, Text, 19 lines
The paper's code and data availability statement is in the Data section.
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:
- 4 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 28 scripts, each with its path and the digest of its content;
- 9 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
Datasets cited
- openneuro:ds007275, at OpenNeuro; found in the references
Code and data availability statement
The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:
- no repository, dataset or request procedure was recognized in it
Read it in the paper: doi.org/10.1073/pnas.2603114123.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 4 authors, 5 keywords, 12 MeSH terms, 5 funders, 123 references.
Cite
This paper
Ilyés, A., Brosig, B. M., Mező, G., & Keresztes, A. (2026). The human hippocampus can pattern separate memories by meaning. Proceedings of the National Academy of Sciences of the United States of America, 123(31), e2603114123. https://
BibTeX
@article{ilyes2026human,
author = {Ilyés, Alex and Brosig, Borbála Mónika and Mező, György and Keresztes, Attila},
title = {{The human hippocampus can pattern separate memories by meaning}},
journal = {Proceedings of the National Academy of Sciences of the United States of America},
year = {2026},
month = jul,
volume = {123},
number = {31},
pages = {e2603114123},
publisher = {National Academy of Sciences},
issn = {0027-8424},
doi = {10.1073/
url = {https://
pmid = {42520121},
pmcid = {PMC13438472}
}
RIS
TY - JOUR
AU - Ilyés, Alex
AU - Brosig, Borbála Mónika
AU - Mező, György
AU - Keresztes, Attila
TI - The human hippocampus can pattern separate memories by meaning
T2 - Proceedings of the National Academy of Sciences of the United States of America
J2 - Proc Natl Acad Sci U S A
PY - 2026
DA - 2026/
VL - 123
IS - 31
SP - e2603114123
SN - 0027-8424
PB - National Academy of Sciences
DO - 10.1073/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1073/
"type": "article-journal",
"title": "The human hippocampus can pattern separate memories by meaning",
"container-title": "Proceedings of the National Academy of Sciences of the United States of America",
"author": [
{
"family": "Ilyés",
"given": "Alex"
},
{
"family": "Brosig",
"given": "Borbála Mónika"
},
{
"family": "Mező",
"given": "György"
},
{
"family": "Keresztes",
"given": "Attila"
}
],
"container-title-short":
"volume": "123",
"issue": "31",
"page": "e2603114123",
"DOI": "10.1073/
"PMID": "42520121",
"PMCID": "PMC13438472",
"ISSN": "0027-8424",
"publisher": "National Academy of Sciences",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
28
]
]
}
}
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/s41467-026-73865-9 [code]
- Histamine shapes the neurocomputational dynamics of human learning.Journal: Nature communicationsIn common: PsychoPy, rstatix, easystats, 12 other tools, cognitive, 2 references
- [2] doi:10.1093/braincomms/fcag255 [code]
- Impaired consolidation of spatial memory during sleep in patients with leucine-rich glioma-inactivated 1-associated limbic encephalitis.Journal: Brain communicationsIn common: afex, rstatix, emmeans, 6 other tools, cognitive, 6 references
- [3] 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 consciousnessIn common: afex, easystats, broom, 12 other tools, cognitive
- [4] doi:10.1002/hbm.70512 [code]
- Precision Imaging for Intraindividual Investigation of the Reward Response.Journal: Human brain mappingIn common: PsychoPy, psych, easystats, 10 other tools, 2 references
- [5] 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, easystats, broom, 10 other tools, cognitive, 1 reference
- [6] doi:10.1126/sciadv.aec9291 [code]
- Computational mechanisms of perception in autism revealed using games inspired by rodent operant tasks.Journal: Science advancesIn common: afex, psych, rstatix, 8 other tools, cognitive
- [7] doi:10.1162/imag.a.1245 [code]
- Towards precision EEG connectomics: Evaluating the benefits of dense sampling.Journal: Imaging neuroscience (Cambridge, Mass.)In common: psych, rstatix, lmerTest, 11 other tools, 1 reference
- [8] doi:10.1016/j.nicl.2026.104012 [code]
- Structural-functional multilayer brain network properties and outcome of combined repetitive transcranial magnetic stimulation and psychotherapy for obsessive-compulsive disorder.Journal: NeuroImage. ClinicalIn common: afex, psych, rstatix, 10 other tools, 1 reference
- [9] doi:10.1038/s41398-026-04010-9 [code]
- Bullying victimization and brain development: a longitudinal structural magnetic resonance imaging study from adolescence to early adulthood.Journal: Translational psychiatryIn common: psych, rstatix, easystats, 8 other tools, 1 reference
- [10] doi:10.1038/s41467-026-72934-3 [code]
- Multi-focal ultrasound neuromodulation to the dorsal anterior cingulate cortex disrupts behavioural and neural pain processing.Journal: Nature communicationsIn common: rstatix, broom, emmeans, 6 other tools, 4 references
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.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 4 repositories of the authors' code, each at its verified commit and with its license, 28 scripts, and 9 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:dddfe8d79d143a27…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
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.
