highspeed-analysis-behavior.Rmd 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. ## Behavior
  2. ### Initialization
  3. #### Load data and files
  4. We set the paths and source the basic setup script:
  5. ```{r, warning=FALSE, message=FALSE}
  6. knitr::opts_chunk$set(echo = TRUE)
  7. # find the path to the root of this project:
  8. if (!requireNamespace("here")) install.packages("here")
  9. if ( basename(here::here()) == "highspeed" ) {
  10. path_root = here::here("highspeed-analysis")
  11. } else {
  12. path_root = here::here()
  13. }
  14. # source all relevant functions from the setup R script:
  15. source(file.path(path_root, "code", "highspeed-analysis-setup.R"))
  16. ```
  17. #### Signal-detection labeling
  18. We assign labels from signal detection theory that will be used in one of the analyses below:
  19. ```{r}
  20. # denotes misses (key was not pressed and stimulus was upside-down):
  21. dt_events$sdt_type[
  22. dt_events$key_down == 0 & dt_events$stim_orient == 180] <- "miss"
  23. # denotes hits (key was pressed and stimulus was upside-down):
  24. dt_events$sdt_type[
  25. dt_events$key_down == 1 & dt_events$stim_orient == 180] <- "hit"
  26. # denotes correct rejection (key was not pressed and stimulus was upright):
  27. dt_events$sdt_type[
  28. dt_events$key_down == 0 & dt_events$stim_orient == 0] <- "correct rejection"
  29. # denotes false alarms (key was pressed and stimulus was upright):
  30. dt_events$sdt_type[
  31. dt_events$key_down == 1 & dt_events$stim_orient == 0] <- "false alarm"
  32. ```
  33. ### Stimulus timings
  34. We calculate the differences between consecutive stimulus onsets:
  35. ```{r}
  36. dt_events %>%
  37. # get duration of stimuli by calculating differences between consecutive onsets:
  38. .[, duration_check := shift(onset, type = "lead") - onset,
  39. by = .(subject, run_study)] %>%
  40. # get the difference between the expected and actual stimulus duration:
  41. .[, duration_diff := duration_check - duration, by = .(subject, run_study)] %>%
  42. # for each condition and trial check participants' responses:
  43. .[, by = .(subject, condition, trial), ":=" (
  44. # for each trial check if a key has been pressed:
  45. trial_key_down = ifelse(any(key_down == 1, na.rm = TRUE), 1, 0),
  46. # for each trial check if the participant was accurate:
  47. trial_accuracy = ifelse(any(accuracy == 1, na.rm = TRUE), 1, 0)
  48. )] %>%
  49. .[, trial_type := factor(trial_type, levels = rev(unique(trial_type)))]
  50. ```
  51. ```{r}
  52. timings_summary = dt_events %>%
  53. filter(condition %in% c("sequence", "repetition") & trial_type == "interval") %>%
  54. setDT(.) %>%
  55. .[, by = .(subject, condition, trial_type), {
  56. results = t.test(duration_diff, mu = 0.001, alternative = "two.sided")
  57. list(
  58. mean = mean(duration_diff, na.rm = TRUE),
  59. sd = sd(duration_diff, na.rm = TRUE),
  60. min = min(duration_diff, na.rm = TRUE),
  61. max = max(duration_diff, na.rm = TRUE),
  62. num = .N,
  63. tvalue = results$statistic,
  64. df = results$parameter,
  65. pvalue = results$p.value,
  66. pvalue_round = round_pvalues(results$p.value)
  67. )
  68. }] %>%
  69. .[, trial_type := factor(trial_type, levels = rev(unique(trial_type)))] %>%
  70. setorder(., condition, trial_type)
  71. rmarkdown::paged_table(timings_summary)
  72. ```
  73. We plot the differences in expected versus actual timings of individual stimuli in the behavioral task:
  74. ```{r}
  75. ggplot(data = dt_events, aes(
  76. y = as.numeric(duration_diff),
  77. x = as.factor(trial_type),
  78. fill = as.factor(trial_type)), na.rm = TRUE) +
  79. facet_grid(vars(as.factor(trial_key_down)), vars(as.factor(condition))) +
  80. geom_point(
  81. aes(y = as.numeric(duration_diff), color = as.factor(trial_type)),
  82. position = position_jitter(width = .15), size = .5, alpha = 1, na.rm = TRUE) +
  83. geom_boxplot(width = .1, outlier.shape = NA, alpha = 0.5, na.rm = TRUE) +
  84. scale_color_brewer(palette = "Spectral") +
  85. scale_fill_brewer(palette = "Spectral") +
  86. #coord_capped_flip(left = "both", bottom = "both", expand = TRUE) +
  87. coord_flip() +
  88. theme(legend.position = "none") +
  89. xlab("Trial event (in serial order)") +
  90. ylab("Difference between expected and actual timing (in s)") +
  91. theme(strip.text = element_text(margin = margin(unit(c(t = 2, r = 2, b = 2, l = 2), "pt")))) +
  92. theme(legend.position = "none") +
  93. theme(panel.background = element_blank())
  94. ```
  95. ```{r, echo=FALSE, eval=FALSE}
  96. ggsave(filename = "highspeed_plot_behavior_timing_differences.pdf",
  97. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  98. dpi = "retina", width = 6, height = 4)
  99. ```
  100. We check the timing of the inter-trial interval on oddball trials:
  101. ```{r}
  102. dt_odd_iti_mean = dt_events %>%
  103. # filter for the stimulus intervals on oddball trials:
  104. filter(condition == "oddball" & trial_type == "interval") %>%
  105. setDT(.) %>%
  106. # calculate the mean duration of the oddball intervals for each participant:
  107. .[, by = .(subject), .(
  108. mean_duration = mean(duration, na.rm = TRUE),
  109. num_trials = .N
  110. )] %>%
  111. verify(num_trials == 600)
  112. rmarkdown::paged_table(head(dt_odd_iti_mean))
  113. ```
  114. ### Behavioral performance
  115. #### Mean accuracy
  116. We calculate the mean behavioral accuracy across all trials of all three task conditions (slow, sequence, and repetition trials):
  117. ```{r, echo=TRUE}
  118. # behavioral chance level is at 50%:
  119. chance_level = 50
  120. dt_acc = dt_events %>%
  121. # filter out all events that are not related to a participants' response:
  122. filter(!is.nan(accuracy)) %>%
  123. # filter for only upside down stimuli on slow trials:
  124. filter(!(condition == "oddball" & stim_orient == 0)) %>%
  125. setDT(.) %>%
  126. # check if the number of trials matches for every subject:
  127. verify(.[(condition == "oddball"), by = .(subject), .(
  128. num_trials = .N)]$num_trials == 120) %>%
  129. verify(.[(condition == "sequence"), by = .(subject), .(
  130. num_trials = .N)]$num_trials == 75) %>%
  131. verify(.[(condition == "repetition"), by = .(subject), .(
  132. num_trials = .N)]$num_trials == 45) %>%
  133. # calculate the average accuracy for each participant and condition:
  134. .[, by = .(subject, condition), .(
  135. mean_accuracy = mean(accuracy, na.rm = TRUE) * 100,
  136. num_trials = .N)] %>%
  137. # check if the accuracy values are between 0 and 100:
  138. assert(within_bounds(lower.bound = 0, upper.bound = 100), mean_accuracy) %>%
  139. # create new variable that specifies excluded participants:
  140. mutate(exclude = ifelse(mean_accuracy < chance_level, "yes", "no")) %>%
  141. # create a short name for the conditions:
  142. mutate(condition_short = substr(condition, start = 1, stop = 3)) %>%
  143. # reorder the condition factor in descending order of accuracy:
  144. transform(condition_short = fct_reorder(
  145. condition_short, mean_accuracy, .desc = TRUE))
  146. rmarkdown::paged_table(dt_acc)
  147. ```
  148. We create a list of participants that will be excluded because their performance is below the 50% chance level in either or both sequence and repetition trials:
  149. ```{r, echo=TRUE}
  150. # create a list with all excluded subject ids and print the list:
  151. subjects_excluded = unique(dt_acc$subject[dt_acc$exclude == "yes"])
  152. print(subjects_excluded)
  153. ```
  154. We calculate the mean behavioral accuracy across all three task conditions (slow, sequence, and repetition trials), *excluding* participants that performed below chance on either or both sequence and repetition trials:
  155. ```{r, echo=TRUE, results="hold"}
  156. dt_acc_mean = dt_acc %>%
  157. # filter out all data of excluded participants:
  158. filter(!(subject %in% unique(subject[exclude == "yes"]))) %>%
  159. # check if the number of participants matches expectations:
  160. verify(length(unique(subject)) == 36) %>%
  161. setDT(.) %>%
  162. # calculate mean behavioral accuracy across participants for each condition:
  163. .[, by = .(condition), {
  164. ttest_results = t.test(
  165. mean_accuracy, mu = chance_level, alternative = "greater")
  166. list(
  167. pvalue = ttest_results$p.value,
  168. pvalue_rounded = round_pvalues(ttest_results$p.value),
  169. tvalue = round(ttest_results$statistic, digits = 2),
  170. conf_lb = round(ttest_results$conf.int[1], digits = 2),
  171. conf_ub = round(ttest_results$conf.int[2], digits = 2),
  172. df = ttest_results$parameter,
  173. num_subs = .N,
  174. mean_accuracy = round(mean(mean_accuracy), digits = 2),
  175. SD = round(sd(mean_accuracy), digits = 2),
  176. cohens_d = round((mean(mean_accuracy) - chance_level) / sd(mean_accuracy), 2),
  177. sem_upper = mean(mean_accuracy) + (sd(mean_accuracy)/sqrt(.N)),
  178. sem_lower = mean(mean_accuracy) - (sd(mean_accuracy)/sqrt(.N))
  179. )}] %>%
  180. verify(num_subs == 36) %>%
  181. # create a short name for the conditions:
  182. mutate(condition_short = substr(condition, start = 1, stop = 3)) %>%
  183. # reorder the condition factor in descending order of accuracy:
  184. transform(condition_short = fct_reorder(condition_short, mean_accuracy, .desc = TRUE))
  185. # show the table (https://rstudio.github.io/distill/tables.html):
  186. rmarkdown::paged_table(dt_acc_mean)
  187. ```
  188. #### Above-chance performance
  189. We plot only data of above-chance performers:
  190. ```{r, echo = FALSE}
  191. fig_behav_all = ggplot(data = subset(dt_acc, exclude == "no"), aes(
  192. x = as.factor(condition_short), y = as.numeric(mean_accuracy),
  193. group = as.factor(condition_short), fill = as.factor(condition_short))) +
  194. geom_bar(stat = "summary", fun = "mean", color = "black", fill = "white") +
  195. geom_dotplot(binaxis = "y", stackdir = "center", stackratio = 0.5,
  196. color = "black", fill = "lightgray", alpha = 0.5,
  197. inherit.aes = TRUE, binwidth = 2) +
  198. geom_errorbar(stat = "summary", fun.data = "mean_se", width = 0.0, color = "black") +
  199. ylab("Accuracy (%)") + xlab("Condition") +
  200. scale_color_manual(values = c("darkgray", "red"), name = "Outlier") +
  201. geom_hline(aes(yintercept = 50), linetype = "dashed", color = "black") +
  202. guides(shape = FALSE, color = FALSE, fill = FALSE) +
  203. coord_capped_cart(left = "both", expand = TRUE, ylim = c(0, 100)) +
  204. theme(legend.position = "none") +
  205. theme(panel.border = element_blank()) +
  206. theme(axis.text = element_text(color = "black")) +
  207. theme(axis.ticks = element_line(color = "black")) +
  208. theme(axis.line.y = element_line(colour = "black"),
  209. axis.ticks.x = element_blank(),
  210. panel.grid.major = element_blank(),
  211. panel.grid.minor = element_blank(),
  212. panel.border = element_blank(),
  213. panel.background = element_blank())
  214. fig_behav_all
  215. ```
  216. #### Figure S1a
  217. We plot data of all participants with below chance performers highlighted in red.
  218. ```{r, echo=TRUE}
  219. fig_behav_all_outlier = ggplot(data = dt_acc_mean,
  220. mapping = aes(x = as.factor(condition_short), y = as.numeric(mean_accuracy),
  221. group = as.factor(condition_short), fill = as.factor(condition_short))) +
  222. geom_bar(aes(fill = as.factor(condition)), stat = "identity",
  223. color = "black", fill = "white") +
  224. geom_point(data = subset(dt_acc, exclude == "no"),
  225. aes(color = as.factor(exclude)),
  226. position = position_jitter(width = 0.2, height = 0, seed = 2),
  227. alpha = 0.5, inherit.aes = TRUE, pch = 21,
  228. color = "black", fill = "lightgray") +
  229. geom_point(data = subset(dt_acc, exclude == "yes"),
  230. aes(color = as.factor(exclude), shape = as.factor(subject)),
  231. position = position_jitter(width = 0.05, height = 0, seed = 4),
  232. alpha = 1, inherit.aes = TRUE, color = "red") +
  233. geom_errorbar(aes(ymin = sem_lower, ymax = sem_upper), width = 0.0, color = "black") +
  234. ylab("Accuracy (%)") + xlab("Condition") +
  235. scale_color_manual(values = c("darkgray", "red"), name = "Outlier") +
  236. geom_hline(aes(yintercept = 50), linetype = "dashed", color = "black") +
  237. coord_capped_cart(left = "both", bottom = "none", expand = TRUE, ylim = c(0, 100)) +
  238. theme(axis.ticks.x = element_line(color = "white"),
  239. axis.line.x = element_line(color = "white")) +
  240. guides(shape = FALSE, fill = FALSE) +
  241. theme(axis.text = element_text(color = "black")) +
  242. theme(axis.ticks = element_line(color = "black")) +
  243. theme(axis.line.y = element_line(colour = "black"),
  244. axis.ticks.x = element_blank(),
  245. panel.grid.major = element_blank(),
  246. panel.grid.minor = element_blank(),
  247. panel.border = element_blank(),
  248. panel.background = element_blank())
  249. fig_behav_all_outlier
  250. ```
  251. #### Source Data File Fig. S1a
  252. ```{r, echo=TRUE}
  253. dt_acc %>%
  254. select(-num_trials) %>%
  255. write.csv(., file = file.path(path_sourcedata, "source_data_figure_s1a.csv"),
  256. row.names = FALSE)
  257. ```
  258. ### Slow trials
  259. #### Mean accuracy (all trials)
  260. We calculate the mean accuracy on slow trials (oddball task condition) across all trials in the final sample (only participants who performed above chance):
  261. ```{r, echo=TRUE}
  262. # we use the dataframe containing the accuracy data
  263. dt_acc_odd = dt_acc %>%
  264. # filter for oddball / slow trials only:
  265. filter(condition == "oddball") %>%
  266. # exclude participants with below chance performance::
  267. filter(!(subject %in% subjects_excluded)) %>%
  268. # verify that the number of participants (final sample) is correct:
  269. verify(all(.N == 36))
  270. ```
  271. We plot the mean behavioral accuracy on slow trials (oddball task condition) in the final sample:
  272. ```{r, echo=TRUE, fig.width=3}
  273. fig_behav_odd = ggplot(data = dt_acc_odd, aes(
  274. x = "mean_acc", y = as.numeric(mean_accuracy))) +
  275. geom_bar(stat = "summary", fun = "mean", fill = "lightgray") +
  276. #geom_dotplot(binaxis = "y", stackdir = "center", stackratio = 0.5,
  277. # color = "black", fill = "lightgray", alpha = 0.5,
  278. # inherit.aes = TRUE, binwidth = 0.5) +
  279. geom_point(position = position_jitter(width = 0.2, height = 0, seed = 2),
  280. alpha = 0.5, inherit.aes = TRUE, pch = 21,
  281. color = "black", fill = "lightgray") +
  282. geom_errorbar(stat = "summary", fun.data = "mean_se", width = 0.0, color = "black") +
  283. ylab("Accuracy (%)") + xlab("Condition") +
  284. scale_color_manual(values = c("darkgray", "red"), name = "Outlier") +
  285. geom_hline(aes(yintercept = 50), linetype = "dashed", color = "black") +
  286. #coord_capped_cart(left = "both", bottom = "none", expand = TRUE, ylim = c(90, 100)) +
  287. theme(plot.title = element_text(size = 12, face = "plain")) +
  288. theme(axis.ticks.x = element_line(color = "white"),
  289. axis.line.x = element_line(color = "white")) +
  290. theme(axis.title.x = element_text(color = "white"),
  291. axis.text.x = element_text(color = "white")) +
  292. ggtitle("Slow") +
  293. theme(plot.title = element_text(hjust = 0.5))
  294. fig_behav_odd
  295. ```
  296. #### Mean accuracy (per run)
  297. We calculate the mean behavioral accuracy on slow trials (oddball task condition) for each of the eight task runs *for each* participant:
  298. ```{r}
  299. # calculate the mean accuracy per session and run for every participant:
  300. dt_odd_behav_run_sub = dt_events %>%
  301. # exclude participants performing below chance:
  302. filter(!(subject %in% subjects_excluded)) %>%
  303. # select only oddball condition and stimulus events:
  304. filter(condition == "oddball" & trial_type == "stimulus") %>%
  305. # filter for upside-down trials (oddballs) only:
  306. filter(stim_orient == 180) %>%
  307. setDT(.) %>%
  308. # calculate mean accuracy per session and run:
  309. .[, by = .(subject, session, run_study, run_session), .(
  310. mean_accuracy = mean(accuracy))] %>%
  311. # express accuracy in percent by multiplying with 100:
  312. transform(mean_accuracy = mean_accuracy * 100) %>%
  313. # check whether the mean accuracy is within the expected range of 0 to 100:
  314. assert(within_bounds(lower.bound = 0, upper.bound = 100), mean_accuracy)
  315. ```
  316. We calculate the mean behavioral accuracy on slow trials (oddball task condition) for each of the eight task runs *across* participants:
  317. ```{r}
  318. # calculate mean accuracy per session and run across participants:
  319. dt_odd_behav_run_mean = dt_odd_behav_run_sub %>%
  320. setDT(.) %>%
  321. # average across participants:
  322. .[, by = .(session, run_study, run_session), .(
  323. mean_accuracy = mean(mean_accuracy),
  324. num_subs = .N,
  325. sem_upper = mean(mean_accuracy) + (sd(mean_accuracy)/sqrt(.N)),
  326. sem_lower = mean(mean_accuracy) - (sd(mean_accuracy)/sqrt(.N))
  327. )] %>%
  328. verify(num_subs == 36) %>%
  329. # z-score the accuracy values:
  330. mutate(mean_accuracy_z = scale(mean_accuracy, scale = TRUE, center = TRUE))
  331. ```
  332. We run a LME model to test the linear effect of task run on behavioral accuracy:
  333. ```{r, results="hold", echo=TRUE}
  334. lme_odd_behav_run = lmerTest::lmer(
  335. mean_accuracy ~ run_study + (1 + run_study | subject),
  336. data = dt_odd_behav_run_sub, na.action = na.omit, control = lcctrl)
  337. summary(lme_odd_behav_run)
  338. anova(lme_odd_behav_run)
  339. ```
  340. We run a second model to test run- and session-specific effects:
  341. ```{r, results="hold"}
  342. dt <- dt_odd_behav_run_sub %>%
  343. transform(run_session = as.factor(paste0("run-0", run_session)),
  344. session = as.factor(paste0("ses-0", session)))
  345. ```
  346. ```{r, results="hold"}
  347. lme_odd_behav_run = lmerTest::lmer(
  348. mean_accuracy ~ session + run_session + (1 + session + run_session | subject),
  349. data = dt, na.action = na.omit, control = lcctrl)
  350. summary(lme_odd_behav_run)
  351. emmeans(lme_odd_behav_run, list(pairwise ~ run_session | session))
  352. anova(lme_odd_behav_run)
  353. rm(dt)
  354. ```
  355. #### Figure S1c
  356. We plot the behavioral accuracy on slow trials (oddball task condition) across task runs (x-axis) for each study session (panels):
  357. ```{r, echo=TRUE}
  358. # change labels of the facet:
  359. facet_labels_new = unique(paste0("Session ", dt_events$session))
  360. facet_labels_old = as.character(unique(dt_events$session))
  361. names(facet_labels_new) = facet_labels_old
  362. # plot behavioral accuracy across runs:
  363. plot_odd_run = ggplot(data = dt_odd_behav_run_mean, mapping = aes(
  364. y = as.numeric(mean_accuracy), x = as.numeric(run_session))) +
  365. geom_ribbon(aes(ymin = sem_lower, ymax = sem_upper), alpha = 0.5, fill = "gray") +
  366. geom_line(color = "black") +
  367. facet_wrap(~ as.factor(session), labeller = as_labeller(facet_labels_new)) +
  368. ylab("Accuracy (%)") + xlab("Run") +
  369. ylim(c(90, 100)) +
  370. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(90,100)) +
  371. theme(axis.ticks.x = element_text(color = "white"),
  372. axis.line.x = element_line(color = "white")) +
  373. theme(strip.text.x = element_text(margin = margin(b = 2, t = 2))) +
  374. theme(axis.text = element_text(color = "black")) +
  375. theme(axis.ticks = element_line(color = "black")) +
  376. theme(axis.line.y = element_line(colour = "black"),
  377. axis.ticks.x = element_blank(),
  378. panel.grid.major = element_blank(),
  379. panel.grid.minor = element_blank(),
  380. panel.border = element_blank(),
  381. panel.background = element_blank())
  382. plot_odd_run
  383. ```
  384. #### Source Data File Fig. S1c
  385. ```{r}
  386. dt_odd_behav_run_mean %>%
  387. select(-num_subs, -mean_accuracy_z) %>%
  388. write.csv(., file = file.path(path_sourcedata, "source_data_figure_s1c.csv"),
  389. row.names = FALSE)
  390. ```
  391. #### Misses vs. false alarms
  392. We calculate the mean frequency of misses (missed response to upside-down images) and false alarms (incorrect response to upright images):
  393. ```{r, echo=TRUE}
  394. dt_odd_behav_sdt_sub = dt_events %>%
  395. # exclude participants performing below chance:
  396. filter(!(subject %in% subjects_excluded)) %>%
  397. # select only oddball condition and stimulus events:
  398. filter(condition == "oddball" & trial_type == "stimulus") %>%
  399. setDT(.) %>%
  400. # create new variable with number of upside-down / upright stimuli per run:
  401. .[, by = .(subject, session, run_session, stim_orient), ":=" (
  402. num_orient = .N
  403. )] %>%
  404. # get the number of signal detection trial types for each run:
  405. .[, by = .(subject, session, run_session, sdt_type), .(
  406. num_trials = .N,
  407. freq = .N/unique(num_orient)
  408. )] %>%
  409. # add missing values:
  410. complete(nesting(subject, session, run_session), nesting(sdt_type),
  411. fill = list(num_trials = 0, freq = 0)) %>%
  412. transform(freq = freq * 100) %>%
  413. filter(sdt_type %in% c("false alarm", "miss"))
  414. ```
  415. We run a LME model to test the effect of signal detection type (miss vs. false alarm), task run and session on the frequency of those events:
  416. ```{r, results = "hold"}
  417. lme_odd_behav_sdt = lmer(
  418. freq ~ sdt_type + run_session * session + (1 + run_session + session | subject),
  419. data = subset(dt_odd_behav_sdt_sub), na.action = na.omit, control = lcctrl)
  420. summary(lme_odd_behav_sdt)
  421. anova(lme_odd_behav_sdt)
  422. emmeans_results = emmeans(lme_odd_behav_sdt, list(pairwise ~ sdt_type))
  423. emmeans_pvalues = round_pvalues(summary(emmeans_results[[2]])$p.value)
  424. emmeans_results
  425. ```
  426. #### Figure S1b
  427. We plot the frequency of misses and false alarms as a function of task run and study session:
  428. ```{r, echo=TRUE}
  429. plot_odd_sdt = ggplot(data = dt_odd_behav_sdt_sub, mapping = aes(
  430. y = as.numeric(freq), x = as.numeric(run_session),
  431. fill = as.factor(sdt_type), color = as.factor(sdt_type))) +
  432. stat_summary(geom = "bar", fun = mean, position = position_dodge(),
  433. na.rm = TRUE) +
  434. stat_summary(geom = "errorbar", fun.data = mean_se,
  435. position = position_dodge(0.9), width = 0, color = "black") +
  436. facet_wrap(~ as.factor(session), labeller = as_labeller(facet_labels_new)) +
  437. geom_dotplot(
  438. aes(group = interaction(run_session, session, sdt_type)),
  439. binaxis = "y", stackdir = "center", stackratio = 0.2, alpha = 0.7,
  440. inherit.aes = TRUE, binwidth = 0.2, position = position_dodge(),
  441. color = "black") +
  442. ylab("Frequency (%)") + xlab("Run") +
  443. coord_capped_cart(left = "both", bottom = "both",
  444. expand = TRUE, ylim = c(0, 15)) +
  445. scale_fill_viridis(name = "Error", discrete = TRUE) +
  446. scale_color_viridis(name = "Error", discrete = TRUE) +
  447. theme(strip.text.x = element_text(margin = margin(b = 2, t = 2))) +
  448. theme(legend.position = "top", legend.direction = "horizontal",
  449. legend.justification = "center", legend.margin = margin(0, 0, 0, 0),
  450. legend.box.margin = margin(t = 0, r = 0, b = -5, l = 0)) +
  451. theme(axis.text = element_text(color = "black")) +
  452. theme(axis.ticks.x = element_line(color = "white")) +
  453. theme(axis.line.x = element_line(color = "white")) +
  454. theme(axis.ticks.y = element_line(color = "black")) +
  455. theme(axis.line.y = element_line(colour = "black"),
  456. panel.grid.major = element_blank(),
  457. panel.grid.minor = element_blank(),
  458. panel.border = element_blank(),
  459. panel.background = element_blank())
  460. plot_odd_sdt
  461. ```
  462. #### Source Data File Fig. S1b
  463. ```{r}
  464. dt_odd_behav_sdt_sub %>%
  465. select(-num_trials) %>%
  466. write.csv(., file = file.path(path_sourcedata, "source_data_figure_s1b.csv"),
  467. row.names = FALSE)
  468. ```
  469. ### Sequence trials
  470. #### Effect of sequence speed
  471. We calculate the mean behavioral accuracy on sequence trials for each of the five sequence speeds (inter-stimulus intervals):
  472. ```{r, echo=TRUE}
  473. dt_seq_behav = dt_events %>%
  474. # filter behavioral events data for sequence trials only:
  475. filter(condition == "sequence") %>%
  476. setDT(.) %>%
  477. # create additional variables to describe each trial:
  478. .[, by = .(subject, trial), ":=" (
  479. trial_key_down = ifelse(any(key_down == 1, na.rm = TRUE), 1, 0),
  480. trial_accuracy = ifelse(any(accuracy == 1, na.rm = TRUE), 1, 0),
  481. trial_target_position = serial_position[which(target == 1)],
  482. trial_speed = unique(interval_time[which(!is.na(interval_time))])
  483. )] %>%
  484. # filter for choice trials only:
  485. filter(trial_type == "choice") %>%
  486. setDT(.) %>%
  487. # group speed conditions into fast and slow conditions:
  488. mutate(speed = ifelse(trial_speed %in% c(2.048, 0.512), "slow", "fast")) %>%
  489. # define variable factors of interest as numeric:
  490. transform(trial_speed = as.numeric(trial_speed)) %>%
  491. transform(trial_target_position = as.numeric(trial_target_position)) %>%
  492. setDT(.)
  493. ```
  494. ```{r}
  495. dt_seq_behav_speed = dt_seq_behav %>%
  496. # filter out excluded subjects:
  497. filter(!(subject %in% subjects_excluded)) %>%
  498. setDT(.) %>%
  499. # average accuracy for each participant:
  500. .[, by = .(subject, trial_speed), .(
  501. num_trials = .N,
  502. mean_accuracy = mean(accuracy)
  503. )] %>%
  504. transform(mean_accuracy = mean_accuracy * 100) %>%
  505. setDT(.) %>%
  506. verify(all(num_trials == 15)) %>%
  507. verify(.[, by = .(trial_speed), .(
  508. num_subjects = .N
  509. )]$num_subjects == 36) %>%
  510. setorder(subject, trial_speed) %>%
  511. mutate(trial_speed = as.numeric(trial_speed)) %>%
  512. setDT(.)
  513. ```
  514. We run a LME model to test the effect of sequence speed (inter-stimulus interval) on mean behavioral accuracy on sequence trials:
  515. ```{r, results="hold", echo=TRUE}
  516. lme_seq_behav = lmer(
  517. mean_accuracy ~ trial_speed + (1 + trial_speed | subject),
  518. data = dt_seq_behav_speed, na.action = na.omit, control = lcctrl)
  519. summary(lme_seq_behav)
  520. anova(lme_seq_behav)
  521. emmeans_results = emmeans(lme_seq_behav, list(pairwise ~ trial_speed))
  522. emmeans_pvalues = round_pvalues(summary(emmeans_results[[2]])$p.value)
  523. emmeans_results
  524. emmeans_pvalues
  525. ```
  526. We compare mean behavioral accuracy at each sequence speed level to the chancel level of 50%:
  527. ```{r}
  528. chance_level = 50
  529. dt_seq_behav_mean = dt_seq_behav_speed %>%
  530. # average across participants:
  531. .[, by = .(trial_speed), {
  532. ttest_results = t.test(
  533. mean_accuracy, mu = chance_level, alternative = "greater")
  534. list(
  535. mean_accuracy = round(mean(mean_accuracy), digits = 2),
  536. sd_accuracy = round(sd(mean_accuracy), digits = 2),
  537. tvalue = round(ttest_results$statistic, digits = 2),
  538. conf_lb = round(ttest_results$conf.int[1], digits = 2),
  539. conf_ub = round(ttest_results$conf.int[2], digits = 2),
  540. pvalue = ttest_results$p.value,
  541. cohens_d = round((mean(mean_accuracy) - chance_level)/sd(mean_accuracy), 2),
  542. df = ttest_results$parameter,
  543. num_subs = .N,
  544. sem_upper = mean(mean_accuracy) + (sd(mean_accuracy)/sqrt(.N)),
  545. sem_lower = mean(mean_accuracy) - (sd(mean_accuracy)/sqrt(.N))
  546. )}] %>%
  547. verify(num_subs == 36) %>%
  548. mutate(sem_range = sem_upper - sem_lower) %>%
  549. mutate(pvalue_adjust = p.adjust(pvalue, method = "fdr")) %>%
  550. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust))
  551. # print paged table:
  552. rmarkdown::paged_table(dt_seq_behav_mean)
  553. ```
  554. We calculate the reduction in mean behavioral accuracy comparing the fastest and slowest speed condition:
  555. ```{r}
  556. a = dt_seq_behav_mean$mean_accuracy[dt_seq_behav_mean$trial_speed == 2.048]
  557. b = dt_seq_behav_mean$mean_accuracy[dt_seq_behav_mean$trial_speed == 0.032]
  558. reduced_acc = round((1 - (b/a)) * 100, 2)
  559. sprintf("reduction in accuracy: %.2f", reduced_acc)
  560. ```
  561. #### Figure 1e
  562. ```{r, echo=TRUE}
  563. fig_seq_speed = ggplot(data = dt_seq_behav_speed, mapping = aes(
  564. y = as.numeric(mean_accuracy), x = as.factor(as.numeric(trial_speed)*1000),
  565. fill = as.factor(trial_speed), color = as.factor(trial_speed))) +
  566. geom_bar(stat = "summary", fun = "mean") +
  567. geom_dotplot(binaxis = "y", stackdir = "center", stackratio = 0.5,
  568. color = "black", alpha = 0.5,
  569. inherit.aes = TRUE, binwidth = 2) +
  570. geom_errorbar(stat = "summary", fun.data = "mean_se", width = 0.0, color = "black") +
  571. geom_hline(aes(yintercept = 50), linetype = "dashed", color = "black") +
  572. ylab("Accuracy (%)") + xlab("Sequence speed (ms)") +
  573. scale_fill_viridis(discrete = TRUE, guide = FALSE, option = "cividis") +
  574. scale_color_viridis(discrete = TRUE, guide = FALSE, option = "cividis") +
  575. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(0, 100)) +
  576. theme(plot.title = element_text(size = 12, face = "plain")) +
  577. theme(axis.ticks.x = element_blank(), axis.line.x = element_blank()) +
  578. ggtitle("Sequence") +
  579. theme(plot.title = element_text(hjust = 0.5)) +
  580. theme(axis.text = element_text(color = "black")) +
  581. theme(axis.ticks.x = element_line(color = "white")) +
  582. theme(axis.line.x = element_line(color = "white")) +
  583. theme(axis.ticks.y = element_line(color = "black")) +
  584. theme(axis.line.y = element_line(colour = "black"),
  585. panel.grid.major = element_blank(),
  586. panel.grid.minor = element_blank(),
  587. panel.border = element_blank(),
  588. panel.background = element_blank())
  589. fig_seq_speed
  590. ```
  591. #### Source Data File Fig. 1e
  592. ```{r}
  593. dt_seq_behav_speed %>%
  594. select(-num_trials) %>%
  595. write.csv(., file = file.path(path_sourcedata, "source_data_figure_1e.csv"),
  596. row.names = FALSE)
  597. ```
  598. #### Effect of target position
  599. We calculate the mean behavioral accuracy on sequence trials for each of possible serial position of the target stimulus:
  600. ```{r}
  601. dt_seq_behav_position = dt_seq_behav %>%
  602. # filter out excluded subjects:
  603. filter(!(subject %in% subjects_excluded)) %>% setDT(.) %>%
  604. # average accuracy for each participant:
  605. .[, by = .(subject, trial_target_position), .(
  606. num_trials = .N,
  607. mean_accuracy = mean(accuracy)
  608. )] %>%
  609. verify(.[, by = .(trial_target_position), .(
  610. num_subs = .N
  611. )]$num_subs == 36) %>%
  612. transform(mean_accuracy = mean_accuracy * 100) %>%
  613. setorder(subject, trial_target_position)
  614. ```
  615. ```{r}
  616. lme_seq_behav_position = lmer(
  617. mean_accuracy ~ trial_target_position + (1 + trial_target_position | subject),
  618. data = dt_seq_behav_position, na.action = na.omit, control = lcctrl)
  619. summary(lme_seq_behav_position)
  620. anova(lme_seq_behav_position)
  621. ```
  622. #### Figure S1d
  623. ```{r, echo=TRUE}
  624. fig_seq_position = ggplot(data = dt_seq_behav_position, mapping = aes(
  625. y = as.numeric(mean_accuracy), x = as.factor(trial_target_position),
  626. fill = as.factor(trial_target_position), color = as.factor(trial_target_position))) +
  627. geom_bar(stat = "summary", fun = "mean") +
  628. geom_dotplot(binaxis = "y", stackdir = "center", stackratio = 0.5,
  629. color = "black", alpha = 0.5,
  630. inherit.aes = TRUE, binwidth = 2) +
  631. geom_errorbar(stat = "summary", fun.data = "mean_se", width = 0.0, color = "black") +
  632. geom_hline(aes(yintercept = 50), linetype = "dashed", color = "black") +
  633. ylab("Accuracy (%)") + xlab("Target position") +
  634. scale_fill_manual(values = color_events, guide = FALSE) +
  635. scale_color_manual(values = color_events, guide = FALSE) +
  636. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(0, 100)) +
  637. theme(axis.ticks.x = element_blank(), axis.line.x = element_blank()) +
  638. theme(axis.text = element_text(color = "black")) +
  639. theme(axis.ticks.x = element_line(color = "white")) +
  640. theme(axis.line.x = element_line(color = "white")) +
  641. theme(axis.ticks.y = element_line(color = "black")) +
  642. theme(axis.line.y = element_line(colour = "black"),
  643. panel.grid.major = element_blank(),
  644. panel.grid.minor = element_blank(),
  645. panel.border = element_blank(),
  646. panel.background = element_blank())
  647. fig_seq_position
  648. ```
  649. #### Source Data File Fig. S1d
  650. ```{r}
  651. dt_seq_behav_position %>%
  652. select(-num_trials) %>%
  653. write.csv(., file = file.path(path_sourcedata, "source_data_figure_s1d.csv"),
  654. row.names = FALSE)
  655. ```
  656. ### Repetition trials
  657. #### Mean accuracy
  658. We calculate mean behavioral accuracy in repetition trials for each participant:
  659. ```{r}
  660. dt_rep_behav = dt_events %>%
  661. # filter for repetition trials only:
  662. filter(condition == "repetition") %>% setDT(.) %>%
  663. # create additional variables to describe each trial:
  664. .[, by = .(subject, trial), ":=" (
  665. trial_key_down = ifelse(any(key_down == 1, na.rm = TRUE), 1, 0),
  666. trial_accuracy = ifelse(any(accuracy == 1, na.rm = TRUE), 1, 0),
  667. trial_target_position = serial_position[which(target == 1)],
  668. trial_speed = unique(interval_time[which(!is.na(interval_time))])
  669. )] %>%
  670. # select only choice trials that contain the accuracy data:
  671. filter(trial_type == "choice") %>% setDT(.) %>%
  672. verify(all(trial_accuracy == accuracy)) %>%
  673. # average across trials separately for each participant:
  674. .[, by = .(subject, trial_target_position), .(
  675. num_trials = .N,
  676. mean_accuracy = mean(accuracy)
  677. )] %>%
  678. verify(all(num_trials == 5)) %>%
  679. # transform mean accuracy into percent (%)
  680. transform(mean_accuracy = mean_accuracy * 100) %>%
  681. # check if accuracy values range between 0 and 100
  682. verify(between(x = mean_accuracy, lower = 0, upper = 100)) %>%
  683. mutate(interference = ifelse(
  684. trial_target_position == 2, "fwd", trial_target_position)) %>%
  685. transform(interference = ifelse(
  686. trial_target_position == 9, "bwd", interference))
  687. ```
  688. We run separate one-sided one-sample t-tests to access if mean behavioral performance for every repetition condition differs from a 50% chance level:
  689. ```{r}
  690. chance_level = 50
  691. dt_rep_behav_chance = dt_rep_behav %>%
  692. # filter out excluded subjects:
  693. filter(!(subject %in% subjects_excluded)) %>%
  694. setDT(.) %>%
  695. # average across participants:
  696. .[, by = .(trial_target_position), {
  697. ttest_results = t.test(
  698. mean_accuracy, mu = chance_level, alternative = "greater")
  699. list(
  700. mean_accuracy = round(mean(mean_accuracy), digits = 2),
  701. sd_accuracy = round(sd(mean_accuracy), digits = 2),
  702. tvalue = round(ttest_results$statistic, digits = 2),
  703. pvalue = ttest_results$p.value,
  704. conf_lb = round(ttest_results$conf.int[1], digits = 2),
  705. conf_ub = round(ttest_results$conf.int[2], digits = 2),
  706. cohens_d = round((mean(mean_accuracy) - chance_level)/sd(mean_accuracy), 2),
  707. df = ttest_results$parameter,
  708. num_subs = .N,
  709. sem_upper = mean(mean_accuracy) + (sd(mean_accuracy)/sqrt(.N)),
  710. sem_lower = mean(mean_accuracy) - (sd(mean_accuracy)/sqrt(.N))
  711. )}] %>% verify(num_subs == 36) %>%
  712. mutate(sem_range = sem_upper - sem_lower) %>%
  713. setDT(.) %>%
  714. filter(trial_target_position %in% seq(2,9)) %>%
  715. # create additional variable to label forward and backward interference:
  716. mutate(interference = ifelse(
  717. trial_target_position == 2, "fwd", trial_target_position)) %>%
  718. transform(interference = ifelse(
  719. trial_target_position == 9, "bwd", interference)) %>%
  720. mutate(pvalue_adjust = p.adjust(pvalue, method = "fdr")) %>%
  721. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust)) %>%
  722. mutate(significance = ifelse(pvalue_adjust < 0.05, "*", "")) %>%
  723. mutate(cohens_d = paste0("d = ", cohens_d, significance)) %>%
  724. mutate(label = paste0(
  725. trial_target_position - 1, "/", 10 - trial_target_position)) %>%
  726. setDT(.) %>%
  727. setorder(trial_target_position)
  728. # print table:
  729. rmarkdown::paged_table(dt_rep_behav_chance)
  730. ```
  731. #### Figure 1f
  732. We plot the results of the forward and backward interference conditions:
  733. ```{r, echo=TRUE}
  734. plot_data = dt_rep_behav_chance %>% filter(trial_target_position %in% c(2,9))
  735. fig_behav_rep = ggplot(data = plot_data, mapping = aes(
  736. y = as.numeric(mean_accuracy), x = fct_rev(as.factor(interference)),
  737. fill = as.factor(interference))) +
  738. geom_bar(stat = "summary", fun = "mean") +
  739. geom_dotplot(data = dt_rep_behav %>%
  740. filter(!(subject %in% subjects_excluded)) %>%
  741. filter(trial_target_position %in% c(2,9)) %>% setDT(.) %>%
  742. .[, by = .(subject, interference), .(
  743. mean_accuracy = mean(mean_accuracy)
  744. )],
  745. binaxis = "y", stackdir = "center", stackratio = 0.5,
  746. color = "black", alpha = 0.5, inherit.aes = TRUE, binwidth = 2) +
  747. geom_errorbar(aes(ymin = sem_lower, ymax = sem_upper), width = 0.0, color = "black") +
  748. ylab("Accuracy (%)") + xlab("Interfererence") +
  749. ggtitle("Repetition") +
  750. theme(plot.title = element_text(hjust = 0.5)) +
  751. scale_fill_manual(values = c("red", "dodgerblue"), guide = FALSE) +
  752. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(0,100)) +
  753. theme(axis.ticks.x = element_blank(), axis.line.x = element_blank()) +
  754. theme(plot.title = element_text(size = 12, face = "plain")) +
  755. #scale_y_continuous(labels = label_fill(seq(0, 100, 12.5), mod = 2), breaks = seq(0, 100, 12.5)) +
  756. geom_hline(aes(yintercept = 50), linetype = "dashed", color = "black") +
  757. #geom_text(aes(y = as.numeric(mean_accuracy) + 10, label = pvalue_adjust_round), size = 3) +
  758. theme(axis.text = element_text(color = "black")) +
  759. theme(axis.ticks.x = element_line(color = "white")) +
  760. theme(axis.line.x = element_line(color = "white")) +
  761. theme(axis.ticks.y = element_line(color = "black")) +
  762. theme(axis.line.y = element_line(colour = "black"),
  763. panel.grid.major = element_blank(),
  764. panel.grid.minor = element_blank(),
  765. panel.border = element_blank(),
  766. panel.background = element_blank())
  767. fig_behav_rep
  768. ```
  769. #### Source Data File Fig. 1f
  770. ```{r}
  771. dt_rep_behav %>%
  772. select(-num_trials) %>%
  773. write.csv(., file = file.path(path_sourcedata, "source_data_figure_1f.csv"),
  774. row.names = FALSE)
  775. ```
  776. #### Figure S1e
  777. We plot the results of all intermediate repetition conditions:
  778. ```{r, echo=TRUE}
  779. plot_data = dt_rep_behav_chance %>% filter(trial_target_position %in% seq(2,9))
  780. plot_behav_rep_all = ggplot(data = plot_data, mapping = aes(
  781. y = as.numeric(mean_accuracy), x = as.numeric(trial_target_position),
  782. fill = as.numeric(trial_target_position))) +
  783. geom_bar(stat = "identity") +
  784. geom_dotplot(data = dt_rep_behav %>%
  785. filter(!(subject %in% subjects_excluded)) %>%
  786. filter(trial_target_position %in% seq(2,9)) %>% setDT(.) %>%
  787. .[, by = .(subject, trial_target_position), .(
  788. mean_accuracy = mean(mean_accuracy)
  789. )],
  790. aes(x = as.numeric(trial_target_position),
  791. fill = as.numeric(trial_target_position),
  792. group = as.factor(trial_target_position)),
  793. binaxis = "y", stackdir = "center", stackratio = 0.5,
  794. inherit.aes = TRUE, binwidth = 2, color = "black", alpha = 0.5) +
  795. geom_errorbar(aes(ymin = sem_lower, ymax = sem_upper), width = 0.0, color = "black") +
  796. geom_text(aes(y = as.numeric(mean_accuracy) + 7, label = cohens_d), size = 2.5) +
  797. ylab("Accuracy (%)") + xlab("First / second item repetitions") +
  798. scale_fill_gradient(low = "dodgerblue", high = "red", guide = FALSE) +
  799. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(0,100)) +
  800. scale_x_continuous(labels = plot_data$label, breaks = seq(2, 9, 1)) +
  801. geom_hline(aes(yintercept = 50), linetype = "dashed", color = "black") +
  802. theme(axis.ticks.x = element_blank(), axis.line.x = element_blank()) +
  803. theme(axis.text = element_text(color = "black")) +
  804. theme(axis.ticks.x = element_line(color = "white")) +
  805. theme(axis.line.x = element_line(color = "white")) +
  806. theme(axis.ticks.y = element_line(color = "black")) +
  807. theme(axis.line.y = element_line(colour = "black"),
  808. panel.grid.major = element_blank(),
  809. panel.grid.minor = element_blank(),
  810. panel.border = element_blank(),
  811. panel.background = element_blank())
  812. plot_behav_rep_all
  813. ```
  814. #### Source Data File Fig. S1e
  815. ```{r}
  816. dt_rep_behav %>%
  817. select(-num_trials) %>%
  818. write.csv(., file = file.path(path_sourcedata, "source_data_figure_s1e.csv"),
  819. row.names = FALSE)
  820. ```
  821. ```{r, echo=TRUE, eval=FALSE}
  822. ggsave(filename = "highspeed_plot_behavior_repetition_supplement.pdf",
  823. plot = last_plot(), device = cairo_pdf, path = path_figures,
  824. scale = 1, dpi = "retina", width = 5, height = 3, units = "in")
  825. ```
  826. We run a LME model to test the effect of repetition condition on mean behavioral accuracy in repetition trials:
  827. ```{r}
  828. lme_rep_behav_condition = lmer(
  829. mean_accuracy ~ trial_target_position + (1 + trial_target_position|subject),
  830. data = dt_rep_behav, na.action = na.omit, control = lcctrl)
  831. summary(lme_rep_behav_condition)
  832. anova(lme_rep_behav_condition)
  833. ```
  834. ### Figure Main
  835. We plot the figure for the main text:
  836. ```{r, echo=FALSE}
  837. plot_grid(fig_behav_odd, fig_seq_speed, fig_behav_rep, ncol = 3,
  838. rel_widths = c(2, 4.5, 2.5), labels = c("d", "e", "f"))
  839. ```
  840. ```{r, echo=FALSE, eval=FALSE}
  841. ggsave(filename = "highspeed_plot_behavior_horizontal.pdf",
  842. plot = last_plot(), device = cairo_pdf, path = path_figures,
  843. scale = 1, dpi = "retina", width = 7, height = 3, units = "in")
  844. ```
  845. ```{r, echo=FALSE}
  846. ggsave(filename = "wittkuhn_schuck_figure_1ef.pdf",
  847. plot = last_plot(), device = cairo_pdf, path = path_figures,
  848. scale = 1, dpi = "retina", width = 7, height = 3, units = "in")
  849. ```
  850. ### Figure SI
  851. We plot the figure for the supplementary information:
  852. ```{r, echo=FALSE}
  853. plot_grid(
  854. plot_grid(
  855. fig_behav_all_outlier, plot_odd_sdt, plot_odd_run,
  856. rel_widths = c(3.5, 6, 5), ncol = 3, nrow = 1, labels = c("a", "b", "c")),
  857. plot_grid(
  858. fig_seq_position, plot_behav_rep_all, labels = c("d", "e"),
  859. ncol = 2, nrow = 1, rel_widths = c(4, 6)),
  860. nrow = 2)
  861. ```
  862. ```{r, echo=FALSE, eval=FALSE}
  863. ggsave(filename = "highspeed_plot_behavior_supplement.pdf",
  864. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  865. dpi = "retina", width = 8, height = 5)
  866. ```
  867. ```{r}
  868. ggsave(filename = "wittkuhn_schuck_figure_s1.pdf",
  869. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  870. dpi = "retina", width = 8, height = 5)
  871. ```
  872. ## Participants
  873. We analyze characteristics of the participants:
  874. ```{r, results="hold"}
  875. # read data table with participant information:
  876. dt_participants <- do.call(rbind, lapply(Sys.glob(path_participants), fread))
  877. # remove selected participants from the data table:
  878. dt_participants = dt_participants %>%
  879. filter(!(participant_id %in% subjects_excluded)) %>%
  880. setDT(.)
  881. base::table(dt_participants$sex)
  882. round(sd(dt_participants$age), digits = 2)
  883. base::summary(
  884. dt_participants[, c("age", "digit_span", "session_interval"), with = FALSE])
  885. round(sd(dt_participants$session_interval), digits = 2)
  886. ```