OSCR

Trial-by-trial fMRI-neurofeedback dissociates fusiform and occipital contributions to face detection and recognition.

Code ↔ Paper

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

The 21 matches · 2 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
  1. [1] § Results › Behavioural performance in the visual task › Response latencies ↔ supplementary_figures/fig5/sfig5_behavioral_barplots.R, lines 1–44 · score 0.85 · identify_outliers, response latencies, EXP participants, image frames, rstatix, IQR
  2. [2] § Results › Impact of self-regulation on subsequent activation of target ROIs during face detection and recognition ↔ fig5/fig5_models2to5_task_effects.R, lines 1–46 · score 0.85 · regOFA, FFA detection responses, regFFA, OFA detection responses, Dot whisker, FFA recognition responses
  3. [3] § Results › NFB self-regulation performance › Learning across runs ↔ fig3/fig3_model1_learning.R, lines 1–47 · score 0.85 · percent signal change, diffPSC, Linear Mixed, predicted marginal, Dot whisker, Training Day
  4. [4] § Results › NFB self-regulation performance › Session by group TS comparisons ↔ supplementary_figures/fig1/sfig1_first_vs_last_run_permutation.m, lines 1–39 · score 0.84 · FFA targeted sessions, regulation blocks, OFA targeted, training session revealed, FFA activity, 1–7
  5. [5] § Methods › Self-regulation performance › Linear mixed-effects models ↔ fig5/fig5_models2to5_task_effects.R, lines 321–399 · score 0.73 · unstandardized model, dot whisker, linear mixed, Marginal, fitted, coefficients
  6. [6] § Methods › Technical details › NFB setup › Preprocessing with prepNFB Tool ↔ functions/my_spm_check_registration.m, the whole file · a weak match · score 0.73 · Wellcome Trust, prepNFB, simplify, Neuroimaging, SPM, coregistration
  7. [7] § Results › NFB self-regulation performance › Session by group TS comparisons ↔ supplementary_figures/fig1/sfig1_first_vs_last_run_permutation.m, lines 1–39 · score 0.72 · target session minus, volume permutation, sign flipping, Shaded error, pronounced, training session
  8. [8] § Methods › Self-regulation performance › Linear mixed-effects models ↔ fig6/fig6_models6and7_behavior.R, lines 414–464 · score 0.72 · unstandardized model, post hoc, dot whisker, deviation, variables, coefficients
  9. [9] § Methods › The effects of self-regulation performance on ROI detection and recognition responses ↔ supplementary_figures/fig4/sfig4_models2to5_animal_trials.R, lines 1–45 · score 0.70 · regOFA, recognition models, regFFA, OFA detection response, Training day, interaction
  10. [10] § Methods › The effects of self-regulation performance on ROI detection and recognition responses ↔ fig5/fig5_models2to5_task_effects.R, lines 1–46 · score 0.70 · regOFA, recognition models, regFFA, OFA detection response, Training day, interaction
  11. [11] § Results › The effects of ROI detection and recognition responses on behavioural performance ↔ supplementary_figures/fig8/sfig8_sts_learning.R, lines 91–174 · score 0.67 · linear mixed model, simple slope, standardized coefficient, Dot whisker, Training Day, marginal
  12. [12] § Methods › Pre-training › Functional localizer task ↔ functions/run_offa_loc.m, lines 2–42 · score 0.66 · fearful faces, neutral faces, oval, houses, scrambled, button
  13. [13] § Results › NFB self-regulation performance › Session by group TS comparisons ↔ fig2/fig2_within_group_between_session_permutation.m, lines 1–29 · score 0.62 · volume permutation, sign flipping, Shaded error, scores, modulation, Figure 2
  14. [14] § Results › Impact of self-regulation on subsequent activation of target ROIs during face detection and recognition › Detection-related activity ↔ fig6/fig6_models6and7_behavior.R, lines 163–205 · score 0.60 · p.holm, Post hoc, simple slopes, OFA detection, SE, CI
  15. [15] § Methods › Path analysis using structural equation modelling ↔ fig7/fig7_sem_path_models.py, lines 1–36 · score 0.59 · fit statistic, model fitting, Training Day, Semopy, covariance, CONT
  16. [16] § Methods › Technical details › NFB setup › ROI selection with analyse localizer tool ↔ functions/my_spm_check_registration.m, the whole file · a weak match · score 0.58 · ROI masks, prepNFB, coregister, template, position, tool
  17. [17] § Results › Behavioural performance in the visual task › Response latencies ↔ supplementary_figures/fig5/sfig5_behavioral_barplots.R, lines 154–236 · score 0.56 · Post hoc, Holm corrected, p.holm, Training Session, SD, detection
  18. [18] § Results › NFB self-regulation performance › Learning across runs ↔ fig6/fig6_models6and7_behavior.R, lines 207–248 · score 0.55 · p.holm, Post hoc, OFA session, FFA
  19. [19] § Methods › Participants ↔ fig3/fig3_model1_learning.R, lines 1–47 · score 0.53 · received sham feedback, yoked, training, NFB, regulation
  20. [20] § Methods › Technical details › NFB setup › ROI selection with analyse localizer tool ↔ fig4/fig4_whole_brain_regulation.py, lines 1–48 · score 0.52 · activation maps, located, hemisphere, threshold, smoothed, voxels
  21. [21] § Methods › Offline analysis of whole brain data › Preprocessing ↔ functions/analyze_rs.m, lines 1–73 · score 0.50 · Preprocessing steps, scans, SPM, realignment, Temporal, smoothing

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 · 399 lines · 18 KB · no license · 3 matches

  1. # =============================================================================
  2. # Figure 5 — Models 2–5: Impact of NFB Self-Regulation on Face Detection
  3. # and Recognition
  4. # =============================================================================
  5. #
  6. # Paper: ReFOFA (NCOMMS-24-11279)
  7. # Sample: Experimental group only, face stimuli only (N = 22, 1494 trials)
  8. #
  9. # Models:
  10. # Model 2 (md1): DV = FFA detection response (task_detect_FFA_beta_s)
  11. # Model 3 (md3): DV = OFA detection response (task_detect_OFA_beta_s)
  12. # Model 4 (md2): DV = FFA recognition response (task_recogn_FFA_beta_s)
  13. # Model 5 (md4): DV = OFA recognition response (task_recogn_OFA_beta_s)
  14. #
  15. # Key predictors: regFFA_s, regOFA_s (NFB regulation PSC, z-scored)
  16. # Interactions: regFFA × regOFA × Session (three-way)
  17. # Covariates: runID, Training_Day, detection_frms,
  18. # + detection beta for recognition models
  19. # Random effects: (1|subID) + (1|stimID)
  20. #
  21. # Output:
  22. # Left panel — Dot-whisker coefficients (Models 2 & 3: Detection)
  23. # Right panel — Dot-whisker coefficients (Models 4 & 5: Recognition)
  24. # Center — Predicted marginal effects with marginal density plots
  25. # =============================================================================
  26. rm(list = ls())
  27. # --- 1. Libraries ------------------------------------------------------------
  28. library(readxl) # read_excel() for source data
  29. library(lme4) # lmer() for mixed-effects models
  30. library(lmerTest) # p-values via Satterthwaite
  31. library(sjPlot) # plot_model() for predicted effects
  32. library(ggplot2) # plotting framework
  33. library(dotwhisker) # dwplot() for coefficient plots
  34. library(dplyr) # data wrangling
  35. library(arm) # standardize()
  36. library(emmeans) # emtrends() for simple slopes
  37. library(reghelper) # simple_slopes()
  38. library(egg) # theme_article()
  39. library(patchwork) # plot composition
  40. library(cowplot) # plot_grid() for combining ggMarginal plots
  41. library(ggExtra) # ggMarginal() for marginal density plots
  42. library(ggrastr) # rasterise() for efficient raw data overlay
  43. # --- 2. Working directory & data ---------------------------------------------
  44. # Set working directory to the script's location (works in RStudio)
  45. if (requireNamespace("rstudioapi", quietly = TRUE) && rstudioapi::isAvailable()) {
  46. setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
  47. } else {}
  48. setwd("..") # move up to "code and source data" root
  49. # Read from Source Data Excel (skip row 1 = description)
  50. df <- read_excel("sourceData.xlsx", sheet = "Fig. 5", skip = 1)
  51. cat("Data loaded:", nrow(df), "trials,", length(unique(df$subID)), "subjects\n")
  52. # --- 3. Factor coding --------------------------------------------------------
  53. # Sum-to-zero (deviation) contrasts: −0.5 / +0.5
  54. # Levels ordered so the contrast direction matches the manuscript
  55. df$Regulation <- factor(df$Regulation, levels = c("OFA", "FFA"))
  56. contrasts(df$Regulation) <- c(-0.5, 0.5)
  57. df$Training_Day <- factor(df$Training_Day, ordered = TRUE)
  58. # Mean-center runID for consistent conditional effect interpretation
  59. df$runID <- df$runID - mean(df$runID)
  60. # Ensure scaled variables are numeric (read_excel may import as list-columns)
  61. scale_cols <- c("regFFA_s", "regOFA_s", "diffROI_s",
  62. "task_detect_FFA_beta_s", "task_detect_OFA_beta_s",
  63. "task_recogn_FFA_beta_s", "task_recogn_OFA_beta_s",
  64. "task_FFA_beta_s", "task_OFA_beta_s")
  65. for (col in scale_cols) {
  66. df[[col]] <- as.numeric(df[[col]])
  67. }
  68. # --- 4. Model fitting --------------------------------------------------------
  69. # Note on model numbering:
  70. # Paper Model 2 → md1 (FFA detection DV)
  71. # Paper Model 3 → md3 (OFA detection DV)
  72. # Paper Model 4 → md2 (FFA recognition DV)
  73. # Paper Model 5 → md4 (OFA recognition DV)
  74. # This follows the original analysis script naming convention.
  75. cat("\n--- Fitting Model 2: FFA detection ---\n")
  76. md1 <- lmer(task_detect_FFA_beta_s ~ regFFA_s + regOFA_s + Regulation +
  77. runID + Training_Day + detection_frms +
  78. regFFA_s * regOFA_s * Regulation +
  79. (1|subID) + (1|stimID),
  80. data = df, REML = TRUE)
  81. print(summary(md1))
  82. cat("\n--- Fitting Model 3: OFA detection ---\n")
  83. md3 <- lmer(task_detect_OFA_beta_s ~ regFFA_s + regOFA_s + Regulation +
  84. runID + Training_Day + detection_frms +
  85. regFFA_s * regOFA_s * Regulation +
  86. (1|subID) + (1|stimID),
  87. data = df, REML = TRUE)
  88. print(summary(md3))
  89. cat("\n--- Fitting Model 4: FFA recognition ---\n")
  90. md2 <- lmer(task_recogn_FFA_beta_s ~ regFFA_s + regOFA_s + Regulation +
  91. runID + Training_Day + detection_frms +
  92. task_detect_FFA_beta_s +
  93. regFFA_s * regOFA_s * Regulation +
  94. (1|subID) + (1|stimID),
  95. data = df, REML = TRUE)
  96. print(summary(md2))
  97. cat("\n--- Fitting Model 5: OFA recognition ---\n")
  98. md4 <- lmer(task_recogn_OFA_beta_s ~ regFFA_s + regOFA_s + Regulation +
  99. runID + Training_Day + detection_frms +
  100. task_detect_OFA_beta_s +
  101. regFFA_s * regOFA_s * Regulation +
  102. (1|subID) + (1|stimID),
  103. data = df, REML = TRUE)
  104. print(summary(md4))
  105. # --- 4a. Standardized coefficients with CIs ----------------------------------
  106. cat("\n--- Standardized coefficients (arm::standardize) with 95% Wald CIs ---\n")
  107. std_with_ci <- function(model, label) {
  108. std_obj <- standardize(model)
  109. coefs <- as.data.frame(summary(std_obj)$coefficients)
  110. ci <- confint(std_obj, method = "Wald")
  111. ci <- ci[rownames(coefs), ]
  112. result <- cbind(coefs, ci)
  113. cat(paste0("\n", label, ":\n"))
  114. print(result)
  115. return(result)
  116. }
  117. md1_std_ci <- std_with_ci(md1, "Model 2: FFA detection")
  118. md3_std_ci <- std_with_ci(md3, "Model 3: OFA detection")
  119. md2_std_ci <- std_with_ci(md2, "Model 4: FFA recognition")
  120. md4_std_ci <- std_with_ci(md4, "Model 5: OFA recognition")
  121. # Keep arm::standardize model objects for dwplot (by_2sd = FALSE)
  122. md1_std_obj <- standardize(md1)
  123. md3_std_obj <- standardize(md3)
  124. md2_std_obj <- standardize(md2)
  125. md4_std_obj <- standardize(md4)
  126. # --- 4b. Simple slopes via emtrends (Holm-corrected per model) ---------------
  127. # For each model, we test 4 slopes: 2 predictors (regFFA, regOFA) × 2 sessions.
  128. # Holm correction is applied across the 4 slopes within each model.
  129. holm_correct_slopes <- function(model, model_label) {
  130. t_ffa <- as.data.frame(summary(emtrends(model, ~ Regulation, var = "regFFA_s"),
  131. infer = c(TRUE, TRUE), level = 0.95))
  132. t_ofa <- as.data.frame(summary(emtrends(model, ~ Regulation, var = "regOFA_s"),
  133. infer = c(TRUE, TRUE), level = 0.95))
  134. names(t_ffa)[grep("trend", names(t_ffa))] <- "slope"
  135. names(t_ofa)[grep("trend", names(t_ofa))] <- "slope"
  136. t_ffa$predictor <- "regFFA"
  137. t_ofa$predictor <- "regOFA"
  138. combined <- rbind(t_ffa, t_ofa)
  139. combined$p.holm <- p.adjust(combined$p.value, method = "holm")
  140. combined$sig <- ifelse(combined$p.holm < 0.001, "***",
  141. ifelse(combined$p.holm < 0.01, "**",
  142. ifelse(combined$p.holm < 0.05, "*", "ns.")))
  143. ratio_col <- ifelse("t.ratio" %in% names(combined), "t.ratio", "z.ratio")
  144. cat("\n===", model_label, "— Simple slopes (Holm-corrected for 4 tests) ===\n")
  145. print(combined[, c("predictor", "Regulation", "slope", "SE", "df",
  146. "lower.CL", "upper.CL", ratio_col,
  147. "p.value", "p.holm", "sig")])
  148. return(combined)
  149. }
  150. slopes_md1 <- holm_correct_slopes(md1, "Model 2: FFA detection")
  151. slopes_md3 <- holm_correct_slopes(md3, "Model 3: OFA detection")
  152. slopes_md2 <- holm_correct_slopes(md2, "Model 4: FFA recognition")
  153. slopes_md4 <- holm_correct_slopes(md4, "Model 5: OFA recognition")
  154. # --- 5. Coefficient plots (dot-whisker) --------------------------------------
  155. # Uses arm::standardize model objects with by_2sd = FALSE so that plotted
  156. # coefficients match the standardized values reported in the text.
  157. # Color scheme: blue = FFA ROI, red = OFA ROI
  158. colorSpecs <- c('#0F4889', '#D84545',
  159. '#0F4889', '#D84545',
  160. '#0F4889', '#D84545',
  161. '#0F4889', '#D84545',
  162. '#0F4889', '#D84545',
  163. '#0F4889', '#D84545',
  164. '#0F4889', '#D84545')
  165. predictor_labels_std <- c(
  166. z.regFFA_s = "regFFA",
  167. z.regOFA_s = "regOFA",
  168. c.Regulation = "Session",
  169. `z.regFFA_s:z.regOFA_s` = "regFFA*regOFA",
  170. `z.regFFA_s:c.Regulation` = "regFFA*Session",
  171. `z.regOFA_s:c.Regulation` = "regOFA*Session",
  172. `z.regFFA_s:z.regOFA_s:c.Regulation` = "regFFA*regOFA*Session"
  173. )
  174. variable_order_std <- c("z.regFFA_s", "z.regOFA_s", "c.Regulation",
  175. "z.regFFA_s:z.regOFA_s",
  176. "z.regFFA_s:c.Regulation", "z.regOFA_s:c.Regulation",
  177. "z.regFFA_s:z.regOFA_s:c.Regulation")
  178. # Detection: Models 2 & 3
  179. p1 <- dwplot(list(md3_std_obj, md1_std_obj),
  180. by_2sd = FALSE, ci = 0.95,
  181. dot_args = list(size = 4, shape = 21, fill = colorSpecs, color = "black", stroke = 1.2),
  182. whisker_args = list(size = 1, color = colorSpecs),
  183. style = "dotwhisker",
  184. vline = geom_vline(xintercept = 0, colour = "grey60",
  185. size = 1, linetype = 2),
  186. vars_order = variable_order_std) %>%
  187. relabel_predictors(predictor_labels_std) +
  188. scale_color_manual(name = "ROI", labels = c("FFA", "OFA")) +
  189. xlab("Standardized Coefficient (ß)") + ylab("") +
  190. ggtitle("Model 2 and 3: Detection") +
  191. theme_blank() +
  192. theme_article()
  193. # Recognition: Models 4 & 5
  194. p2 <- dwplot(list(md4_std_obj, md2_std_obj),
  195. by_2sd = FALSE, ci = 0.95,
  196. dot_args = list(size = 4, shape = 21, fill = colorSpecs, color = "black", stroke = 1.2),
  197. whisker_args = list(size = 1, color = colorSpecs),
  198. style = "dotwhisker",
  199. vline = geom_vline(xintercept = 0, colour = "grey60",
  200. size = 1, linetype = 2),
  201. vars_order = variable_order_std) %>%
  202. relabel_predictors(predictor_labels_std) +
  203. scale_color_manual(name = "ROI", labels = c("FFA", "OFA")) +
  204. xlab("Standardized Coefficient (ß)") + ylab("") +
  205. ggtitle("Model 4 and 5: Recognition") +
  206. theme_blank() +
  207. theme_article()
  208. # --- 6. Marginal effects with density margins --------------------------------
  209. colorSpecs_ffa_2 <- c('#378AD3', '#0C4787') # light/dark blue
  210. colorSpecs_ofa_2 <- c('#FF8585', '#D74545') # light/dark red
  211. ylimits <- c(-1, 2)
  212. densPlot_size <- 8
  213. # -- 6a. DETECTION panels (pl1–pl4) --
  214. # pl1: regFFA → FFA detection
  215. pl1_base <- plot_model(md1, type = "pred", terms = c('regFFA_s', 'Regulation'),
  216. legend.title = "Session", show.legend = FALSE,
  217. colors = colorSpecs_ffa_2) +
  218. theme_sjplot2() + geom_line(size = 1) +
  219. rasterise(geom_point(data = df,
  220. aes(x = regFFA_s, y = task_detect_FFA_beta_s, color = Regulation),
  221. alpha = 0.15, size = 0.5, inherit.aes = FALSE)) +
  222. xlab('regFFA (PSC)') + ylab(expression(paste("Detection Resp ", (beta)))) +
  223. coord_cartesian(ylim = ylimits) + ggtitle('FFA')
  224. pl1 <- ggMarginal(pl1_base, type = "density", groupColour = TRUE,
  225. groupFill = TRUE, alpha = 0.3, size = densPlot_size)
  226. # pl2: regFFA → OFA detection
  227. pl2_base <- plot_model(md3, type = "pred", terms = c('regFFA_s', 'Regulation'),
  228. legend.title = "Session", show.legend = FALSE,
  229. colors = colorSpecs_ofa_2) +
  230. theme_sjplot2() + geom_line(size = 1) +
  231. rasterise(geom_point(data = df,
  232. aes(x = regFFA_s, y = task_detect_OFA_beta_s, color = Regulation),
  233. alpha = 0.15, size = 0.5, inherit.aes = FALSE)) +
  234. xlab('regFFA (PSC)') + ylab(expression(paste("Detection Resp ", (beta)))) +
  235. coord_cartesian(ylim = ylimits) + ggtitle('OFA')
  236. pl2 <- ggMarginal(pl2_base, type = "density", groupColour = TRUE,
  237. groupFill = TRUE, alpha = 0.3, size = densPlot_size)
  238. # pl3: regOFA → FFA detection
  239. pl3_base <- plot_model(md1, type = "pred", terms = c('regOFA_s', 'Regulation'),
  240. legend.title = "Session", show.legend = FALSE,
  241. colors = colorSpecs_ffa_2) +
  242. theme_sjplot2() + geom_line(size = 1) +
  243. rasterise(geom_point(data = df,
  244. aes(x = regOFA_s, y = task_detect_FFA_beta_s, color = Regulation),
  245. alpha = 0.15, size = 0.5, inherit.aes = FALSE)) +
  246. xlab('regOFA (PSC)') + ylab(expression(paste("Detection Resp ", (beta)))) +
  247. coord_cartesian(ylim = ylimits) + ggtitle('FFA')
  248. pl3 <- ggMarginal(pl3_base, type = "density", groupColour = TRUE,
  249. groupFill = TRUE, alpha = 0.3, size = densPlot_size)
  250. # pl4: regOFA → OFA detection
  251. pl4_base <- plot_model(md3, type = "pred", terms = c('regOFA_s', 'Regulation'),
  252. legend.title = "Session", show.legend = FALSE,
  253. colors = colorSpecs_ofa_2) +
  254. theme_sjplot2() + geom_line(size = 1) +
  255. rasterise(geom_point(data = df,
  256. aes(x = regOFA_s, y = task_detect_OFA_beta_s, color = Regulation),
  257. alpha = 0.15, size = 0.5, inherit.aes = FALSE)) +
  258. xlab('regOFA (PSC)') + ylab(expression(paste("Detection Resp ", (beta)))) +
  259. coord_cartesian(ylim = ylimits) + ggtitle('OFA')
  260. pl4 <- ggMarginal(pl4_base, type = "density", groupColour = TRUE,
  261. groupFill = TRUE, alpha = 0.3, size = densPlot_size)
  262. # -- 6b. RECOGNITION panels (pl5–pl8) --
  263. # pl5: regFFA → FFA recognition
  264. pl5_base <- plot_model(md2, type = "pred", terms = c('regFFA_s', 'Regulation'),
  265. legend.title = "Session", show.legend = FALSE,
  266. colors = colorSpecs_ffa_2) +
  267. theme_sjplot2() + geom_line(size = 1) +
  268. rasterise(geom_point(data = df,
  269. aes(x = regFFA_s, y = task_recogn_FFA_beta_s, color = Regulation),
  270. alpha = 0.15, size = 0.5, inherit.aes = FALSE)) +
  271. xlab('regFFA (PSC)') + ylab(expression(paste("Recognition Resp ", (beta)))) +
  272. coord_cartesian(ylim = ylimits) + ggtitle('FFA')
  273. pl5 <- ggMarginal(pl5_base, type = "density", groupColour = TRUE,
  274. groupFill = TRUE, alpha = 0.3, size = densPlot_size)
  275. # pl6: regFFA → OFA recognition
  276. pl6_base <- plot_model(md4, type = "pred", terms = c('regFFA_s', 'Regulation'),
  277. legend.title = "Session", show.legend = FALSE,
  278. colors = colorSpecs_ofa_2) +
  279. theme_sjplot2() + geom_line(size = 1) +
  280. rasterise(geom_point(data = df,
  281. aes(x = regFFA_s, y = task_recogn_OFA_beta_s, color = Regulation),
  282. alpha = 0.15, size = 0.5, inherit.aes = FALSE)) +
  283. xlab('regFFA (PSC)') + ylab(expression(paste("Recognition Resp ", (beta)))) +
  284. coord_cartesian(ylim = ylimits) + ggtitle('OFA')
  285. pl6 <- ggMarginal(pl6_base, type = "density", groupColour = TRUE,
  286. groupFill = TRUE, alpha = 0.3, size = densPlot_size)
  287. # pl7: regOFA → FFA recognition
  288. pl7_base <- plot_model(md2, type = "pred", terms = c('regOFA_s', 'Regulation'),
  289. legend.title = "Session", show.legend = FALSE,
  290. colors = colorSpecs_ffa_2) +
  291. theme_sjplot2() + geom_line(size = 1) +
  292. rasterise(geom_point(data = df,
  293. aes(x = regOFA_s, y = task_recogn_FFA_beta_s, color = Regulation),
  294. alpha = 0.15, size = 0.5, inherit.aes = FALSE)) +
  295. xlab('regOFA (PSC)') + ylab(expression(paste("Recognition Resp ", (beta)))) +
  296. coord_cartesian(ylim = ylimits) + ggtitle('FFA')
  297. pl7 <- ggMarginal(pl7_base, type = "density", groupColour = TRUE,
  298. groupFill = TRUE, alpha = 0.3, size = densPlot_size)
  299. # pl8: regOFA → OFA recognition
  300. pl8_base <- plot_model(md4, type = "pred", terms = c('regOFA_s', 'Regulation'),
  301. legend.title = "Session", show.legend = FALSE,
  302. colors = colorSpecs_ofa_2) +
  303. theme_sjplot2() + geom_line(size = 1) +
  304. rasterise(geom_point(data = df,
  305. aes(x = regOFA_s, y = task_recogn_OFA_beta_s, color = Regulation),
  306. alpha = 0.15, size = 0.5, inherit.aes = FALSE)) +
  307. xlab('regOFA (PSC)') + ylab(expression(paste("Recognition Resp ", (beta)))) +
  308. coord_cartesian(ylim = ylimits) + ggtitle('OFA')
  309. pl8 <- ggMarginal(pl8_base, type = "density", groupColour = TRUE,
  310. groupFill = TRUE, alpha = 0.3, size = densPlot_size)
  311. # --- 7. Assemble figure ------------------------------------------------------
  312. # Detection half: regFFA panels | regOFA panels | coefficient plot
  313. figure1 <- cowplot::plot_grid(
  314. cowplot::plot_grid(pl1, pl2, ncol = 1), # regFFA → FFA/OFA detection
  315. cowplot::plot_grid(pl3, pl4, ncol = 1), # regOFA → FFA/OFA detection
  316. NULL, # spacing
  317. p1, # dot-whisker
  318. ncol = 4,
  319. rel_widths = c(1, 1, 0.3, 1.2)
  320. )
  321. # Recognition half: coefficient plot | regFFA panels | regOFA panels
  322. figure2 <- cowplot::plot_grid(
  323. p2, # dot-whisker
  324. NULL, # spacing
  325. cowplot::plot_grid(pl5, pl6, ncol = 1), # regFFA → FFA/OFA recognition
  326. cowplot::plot_grid(pl7, pl8, ncol = 1), # regOFA → FFA/OFA recognition
  327. ncol = 4,
  328. rel_widths = c(1.2, 0.3, 1, 1)
  329. )
  330. # --- 8. Summary table (for SFig. 2) ------------------------------------------
  331. # Full unstandardized model output tables for the supplementary materials
  332. # (SFig. 2). Raw coefficients are reported in the original units of the model
  333. # (z-scored task beta responses) and include all covariates, random effects,
  334. # and fit statistics. Standardized coefficients are reported in the main text
  335. # and dot-whisker plots (from arm::standardize) for visual comparison across
  336. # predictors on a common scale.
  337. myDV <- c('Model 2: FFA detection', 'Model 3: OFA Detection',
  338. 'Model 4: FFA Recognition', 'Model 5: OFA Recognition')
  339. tab_model(md1, md3, md2, md4,
  340. dv.labels = myDV,
  341. show.se = TRUE,
  342. string.est = "Estimate", string.se = "SE",
  343. title = 'Linear Mixed Models: Self-Regulation → Task Responses')

