highspeed-analysis-sequence.Rmd 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744
  1. ## Detecting sequentiality
  2. ### Initialization
  3. We load the data and relevant functions:
  4. ```{r, warning=FALSE, message=FALSE, echo=TRUE}
  5. # find the path to the root of this project:
  6. if (!requireNamespace("here")) install.packages("here")
  7. if ( basename(here::here()) == "highspeed" ) {
  8. path_root = here::here("highspeed-analysis")
  9. } else {
  10. path_root = here::here()
  11. }
  12. # source all relevant functions from the setup R script:
  13. source(file.path(path_root, "code", "highspeed-analysis-setup.R"))
  14. load(file.path(path_root, "data", "tmp", "dt_periods.Rdata"))
  15. load(file.path(path_root, "data", "tmp", "dt_odd_seq_sim_diff.Rdata"))
  16. load(file.path(path_root, "data", "tmp", "dt_odd_seq_sim.Rdata"))
  17. sub_exclude <- c("sub-24", "sub-31", "sub-37", "sub-40")
  18. ```
  19. ### Data preparation
  20. We create a function to determine early and late zones of forward and backward periods:
  21. ```{r}
  22. get_zones = function(trs_in){
  23. if (length(trs_in) == 3) {
  24. early = trs_in[c(2)]
  25. late = trs_in[c(3)]
  26. } else if (length(trs_in) == 4) {
  27. early = trs_in[c(2)]
  28. late = trs_in[c(4)]
  29. } else if (length(trs_in) == 5) {
  30. early = trs_in[c(2)]
  31. late = trs_in[c(4)]
  32. } else if (length(trs_in) == 6) {
  33. early = trs_in[c(2, 3)]
  34. late = trs_in[c(5, 6)]
  35. } else if (length(trs_in) == 7) {
  36. early = trs_in[c(2, 3)]
  37. late = trs_in[c(5, 6)]
  38. }
  39. return(list(early = early, late = late))
  40. }
  41. ```
  42. We prepare event and decoding data of sequence trials:
  43. ```{r}
  44. # create a subset of the events data table only including sequence task events:
  45. dt_events_seq = dt_events %>%
  46. filter(condition == "sequence" & trial_type == "stimulus")
  47. # create a subset of the decoding data only including the sequence task data:
  48. dt_pred_seq = dt_pred %>%
  49. filter(condition == "sequence" & class != "other" & mask == "cv" & stim != "cue") %>%
  50. setDT(.) %>%
  51. # add serial position, change trial and target cue to the sequence data table:
  52. .[, c("position", "change", "trial_cue", "accuracy", "trial_cue_position") := get_pos(
  53. .SD, dt_events_seq), by = .(id, trial, class), .SDcols = c("id", "trial", "class")] %>%
  54. # add variable to later pool trial_cue_position 1 to 3:
  55. mutate(cue_pos_label = ifelse(trial_cue_position <= 3, "1-3", trial_cue_position)) %>%
  56. setDT(.)
  57. ```
  58. We define the forward and backward periods depending on the response functions:
  59. ```{r}
  60. # define forward and backward period depending on response functions:
  61. for (cspeed in unique(dt_pred_seq$tITI)) {
  62. for (period in c("forward", "backward")) {
  63. # get trs in the relevant forward or backward period based on response functions:
  64. trs_period = dt_periods[[which(dt_periods$speed == cspeed), period]]
  65. # set the period variable in the sequence data table accordingly:
  66. dt_pred_seq$period[
  67. dt_pred_seq$tITI %in% cspeed & dt_pred_seq$seq_tr %in% trs_period] = period
  68. for (zone in c("early", "late")) {
  69. trs_zone = get_zones(trs_period)[[zone]]
  70. dt_pred_seq$zone[
  71. dt_pred_seq$tITI %in% cspeed & dt_pred_seq$seq_tr %in% trs_zone] = zone
  72. }
  73. }
  74. }
  75. # assign the excluded label to all trs that are not in the forward or backward period:
  76. dt_pred_seq$period[is.na(dt_pred_seq$period)] = "excluded"
  77. ```
  78. We exclude all participants with below-chance performance from the analyses:
  79. ```{r}
  80. # exclude participants with below-chance performance:
  81. dt_pred_seq = dt_pred_seq %>%
  82. filter(!(id %in% sub_exclude)) %>%
  83. verify(length(unique(id)) == 36) %>%
  84. setDT(.)
  85. ```
  86. We calculate the number of correct and incorrect sequence trials:
  87. ```{r}
  88. dt_num_correct <- dt_pred_seq %>%
  89. # calculate the number of trials for each accuracy level for each participant:
  90. .[, by = .(classification, id, accuracy), .(
  91. num_trials = length(unique(trial))
  92. )] %>%
  93. # select only the one-versus-rest decoding approach:
  94. filter(classification == "ovr") %>%
  95. setDT(.) %>%
  96. # verify that the sum of all trials equals 75 for all participants:
  97. verify(.[, by = .(classification, id), .(
  98. sum_trials = sum(num_trials))]$sum_trials == 75) %>%
  99. # complete missing values for number of trials for each accuracy level:
  100. complete(classification, id, accuracy, fill = list(num_trials = 0)) %>%
  101. setDT(.) %>%
  102. # verify that there are two accuracy levels per participant:
  103. verify(.[, by = .(classification, id), .(
  104. num_acc_levels = .N)]$num_acc_levels == 2) %>%
  105. # calculate the mean number of (in)accurate trials per participant:
  106. .[, by = .(classification, accuracy), .(
  107. num_subs = .N,
  108. mean_num_trials = mean(num_trials),
  109. percent_trials = mean(num_trials)/75
  110. )]
  111. # print formatted table:
  112. rmarkdown::paged_table(dt_num_correct)
  113. ```
  114. ### Probability time courses
  115. We calculate the decoding probability time-courses:
  116. ```{r}
  117. # select the variable of interest:
  118. variable = "probability_norm"
  119. dt_pred_seq_prob = dt_pred_seq %>%
  120. # average across trials separately for each position, TR, and participant
  121. .[, by = .(id, classification, tITI, period, seq_tr, position), .(
  122. num_trials = .N,
  123. mean_prob = mean(get(variable)) * 100
  124. )] %>%
  125. # check if the averaged data consists of 15 sequence trial per participant:
  126. verify(all(num_trials == 15)) %>%
  127. # average across participants and calculate standard error of the mean:
  128. .[, by = .(classification, tITI, period, seq_tr, position), .(
  129. num_subs = .N,
  130. mean_prob = mean(mean_prob),
  131. sem_upper = mean(mean_prob) + (sd(mean_prob)/sqrt(.N)),
  132. sem_lower = mean(mean_prob) - (sd(mean_prob)/sqrt(.N))
  133. )] %>%
  134. # check if averaged data is consistent with expected number of participants:
  135. verify(all(num_subs == 36)) %>%
  136. # create a new variable that expresses TRs as time from stimulus onset:
  137. mutate(time = (seq_tr - 1) * 1.25) %>%
  138. setDT(.)
  139. ```
  140. We plot the decoding probability time-courses:
  141. ```{r}
  142. plot_raw_probas = function(dt1){
  143. dt_reduced = dt1 %>%
  144. setDT(.) %>%
  145. .[, by = .(classification, tITI, period), .(
  146. xmin = min(seq_tr) - 0.5,
  147. xmax = max(seq_tr) + 0.5
  148. )] %>%
  149. filter(period != "excluded") %>%
  150. mutate(fill = ifelse(period == "forward", "dodgerblue", "red"))
  151. plot = ggplot(data = dt1, mapping = aes(
  152. x = as.factor(seq_tr), y = as.numeric(mean_prob),
  153. group = as.factor(position)), environment = environment()) +
  154. geom_rect(data = dt_reduced, aes(
  155. xmin = xmin, xmax = xmax, ymin = 0, ymax = 40),
  156. alpha = 0.05, inherit.aes = FALSE, show.legend = FALSE, fill = dt_reduced$fill) +
  157. facet_wrap(facets = ~ as.factor(tITI), labeller = get_labeller(array = dt1$tITI), nrow = 1) +
  158. geom_ribbon(aes(ymin = sem_lower, ymax = sem_upper,
  159. fill = as.factor(position)), alpha = 0.5) +
  160. geom_line(mapping = aes(color = as.factor(position))) +
  161. theme(legend.position = "top", legend.direction = "horizontal",
  162. legend.justification = "center", legend.margin = margin(0, 0, 0, 0),
  163. legend.box.margin = margin(t = 0, r = 0, b = -5, l = 0)) +
  164. xlab("Time from sequence onset (TRs; 1 TR = 1.25 s)") +
  165. ylab("Probability (%)") +
  166. scale_color_manual(values = color_events, name = "Serial event") +
  167. scale_fill_manual(values = color_events, name = "Serial event") +
  168. scale_x_discrete(labels = label_fill(seq(1, 13, 1), mod = 4), breaks = seq(1, 13, 1)) +
  169. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(0, 25)) +
  170. theme(panel.border = element_blank(), axis.line = element_line()) +
  171. theme(axis.line = element_line(colour = "black"),
  172. panel.grid.major = element_blank(),
  173. panel.grid.minor = element_blank(),
  174. panel.border = element_blank(),
  175. panel.background = element_blank()) +
  176. theme(strip.text.x = element_text(margin = margin(b = 2, t = 2))) +
  177. guides(color = guide_legend(nrow = 1))
  178. return(plot)
  179. }
  180. fig_seq_probas = plot_raw_probas(dt1 = subset(dt_pred_seq_prob, classification == "ovr"))
  181. fig_seq_probas
  182. ```
  183. We plot the decoding probabilities as a heat-map:
  184. ```{r, echo=FALSE}
  185. plot_data = subset(dt_pred_seq_prob, classification == "ovr" & !(tITI %in% c(2.048)))
  186. ggplot(plot_data, aes(x = as.factor(position), y = as.factor(seq_tr), fill = as.numeric(mean_prob))) +
  187. facet_wrap(facets = ~ as.factor(tITI),
  188. labeller = get_labeller(array = plot_data$tITI), nrow = 1) +
  189. geom_tile() +
  190. xlab("Serial event position") + ylab("Time from sequence onset (TRs)") +
  191. scale_fill_viridis(option = "inferno", name = "Probability (%)") +
  192. scale_y_discrete(labels = label_fill(seq(1, 13, 1), mod = 4), breaks = seq(1, 13, 1)) +
  193. lemon::coord_capped_cart(left = "both", bottom = "both", expand = TRUE) +
  194. theme(panel.border = element_blank(), axis.line = element_line()) +
  195. theme(strip.text.x = element_text(margin = margin(b = 2, t = 2))) +
  196. theme(legend.position = "top", legend.direction = "horizontal",
  197. legend.justification = "center", legend.margin = margin(0, 0, 0, 0),
  198. legend.box.margin = margin(t = 0, r = 0, b = -5, l = 0)) +
  199. guides(color = guide_legend(nrow = 1)) +
  200. theme(panel.border = element_blank(), axis.line = element_line())
  201. ```
  202. ### Influence of target cue position
  203. We analyze the probabilities by target cue position:
  204. ```{r}
  205. # select the variable of interest:
  206. variable = "probability_norm"
  207. dt_pred_seq_prob_cue = dt_pred_seq %>%
  208. # average across trials separately for each position, TR, and participant
  209. .[, by = .(id, classification, tITI, period, seq_tr, position, cue_pos_label), .(
  210. num_trials = .N,
  211. mean_prob = mean(get(variable)) * 100
  212. )] %>%
  213. # average across participants and calculate standard error of the mean:
  214. .[, by = .(classification, tITI, period, seq_tr, position,cue_pos_label), .(
  215. num_subs = .N,
  216. mean_num_trials = mean(num_trials),
  217. sd_num_trials = sd(num_trials),
  218. mean_prob = mean(mean_prob),
  219. sem_upper = mean(mean_prob) + (sd(mean_prob)/sqrt(.N)),
  220. sem_lower = mean(mean_prob) - (sd(mean_prob)/sqrt(.N))
  221. )] %>%
  222. # check if averaged data is consistent with expected number of participants:
  223. verify(all(num_subs == 36)) %>%
  224. # check that the SD of the number of trials per cue position is 0
  225. # which means that each participant has the same number of trials per cue position:
  226. verify(all(sd_num_trials == 0)) %>%
  227. verify(all(mean_num_trials == 5)) %>%
  228. # create a new variable that expresses TRs as time from stimulus onset:
  229. mutate(time = (seq_tr - 1) * 1.25) %>%
  230. transform(tITI = paste0(as.numeric(tITI) * 1000, " ms")) %>%
  231. transform(tITI = factor(tITI, levels = c(
  232. "32 ms", "64 ms", "128 ms", "512 ms", "2048 ms"))) %>%
  233. setDT(.)
  234. ```
  235. We plot the probabilities by target cue position:
  236. ```{r}
  237. plot_raw_probas_cue = function(dt1){
  238. plot = ggplot(data = dt1, mapping = aes(
  239. x = as.factor(seq_tr), y = as.numeric(mean_prob),
  240. group = as.factor(position))) +
  241. facet_grid(rows = vars(cue_pos_label), cols = vars(tITI)) +
  242. geom_ribbon(aes(ymin = sem_lower, ymax = sem_upper,
  243. fill = as.factor(position)), alpha = 0.5) +
  244. geom_line(mapping = aes(color = as.factor(position))) +
  245. theme(legend.position = "top", legend.direction = "horizontal",
  246. legend.justification = "center", legend.margin = margin(0, 0, 0, 0),
  247. legend.box.margin = margin(t = 0, r = 0, b = -5, l = 0)) +
  248. xlab("Time from sequence onset (TRs)") + ylab("Probability (%)") +
  249. scale_color_manual(values = color_events, name = "Serial event") +
  250. scale_fill_manual(values = color_events, name = "Serial event") +
  251. scale_x_discrete(labels = label_fill(seq(1, 13, 1), mod = 4), breaks = seq(1, 13, 1)) +
  252. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(0, 25)) +
  253. theme(panel.border = element_blank(), axis.line = element_line()) +
  254. theme(axis.line = element_line(colour = "black"),
  255. panel.grid.major = element_blank(),
  256. panel.grid.minor = element_blank(),
  257. panel.border = element_blank(),
  258. panel.background = element_blank())
  259. theme(strip.text.x = element_text(margin = margin(b = 2, t = 2))) +
  260. guides(color = guide_legend(nrow = 1))
  261. return(plot)
  262. }
  263. fig_seq_probas_cue = plot_raw_probas_cue(dt1 = subset(dt_pred_seq_prob_cue, classification == "ovr"))
  264. fig_seq_probas_cue
  265. ```
  266. ### Regression slopes
  267. ```{r, echo=FALSE, eval=FALSE}
  268. # select positions within every TR that should be selected:
  269. pos_sel = seq(1, 5)
  270. set.seed(4)
  271. probability = runif(5)
  272. # earlier events have higher probability:
  273. probability = c(0.6, 0.9, 0.1, 0.5, 0.2)
  274. position = seq(1, 5, 1)
  275. position = c(1, 3, 2, 4, 5)
  276. ordered_positions = probability[order(probability, decreasing = TRUE)]
  277. diff(ordered_positions)
  278. # order the probabilities in decreasing order (first = highest):
  279. prob_order_idx = order(probability, decreasing = TRUE)
  280. # order the positions by probability:
  281. pos_order = position[prob_order_idx]
  282. # order the probabilities:
  283. prob_order = probability[prob_order_idx]
  284. # select positions
  285. pos_order_sel = pos_order[pos_sel]
  286. prob_order_sel = prob_order[pos_sel]
  287. ```
  288. We compare the mean indices of association (regression slope, correlation,
  289. mean serial position) for every TR:
  290. ```{r}
  291. # select positions within every TR that should be selected:
  292. pos_sel = seq(1, 5)
  293. # define relevant variables:
  294. variable = "probability_norm"
  295. cor_method = "kendall"
  296. # calculate indices of association at every TR:
  297. dt_pred_seq_cor = dt_pred_seq %>%
  298. # here, we can filter for specific sequence events:
  299. filter(position %in% seq(1, 5, by = 1)) %>%
  300. setDT(.) %>%
  301. # order positions by decreasing probability and calculate step size
  302. # calculate correlation and slope between position and probability
  303. # verify that there are five probabilities (one for each class) per volume
  304. # verify that all correlations range between -1 and 1
  305. .[, by = .(id, classification, tITI, period, trial_tITI, seq_tr), {
  306. # order the probabilities in decreasing order (first = highest):
  307. prob_order_idx = order(get(variable), decreasing = TRUE)
  308. # order the positions by probability:
  309. pos_order = position[prob_order_idx]
  310. # order the probabilities:
  311. prob_order = get(variable)[prob_order_idx]
  312. # select positions
  313. pos_order_sel = pos_order[pos_sel]
  314. prob_order_sel = prob_order[pos_sel]
  315. list(
  316. # calculate the number of events:
  317. num_events = length(pos_order_sel[!is.na(pos_order_sel)]),
  318. # calculate the mean step size between probability-ordered events:
  319. mean_step = mean(diff(pos_order_sel)),
  320. # calculate the mean correlation between positions and their probabilities:
  321. cor = cor.test(pos_order_sel, prob_order_sel, method = cor_method)$estimate,
  322. # calculate the slope of a linear regression between position and probabilities:
  323. slope = coef(lm(prob_order_sel ~ pos_order_sel))[2]
  324. # verify that the number of events matches selection and correlations -1 < r < 1
  325. )}] %>% verify(all(num_events == length(pos_sel))) %>% #verify(between(cor, -1, 1)) %>%
  326. # average across trials for each participant (flip values by multiplying with -1):
  327. # verify that the number of trials per participant is correct:
  328. .[, by = .(id, classification, tITI, period, seq_tr), .(
  329. num_trials = .N,
  330. mean_cor = mean(cor) * (-1),
  331. mean_step = mean(mean_step),
  332. mean_slope = mean(slope) * (-1)
  333. )] %>%
  334. verify(all(num_trials == 15)) %>%
  335. # shorten the period name:
  336. mutate(period_short = ifelse(period == "forward", "fwd", period)) %>%
  337. transform(period_short = ifelse(period == "backward", "bwd", period_short)) %>%
  338. mutate(color = ifelse(period_short == "fwd", "dodgerblue", "red")) %>% setDT(.)
  339. ```
  340. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  341. cfg = list(variable = "mean_cor", threshold = 2.021, baseline = 0,
  342. grouping = c("classification", "tITI"), n_perms = 10000, n_trs = 13)
  343. dt_pred_seq_cor_cluster = cluster_permutation(dt_pred_seq_cor, cfg)
  344. ```
  345. We compare the mean indices of association (regression slope, correlation,
  346. mean serial position) against zero (the expectation of no association)
  347. for every TR:
  348. ```{r}
  349. seq_test_time <- function(data, variable){
  350. data_out = data %>%
  351. # average across participants for every speed at every TR:
  352. # check if the number of participants matches:
  353. .[, by = .(classification, tITI, period, seq_tr), {
  354. # perform a two-sided one-sample t-test against zero (baseline):
  355. ttest_results = t.test(get(variable), alternative = "two.sided", mu = 0);
  356. list(
  357. num_subs = .N,
  358. mean_variable = mean(get(variable)),
  359. pvalue = ttest_results$p.value,
  360. tvalue = ttest_results$statistic,
  361. df = ttest_results$parameter,
  362. cohens_d = round(abs(mean(mean(get(variable)) - 0)/sd(get(variable))), 2),
  363. sem_upper = mean(get(variable)) + (sd(get(variable))/sqrt(.N)),
  364. sem_lower = mean(get(variable)) - (sd(get(variable))/sqrt(.N))
  365. )}] %>% verify(all(num_subs == 36)) %>% verify(all((num_subs - df) == 1)) %>%
  366. # adjust p-values for multiple comparisons (filter for forward and backward period):
  367. # check if the number of comparisons matches expectations:
  368. .[period %in% c("forward", "backward"), by = .(classification), ":=" (
  369. num_comp = .N,
  370. pvalue_adjust = p.adjust(pvalue, method = "fdr", n = .N)
  371. )] %>% verify(all(num_comp == 39, na.rm = TRUE)) %>%
  372. # round the original p-values according to the apa standard:
  373. mutate(pvalue_round = round_pvalues(pvalue)) %>%
  374. # round the adjusted p-value:
  375. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust)) %>%
  376. # sort data table:
  377. setorder(., classification, period, tITI, seq_tr) %>%
  378. # create new variable indicating significance below 0.05
  379. mutate(significance = ifelse(pvalue_adjust < 0.05, "*", ""))
  380. return(data_out)
  381. }
  382. ```
  383. ```{r}
  384. # filter for significant p-values to make reporting easier:
  385. rmarkdown::paged_table(seq_test_time(data = dt_pred_seq_cor, variable = "mean_cor") %>%
  386. filter(pvalue_adjust < 0.05, classification == "ovr"))
  387. rmarkdown::paged_table(seq_test_time(data = dt_pred_seq_cor, variable = "mean_step") %>%
  388. filter(pvalue_adjust < 0.05, classification == "ovr"))
  389. rmarkdown::paged_table(seq_test_time(data = dt_pred_seq_cor, variable = "mean_slope") %>%
  390. filter(pvalue_adjust < 0.05, classification == "ovr"))
  391. ```
  392. ```{r}
  393. plot_seq_cor_time = function(dt, variable){
  394. # select the variable of interest, determine y-axis label and adjust axis:
  395. if (variable == "mean_slope") {
  396. ylabel = "Regression slope"
  397. adjust_axis = 0.1
  398. } else if (variable == "mean_cor") {
  399. ylabel = expression("Correlation ("*tau*")")
  400. adjust_axis = 1
  401. } else if (variable == "mean_step") {
  402. ylabel = "Mean step size"
  403. adjust_axis = 1
  404. }
  405. plot = ggplot(data = dt, mapping = aes(
  406. x = seq_tr, y = mean_variable, group = as.factor(as.numeric(tITI) * 1000),
  407. fill = as.factor(as.numeric(tITI) * 1000))) +
  408. geom_hline(aes(yintercept = 0), linetype = "solid", color = "gray") +
  409. geom_ribbon(aes(ymin = sem_lower, ymax = sem_upper), alpha = 0.5, color = NA) +
  410. geom_line(mapping = aes(color = as.factor(as.numeric(tITI) * 1000))) +
  411. xlab("Time from sequence onset (TRs)") + ylab(ylabel) +
  412. scale_colour_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis") +
  413. scale_fill_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis") +
  414. scale_x_continuous(labels = label_fill(seq(1, 13, 1), mod = 4), breaks = seq(1, 13, 1)) +
  415. guides(color = guide_legend(nrow = 1)) +
  416. annotate("text", x = 1, y = -0.4 * adjust_axis, label = "1 TR = 1.25 s",
  417. hjust = 0, size = rel(2)) +
  418. coord_capped_cart(left = "both", bottom = "both", expand = TRUE,
  419. ylim = c(-0.4 * adjust_axis, 0.4 * adjust_axis)) +
  420. theme(panel.border = element_blank(), axis.line = element_line()) +
  421. theme(axis.line = element_line(colour = "black"),
  422. panel.grid.major = element_blank(),
  423. panel.grid.minor = element_blank(),
  424. panel.border = element_blank(),
  425. panel.background = element_blank()) +
  426. theme(legend.position = "top", legend.direction = "horizontal",
  427. legend.justification = "center", legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
  428. legend.box.margin = margin(t = 0, r = 0, b = 0, l = 0)) +
  429. geom_segment(aes(x = 0.05, xend = 0.05, y = 0.01 * adjust_axis, yend = 0.4 * adjust_axis),
  430. arrow = arrow(length = unit(5, "pt")), color = "darkgray") +
  431. geom_segment(aes(x = 0.05, xend = 0.05, y = -0.01 * adjust_axis, yend = -0.4 * adjust_axis),
  432. arrow = arrow(length = unit(5, "pt")), color = "darkgray") +
  433. annotate(geom = "text", x = 0.4, y = 0.2 * adjust_axis, label = "Forward order",
  434. color = "darkgray", angle = 90, size = 3) +
  435. annotate(geom = "text", x = 0.4, y = -0.2 * adjust_axis, label = "Backward order",
  436. color = "darkgray", angle = 90, size = 3)
  437. return(plot)
  438. }
  439. ```
  440. ```{r}
  441. fig_seq_cor_time = plot_seq_cor_time(dt = subset(
  442. seq_test_time(data = dt_pred_seq_cor, variable = "mean_cor"),
  443. classification == "ovr"), variable = "mean_cor")
  444. fig_seq_slope_time = plot_seq_cor_time(dt = subset(
  445. seq_test_time(data = dt_pred_seq_cor, variable = "mean_slope"),
  446. classification == "ovr"), variable = "mean_slope")
  447. fig_seq_step_time = plot_seq_cor_time(dt = subset(
  448. seq_test_time(data = dt_pred_seq_cor, variable = "mean_step"),
  449. classification == "ovr"), variable = "mean_step")
  450. fig_seq_cor_time; fig_seq_slope_time; fig_seq_step_time
  451. ```
  452. ```{r, eval=FALSE, echo=FALSE, include=FALSE}
  453. ggsave(filename = "highsspeed_plot_decoding_sequence_timecourses_slopes.pdf",
  454. plot = fig_seq_slope_time, device = cairo_pdf, path = path_figures, scale = 1,
  455. dpi = "retina", width = 5.5, height = 3)
  456. ```
  457. We test depending on the target cue position:
  458. ```{r}
  459. # select positions within every TR that should be selected:
  460. pos_sel = seq(1, 5)
  461. # define relevant variables:
  462. variable = "probability_norm"
  463. cor_method = "kendall"
  464. # calculate indices of association at every TR:
  465. dt_pred_seq_cor_cue = dt_pred_seq %>%
  466. # here, we can filter for specific sequence events:
  467. filter(position %in% seq(1, 5, by = 1)) %>% setDT(.) %>%
  468. # order positions by decreasing probability and calculate step size
  469. # calculate correlation and slope between position and probability
  470. # verify that there are five probabilities (one for each class) per volume
  471. # verify that all correlations range between -1 and 1
  472. .[, by = .(id, classification, tITI, period, trial_tITI, seq_tr, cue_pos_label), {
  473. # order the probabilities in decreasing order (first = highest):
  474. prob_order_idx = order(get(variable), decreasing = TRUE)
  475. # order the positions by probability:
  476. pos_order = position[prob_order_idx]
  477. # order the probabilities:
  478. prob_order = get(variable)[prob_order_idx]
  479. # select positions
  480. pos_order_sel = pos_order[pos_sel]
  481. prob_order_sel = prob_order[pos_sel]
  482. list(
  483. # calculate the number of events:
  484. num_events = length(pos_order_sel[!is.na(pos_order_sel)]),
  485. # calculate the mean step size between probability-ordered events:
  486. mean_step = mean(diff(pos_order_sel)),
  487. # calculate the mean correlation between positions and their probabilities:
  488. cor = cor.test(pos_order_sel, prob_order_sel, method = cor_method)$estimate,
  489. # calculate the slope of a linear regression between position and probabilities:
  490. slope = coef(lm(prob_order_sel ~ pos_order_sel))[2]
  491. # verify that the number of events matches selection and correlations -1 < r < 1
  492. )}] %>% verify(all(num_events == length(pos_sel))) %>% #verify(between(cor, -1, 1)) %>%
  493. # average across trials for each participant (flip values by multiplying with -1):
  494. # verify that the number of trials per participant is correct:
  495. .[, by = .(id, classification, tITI, period, seq_tr, cue_pos_label), .(
  496. num_trials = .N,
  497. mean_cor = mean(cor) * (-1),
  498. mean_step = mean(mean_step),
  499. mean_slope = mean(slope) * (-1)
  500. )] %>%
  501. verify(all(num_trials == 5)) %>%
  502. # shorten the period name:
  503. mutate(period_short = ifelse(period == "forward", "fwd", period)) %>%
  504. transform(period_short = ifelse(period == "backward", "bwd", period_short)) %>%
  505. mutate(color = ifelse(period_short == "fwd", "dodgerblue", "red")) %>% setDT(.)
  506. ```
  507. ```{r}
  508. seq_test_time_cue <- function(data, variable){
  509. data_out = data %>%
  510. # average across participants for every speed at every TR:
  511. # check if the number of participants matches:
  512. .[, by = .(classification, tITI, period, seq_tr, cue_pos_label), {
  513. # perform a two-sided one-sample t-test against zero (baseline):
  514. ttest_results = t.test(get(variable), alternative = "two.sided", mu = 0);
  515. list(
  516. num_subs = .N,
  517. mean_variable = mean(get(variable)),
  518. pvalue = ttest_results$p.value,
  519. tvalue = ttest_results$statistic,
  520. df = ttest_results$parameter,
  521. cohens_d = round(abs(mean(mean(get(variable)) - 0)/sd(get(variable))), 2),
  522. sem_upper = mean(get(variable)) + (sd(get(variable))/sqrt(.N)),
  523. sem_lower = mean(get(variable)) - (sd(get(variable))/sqrt(.N))
  524. )}] %>% verify(all(num_subs == 36)) %>% verify(all((num_subs - df) == 1)) %>%
  525. # adjust p-values for multiple comparisons (filter for forward and backward period):
  526. # check if the number of comparisons matches expectations:
  527. .[period %in% c("forward", "backward"), by = .(classification), ":=" (
  528. num_comp = .N,
  529. pvalue_adjust = p.adjust(pvalue, method = "fdr", n = .N)
  530. )] %>% #verify(all(num_comp == 39, na.rm = TRUE)) %>%
  531. # round the original p-values according to the apa standard:
  532. mutate(pvalue_round = round_pvalues(pvalue)) %>%
  533. # round the adjusted p-value:
  534. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust)) %>%
  535. # sort data table:
  536. setorder(., classification, period, tITI, seq_tr) %>%
  537. # create new variable indicating significance below 0.05
  538. mutate(significance = ifelse(pvalue_adjust < 0.05, "*", ""))
  539. return(data_out)
  540. }
  541. ```
  542. ```{r, echo=FALSE}
  543. plot_seq_cor_time_cue = function(dt, variable){
  544. # select the variable of interest, determine y-axis label and adjust axis:
  545. if (variable == "mean_slope") {
  546. ylabel = "Regression slope"
  547. adjust_axis = 0.1
  548. } else if (variable == "mean_cor") {
  549. ylabel = expression("Correlation ("*tau*")")
  550. adjust_axis = 1
  551. } else if (variable == "mean_step") {
  552. ylabel = "Mean step size"
  553. adjust_axis = 1
  554. }
  555. plot = ggplot(data = dt, mapping = aes(
  556. x = seq_tr, y = mean_variable, group = as.factor(as.numeric(tITI) * 1000),
  557. fill = as.factor(as.numeric(tITI) * 1000))) +
  558. geom_hline(aes(yintercept = 0), linetype = "solid", color = "gray") +
  559. geom_ribbon(aes(ymin = sem_lower, ymax = sem_upper), alpha = 0.5, color = NA) +
  560. geom_line(mapping = aes(color = as.factor(as.numeric(tITI) * 1000))) +
  561. facet_wrap(~ cue_pos_label) +
  562. xlab("Time from sequence onset (TRs)") + ylab(ylabel) +
  563. scale_colour_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis") +
  564. scale_fill_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis") +
  565. scale_x_continuous(labels = label_fill(seq(1, 13, 1), mod = 4), breaks = seq(1, 13, 1)) +
  566. guides(color = guide_legend(nrow = 1)) +
  567. annotate("text", x = 1, y = -0.4 * adjust_axis, label = "1 TR = 1.25 s",
  568. hjust = 0, size = rel(2)) +
  569. coord_capped_cart(left = "both", bottom = "both", expand = TRUE,
  570. ylim = c(-0.4 * adjust_axis, 0.4 * adjust_axis)) +
  571. theme(panel.border = element_blank(), axis.line = element_line()) +
  572. theme(axis.line = element_line(colour = "black"),
  573. panel.grid.major = element_blank(),
  574. panel.grid.minor = element_blank(),
  575. panel.border = element_blank(),
  576. panel.background = element_blank()) +
  577. theme(legend.position = "top", legend.direction = "horizontal",
  578. legend.justification = "center", legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
  579. legend.box.margin = margin(t = 0, r = 0, b = 0, l = 0)) +
  580. geom_segment(aes(x = 0.05, xend = 0.05, y = 0.01 * adjust_axis, yend = 0.4 * adjust_axis),
  581. arrow = arrow(length = unit(5, "pt")), color = "darkgray") +
  582. geom_segment(aes(x = 0.05, xend = 0.05, y = -0.01 * adjust_axis, yend = -0.4 * adjust_axis),
  583. arrow = arrow(length = unit(5, "pt")), color = "darkgray") +
  584. annotate(geom = "text", x = 0.6, y = 0.2 * adjust_axis, label = "Forward",
  585. color = "darkgray", angle = 90, size = 2) +
  586. annotate(geom = "text", x = 0.6, y = -0.2 * adjust_axis, label = "Backward",
  587. color = "darkgray", angle = 90, size = 2)
  588. return(plot)
  589. }
  590. ```
  591. ```{r}
  592. fig_seq_slope_time_cue = plot_seq_cor_time_cue(dt = subset(
  593. seq_test_time_cue(data = dt_pred_seq_cor_cue, variable = "mean_slope"),
  594. classification == "ovr"), variable = "mean_slope")
  595. fig_seq_slope_time_cue
  596. ```
  597. ### Correlation of regression time courses
  598. #### Correlation between participants
  599. We calculate the correlations between the predicted and the observed time courses *between* participants for each of the five speed conditions (inter-stimulus intervals):
  600. ```{r, echo=TRUE}
  601. # observed time courses:
  602. dt_data_between = seq_test_time(
  603. data = dt_pred_seq_cor, variable = "mean_slope") %>%
  604. filter(classification == "ovr") %>%
  605. transform(tITI = as.factor(as.numeric(tITI) * 1000)) %>%
  606. setorder(classification, tITI, seq_tr)
  607. # predicted time courses:
  608. dt_model_between = dt_odd_seq_sim_diff %>%
  609. transform(time = time + 1) %>%
  610. filter(time %in% seq(1, 13, 1)) %>%
  611. setorder(classification, speed, time)
  612. # combine in one data table:
  613. dt_between = data.table(
  614. speed = dt_data_between$tITI,
  615. tr = dt_data_between$seq_tr,
  616. empirical = dt_data_between$mean_variable,
  617. prediction = dt_model_between$mean_difference)
  618. # calculate the correlation between
  619. dt_between_results = dt_between %>%
  620. .[, by = .(speed), {
  621. cor = cor.test(empirical, prediction, method = "pearson")
  622. list(
  623. num_trs = .N,
  624. pvalue = cor$p.value,
  625. pvalue_round = round_pvalues(cor$p.value),
  626. correlation = round(cor$estimate, 2)
  627. )
  628. }] %>%
  629. verify(num_trs == 13) %>%
  630. select(-num_trs)
  631. # show the table with the correlations:
  632. rmarkdown::paged_table(dt_between_results)
  633. ```
  634. We plot the correlations between the regression slope time courses predicted by the model vs. the observed data *between* participants:
  635. ```{r, echo=TRUE, warning=FALSE, message=FALSE}
  636. fig_seq_cor_between = ggplot(
  637. data = dt_between,
  638. mapping = aes(
  639. x = prediction, y = empirical, color = speed, fill = speed)) +
  640. geom_point(alpha = 1) +
  641. geom_smooth(method = lm, se = FALSE, alpha = 0.5, fullrange = TRUE) +
  642. scale_colour_viridis(
  643. name = "Speed (ms)", discrete = TRUE,
  644. option = "cividis", guide = FALSE) +
  645. scale_fill_viridis(
  646. name = "Speed (ms)", discrete = TRUE,
  647. option = "cividis", guide = FALSE) +
  648. xlab("Predicted slope") +
  649. ylab("Observed slope") +
  650. # guides(color = guide_legend(nrow = 1)) +
  651. coord_capped_cart(
  652. left = "both", bottom = "both", expand = TRUE,
  653. xlim = c(-0.4, 0.4), ylim = c(-0.05, 0.05)) +
  654. theme(legend.position = "top",
  655. legend.direction = "horizontal",
  656. legend.justification = "center",
  657. legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
  658. legend.box.margin = margin(t = 0, r = 0, b = 0, l = 0)) +
  659. theme(axis.line = element_line(colour = "black"),
  660. panel.grid.major = element_blank(),
  661. panel.grid.minor = element_blank(),
  662. panel.border = element_blank(),
  663. panel.background = element_blank())
  664. # show the plot:
  665. fig_seq_cor_between
  666. ```
  667. #### Correlation within participants
  668. We calculate the correlations between the predicted and the observed time courses *within* participants for each of the five speed conditions (inter-stimulus intervals):
  669. ```{r}
  670. # observed regression slope time courses
  671. dt_data_within = dt_pred_seq_cor %>%
  672. filter(classification == "ovr") %>%
  673. transform(tITI = as.factor(as.numeric(tITI) * 1000)) %>%
  674. setorder(classification, id, tITI, seq_tr)
  675. # predicted regression slope time courses
  676. dt_model_within = dt_odd_seq_sim %>%
  677. transform(time = time + 1) %>%
  678. filter(time %in% seq(1, 13, 1)) %>%
  679. setorder(classification, id, speed, time)
  680. # combine in one data table:
  681. dt_within = data.table(
  682. id = dt_data_within$id,
  683. speed = dt_data_within$tITI,
  684. time = dt_data_within$seq_tr,
  685. empirical = dt_data_within$mean_slope,
  686. prediction = dt_model_within$probability)
  687. # run correlations:
  688. dt_within_cor = dt_within %>%
  689. .[, by = .(id, speed), {
  690. cor = cor.test(empirical, prediction, method = "pearson")
  691. list(
  692. num_trs = .N,
  693. pvalue = cor$p.value,
  694. estimate = as.numeric(cor$estimate)
  695. )}] %>%
  696. verify(num_trs == 13)
  697. # run t-tests over correlation coefficients for each speed level:
  698. dt_within_cor_results = setDT(dt_within_cor) %>%
  699. .[, by = .(speed), {
  700. ttest_results = t.test(
  701. estimate, mu = 0, alternative = "two.sided", paired = FALSE)
  702. list(
  703. num_subs = .N,
  704. mean_estimate = round(mean(estimate), 2),
  705. pvalue = ttest_results$p.value,
  706. tvalue = round(ttest_results$statistic, 2),
  707. df = ttest_results$parameter,
  708. cohens_d = round((mean(estimate) - 0)/sd(estimate), 2)
  709. )}] %>%
  710. verify(num_subs == 36) %>%
  711. verify((num_subs - df) == 1) %>%
  712. # adjust p-values for multiple comparisons:
  713. # check if the number of comparisons matches expectations:
  714. .[, ":=" (
  715. num_comp = .N,
  716. pvalue_adjust = p.adjust(pvalue, method = "fdr", n = .N)
  717. )] %>%
  718. # round the original p-values according to the apa standard:
  719. mutate(pvalue_round = round_pvalues(pvalue)) %>%
  720. # round the adjusted p-value:
  721. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust)) %>%
  722. # create new variable indicating significance below 0.05
  723. mutate(significance = ifelse(pvalue_adjust < 0.05, "*", ""))
  724. # show the table with the t-test results:
  725. rmarkdown::paged_table(dt_within_cor_results)
  726. ```
  727. We plot the correlations between the predicted and the observed time courses *within* participants for each of the five speed conditions (inter-stimulus intervals):
  728. ```{r, echo=TRUE}
  729. fig_seq_cor_within = ggplot(
  730. data = dt_within_cor,
  731. mapping = aes(
  732. x = speed, y = estimate, color = speed, fill = speed, group = speed)) +
  733. stat_summary(geom = "bar", fun = "mean") +
  734. geom_dotplot(binaxis = "y", stackdir = "center", stackratio = 0.5,
  735. color = "white", alpha = 0.5,
  736. inherit.aes = TRUE, binwidth = 0.05) +
  737. stat_summary(geom = "errorbar", fun.data = "mean_se", width = 0, color = "black") +
  738. scale_colour_viridis(
  739. name = "Speed (ms)", discrete = TRUE, option = "cividis", guide = FALSE) +
  740. scale_fill_viridis(
  741. name = "Speed (ms)", discrete = TRUE, option = "cividis", guide = FALSE) +
  742. xlab("Speed (in ms)") +
  743. ylab("Correlation (r)") +
  744. #guides(color = guide_legend(nrow = 1)) +
  745. coord_capped_cart(left = "both", bottom = "both", expand = TRUE) +
  746. theme(legend.position = "top", legend.direction = "horizontal",
  747. legend.justification = "center", legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
  748. legend.box.margin = margin(t = 0, r = 0, b = 0, l = 0)) +
  749. theme(axis.ticks.x = element_line(colour = "white"),
  750. axis.line.x = element_line(colour = "white")) +
  751. theme(axis.title.x = element_blank(), axis.text.x = element_blank()) +
  752. theme(axis.line = element_line(colour = "black"),
  753. panel.grid.major = element_blank(),
  754. panel.grid.minor = element_blank(),
  755. panel.border = element_blank(),
  756. panel.background = element_blank())
  757. # show figure:
  758. fig_seq_cor_within
  759. ```
  760. Calculate the average correlation or average regression slope
  761. for each time period (forward versus backward) for all five speed conditions:
  762. ```{r, echo=TRUE}
  763. seq_test_period <- function(data, variable){
  764. data_out = data %>%
  765. # filter out the excluded time period (select only forward and backward period):
  766. filter(period != "excluded") %>%
  767. setDT(.) %>%
  768. # average for each time period and speed condition for every participant:
  769. .[, by = .(classification, id, tITI, period), .(
  770. mean_variable = mean(get(variable)))] %>%
  771. # average across participants for every speed at every TR:
  772. # check if the number of participants matches:
  773. .[, by = .(classification, tITI, period), {
  774. # perform a two-sided one-sample t-test against zero (baseline):
  775. ttest_results = t.test(mean_variable, alternative = "two.sided", mu = 0);
  776. list(
  777. num_subs = .N,
  778. mean_variable = mean(mean_variable),
  779. pvalue = ttest_results$p.value,
  780. tvalue = round(abs(ttest_results$statistic), 2),
  781. df = ttest_results$parameter,
  782. cohens_d = abs(round((mean(mean_variable) - 0) / sd(mean_variable), 2)),
  783. sem_upper = mean(mean_variable) + (sd(mean_variable)/sqrt(.N)),
  784. sem_lower = mean(mean_variable) - (sd(mean_variable)/sqrt(.N))
  785. )
  786. }] %>%
  787. verify(all(num_subs == 36)) %>%
  788. verify(all((num_subs - df) == 1)) %>%
  789. # adjust p-values for multiple comparisons:
  790. # check if the number of comparisons matches expectations:
  791. .[period %in% c("forward", "backward"), by = .(classification), ":=" (
  792. num_comp = .N,
  793. pvalue_adjust = p.adjust(pvalue, method = "fdr", n = .N)
  794. )] %>%
  795. verify(num_comp == 10) %>%
  796. # add variable that indicates significance with stupid significance stars:
  797. mutate(significance = ifelse(pvalue < 0.05, "*", "")) %>%
  798. # round the original p-values according to APA manual:
  799. mutate(pvalue_round = round_pvalues(pvalue)) %>%
  800. # round the adjusted p-value:
  801. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust)) %>%
  802. # sort data table:
  803. setorder(classification, period, tITI) %>%
  804. # shorten the period name:
  805. mutate(period_short = ifelse(period == "forward", "fwd", period)) %>%
  806. transform(period_short = ifelse(period == "backward", "bwd", period_short)) %>%
  807. mutate(color = ifelse(period_short == "fwd", "dodgerblue", "red")) %>% setDT(.)
  808. return(data_out)
  809. }
  810. ```
  811. ```{r}
  812. rmarkdown::paged_table(
  813. seq_test_period(data = dt_pred_seq_cor, variable = "mean_cor") %>%
  814. filter(pvalue_adjust < 0.05, classification == "ovr"))
  815. rmarkdown::paged_table(
  816. seq_test_period(data = dt_pred_seq_cor, variable = "mean_step") %>%
  817. filter(pvalue_adjust < 0.05, classification == "ovr"))
  818. rmarkdown::paged_table(
  819. seq_test_period(data = dt_pred_seq_cor, variable = "mean_slope") %>%
  820. filter(pvalue_adjust < 0.05, classification == "ovr"))
  821. ```
  822. ```{r, echo=TRUE}
  823. plot_seq_cor_period = function(data, variable){
  824. # select the variable of interest, determine y-axis label and adjust axis:
  825. if (variable == "mean_slope") {
  826. ylabel = "Regression slope"
  827. adjust_axis = 0.1
  828. } else if (variable == "mean_cor") {
  829. ylabel = expression("Correlation ("*tau*")")
  830. adjust_axis = 1
  831. } else if (variable == "mean_step") {
  832. ylabel = "Mean step size"
  833. adjust_axis = 1
  834. }
  835. dt_forward = data.table(xmin = 0, xmax = 5.5, ymin = 0, ymax = 0.4 * adjust_axis)
  836. dt_backward = data.table(xmin = 0, xmax = 5.5, ymin = 0, ymax = -0.4 * adjust_axis)
  837. # average across participants for every speed at every TR:
  838. plot_data = data %>% setDT(.) %>%
  839. .[, by = .(classification, id, tITI, period_short), .(
  840. mean_variable = mean(get(variable))
  841. )] %>% filter(classification == "ovr" & period_short != "excluded")
  842. plot_stat = seq_test_period(data = data, variable = variable)
  843. # plot average correlation or betas for each speed condition and time period:
  844. plot = ggplot(data = plot_data, aes(
  845. x = fct_rev(as.factor(period_short)), y = as.numeric(mean_variable),
  846. fill = as.factor(as.numeric(tITI) * 1000))) +
  847. geom_bar(stat = "summary", fun = "mean", width = 0.9, show.legend = TRUE) +
  848. geom_dotplot(binaxis = "y", stackdir = "center", stackratio = 0.5, alpha = 0.2,
  849. binwidth = 0.01 * adjust_axis, show.legend = FALSE) +
  850. #geom_point(position = position_jitterdodge(jitter.height = 0, seed = 4, jitter.width = 0.2),
  851. # pch = 21, alpha = 0.2, show.legend = FALSE) +
  852. geom_errorbar(stat = "summary", fun.data = "mean_se", width = 0.0, color = "black") +
  853. geom_text(data = subset(plot_stat, classification == "ovr"), aes(
  854. x = fct_rev(as.factor(period_short)), y = round_updown(as.numeric(mean_variable), 0.6 * adjust_axis),
  855. label = paste0("d=", sprintf("%.2f", cohens_d), significance)), size = 3.3, show.legend = FALSE,
  856. color = subset(plot_stat, classification == "ovr")$color) +
  857. facet_wrap(~ as.factor(as.numeric(tITI) * 1000), strip.position = "bottom", nrow = 1) +
  858. xlab("Period") + ylab(ylabel) +
  859. scale_fill_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis") +
  860. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(-0.6, 0.6) * adjust_axis) +
  861. theme(panel.border = element_blank(), axis.line = element_line()) +
  862. theme(axis.line = element_line(colour = "black"),
  863. panel.grid.major = element_blank(),
  864. panel.grid.minor = element_blank(),
  865. panel.border = element_blank(),
  866. panel.background = element_blank()) +
  867. theme(axis.ticks.x = element_line(color = "white"),
  868. axis.line.x = element_line(color = "white")) +
  869. theme(legend.position = "top", legend.direction = "horizontal", legend.box = "vertical",
  870. legend.justification = "center", legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
  871. legend.box.margin = margin(t = 0, r = 0, b = -5, l = 0)) +
  872. theme(panel.spacing = unit(0, "lines"), strip.background = element_blank(),
  873. strip.placement = "outside", strip.text = element_blank())
  874. return(plot)
  875. }
  876. fig_seq_cor_period = plot_seq_cor_period(data = dt_pred_seq_cor, variable = "mean_cor")
  877. fig_seq_slope_period = plot_seq_cor_period(data = dt_pred_seq_cor, variable = "mean_slope")
  878. fig_seq_step_period = plot_seq_cor_period(data = dt_pred_seq_cor, variable = "mean_step")
  879. fig_seq_cor_period; fig_seq_step_period; fig_seq_slope_period;
  880. ```
  881. ```{r, echo = FALSE}
  882. plot_seq_cor_facet = function(dt, variable){
  883. # create separate datatable to plot rectangles indicating forward / backward period:
  884. dt_reduced = dt %>% setDT(.) %>%
  885. .[, by = .(classification, tITI, period), .(
  886. xmin = min(seq_tr) - 0.5,
  887. xmax = max(seq_tr) + 0.5
  888. )] %>%
  889. filter(period != "excluded") %>%
  890. mutate(fill = ifelse(period == "forward", "dodgerblue", "red"))
  891. # select the variable of interest, determine y-axis label and adjust axis:
  892. if (variable == "mean_slope") {
  893. ylabel = "Regression slope"
  894. adjust_axis = 0.1
  895. } else if (variable == "mean_cor") {
  896. ylabel = expression("Correlation ("*tau*")")
  897. adjust_axis = 1
  898. } else if (variable == "mean_step") {
  899. ylabel = "Mean step size"
  900. adjust_axis = 1
  901. }
  902. plot = ggplot(data = dt, mapping = aes(
  903. x = as.factor(seq_tr), y = as.numeric(mean_variable),
  904. group = as.factor(tITI), fill = as.factor(tITI), color = as.factor(tITI))) +
  905. # add background rectangles to indicate the forward and backward period:
  906. geom_rect(data = dt_reduced, aes(
  907. xmin = xmin, xmax = xmax, ymin = -0.4 * adjust_axis, ymax = 0.4 * adjust_axis),
  908. alpha = 0.05, inherit.aes = FALSE, show.legend = FALSE, fill = dt_reduced$fill) +
  909. geom_hline(aes(yintercept = 0), linetype = "solid", color = "gray") +
  910. facet_wrap(facets = ~ as.factor(tITI), labeller = get_labeller(dt$tITI), nrow = 1) +
  911. geom_ribbon(aes(ymin = sem_lower, ymax = sem_upper), alpha = 0.5, color = NA) +
  912. geom_line() +
  913. geom_point(data = subset(dt, pvalue_adjust < 0.05), pch = 21, fill = "red",
  914. color = "black", show.legend = FALSE) +
  915. xlab("Time from sequence onset (TRs)") + ylab(ylabel) +
  916. theme(legend.position = "top", legend.direction = "horizontal",
  917. legend.justification = "center", legend.margin = margin(0, 0, 0, 0),
  918. legend.box.margin = margin(t = 0, r = 0, b = -5, l = 0)) +
  919. scale_colour_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis", guide = FALSE) +
  920. scale_fill_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis", guide = FALSE) +
  921. scale_x_discrete(labels = label_fill(seq(1, 13, 1), mod = 4), breaks = seq(1, 13, 1)) +
  922. theme(strip.text.x = element_text(margin = margin(b = 2, t = 2))) +
  923. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(-0.4, 0.4) * adjust_axis) +
  924. theme(axis.line = element_line(colour = "black"),
  925. panel.grid.major = element_blank(),
  926. panel.grid.minor = element_blank(),
  927. panel.border = element_blank(),
  928. panel.background = element_blank())
  929. return(plot)
  930. }
  931. ```
  932. We repeat the same calculations, just splitting up the data by the serial position of the cued image:
  933. ```{r}
  934. seq_test_period_cue <- function(data, variable){
  935. data_out = data %>%
  936. # filter out the excluded time period (select only forward and backward period):
  937. filter(period != "excluded") %>% setDT(.) %>%
  938. # average for each time period and speed condition for every participant:
  939. .[, by = .(classification, id, tITI, period, cue_pos_label), .(
  940. mean_variable = mean(get(variable)))] %>%
  941. # average across participants for every speed at every TR:
  942. # check if the number of participants matches:
  943. .[, by = .(classification, tITI, period, cue_pos_label), {
  944. # perform a two-sided one-sample t-test against zero (baseline):
  945. ttest_results = t.test(mean_variable, alternative = "two.sided", mu = 0);
  946. list(
  947. num_subs = .N,
  948. mean_variable = mean(mean_variable),
  949. pvalue = ttest_results$p.value,
  950. tvalue = round(abs(ttest_results$statistic), 2),
  951. df = ttest_results$parameter,
  952. cohens_d = abs(round((mean(mean_variable) - 0) / sd(mean_variable), 2)),
  953. sem_upper = mean(mean_variable) + (sd(mean_variable)/sqrt(.N)),
  954. sem_lower = mean(mean_variable) - (sd(mean_variable)/sqrt(.N))
  955. )
  956. }] %>% verify(all(num_subs == 36)) %>% verify(all((num_subs - df) == 1)) %>%
  957. # adjust p-values for multiple comparisons:
  958. # check if the number of comparisons matches expectations:
  959. .[period %in% c("forward", "backward"), by = .(classification), ":=" (
  960. num_comp = .N,
  961. pvalue_adjust = p.adjust(pvalue, method = "fdr", n = .N)
  962. )] %>% #verify(num_comp == 10) %>%
  963. # add variable that indicates significance with stupid significance stars:
  964. mutate(significance = ifelse(pvalue < 0.05, "*", "")) %>%
  965. # round the original p-values according to APA manual:
  966. mutate(pvalue_round = round_pvalues(pvalue)) %>%
  967. # round the adjusted p-value:
  968. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust)) %>%
  969. # sort data table:
  970. setorder(classification, period, tITI) %>%
  971. # shorten the period name:
  972. mutate(period_short = ifelse(period == "forward", "fwd", period)) %>%
  973. transform(period_short = ifelse(period == "backward", "bwd", period_short)) %>%
  974. mutate(color = ifelse(period_short == "fwd", "dodgerblue", "red")) %>% setDT(.)
  975. return(data_out)
  976. }
  977. ```
  978. ```{r}
  979. rmarkdown::paged_table(
  980. seq_test_period_cue(data = dt_pred_seq_cor_cue, variable = "mean_cor") %>%
  981. filter(pvalue_adjust < 0.05, classification == "ovr"))
  982. rmarkdown::paged_table(
  983. seq_test_period_cue(data = dt_pred_seq_cor_cue, variable = "mean_step") %>%
  984. filter(pvalue_adjust < 0.05, classification == "ovr"))
  985. rmarkdown::paged_table(
  986. seq_test_period_cue(data = dt_pred_seq_cor_cue, variable = "mean_slope") %>%
  987. filter(pvalue_adjust < 0.05, classification == "ovr"))
  988. ```
  989. We plot the same data, just splitting up the data by the serial position of the cued image:
  990. ```{r}
  991. plot_seq_cor_period_cue = function(data, variable){
  992. # select the variable of interest, determine y-axis label and adjust axis:
  993. if (variable == "mean_slope") {
  994. ylabel = "Regression slope"
  995. adjust_axis = 0.1
  996. } else if (variable == "mean_cor") {
  997. ylabel = expression("Correlation ("*tau*")")
  998. adjust_axis = 1
  999. } else if (variable == "mean_step") {
  1000. ylabel = "Mean step size"
  1001. adjust_axis = 1
  1002. }
  1003. dt_forward = data.table(xmin = 0, xmax = 5.5, ymin = 0, ymax = 0.4 * adjust_axis)
  1004. dt_backward = data.table(xmin = 0, xmax = 5.5, ymin = 0, ymax = -0.4 * adjust_axis)
  1005. # average across participants for every speed at every TR:
  1006. plot_data = data %>% setDT(.) %>%
  1007. .[, by = .(classification, id, tITI, period_short, cue_pos_label), .(
  1008. mean_variable = mean(get(variable))
  1009. )] %>% filter(classification == "ovr" & period_short != "excluded")
  1010. plot_stat = seq_test_period_cue(data = data, variable = variable)
  1011. # plot average correlation or betas for each speed condition and time period:
  1012. plot = ggplot(data = plot_data, aes(
  1013. x = fct_rev(as.factor(period_short)), y = as.numeric(mean_variable),
  1014. fill = as.factor(as.numeric(tITI) * 1000))) +
  1015. geom_bar(stat = "summary", fun = "mean", width = 0.9, show.legend = TRUE) +
  1016. geom_dotplot(binaxis = "y", stackdir = "center", stackratio = 0.5, alpha = 0.2,
  1017. binwidth = 0.01 * adjust_axis, show.legend = FALSE) +
  1018. geom_errorbar(stat = "summary", fun.data = "mean_se", width = 0.0, color = "black") +
  1019. geom_text(data = subset(plot_stat, classification == "ovr"), aes(
  1020. x = fct_rev(as.factor(period_short)), y = round_updown(as.numeric(mean_variable), 0.5 * adjust_axis),
  1021. label = paste0("d=", cohens_d, significance)), size = 3.0, show.legend = FALSE,
  1022. color = subset(plot_stat, classification == "ovr")$color) +
  1023. facet_grid(rows = vars(cue_pos_label),
  1024. cols = vars(as.factor(as.numeric(tITI) * 1000))) +
  1025. xlab("Period") + ylab(ylabel) +
  1026. scale_fill_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis") +
  1027. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(-0.6, 0.6) * adjust_axis) +
  1028. theme(panel.border = element_blank(), axis.line = element_line()) +
  1029. theme(axis.line = element_line(colour = "black"),
  1030. panel.grid.major = element_blank(),
  1031. panel.grid.minor = element_blank(),
  1032. panel.border = element_blank(),
  1033. panel.background = element_blank()) +
  1034. #theme(axis.ticks.x = element_blank(), axis.line.x = element_blank()) +
  1035. theme(legend.position = "top", legend.direction = "horizontal", legend.box = "vertical",
  1036. legend.justification = "center", legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
  1037. legend.box.margin = margin(t = 0, r = 0, b = -5, l = 0))
  1038. #theme(panel.spacing = unit(0, "lines"), strip.background = element_blank(),
  1039. # strip.placement = "outside", strip.text = element_blank())
  1040. return(plot)
  1041. }
  1042. fig_seq_cor_period_cue = plot_seq_cor_period_cue(data = dt_pred_seq_cor_cue, variable = "mean_cor")
  1043. fig_seq_slope_period_cue = plot_seq_cor_period_cue(data = dt_pred_seq_cor_cue, variable = "mean_slope")
  1044. fig_seq_step_period_cue = plot_seq_cor_period_cue(data = dt_pred_seq_cor_cue, variable = "mean_step")
  1045. fig_seq_cor_period_cue; fig_seq_step_period_cue; fig_seq_slope_period_cue;
  1046. ```
  1047. Combine plots for cue period:
  1048. ```{r, echo=FALSE}
  1049. plot_grid(fig_seq_probas_cue, fig_seq_slope_time_cue, fig_seq_slope_period_cue,
  1050. labels = c("a", "b", "c"), nrow = 3, rel_heights = c(5, 4, 6))
  1051. ```
  1052. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  1053. ggsave(filename = "highspeed_plot_decoding_sequence_cue_effects.pdf",
  1054. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1055. dpi = "retina", width = 6, height = 10)
  1056. ```
  1057. ```{r}
  1058. # create a data frame with the relevant data to run the LME:
  1059. lme_seq_cor_data = dt_pred_seq_cor %>%
  1060. filter(classification == "ovr" & period != "excluded") %>%
  1061. transform(tITI = as.factor(tITI))
  1062. # define linear mixed effects model with by-participant random intercepts:
  1063. lme_seq_cor = lmer(mean_slope ~ tITI * period + (1|id),
  1064. data = lme_seq_cor_data, na.action = na.omit, control = lcctrl)
  1065. summary(lme_seq_cor)
  1066. anova(lme_seq_cor)
  1067. emmeans_results = emmeans(lme_seq_cor, list(pairwise ~ period | tITI))
  1068. emmeans_pvalues = round_pvalues(summary(emmeans_results[[2]])$p.value)
  1069. ```
  1070. ### Serial target position
  1071. We calculate the average serial position at each TR:
  1072. ```{r}
  1073. dt_pred_seq_pos = dt_pred_seq %>%
  1074. # get the position with the highest probability at every TR:
  1075. .[, by = .(classification, id, period, tITI, trial_tITI, seq_tr), .(
  1076. num_positions = .N,
  1077. max_position = position[which.max(probability_norm)]
  1078. )] %>%
  1079. # verify that the number of position per TR matches:
  1080. verify(all(num_positions == 5)) %>%
  1081. # average the maximum position across trials for each speed condition:
  1082. .[, by = .(classification, id, period, tITI, seq_tr), .(
  1083. num_trials = .N,
  1084. mean_position = mean(max_position)
  1085. )] %>%
  1086. # verify that the number of trials per participant is correct:
  1087. verify(all(num_trials == 15)) %>%
  1088. # calculate the difference of the mean position from baseline (which is 3)
  1089. mutate(position_diff = mean_position - 3) %>%
  1090. setDT(.) %>%
  1091. # set the speed condition and period variable to a factorial variable:
  1092. transform(tTII = as.factor(tITI)) %>%
  1093. transform(period = as.factor(period))
  1094. ```
  1095. We calculate whether the average serial position is significantly different
  1096. from baseline separately for every speed and period (forward vs. backward):
  1097. ```{r}
  1098. dt_pred_seq_pos_period = dt_pred_seq_pos %>%
  1099. # focus on the forward and backward period only:
  1100. filter(period != "excluded") %>% setDT(.) %>%
  1101. # average the mean position across trs for each period and speed condition:
  1102. .[, by = .(classification, id, period, tITI), .(
  1103. position_diff = mean(position_diff)
  1104. )] %>%
  1105. # average across participants for each speed condition and volume:
  1106. .[, by = .(classification, period, tITI), {
  1107. ttest_results = t.test(position_diff, alternative = "two.sided", mu = 0)
  1108. list(
  1109. num_subs = .N,
  1110. tvalue = round(ttest_results$statistic, 2),
  1111. pvalue = ttest_results$p.value,
  1112. df = ttest_results$parameter,
  1113. cohens_d = abs(round((mean(position_diff) - 0) / sd(position_diff), 2)),
  1114. position_diff = mean(position_diff),
  1115. conf_lb = round(ttest_results$conf.int[1], 2),
  1116. conf_ub = round(ttest_results$conf.int[2], 2),
  1117. sd_position = sd(position_diff),
  1118. sem_upper = mean(position_diff) + (sd(position_diff)/sqrt(.N)),
  1119. sem_lower = mean(position_diff) - (sd(position_diff)/sqrt(.N))
  1120. )
  1121. }] %>% verify(all(num_subs == 36)) %>%
  1122. # adjust p-values for multiple comparisons:
  1123. .[, by = .(classification), ":=" (
  1124. num_comp = .N,
  1125. pvalue_adjust = p.adjust(pvalue, method = "fdr", n = .N)
  1126. )] %>%
  1127. verify(all(num_comp == 10)) %>%
  1128. # add variable that indicates significance with stupid significance stars:
  1129. mutate(significance = ifelse(pvalue_adjust < 0.05, "*", "")) %>%
  1130. # round the original p-values:
  1131. mutate(pvalue_round = round_pvalues(pvalue)) %>%
  1132. # round the p-values adjusted for multiple comparisons:
  1133. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust)) %>%
  1134. # sort the datatable for each speed and TR:
  1135. setorder(., classification, period, tITI) %>%
  1136. # shorten the period name:
  1137. mutate(period_short = ifelse(period == "forward", "fwd", period)) %>%
  1138. transform(period_short = ifelse(period == "backward", "bwd", period_short)) %>%
  1139. mutate(color = ifelse(period_short == "fwd", "dodgerblue", "red")) %>% setDT(.)
  1140. dt_pred_seq_pos_period %>%
  1141. filter(classification == "ovr", pvalue_adjust < 0.05) %>%
  1142. rmarkdown::paged_table(.)
  1143. ```
  1144. We calculate the mean serial position at every TR and compare it against baseline:
  1145. ```{r}
  1146. dt_pred_seq_pos_tr = dt_pred_seq_pos %>%
  1147. # average across participants for each speed condition and volume:
  1148. .[, by = .(classification, period, tITI, seq_tr), {
  1149. ttest_results = t.test(mean_position, alternative = "two.sided", mu = 3)
  1150. list(
  1151. num_subs = .N,
  1152. tvalue = ttest_results$statistic,
  1153. pvalue = ttest_results$p.value,
  1154. df = ttest_results$parameter,
  1155. mean_position = mean(mean_position),
  1156. sd_position = sd(mean_position),
  1157. sem_upper = mean(mean_position) + (sd(mean_position)/sqrt(.N)),
  1158. sem_lower = mean(mean_position) - (sd(mean_position)/sqrt(.N))
  1159. )
  1160. }] %>% verify(all(num_subs == 36)) %>%
  1161. # adjust p-values for multiple comparisons:
  1162. .[period %in% c("forward", "backward"), by = .(classification), ":=" (
  1163. num_comp = .N,
  1164. pvalue_adjust = p.adjust(pvalue, method = "fdr", n = .N)
  1165. )] %>% verify(all(num_comp == 39, na.rm = TRUE)) %>%
  1166. # round the original p-values:
  1167. mutate(pvalue_rounded = round_pvalues(pvalue)) %>%
  1168. # round the p-values adjusted for multiple comparisons:
  1169. mutate(pvalue_adjust_rounded = round_pvalues(pvalue_adjust)) %>%
  1170. #
  1171. mutate(significance = ifelse(pvalue_adjust < 0.05, "***", "")) %>%
  1172. # sort the datatable for each speed and TR:
  1173. setorder(., classification, period, tITI, seq_tr)
  1174. dt_pred_seq_pos_tr %>%
  1175. filter(classification == "ovr", pvalue_adjust < 0.05)
  1176. ```
  1177. ```{r, eval = FALSE}
  1178. cfg = list(variable = "mean_position", threshold = 2.021, baseline = 3,
  1179. grouping = c("classification", "tITI"), n_perms = 10000, n_trs = 13)
  1180. dt_pred_seq_pos_cluster = cluster_permutation(dt_pred_seq_pos_sub, cfg)
  1181. ```
  1182. ```{r}
  1183. # define linear mixed effects model with by-participant random intercepts:
  1184. lme_seq_pos = lmer(position_diff ~ tITI * period + (1 + tITI + period |id),
  1185. data = subset(dt_pred_seq_pos, classification == "ovr" & period != "excluded"),
  1186. na.action = na.omit, control = lcctrl)
  1187. summary(lme_seq_pos)
  1188. anova(lme_seq_pos)
  1189. emmeans_results = emmeans(lme_seq_pos, list(pairwise ~ period | tITI))
  1190. emmeans_pvalues = round_pvalues(summary(emmeans_results[[2]])$p.value)
  1191. ```
  1192. ```{r, echo=TRUE}
  1193. variable = "position_diff"
  1194. plot_data = dt_pred_seq_pos %>%
  1195. # average across participants for every speed at every TR:
  1196. .[, by = .(classification, id, tITI, period), .(
  1197. mean_variable = mean(get(variable))
  1198. )] %>%
  1199. filter(classification == "ovr" & period != "excluded") %>%
  1200. # shorten the period name:
  1201. mutate(period_short = ifelse(period == "forward", "fwd", period)) %>%
  1202. transform(period_short = ifelse(period == "backward", "bwd", period_short)) %>%
  1203. mutate(color = ifelse(period_short == "fwd", "dodgerblue", "red")) %>%
  1204. setDT(.)
  1205. # plot average correlation or betas for each speed condition and time period:
  1206. fig_seq_pos_period = ggplot(data = plot_data, aes(
  1207. x = fct_rev(as.factor(period_short)), y = as.numeric(mean_variable),
  1208. fill = as.factor(as.numeric(tITI) * 1000))) +
  1209. geom_bar(stat = "summary", fun = "mean", width = 0.9, show.legend = TRUE) +
  1210. geom_dotplot(binaxis = "y", stackdir = "center", stackratio = 0.5, alpha = 0.2,
  1211. binwidth = 0.05, show.legend = FALSE) +
  1212. geom_errorbar(stat = "summary", fun.data = "mean_se", width = 0.0, color = "black") +
  1213. geom_text(data = subset(dt_pred_seq_pos_period, classification == "ovr"), aes(
  1214. x = fct_rev(as.factor(period_short)), y = round_updown(as.numeric(get(variable)), 1.2),
  1215. label = paste0("d=", sprintf("%.2f", cohens_d), significance)), show.legend = FALSE, size = 3.2,
  1216. color = subset(dt_pred_seq_pos_period, classification == "ovr")$color) +
  1217. facet_wrap(~ as.factor(as.numeric(tITI) * 1000), strip.position = "bottom", nrow = 1) +
  1218. xlab("Period") + ylab("Event position\ncompared to baseline") +
  1219. scale_colour_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis") +
  1220. scale_fill_viridis(name = "Speed (ms)", discrete = TRUE, option = "cividis") +
  1221. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(-1.5, 1.5)) +
  1222. theme(legend.position = "top", legend.direction = "horizontal",
  1223. legend.justification = "center", legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
  1224. legend.box.margin = margin(t = 0, r = 0, b = 0, l = 0)) +
  1225. theme(panel.spacing = unit(0, "lines"), strip.background = element_blank(),
  1226. strip.placement = "outside", strip.text = element_blank()) +
  1227. theme(axis.ticks.x = element_line(colour = "white"),
  1228. axis.line.x = element_line(colour = "white")) +
  1229. theme(axis.line.y = element_line(colour = "black"),
  1230. panel.grid.major = element_blank(),
  1231. panel.grid.minor = element_blank(),
  1232. panel.border = element_blank(),
  1233. panel.background = element_blank())
  1234. fig_seq_pos_period
  1235. ```
  1236. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  1237. ggsave(filename = "highspeed_plot_decoding_sequence_position_period.pdf",
  1238. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1239. dpi = "retina", width = 5, height = 3)
  1240. ```
  1241. ```{r, echo = FALSE}
  1242. plot_seq_pos <- function(dt){
  1243. # create separate datatable to plot rectangles indicating forward / backward period:
  1244. dt_reduced = dt %>% setDT(.) %>%
  1245. .[, by = .(classification, tITI, period), .(
  1246. xmin = min(seq_tr) - 0.5,
  1247. xmax = max(seq_tr) + 0.5
  1248. )] %>%
  1249. filter(period != "excluded") %>%
  1250. mutate(fill = ifelse(period == "forward", "dodgerblue", "red"))
  1251. ggplot(data = dt, mapping = aes(
  1252. x = as.factor(seq_tr), y = as.numeric(mean_position),
  1253. group = as.factor(as.numeric(tITI)*1000), fill = as.factor(as.numeric(tITI)*1000))) +
  1254. #geom_rect(data = dt_reduced, aes(xmin = xmin, xmax = xmax, ymin = 2, ymax = 4),
  1255. # alpha = 0.05, inherit.aes = FALSE, show.legend = FALSE, fill = dt_reduced$fill) +
  1256. geom_hline(aes(yintercept = 3), linetype = "solid", color = "gray") +
  1257. #facet_wrap(facets = ~ as.factor(tITI), labeller = get_labeller(dt$tITI), nrow = 1) +
  1258. geom_ribbon(aes(ymin = sem_lower, ymax = sem_upper), alpha = 0.5, color = NA) +
  1259. geom_line(mapping = aes(color = as.factor(as.numeric(tITI)*1000))) +
  1260. xlab("Time from sequence onset (TRs)") +
  1261. ylab("Event position") +
  1262. scale_colour_viridis(discrete = TRUE, option = "cividis", name = "Speed (ms)", guide = FALSE) +
  1263. scale_fill_viridis(discrete = TRUE, option = "cividis", name = "Speed (ms)", guide = FALSE) +
  1264. scale_x_discrete(labels = label_fill(seq(1, 13, 1), mod = 4), breaks = seq(1, 13, 1)) +
  1265. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(2,4)) +
  1266. theme(strip.text.x = element_text(margin = margin(b = 2, t = 2))) +
  1267. theme(legend.position = "top", legend.direction = "horizontal",
  1268. legend.justification = "center", legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
  1269. legend.box.margin = margin(t = 0, r = 0, b = 0, l = 0)) +
  1270. geom_segment(aes(x = 0.9, xend = 0.9, y = 3.01, yend = 4),
  1271. arrow = arrow(length = unit(5, "pt")), color = "darkgray") +
  1272. geom_segment(aes(x = 0.9, xend = 0.9, y = 3.01, yend = 2),
  1273. arrow = arrow(length = unit(5, "pt")), color = "darkgray") +
  1274. annotate(geom = "text", x = 1.4, y = 3.5, label = "Later",
  1275. color = "darkgray", angle = 90, size = 3) +
  1276. annotate(geom = "text", x = 1.4, y = 2.5, label = "Earlier",
  1277. color = "darkgray", angle = 90, size = 3) +
  1278. annotate("text", x = 13, y = 2, label = "1 TR = 1.25 s",
  1279. hjust = 1, size = rel(2)) +
  1280. theme(axis.line = element_line(colour = "black"),
  1281. panel.grid.major = element_blank(),
  1282. panel.grid.minor = element_blank(),
  1283. panel.border = element_blank(),
  1284. panel.background = element_blank())
  1285. }
  1286. fig_seq_pos_time = plot_seq_pos(dt = subset(dt_pred_seq_pos_tr, classification == "ovr"))
  1287. fig_seq_pos_time
  1288. ```
  1289. ```{r, echo = FALSE}
  1290. plot_seq_pos_facet <- function(dt){
  1291. # create separate datatable to plot rectangles indicating forward / backward period:
  1292. dt_reduced = dt %>% setDT(.) %>%
  1293. .[, by = .(classification, tITI, period), .(
  1294. xmin = min(seq_tr) - 0.5,
  1295. xmax = max(seq_tr) + 0.5
  1296. )] %>%
  1297. filter(period != "excluded") %>%
  1298. mutate(fill = ifelse(period == "forward", "dodgerblue", "red"))
  1299. ggplot(data = dt, mapping = aes(
  1300. x = as.factor(seq_tr), y = as.numeric(mean_position),
  1301. group = as.factor(as.numeric(tITI)*1000), fill = as.factor(as.numeric(tITI)*1000))) +
  1302. geom_rect(data = dt_reduced, aes(xmin = xmin, xmax = xmax, ymin = 2, ymax = 4),
  1303. alpha = 0.05, inherit.aes = FALSE, show.legend = FALSE, fill = dt_reduced$fill) +
  1304. geom_hline(aes(yintercept = 3), linetype = "solid", color = "gray") +
  1305. facet_wrap(facets = ~ as.factor(tITI), labeller = get_labeller(dt$tITI), nrow = 1) +
  1306. geom_ribbon(aes(ymin = sem_lower, ymax = sem_upper), alpha = 0.5, color = NA) +
  1307. geom_line(mapping = aes(color = as.factor(as.numeric(tITI)*1000))) +
  1308. geom_point(data = subset(dt, pvalue_adjust < 0.05), pch = 21, fill = "red",
  1309. color = "black", show.legend = FALSE) +
  1310. xlab("Time from sequence onset (TRs)") +
  1311. ylab("Event position") +
  1312. scale_colour_viridis(discrete = TRUE, option = "cividis", name = "Speed (ms)", guide = FALSE) +
  1313. scale_fill_viridis(discrete = TRUE, option = "cividis", name = "Speed (ms)", guide = FALSE) +
  1314. scale_x_discrete(labels = label_fill(seq(1, 13, 1), mod = 4), breaks = seq(1, 13, 1)) +
  1315. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(2,4)) +
  1316. theme(strip.text.x = element_text(margin = margin(b = 2, t = 2))) +
  1317. theme(legend.position = "top", legend.direction = "horizontal",
  1318. legend.justification = "center", legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
  1319. legend.box.margin = margin(t = 0, r = 0, b = 0, l = 0)) +
  1320. theme(axis.line = element_line(colour = "black"),
  1321. panel.grid.major = element_blank(),
  1322. panel.grid.minor = element_blank(),
  1323. panel.border = element_blank(),
  1324. panel.background = element_blank())
  1325. }
  1326. fig_seq_pos_time_facet = plot_seq_pos_facet(dt = subset(dt_pred_seq_pos_tr, classification == "ovr"))
  1327. fig_seq_pos_time_facet
  1328. ```
  1329. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  1330. ggsave(filename = "highspeed_plot_decoding_sequence_timecourse_position.pdf",
  1331. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1332. dpi = "retina", width = 6, height = 3)
  1333. ```
  1334. ### Transititons
  1335. We calculate the step size between consecutively decoded (highest probability) events:
  1336. ```{r}
  1337. dt_pred_seq_step = dt_pred_seq %>%
  1338. # get the position with the highest probability for every TR:
  1339. .[, by = .(classification, id, tITI, trial_tITI, seq_tr), ":=" (
  1340. num_classes = .N,
  1341. rank_order = rank(-probability),
  1342. max_prob = as.numeric(probability == max(probability))
  1343. )] %>%
  1344. # verify that there are five classes per TR:
  1345. verify(all(num_classes == 5)) %>%
  1346. # sort the data table:
  1347. setorder(., classification, id, tITI, trial_tITI, seq_tr) %>%
  1348. # select only classes with the highest probability for every TR:
  1349. filter(max_prob == 1) %>%
  1350. setDT(.) %>%
  1351. # check if the rank order of the event with highest probability match:
  1352. verify(all(rank_order == max_prob)) %>%
  1353. # group by classification, id, speed and trial and calculate step sizes:
  1354. .[, by = .(classification, id, tITI, trial_tITI),
  1355. step := position - shift(position)]
  1356. ```
  1357. We calculate the mean step size for early and late period in the forward and backward phase:
  1358. ```{r}
  1359. dt_pred_seq_step_mean = dt_pred_seq_step %>%
  1360. filter(period != "excluded") %>%
  1361. filter(!(is.na(zone))) %>% setDT(.) %>%
  1362. # shorten the period name:
  1363. mutate(period_short = ifelse(period == "forward", "fwd", period)) %>%
  1364. transform(period_short = ifelse(period == "backward", "bwd", period_short)) %>%
  1365. setDT(.) %>%
  1366. .[, by = .(classification, id, tITI, period_short, zone), .(
  1367. mean_step = mean(step, na.rm = TRUE))]
  1368. ```
  1369. We compare the forward and the backward period using t-tests:
  1370. ```{r}
  1371. dt_pred_seq_step_stat = dt_pred_seq_step_mean %>%
  1372. spread(key = period_short, value = mean_step, drop = TRUE) %>%
  1373. mutate(difference = fwd - bwd) %>% setDT(.) %>%
  1374. # average across participants for each speed condition and volume:
  1375. .[, by = .(classification, tITI, zone), {
  1376. ttest_results = t.test(fwd, bwd, alternative = "two.sided", paired = TRUE)
  1377. list(
  1378. num_subs = .N,
  1379. tvalue = round(ttest_results$statistic, 2),
  1380. pvalue = ttest_results$p.value,
  1381. df = ttest_results$parameter,
  1382. cohens_d = abs(round((mean(fwd) - mean(bwd)) / sd(fwd - bwd), 2)),
  1383. mean_step = mean(difference),
  1384. sd_step = sd(difference),
  1385. sem_upper = mean(difference) + (sd(difference)/sqrt(.N)),
  1386. sem_lower = mean(difference) - (sd(difference)/sqrt(.N))
  1387. )
  1388. }] %>% verify(all(num_subs == 36)) %>%
  1389. # adjust p-values for multiple comparisons:
  1390. .[, by = .(classification), ":=" (
  1391. num_comp = .N,
  1392. pvalue_adjust = p.adjust(pvalue, method = "fdr", n = .N)
  1393. )] %>%
  1394. verify(all(num_comp == 10)) %>%
  1395. # add variable that indicates significance with stupid significance stars:
  1396. mutate(significance = ifelse(pvalue < 0.05, "*", "")) %>%
  1397. # round the original p-values:
  1398. mutate(pvalue_round = round_pvalues(pvalue)) %>%
  1399. # round the p-values adjusted for multiple comparisons:
  1400. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust)) %>%
  1401. # sort the datatable for each speed and TR:
  1402. setorder(., classification, zone, tITI)
  1403. dt_pred_seq_step_stat %>%
  1404. filter(classification == "ovr", pvalue_adjust < 0.05)
  1405. ```
  1406. We compare each period to the baseline:
  1407. ```{r}
  1408. dt_pred_seq_step_stat_baseline = dt_pred_seq_step_mean %>%
  1409. # average across participants for each speed condition and volume:
  1410. .[, by = .(classification, tITI, period_short, zone), {
  1411. ttest_results = t.test(mean_step, mu = 0, alternative = "two.sided")
  1412. list(
  1413. num_subs = .N,
  1414. tvalue = round(ttest_results$statistic, 2),
  1415. pvalue = ttest_results$p.value,
  1416. df = ttest_results$parameter,
  1417. cohens_d = abs(round((mean(mean_step) - 0) / sd(mean_step), 2)),
  1418. mean_step = mean(mean_step),
  1419. sd_step = sd(mean_step),
  1420. sem_upper = mean(mean_step) + (sd(mean_step)/sqrt(.N)),
  1421. sem_lower = mean(mean_step) - (sd(mean_step)/sqrt(.N))
  1422. )
  1423. }] %>% verify(all(num_subs == 36)) %>%
  1424. # adjust p-values for multiple comparisons:
  1425. .[, by = .(classification), ":=" (
  1426. num_comp = .N,
  1427. pvalue_adjust = p.adjust(pvalue, method = "fdr", n = .N)
  1428. )] %>%
  1429. # verf
  1430. verify(all(num_comp == 20)) %>%
  1431. # add variable that indicates significance with stupid significance stars:
  1432. mutate(significance = ifelse(pvalue_adjust < 0.05, "*", "")) %>%
  1433. # round the original p-values:
  1434. mutate(pvalue_round = round_pvalues(pvalue)) %>%
  1435. # round the p-values adjusted for multiple comparisons:
  1436. mutate(pvalue_adjust_round = round_pvalues(pvalue_adjust)) %>%
  1437. # sort the datatable for each speed and TR:
  1438. setorder(., classification, period_short, zone, tITI)
  1439. dt_pred_seq_step_stat_baseline %>%
  1440. filter(classification == "ovr", pvalue < 0.05)
  1441. ```
  1442. ```{r}
  1443. # plot average correlation or betas for each speed condition and time period:
  1444. fig_seq_step = ggplot(data = subset(dt_pred_seq_step_mean, classification == "ovr"), aes(
  1445. x = fct_rev(as.factor(period_short)), y = as.numeric(mean_step),
  1446. fill = as.factor(as.numeric(tITI) * 1000)), color = as.factor(as.numeric(tITI) * 1000)) +
  1447. facet_grid(vars(as.factor(zone)), vars(as.factor(as.numeric(tITI) * 1000)), switch = "x") +
  1448. geom_bar(stat = "summary", fun = "mean", width = 0.9) +
  1449. geom_point(position = position_jitterdodge(jitter.height = 0, seed = 4, jitter.width = 0.2),
  1450. pch = 21, alpha = 0.05, color = "black", show.legend = FALSE) +
  1451. geom_errorbar(stat = "summary", fun.data = "mean_se", width = 0.0, color = "black") +
  1452. geom_text(data = subset(dt_pred_seq_step_stat, classification == "ovr"), aes(
  1453. y = 2, label = paste0("d=", sprintf("%.2f", cohens_d), significance), x = 1.5),
  1454. inherit.aes = FALSE, color = "black", size = 3.3) +
  1455. xlab("Period") + ylab("Step size") +
  1456. scale_colour_viridis(discrete = TRUE, option = "cividis", name = "Speed (ms)") +
  1457. scale_fill_viridis(discrete = TRUE, option = "cividis", name = "Speed (ms)") +
  1458. coord_capped_cart(left = "both", bottom = "both", expand = TRUE, ylim = c(-2, 2)) +
  1459. theme(legend.position = "top", legend.direction = "horizontal",
  1460. legend.justification = "center", legend.margin = margin(t = 0, r = 0, b = -5, l = 0),
  1461. legend.box.margin = margin(t = 0, r = 0, b = 0, l = 0)) +
  1462. theme(panel.spacing.x = unit(0, "lines"), strip.background.x = element_blank(),
  1463. strip.placement.x = "outside", strip.text.x = element_blank()) +
  1464. theme(axis.ticks.x = element_line(colour = "white"),
  1465. axis.line.x = element_line(colour = "white")) +
  1466. #theme(axis.title.x = element_blank()) +
  1467. theme(strip.text = element_text(margin = margin(b = 2, t = 2, r = 2, l = 2))) +
  1468. theme(axis.line.y = element_line(colour = "black"),
  1469. panel.grid.major = element_blank(),
  1470. panel.grid.minor = element_blank(),
  1471. panel.border = element_blank(),
  1472. panel.background = element_blank())
  1473. fig_seq_step
  1474. ```
  1475. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  1476. ggsave(filename = "highspeed_plot_decoding_sequence_step_size.pdf",
  1477. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1478. dpi = "retina", width = 5, height = 3)
  1479. ```
  1480. ```{r, fig.width = 10, fig.height = 4}
  1481. plot_grid(fig_seq_pos_period, fig_seq_step, labels = "auto",
  1482. ncol = 2, label_fontface = "bold", rel_widths = c(5, 6))
  1483. ```
  1484. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  1485. ggsave(filename = "highspeed_plot_decoding_sequence_between_tr.pdf",
  1486. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1487. dpi = "retina", width = 10, height = 4)
  1488. ```
  1489. Plot Figure 3 in the main text:
  1490. ```{r}
  1491. plot_grid(
  1492. plot_grid(fig_seq_probas, labels = c("a"), nrow = 1),
  1493. plot_grid(fig_seq_slope_time, fig_seq_slope_period, labels = c("b", "c"),
  1494. ncol = 2, nrow = 1, label_fontface = "bold", rel_widths = c(4.9, 5)),
  1495. plot_grid(fig_seq_cor_between, fig_seq_cor_within, fig_seq_pos_time,
  1496. labels = c("d", "e", "f"), ncol = 3, rel_widths = c(0.325, 0.325, 0.35)),
  1497. plot_grid(fig_seq_pos_period, fig_seq_step, labels = c("g", "h"),
  1498. ncol = 2, label_fontface = "bold", nrow = 1),
  1499. nrow = 4, label_fontface = "bold", rel_heights = c(2, 3)
  1500. )
  1501. ```
  1502. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  1503. ggsave(filename = "highspeed_plot_decoding_sequence_data.pdf",
  1504. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1505. dpi = "retina", width = 10, height = 12)
  1506. ggsave(filename = "wittkuhn_schuck_figure_3.pdf",
  1507. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1508. dpi = "retina", width = 10, height = 12)
  1509. ```
  1510. ```{r, include=FALSE, echo=TRUE, eval=FALSE, warning=FALSE, message=FALSE}
  1511. title_nomax = ggdraw() + draw_label("Sequence item with highest probability removed", fontface = "plain")
  1512. title_nofirst = ggdraw() + draw_label("First sequence item removed", fontface = "plain")
  1513. title_nolast = ggdraw() + draw_label("Last sequence item removed", fontface = "plain")
  1514. # create a common legend used for the entire figure panel:
  1515. common_legend <- get_legend(fig_seq_slope_time + theme(legend.position = "top"))
  1516. # create the plot of sequence data with the maximum probability removed:
  1517. plot_nomax = plot_grid(fig_seq_slope_time + theme(legend.position = "none"),
  1518. fig_seq_slope_period + theme(legend.position = "none"),
  1519. rel_widths = c(4, 5), labels = "auto", ncol = 2, nrow = 1,
  1520. label_fontface = "bold")
  1521. plot_nofirst = plot_grid(fig_seq_slope_time + theme(legend.position = "none"),
  1522. fig_seq_slope_period + theme(legend.position = "none"),
  1523. rel_widths = c(4, 5), labels = c("c", "d"), ncol = 2, nrow = 1,
  1524. label_fontface = "bold")
  1525. plot_nolast = plot_grid(fig_seq_slope_time + theme(legend.position = "none"),
  1526. fig_seq_slope_period + theme(legend.position = "none"),
  1527. rel_widths = c(4, 5), labels = c("e", "f"), ncol = 2, nrow = 1,
  1528. label_fontface = "bold")
  1529. plot_all = plot_grid(
  1530. common_legend, title_nomax, plot_nomax,
  1531. title_nofirst, plot_nofirst,
  1532. title_nolast, plot_nolast,
  1533. ncol = 1, rel_heights=c(0.1, 0.1, 1, 0.1, 1, 0.1, 1))
  1534. plot_all
  1535. ```
  1536. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  1537. ggsave(filename = "highspeed_plot_decoding_sequence_slope_remove_items.pdf",
  1538. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1539. dpi = "retina", width = 10, height = 10)
  1540. ggsave(filename = "wittkuhn_schuck_figure_s7.pdf",
  1541. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1542. dpi = "retina", width = 10, height = 10)
  1543. ```
  1544. ```{r}
  1545. plot_grid(fig_seq_cor_time, fig_seq_cor_period, fig_seq_step_time, fig_seq_step_period,
  1546. labels = "auto", ncol = 2, nrow = 2, label_fontface = "bold")
  1547. ```
  1548. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  1549. ggsave(filename = "highspeed_plot_decoding_sequence_correlation_step.pdf",
  1550. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1551. dpi = "retina", width = 10, height = 7)
  1552. ggsave(filename = "wittkuhn_schuck_figure_s5.pdf",
  1553. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1554. dpi = "retina", width = 10, height = 7)
  1555. ```
  1556. ```{r}
  1557. seq_test_time(data = dt_pred_seq_cor, variable = "mean_slope") %>%
  1558. filter(pvalue_adjust < 0.05 & classification == "ovr") %>%
  1559. rmarkdown::paged_table(.)
  1560. seq_test_time(data = dt_pred_seq_cor, variable = "mean_cor") %>%
  1561. filter(pvalue_adjust < 0.05 & classification == "ovr") %>%
  1562. rmarkdown::paged_table(.)
  1563. seq_test_time(data = dt_pred_seq_cor, variable = "mean_step") %>%
  1564. filter(pvalue_adjust < 0.05 & classification == "ovr") %>%
  1565. rmarkdown::paged_table(.)
  1566. ```
  1567. ```{r}
  1568. fig_seq_slope_time_facet = plot_seq_cor_facet(dt = subset(
  1569. seq_test_time(data = dt_pred_seq_cor, variable = "mean_slope"),
  1570. classification == "ovr"), variable = "mean_slope")
  1571. fig_seq_cor_time_facet = plot_seq_cor_facet(dt = subset(
  1572. seq_test_time(data = dt_pred_seq_cor, variable = "mean_cor"),
  1573. classification == "ovr"), variable = "mean_cor")
  1574. fig_seq_step_time_facet = plot_seq_cor_facet(dt = subset(
  1575. seq_test_time(data = dt_pred_seq_cor, variable = "mean_step"),
  1576. classification == "ovr"), variable = "mean_step")
  1577. remove_xaxis = theme(axis.title.x = element_blank())
  1578. remove_facets = theme(strip.background = element_blank(), strip.text.x = element_blank())
  1579. plot_grid(fig_seq_slope_time_facet + remove_xaxis,
  1580. fig_seq_pos_time_facet + remove_xaxis + theme(legend.position = "none") + remove_facets,
  1581. fig_seq_cor_time_facet + remove_xaxis + theme(legend.position = "none") + remove_facets,
  1582. fig_seq_step_time_facet + theme(legend.position = "none") + remove_facets,
  1583. labels = "auto", ncol = 1, label_fontface = "bold")
  1584. ```
  1585. ```{r, echo=FALSE, eval=FALSE, include=FALSE}
  1586. ggsave(filename = "highspeed_plot_decoding_sequence_timecourse_slope_correlation_step.pdf",
  1587. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1588. dpi = "retina", width = 7, height = 9)
  1589. ggsave(filename = "wittkuhn_schuck_figure_s6.pdf",
  1590. plot = last_plot(), device = cairo_pdf, path = path_figures, scale = 1,
  1591. dpi = "retina", width = 7, height = 9)
  1592. ```