fig5_models2to5_task_effects.R at commit 45a6b36, no license · at the source

Overview

  1. Laboratory for Behavioural Neurology and Imaging of Cognition, Department of Basic Neuroscience, University of Geneva,Geneva, Switzerland
  2. Center for Bio- and Medical Technologies, Moscow, Russia
  3. Swiss Center for Affective Science, University of Geneva,Geneva, Switzerland
  4. Center for Biomedical Imaging, University of Geneva/EPFL,Lausanne, Switzerland
Institutions: University of Geneva (Switzerland)
Journal: Nature communications, volume 17, issue 1, article 7515
Dates: received 23 February 2024; accepted 27 May 2026; published online 13 June 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41467-026-74331-2 · PMID 42288473 · PMCID PMC13409027 · OpenAlex W7164644657
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: fMRI (modality), human (organism)
Methods: Statistics, fMRI & imaging, Smoothing, state filtering, decompositions, Spectral & time-frequency
Keywords: Extrastriate cortex, Perception
MeSH: Facial Recognition*, Magnetic Resonance Imaging*, Neurofeedback*, Occipital Lobe*, Temporal Lobe*, Adult, Brain Mapping, Face, Female, Humans, Male, Pattern Recognition, Visual, Photic Stimulation, Young Adult (* major topic)
Topic: Face Recognition and Perception (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Citations: not cited yet (Europe PMC); 88 references in the paper

Abstract

Self-regulation of specific brain regions can be achieved using neurofeedback with real-time functional magnetic resonance imaging (rt-fMRI). We leveraged this technique to dissect the role of two tightly interconnected areas implicated in face perception, by interleaving a visual task with upregulation of either the occipital (OFA) or fusiform face-responsive areas (FFA) in a trial-wise manner. Experimental participants (N = 22) successfully enhanced their target region when compared to yoked controls (N = 20). Regulation was face-selective, as evidenced by concomitant increases in other nodes of the face processing network. Critically, face detection was faster with enhanced FFA activity but hindered by enhanced OFA, whereas face identity recognition was optimal with concomitant increases in both FFA and OFA. These results argue against traditional face processing models assuming an information flow from posterior occipital to anterior fusiform cortex and instead support non-hierarchical models where FFA mediates initial face detection and OFA contributes to subsequent identity recognition.

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

Repositories

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

lucp88/prepNFB

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: a9dfcd7af5e41e5708f84f6f0bb9e5f714bd7009, 17 February 2022
Languages: MATLAB (26)
Size: 151 files, 26 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: SPM (16 files), Image Processing Toolbox (2 files), Psychtoolbox (2 files)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
27 files

lucp88/NCOMMS-24-11279A

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 45a6b36e2b19e216fb8cbc9cdae1ed277f9c0fdf, 17 April 2026
Languages: R (9), MATLAB (7), Python (3)
Size: 20 files, 19 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: tidyverse (9 files), ggplot2 (8 files), lme4 (7 files), lmerTest (7 files), emmeans (6 files), patchwork (6 files), cowplot (5 files), Statistics and Machine Learning Toolbox (4 files), shadedErrorBar (4 files), NiBabel (1 file), Nilearn (1 file), NumPy (1 file), pandas (1 file), rstatix (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
20 files

Zenodo 19548058

License: CC-BY-4.0
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: tidyverse (9 files), ggplot2 (8 files), lme4 (7 files), lmerTest (7 files), emmeans (6 files), patchwork (6 files), cowplot (5 files), Statistics and Machine Learning Toolbox (4 files), shadedErrorBar (4 files), NiBabel (1 file), Nilearn (1 file), NumPy (1 file), pandas (1 file), rstatix (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
  • 27 September 2026: the link answers (HTTP 200)
20 files
At the source:

Code availability

The prepNFB toolbox developed for this study is available at https://github.com/lucp88/prepNFB. The real-time fMRI neurofeedback protocol was implemented in a custom version of the OpenNFT suite (http://opennft.org/). Analysis code (R and Python) for reproducing all statistical analyses and figures (main Figs. 2–7 and Supplementary Figs. 1–9), including linear mixed models, permutation tests, and structural equation models, is publicly available at https://github.com/lucp88/NCOMMS-24-11279A and archived on Zenodo (10.5281/zenodo.19548058). All other software and tools used in this study are described in the “Methods” section.

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

Tracing map

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

What the map holds:

  • 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 64 scripts, each with its path and the digest of its content;
  • 21 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

Data availability

The source data underlying all main and Supplementary Figs. are provided in the Source Data file published with this paper. The individual-level neuroimaging and behavioural data generated in this study are available under restricted access due to participant privacy protections under the ethical approval granted by the Ethical Committee of Geneva University Hospital (HUG), which does not permit unrestricted public deposition of identifiable neuroimaging data. Access can be obtained by contacting the corresponding author and completing a data use agreement specifying the intended use. Access requests will be reviewed and responded to within 30 days, subject to ethical approval. Data are available for academic, non-commercial research purposes. Data will remain available for a minimum of 10 years following publication. Source data are provided with this paper.

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

Versions

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

Version 1, 27 September 2026: the first record

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

Cite

This paper

Peek, L., Koush, Y., & Vuilleumier, P. (2026). Trial-by-trial fMRI-neurofeedback dissociates fusiform and occipital contributions to face detection and recognition. Nature communications, 17(1), 7515. https://doi.org/10.1038/s41467-026-74331-2

BibTeX

@article{peek2026trial,
author = {Peek, Lucas and Koush, Yury and Vuilleumier, Patrik},
title = {{Trial-by-trial fMRI-neurofeedback dissociates fusiform and occipital contributions to face detection and recognition}},
journal = {Nature communications},
year = {2026},
month = jun,
volume = {17},
number = {1},
pages = {7515},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/s41467-026-74331-2},
url = {https://doi.org/10.1038/s41467-026-74331-2},
pmid = {42288473},
pmcid = {PMC13409027}
}

RIS

TY - JOUR
AU - Peek, Lucas
AU - Koush, Yury
AU - Vuilleumier, Patrik
TI - Trial-by-trial fMRI-neurofeedback dissociates fusiform and occipital contributions to face detection and recognition
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/06/13
VL - 17
IS - 1
SP - 7515
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/s41467-026-74331-2
UR - https://doi.org/10.1038/s41467-026-74331-2
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41467-026-74331-2",
"type": "article-journal",
"title": "Trial-by-trial fMRI-neurofeedback dissociates fusiform and occipital contributions to face detection and recognition",
"container-title": "Nature communications",
"author": [
{
"family": "Peek",
"given": "Lucas"
},
{
"family": "Koush",
"given": "Yury"
},
{
"family": "Vuilleumier",
"given": "Patrik"
}
],
"container-title-short": "Nat Commun",
"volume": "17",
"issue": "1",
"page": "7515",
"DOI": "10.1038/s41467-026-74331-2",
"PMID": "42288473",
"PMCID": "PMC13409027",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41467-026-74331-2",
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
13
]
]
}
}

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.1162/imag.a.1268 [code]
Real-time fMRI-triggered experience sampling: A proof-of-concept study.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: shadedErrorBar, emmeans, lmerTest, 6 other tools, fMRI, 3 references
[2] doi:10.1093/nc/niag029 [code]
A data-driven approach to identifying and evaluating connectivity-based neural correlates of conscious visual perception.
Journal: Neuroscience of consciousness
In common: emmeans, lmerTest, Nilearn, 9 other tools, 1 reference
[3] doi:10.1162/imag.a.1245 [code]
Towards precision EEG connectomics: Evaluating the benefits of dense sampling.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: rstatix, lmerTest, Nilearn, 9 other tools
[4] doi:10.1162/imag.a.105 [code]
Right posterior theta reflects human parahippocampal phase resetting by salient cues during goal-directed navigation
Journal: n/a
In common: lmerTest, Nilearn, SPM, 7 other tools, fMRI, 2 references
[5] doi:10.7554/elife.109640
Concurrent category-selective neural activity across the ventral occipito-temporal cortex supports a non-hierarchical view of human visual recognition.
Journal: eLife
In common: 9 references
[6] 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. Clinical
In common: rstatix, lmerTest, SPM, 8 other tools, fMRI
[7] doi:10.1038/s41597-026-07377-y [code]
An open-access multi-site fMRI dataset for investigating conscious visual perception.
Journal: Scientific data
In common: emmeans, lmerTest, Nilearn, 7 other tools, fMRI, 1 reference
[8] doi:10.1162/imag.a.1321 [code]
Phase similarity between similar objects indicates representational merging across retrieval training but not sleep.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: rstatix, emmeans, lmerTest, 6 other tools, 2 references
[9] doi:10.1016/j.dcn.2026.101765 [code]
Fusiform face area development correlates with development in higher-order social brain regions.
Journal: Developmental cognitive neuroscience
In common: lmerTest, Nilearn, lme4, 5 other tools, fMRI, 3 references
[10] doi:10.1002/hbm.70512 [code]
Precision Imaging for Intraindividual Investigation of the Reward Response.
Journal: Human brain mapping
In common: Psychtoolbox, lmerTest, lme4, 6 other tools, fMRI, 2 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.

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.