ERPs Pain Empathy 2024, MoBI device, version 2

Recordings with EMOTIV EPOC Flex Gel, 32 channels

Author

Álvaro Rivera-Rei

Published

2025-04-23, Wednesday

Code
cat('\014')     # clean terminal
Code
rm(list = ls()) # clean workspace
library(tidyverse)
library(afex)
library(emmeans)
library(GGally)
library(GGally)
library(easystats)
Code
my_dodge  <- .3
my_jitter <- .2

theme_set(theme_minimal())

a_posteriori_aov_ez <- function(aov_ez_obj, sig_level = .05) {
  factors  <- as.list(rownames(aov_ez_obj$anova_table))
  for (j in 1:length(factors)) {
    if (grepl(':', factors[[j]])) {
      factors[[j]] <- unlist(strsplit(factors[[j]], ':'))
    }
  }
  p_values <- aov_ez_obj$anova_table$`Pr(>F)`
  for (i in 1:length(p_values)) {
    if (p_values[i] <= sig_level) {
      cat(rep('_', 60), '\n', sep = '')
      print(emmeans(aov_ez_obj, factors[[i]], contr = 'pairwise'))
    }
  }
}

a_posteriori_lmer <- function(lmer_obj, sig_level = .05) {
  anova_lmer <- anova(lmer_obj)
  factors  <- as.list(row.names(anova_lmer))
  for (j in 1:length(factors)) {
    if (grepl(':', factors[[j]])) {
      factors[[j]] <- unlist(strsplit(factors[[j]], ':'))
    }
  }
  p_values <- anova_lmer$`Pr(>F)`
  for (i in 1:length(p_values)) {
    if (p_values[i] <= sig_level) {
      cat(rep('_', 60), '\n', sep = '')
      print(emmeans(lmer_obj, factors[[i]], contr = 'pairwise'))
    }
  }
}

a_posteriori_glmer <- function(glmer_obj, sig_level = .05) {
  anova_glmer <- car::Anova(glmer_obj)
  factors  <- as.list(row.names(anova_glmer))
  for (j in 1:length(factors)) {
    if (grepl(':', factors[[j]])) {
      factors[[j]] <- unlist(strsplit(factors[[j]], ':'))
    }
  }
  p_values <- anova_glmer$`Pr(>Chisq)`
  print(anova_glmer)
  for (i in 1:length(p_values)) {
    if (p_values[i] <= sig_level) {
      cat(rep('_', 60), '\n', sep = '')
      print(emmeans(glmer_obj, factors[[i]], contr = 'pairwise'))
    }
  }
}

xclude <- c(15, 22, 24, 36, 44)
Code
csv_answers <- list.files(path = '../csv', pattern = 'pev2_', full.names = TRUE)
answers_df  <- vroom::vroom(csv_answers, col_types = c(Sex = 'c'), show_col_types = FALSE) |> 
  filter(Block > 0) |> 
  mutate(Block = factor(Block)) |> 
  filter(!is.na(Question)) |> 
  mutate(file_info = str_extract(Subject, '.+?(?=_202)')) |>
  mutate(Sex = if_else(Sex == 'f', 'female', 'male')) |> 
  separate(file_info, c('Version', 'ID', 'Group', 'City'), sep = '_', remove = FALSE) |> 
  mutate(Version  = tolower(Version),
         Group    = tolower(Group),
         Group    = str_replace(Group, 'suv', 'vul'),
         Group    = if_else(Group == 'vul', 'vulnerable', 'control'),
         Group    = fct_relevel(Group, 'vulnerable'),
         num_id   = parse_number(ID),
         Question = recode(Question, 'unpleasantness' = 'displeasing', 'pain' = 'painful'),
         Stimulus = case_match(Valence, 'EASE' ~ 'no_pain', 'PAIN' ~ 'pain'),
         City     = case_match(City, 's' ~ 'stgo', 'v' ~ 'viña')) |> 
  mutate_if(is.character, as.factor) |> 
  relocate(Subject, .after = last_col()) |> 
  filter(!(num_id %in% xclude))
write.csv(answers_df,  'data/painEmpathy_2023_answers_clean_version_2.csv',  row.names = FALSE)

erp_averages     <- list.files(path = './data/ave_volt_2_versions', pattern = 'pev2_', full.names = TRUE)
painEmpathy_data <- vroom::vroom(erp_averages, show_col_types = FALSE) |> 
  separate(ERPset, c('Version', 'ID', 'Group', 'City'), sep = '_', remove = FALSE) |> 
  rename(Component = mlabel,
         Amplitude = value,
         Stimulus  = binlabel,
         Electrode = chlabel) |> 
  mutate(Group    = if_else(Group == 'vul', 'vulnerable', 'control'),
         Group    = fct_relevel(Group, 'vulnerable'),
         City     = case_match(City, 's' ~ 'stgo', 'v' ~ 'viña'),
         worklat = gsub('.0', '', worklat, fixed = TRUE),
         num_id  = parse_number(ID),
         chindex = factor(chindex),
         bini    = factor(bini)) |> 
  left_join(unique(answers_df[c('num_id', 'Sex')]), by = 'num_id') |>
  mutate_if(is.character, as.factor) |> 
  mutate(Component = factor(Component, levels = c('N1', 'N2', 'P1', 'P3', 'LPP', 'P3a', 'P3b')),
         Electrode = factor(Electrode, levels = c('FC1', 'Fz', 'FC2',
                                                  'CP1', 'Cz', 'CP2',
                                                  'O1' , 'Oz', 'O2')),
         Lateral   = case_match(Electrode,
                                c('FC1', 'CP1', 'O1') ~ 'left',
                                c('Fz' , 'Cz' , 'Oz') ~ 'center',
                                c('FC2', 'CP2', 'O2') ~ 'right')) |> 
  filter(!(num_id %in% xclude))
write.csv(painEmpathy_data,  file.path('data/painEmpathy_2024_erp_clean_version_2.csv'),  row.names = FALSE)

connectivity_file <- 'data/median_connectivity_2_versions.csv'
label_a <- 'occipital'
label_b <- 'parietal'
connectivity_data <- read_csv(connectivity_file, show_col_types = FALSE) |> 
  separate(ERPset, c('ID', 'Group', 'City'), sep = '_', remove = FALSE) |> 
  mutate(Group    = if_else(Group == 'vul', 'vulnerable', 'control'),
         Group    = fct_relevel(Group, 'vulnerable'),
         Version  = str_sub(image, -2, -1),
         Stimulus = str_sub(image, 1, -4),
         Stimulus = fct_relevel(Stimulus, 'pain'),
         City     = case_match(City, 's' ~ 'stgo', 'v' ~ 'viña'),log_median_connectivity = log(median_connectivity),
         num_id   = parse_number(ID),
         region_b = fct_relevel(region_b, paste0(label_b, '_ipsi'))
         ) |> 
  filter(Version == 'v1') |> 
  left_join(unique(answers_df[c('num_id', 'Sex')]), by = 'num_id') |>
  mutate_if(is.character, as.factor) |> 
  filter(!(num_id %in% xclude))
write_csv(connectivity_data, 'data/painEmpathy_2024_connectivity_clean_version_2.csv')

n1_data  <- subset(painEmpathy_data, Component == 'N1',)
n2_data  <- subset(painEmpathy_data, Component == 'N2',)
p1_data  <- subset(painEmpathy_data, Component == 'P1',)
p3_data  <- subset(painEmpathy_data, Component == 'P3',)
lpp_data <- subset(painEmpathy_data, Component == 'LPP',)
p3a_data <- subset(painEmpathy_data, Component == 'P3a',)
p3b_data <- subset(painEmpathy_data, Component == 'P3b',)
component_data_wide_stimulus <- painEmpathy_data[c('num_id', 'Stimulus', 'Lateral', 'Component', 'Amplitude')] |>
  mutate(Stimulus = fct_relevel(Stimulus, 'pain')) |> 
  pivot_wider(names_from = Component, values_from = Amplitude)

Answers

Code
addmargins(xtabs(~ Sex + Group, data = unique(answers_df[c('num_id', 'Sex', 'Group')])))
        Group
Sex      vulnerable control Sum
  female         25      25  50
  male           25      25  50
  Sum            50      50 100
Code
cat(rep('_', 60), '\n', sep = '')
____________________________________________________________
Code
addmargins(xtabs(~ Sex + Group + City, data = unique(answers_df[c('num_id', 'Sex', 'Group', 'City')])), c(1, 2))
, , City = stgo

        Group
Sex      vulnerable control Sum
  female         25      18  43
  male           24      20  44
  Sum            49      38  87

, , City = viña

        Group
Sex      vulnerable control Sum
  female          0       7   7
  male            1       5   6
  Sum             1      12  13
Code
summary(answers_df)
     Sex       Block        trialN           Image      Valence    
 female:2557   1:2639   Min.   : 1.00   54.1.jpg:  48   EASE:2533  
 male  :2556   2:2474   1st Qu.:16.00   9.1.jpg :  48   PAIN:2580  
                        Median :33.00   2.2.jpg :  47              
                        Mean   :32.55   43.2.jpg:  47              
                        3rd Qu.:49.00   1.2.jpg :  46              
                        Max.   :64.00   11.1.jpg:  46              
                                        (Other) :4831              
     Answer             Question          rT           Session 
 Min.   : 1.00   displeasing:2554   Min.   :    2   Min.   :1  
 1st Qu.:14.00   painful    :2559   1st Qu.: 3157   1st Qu.:1  
 Median :49.00                      Median : 4029   Median :1  
 Mean   :44.56                      Mean   : 4468   Mean   :1  
 3rd Qu.:72.00                      3rd Qu.: 5145   3rd Qu.:1  
 Max.   :97.00                      Max.   :68437   Max.   :1  
                                                               
           file_info    Version           ID              Group     
 pev2_s006_vul_s:  61   pev2:5113   s006   :  61   vulnerable:2556  
 pev2_s040_vul_s:  61               s040   :  61   control   :2557  
 pev2_s126_ctl_s:  61               s126   :  61                    
 pev2_s134_ctl_s:  61               s134   :  61                    
 pev2_s037_vul_s:  60               s037   :  60                    
 pev2_s132_ctl_s:  60               s132   :  60                    
 (Other)        :4749               (Other):4749                    
   City          num_id          Stimulus   
 stgo:4476   Min.   :  1.00   no_pain:2533  
 viña: 637   1st Qu.: 29.00   pain   :2580  
             Median :100.00                 
             Mean   : 76.72                 
             3rd Qu.:126.00                 
             Max.   :150.00                 
                                            
                                Subject    
 pev2_s006_vul_s_2024-10-25_18-31-33:  61  
 pev2_s040_vul_s_2024-11-29_14-50-53:  61  
 pev2_s126_ctl_s_2025-01-17_21-06-11:  61  
 pev2_s134_ctl_s_2025-01-22_15-26-40:  61  
 pev2_s037_vul_s_2024-11-26_17-18-05:  60  
 pev2_s132_ctl_s_2025-01-22_14-03-54:  60  
 (Other)                            :4749  

Pain rating:

Code
pain_rating_lmer <- lmer(Answer ~ Group*Sex*Stimulus + (Stimulus|num_id) + (1|Image), subset(answers_df, Question == 'painful'))
afex_plot(
  pain_rating_lmer,
  x     = 'Stimulus',
  trace = 'Group',
  panel = 'Sex',
  id    = 'num_id',
  error_arg = list(width = .15),
  dodge     = my_dodge,
  data_arg  = list(
    position = 
      position_jitterdodge(
        jitter.width  = my_jitter, 
        jitter.height = 0, 
        dodge.width   = my_dodge  ## needs to be same as dodge
      )),
  mapping   = c('color'),
  point_arg = list(size = 4)
)
pain_rating_lmer@call
lmer(formula = Answer ~ Group * Sex * Stimulus + (Stimulus | 
    num_id) + (1 | Image), data = subset(answers_df, Question == 
    "painful"))
Figure 1: Pain rating by Group, Version & Stimulus
Code
anova(pain_rating_lmer)
Type III Analysis of Variance Table with Satterthwaite's method
                   Sum Sq Mean Sq NumDF   DenDF  F value    Pr(>F)    
Group                 800     800     1  95.109   2.8567  0.094271 .  
Sex                   186     186     1  95.184   0.6645  0.417028    
Stimulus           104025  104025     1 147.650 371.5779 < 2.2e-16 ***
Group:Sex               1       1     1  94.920   0.0033  0.954238    
Group:Stimulus       3185    3185     1  95.237  11.3760  0.001077 ** 
Sex:Stimulus           55      55     1  95.289   0.1954  0.659433    
Group:Sex:Stimulus     78      78     1  95.133   0.2777  0.599425    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
interpret(omega_squared(pain_rating_lmer, alternative = 'two.sided'), rules = 'field2013')
# Effect Size for ANOVA (Type III)

Parameter          | Omega2 (partial) |       95% CI | Interpretation
---------------------------------------------------------------------
Group              |             0.02 | [0.00, 0.10] |          small
Sex                |             0.00 | [0.00, 0.00] |     very small
Stimulus           |             0.71 | [0.64, 0.77] |          large
Group:Sex          |             0.00 | [0.00, 0.00] |     very small
Group:Stimulus     |             0.10 | [0.01, 0.22] |         medium
Sex:Stimulus       |             0.00 | [0.00, 0.00] |     very small
Group:Sex:Stimulus |             0.00 | [0.00, 0.00] |     very small

- Interpretation rule: field2013
Code
a_posteriori_lmer(pain_rating_lmer)
____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Stimulus emmean   SE  df lower.CL upper.CL
 no_pain    23.3 1.76 149     19.8     26.7
 pain       71.1 1.45 168     68.2     73.9

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast       estimate   SE  df t.ratio p.value
 no_pain - pain    -47.8 2.48 149 -19.276  <.0001

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 

____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Group      Stimulus emmean   SE  df lower.CL upper.CL
 vulnerable no_pain    28.3 2.33 125     23.7     32.9
 control    no_pain    18.2 2.33 126     13.6     22.9
 vulnerable pain       68.8 1.86 144     65.2     72.5
 control    pain       73.3 1.86 142     69.6     77.0

Results are averaged over the levels of: Sex 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast                             estimate   SE    df t.ratio p.value
 vulnerable no_pain - control no_pain    10.06 3.06  95.8   3.291  0.0075
 vulnerable no_pain - vulnerable pain   -40.53 3.28 125.9 -12.347  <.0001
 vulnerable no_pain - control pain      -44.99 2.98 223.7 -15.096  <.0001
 control no_pain - vulnerable pain      -50.59 2.99 225.6 -16.943  <.0001
 control no_pain - control pain         -55.05 3.28 125.7 -16.772  <.0001
 vulnerable pain - control pain          -4.45 2.33  95.8  -1.913  0.2295

Results are averaged over the levels of: Sex 
Degrees-of-freedom method: kenward-roger 
P value adjustment: tukey method for comparing a family of 4 estimates 

Unpleasantness rating:

Code
unpleasantness_rating_lmer <- lmer(Answer ~ Group*Sex*Stimulus + (Stimulus|num_id) + (1|Image), subset(answers_df, Question == 'displeasing'))
afex_plot(
  unpleasantness_rating_lmer,
  x     = 'Stimulus',
  trace = 'Group',
  panel = 'Sex',
  id    = 'num_id',
  error_arg = list(width = .15),
  dodge     = my_dodge,
  data_arg  = list(
    position = 
      position_jitterdodge(
        jitter.width  = my_jitter, 
        jitter.height = 0, 
        dodge.width   = my_dodge  ## needs to be same as dodge
      )),
  mapping   = c('color'),
  point_arg = list(size = 4)
)
unpleasantness_rating_lmer@call
lmer(formula = Answer ~ Group * Sex * Stimulus + (Stimulus | 
    num_id) + (1 | Image), data = subset(answers_df, Question == 
    "displeasing"))
Figure 2: Unpleasantness rating by Group, Version & Stimulus
Code
options(width = 120)
anova(unpleasantness_rating_lmer)
Type III Analysis of Variance Table with Satterthwaite's method
                   Sum Sq Mean Sq NumDF   DenDF  F value    Pr(>F)    
Group                  13      13     1  96.032   0.0459  0.830723    
Sex                   292     292     1  95.926   1.0236  0.314210    
Stimulus            81912   81912     1 141.645 286.6576 < 2.2e-16 ***
Group:Sex               7       7     1  95.958   0.0234  0.878846    
Group:Stimulus       2700    2700     1  95.990   9.4498  0.002749 ** 
Sex:Stimulus          582     582     1  95.788   2.0382  0.156645    
Group:Sex:Stimulus    320     320     1  95.855   1.1212  0.292332    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
interpret(omega_squared(unpleasantness_rating_lmer, alternative = 'two.sided'), rules = 'field2013')
# Effect Size for ANOVA (Type III)

Parameter          | Omega2 (partial) |       95% CI | Interpretation
---------------------------------------------------------------------
Group              |             0.00 | [0.00, 0.00] |     very small
Sex                |         2.41e-04 | [0.00, 0.03] |     very small
Stimulus           |             0.67 | [0.58, 0.73] |          large
Group:Sex          |             0.00 | [0.00, 0.00] |     very small
Group:Stimulus     |             0.08 | [0.01, 0.20] |         medium
Sex:Stimulus       |             0.01 | [0.00, 0.08] |          small
Group:Sex:Stimulus |         1.24e-03 | [0.00, 0.05] |     very small

- Interpretation rule: field2013
Code
a_posteriori_lmer(unpleasantness_rating_lmer)
____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Stimulus emmean   SE  df lower.CL upper.CL
 no_pain    22.6 1.65 137     19.3     25.8
 pain       60.0 1.98 125     56.0     63.9

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast       estimate   SE  df t.ratio p.value
 no_pain - pain    -37.4 2.21 142 -16.930  <.0001

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 

____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Group      Stimulus emmean   SE  df lower.CL upper.CL
 vulnerable no_pain    25.9 2.21 118     21.5     30.2
 control    no_pain    19.3 2.22 119     14.9     23.7
 vulnerable pain       57.3 2.70 111     51.9     62.6
 control    pain       62.7 2.71 111     57.3     68.0

Results are averaged over the levels of: Sex 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast                             estimate   SE    df t.ratio p.value
 vulnerable no_pain - control no_pain     6.56 2.95  96.1   2.221  0.1248
 vulnerable no_pain - vulnerable pain   -31.40 2.94 121.5 -10.687  <.0001
 vulnerable no_pain - control pain      -36.79 3.50 196.2 -10.526  <.0001
 control no_pain - vulnerable pain      -37.95 3.50 196.5 -10.855  <.0001
 control no_pain - control pain         -43.34 2.94 122.5 -14.721  <.0001
 vulnerable pain - control pain          -5.39 3.68  95.9  -1.466  0.4622

Results are averaged over the levels of: Sex 
Degrees-of-freedom method: kenward-roger 
P value adjustment: tukey method for comparing a family of 4 estimates 

ERP plots

EDF files were pre-processed in Matlab using the EEGLAB 2023.1 toolbox (Delorme and Makeig 2004), the ERPLAB 10.0 toolbox (Lopez-Calderon and Luck 2014), and automated with in-house scripts. EEG data was high-pass filtered at 0.1 Hz with a 12 dB/oct roll-off. A working time window was selected from 2 seconds before the first Stimulus to 2 seconds after the last one. Defective channels were identified by eye inspection and omitted from the preprocessing steps. Artifacts originating from eye blinks or movements, heart beats, muscle contraction, channel noise, or electrical interference were identified and removed by means of independent Component analysis (ICA) and using the ICLabel 1.4 classifier (Pion-Tonachini, Kreutz-Delgado, and Makeig 2019), Components with an score between 0.8 and 1 in the aforementioned artifactual categories were removed. At this point defective channels were spherically interpolated. Data was re-referenced to infinity with the REST 1.2 toolbox (Dong et al. 2017), low-pass filtered at 35 Hz with a 12 dB/oct roll-off, cut in [-200ms 1000ms] epochs around stimuli, and baseline-corrected relative to the mean voltage in the pre-Stimulus time.

Topographic layout:

(a) Control V2
(b) Vulnerable V2
Figure 3: Topographic Maps

ERPs General description

Code
options(width = 90)
ggplot(
  painEmpathy_data, aes(x = Amplitude, fill = Component, color = Component)) +
  geom_histogram(alpha = .4) +
  facet_wrap(~Component, ncol = 1) +
  theme(strip.text.x = element_blank())
addmargins(xtabs(~ Sex + Group, data = unique(painEmpathy_data[c('num_id', 'Sex', 'Group')])))
        Group
Sex      vulnerable control Sum
  female         25      25  50
  male           24      25  49
  Sum            49      50  99
Code
cat(rep('_', 60), '\n', sep = '')
____________________________________________________________
Code
addmargins(xtabs(~ Sex + Group + City, data = unique(painEmpathy_data[c('num_id', 'Sex', 'Group', 'City')])), c(1, 2))
, , City = stgo

        Group
Sex      vulnerable control Sum
  female         25      18  43
  male           24      20  44
  Sum            49      38  87

, , City = viña

        Group
Sex      vulnerable control Sum
  female          0       7   7
  male            0       5   5
  Sum             0      12  12
Code
summary(painEmpathy_data)
       worklat    Component   Amplitude          chindex      Electrode   bini    
 [105  135]:594   N1 :594   Min.   :-9.1139   16     :792   O1     :792   1:2079  
 [125  145]:594   N2 :594   1st Qu.:-0.6199   18     :792   Oz     :792   2:2079  
 [240  300]:594   P1 :594   Median : 1.3245   19     :792   O2     :792           
 [260  300]:594   P3 :594   Mean   : 1.3948   2      :396   FC1    :396           
 [260  360]:594   LPP:594   3rd Qu.: 3.3220   6      :396   Fz     :396           
 [340  390]:594   P3a:594   Max.   :12.3915   29     :396   FC2    :396           
 [550  750]:594   P3b:594                     (Other):594   (Other):594           
    Stimulus                ERPset     Version           ID              Group     
 no_pain:2079   pev2_s001_vul_s:  42   pev2:4158   s001   :  42   vulnerable:2058  
 pain   :2079   pev2_s002_vul_s:  42               s002   :  42   control   :2100  
                pev2_s003_vul_s:  42               s003   :  42                    
                pev2_s004_vul_s:  42               s004   :  42                    
                pev2_s005_vul_s:  42               s005   :  42                    
                pev2_s006_vul_s:  42               s006   :  42                    
                (Other)        :3906               (Other):3906                    
   City          num_id           Sex         Lateral         
 stgo:3654   Min.   :  1.00   female:2100   Length:4158       
 viña: 504   1st Qu.: 28.00   male  :2058   Class :character  
             Median :100.00                 Mode  :character  
             Mean   : 76.87                                   
             3rd Qu.:126.00                                   
             Max.   :150.00                                   
                                                              
Figure 4: N1, N2, P1, P3 & LPP voltage distributions
Code
ggpairs(
  component_data_wide_stimulus,
  aes(colour = Stimulus, alpha = .5, linewidth = NA),
  columns  = c('N1', 'N2', 'P1', 'P3a', 'P3b', 'LPP'),
  lower    = list(continuous = wrap('points', alpha = .4)),
  progress = FALSE)
Figure 5: N1, N2, P1, P3 & LPP scatter plots

In the front: N1 & N2:

(a) Control V2
(b) Vulnerable V2
Figure 6: Frontal ROI

N1, average from [125 145] ms interval

Electrodes FC1, Fz, FC2

Figure 7: N1 measurement window (voltages averaged over sex)
Code
painEmpathy_n1_lmer <- lmer(Amplitude ~ Group*Sex*Stimulus + (Stimulus|num_id) + (1|num_id:Electrode), n1_data)
afex_plot(
  painEmpathy_n1_lmer,
  x     = 'Stimulus',
  trace = 'Group',
  panel = 'Sex',
  id    = 'num_id',
  error_arg = list(width = .25),
  dodge     = my_dodge,
  data_arg  = list(
    position = 
      position_jitterdodge(
        jitter.width  = my_jitter, 
        jitter.height = 0, 
        dodge.width   = my_dodge  ## needs to be same as dodge
      )),
  mapping   = c('color'),
  point_arg = list(size = 3)
)
painEmpathy_n1_lmer@call
lmer(formula = Amplitude ~ Group * Sex * Stimulus + (Stimulus | 
    num_id) + (1 | num_id:Electrode), data = n1_data)
Figure 8: N1 means by Group & Stimulus
Code
options(width = 110)
anova(painEmpathy_n1_lmer)
Type III Analysis of Variance Table with Satterthwaite's method
                    Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
Group              0.05225 0.05225     1    95  0.1362 0.7129
Sex                0.00217 0.00217     1    95  0.0057 0.9402
Stimulus           0.01421 0.01421     1    95  0.0370 0.8478
Group:Sex          0.84661 0.84661     1    95  2.2070 0.1407
Group:Stimulus     0.36135 0.36135     1    95  0.9420 0.3342
Sex:Stimulus       0.96559 0.96559     1    95  2.5172 0.1159
Group:Sex:Stimulus 0.00719 0.00719     1    95  0.0187 0.8914
Code
interpret(omega_squared(painEmpathy_n1_lmer, alternative = 'two.sided'), rules = 'field2013')
# Effect Size for ANOVA (Type III)

Parameter          | Omega2 (partial) |       95% CI | Interpretation
---------------------------------------------------------------------
Group              |             0.00 | [0.00, 0.00] |     very small
Sex                |             0.00 | [0.00, 0.00] |     very small
Stimulus           |             0.00 | [0.00, 0.00] |     very small
Group:Sex          |             0.01 | [0.00, 0.09] |          small
Group:Stimulus     |             0.00 | [0.00, 0.00] |     very small
Sex:Stimulus       |             0.02 | [0.00, 0.10] |          small
Group:Sex:Stimulus |             0.00 | [0.00, 0.00] |     very small

- Interpretation rule: field2013
Code
a_posteriori_lmer(painEmpathy_n1_lmer)

N2, average from [260 300] ms interval

Electrodes FC1, Fz, FC2

Figure 9: N2 measurement window (voltages averaged over sex)
Code
painEmpathy_n2_lmer <- lmer(Amplitude ~ Group*Sex*Stimulus + (Stimulus|num_id) + (1|num_id:Electrode), n2_data)
afex_plot(
  painEmpathy_n2_lmer,
  x     = 'Stimulus',
  trace = 'Group',
  panel = 'Sex',
  id    = 'num_id',
  error_arg = list(width = .25),
  dodge     = my_dodge,
  data_arg  = list(
    position = 
      position_jitterdodge(
        jitter.width  = my_jitter, 
        jitter.height = 0, 
        dodge.width   = my_dodge  ## needs to be same as dodge
      )),
  mapping   = c('color'),
  point_arg = list(size = 3)
)
painEmpathy_n2_lmer@call
lmer(formula = Amplitude ~ Group * Sex * Stimulus + (Stimulus | 
    num_id) + (1 | num_id:Electrode), data = n2_data)
Figure 10: N2 means by Group & Stimulus
Code
options(width = 110)
anova(painEmpathy_n2_lmer)
Type III Analysis of Variance Table with Satterthwaite's method
                    Sum Sq Mean Sq NumDF  DenDF F value  Pr(>F)  
Group              1.98234 1.98234     1 95.002  5.1371 0.02569 *
Sex                0.05990 0.05990     1 95.002  0.1552 0.69448  
Stimulus           0.37304 0.37304     1 95.000  0.9667 0.32800  
Group:Sex          0.38635 0.38635     1 95.002  1.0012 0.31957  
Group:Stimulus     0.20166 0.20166     1 95.000  0.5226 0.47152  
Sex:Stimulus       0.26166 0.26166     1 95.000  0.6781 0.41232  
Group:Sex:Stimulus 0.50816 0.50816     1 95.000  1.3168 0.25404  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
interpret(omega_squared(painEmpathy_n2_lmer, alternative = 'two.sided'), rules = 'field2013')
# Effect Size for ANOVA (Type III)

Parameter          | Omega2 (partial) |       95% CI | Interpretation
---------------------------------------------------------------------
Group              |             0.04 | [0.00, 0.14] |          small
Sex                |             0.00 | [0.00, 0.00] |     very small
Stimulus           |             0.00 | [0.00, 0.00] |     very small
Group:Sex          |         1.22e-05 | [0.00, 0.00] |     very small
Group:Stimulus     |             0.00 | [0.00, 0.00] |     very small
Sex:Stimulus       |             0.00 | [0.00, 0.00] |     very small
Group:Sex:Stimulus |         3.26e-03 | [0.00, 0.06] |     very small

- Interpretation rule: field2013
Code
a_posteriori_lmer(painEmpathy_n2_lmer)
____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Group      emmean    SE df lower.CL upper.CL
 vulnerable  -1.86 0.273 95    -2.40    -1.32
 control     -2.73 0.271 95    -3.27    -2.19

Results are averaged over the levels of: Sex, Stimulus 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast             estimate    SE df t.ratio p.value
 vulnerable - control    0.872 0.385 95   2.267  0.0257

Results are averaged over the levels of: Sex, Stimulus 
Degrees-of-freedom method: kenward-roger 

In the back: P1 & P3:

(a) Control V2
(b) Vulnerable V2
Figure 11: Occipital ROI

P1, average [105 135] ms interval

Electrodes O1, Oz, O2

Figure 12: P1 measurement window (voltages averaged over sex)
Code
painEmpathy_p1_lmer <- lmer(Amplitude ~ Group*Sex*Stimulus + (Stimulus|num_id) + (1|num_id:Electrode), p1_data)
afex_plot(
  painEmpathy_p1_lmer,
  x     = 'Stimulus',
  trace = 'Group',
  panel = 'Sex',
  id    = 'num_id',
  error_arg = list(width = .25),
  dodge     = my_dodge,
  data_arg  = list(
    position = 
      position_jitterdodge(
        jitter.width  = my_jitter, 
        jitter.height = 0, 
        dodge.width   = my_dodge  ## needs to be same as dodge
      )),
  mapping   = c('color'),
  point_arg = list(size = 3)
)
painEmpathy_p1_lmer@call
lmer(formula = Amplitude ~ Group * Sex * Stimulus + (Stimulus | 
    num_id) + (1 | num_id:Electrode), data = p1_data)
Figure 13: P1 means by Group & Stimulus
Code
options(width = 90)
anova(painEmpathy_p1_lmer)
Type III Analysis of Variance Table with Satterthwaite's method
                    Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
Group              0.00280 0.00280     1    95  0.0138 0.9067
Sex                0.16454 0.16454     1    95  0.8111 0.3701
Stimulus           0.54018 0.54018     1    95  2.6629 0.1060
Group:Sex          0.27908 0.27908     1    95  1.3757 0.2438
Group:Stimulus     0.32676 0.32676     1    95  1.6108 0.2075
Sex:Stimulus       0.27976 0.27976     1    95  1.3791 0.2432
Group:Sex:Stimulus 0.12808 0.12808     1    95  0.6314 0.4288
Code
interpret(omega_squared(painEmpathy_p1_lmer, alternative = 'two.sided'), rules = 'field2013')
# Effect Size for ANOVA (Type III)

Parameter          | Omega2 (partial) |       95% CI | Interpretation
---------------------------------------------------------------------
Group              |             0.00 | [0.00, 0.00] |     very small
Sex                |             0.00 | [0.00, 0.00] |     very small
Stimulus           |             0.02 | [0.00, 0.10] |          small
Group:Sex          |         3.86e-03 | [0.00, 0.06] |     very small
Group:Stimulus     |         6.26e-03 | [0.00, 0.07] |     very small
Sex:Stimulus       |         3.89e-03 | [0.00, 0.06] |     very small
Group:Sex:Stimulus |             0.00 | [0.00, 0.00] |     very small

- Interpretation rule: field2013
Code
a_posteriori_lmer(painEmpathy_p1_lmer)

P3, average from [260 360] ms interval

Electrodes O1, Oz, O2

Figure 14: P3 measurement window (voltages averaged over sex)
Code
painEmpathy_p3_lmer <- lmer(Amplitude ~ Group*Sex*Stimulus + (Stimulus|num_id) + (1|num_id:Electrode), p3_data)
afex_plot(
  painEmpathy_p3_lmer,
  x     = 'Stimulus',
  trace = 'Group',
  panel = 'Sex',
  id    = 'num_id',
  error_arg = list(width = .25),
  dodge     = my_dodge,
  data_arg  = list(
    position = 
      position_jitterdodge(
        jitter.width  = my_jitter, 
        jitter.height = 0, 
        dodge.width   = my_dodge  ## needs to be same as dodge
      )),
  mapping   = c('color'),
  point_arg = list(size = 3)
)
painEmpathy_p3_lmer@call
lmer(formula = Amplitude ~ Group * Sex * Stimulus + (Stimulus | 
    num_id) + (1 | num_id:Electrode), data = p3_data)
Figure 15: P3 means by Group & Stimulus
Code
options(width = 110)
anova(painEmpathy_p3_lmer)
Type III Analysis of Variance Table with Satterthwaite's method
                   Sum Sq Mean Sq NumDF  DenDF F value    Pr(>F)    
Group              0.4366  0.4366     1 95.001  1.7746   0.18600    
Sex                0.3242  0.3242     1 95.001  1.3178   0.25387    
Stimulus           4.1910  4.1910     1 95.002 17.0361 7.873e-05 ***
Group:Sex          0.0401  0.0401     1 95.001  0.1630   0.68729    
Group:Stimulus     0.0161  0.0161     1 95.002  0.0655   0.79851    
Sex:Stimulus       1.0651  1.0651     1 95.002  4.3293   0.04015 *  
Group:Sex:Stimulus 1.5170  1.5170     1 95.002  6.1664   0.01477 *  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
interpret(omega_squared(painEmpathy_p3_lmer, alternative = 'two.sided'), rules = 'field2013')
# Effect Size for ANOVA (Type III)

Parameter          | Omega2 (partial) |       95% CI | Interpretation
---------------------------------------------------------------------
Group              |         7.92e-03 | [0.00, 0.08] |     very small
Sex                |         3.27e-03 | [0.00, 0.06] |     very small
Stimulus           |             0.14 | [0.04, 0.27] |          large
Group:Sex          |             0.00 | [0.00, 0.00] |     very small
Group:Stimulus     |             0.00 | [0.00, 0.00] |     very small
Sex:Stimulus       |             0.03 | [0.00, 0.13] |          small
Group:Sex:Stimulus |             0.05 | [0.00, 0.16] |          small

- Interpretation rule: field2013
Code
a_posteriori_lmer(painEmpathy_p3_lmer)
____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Stimulus emmean    SE df lower.CL upper.CL
 no_pain    3.93 0.235 95     3.46     4.40
 pain       3.47 0.226 95     3.02     3.91

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast       estimate    SE df t.ratio p.value
 no_pain - pain    0.465 0.113 95   4.127  0.0001

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 

____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Sex    Stimulus emmean    SE df lower.CL upper.CL
 female no_pain    3.79 0.331 95     3.13     4.45
 male   no_pain    4.07 0.334 95     3.41     4.73
 female pain       3.09 0.318 95     2.46     3.72
 male   pain       3.84 0.321 95     3.20     4.48

Results are averaged over the levels of: Group 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast                      estimate    SE  df t.ratio p.value
 female no_pain - male no_pain  -0.2790 0.470  95  -0.594  0.9338
 female no_pain - female pain    0.6994 0.159  95   4.413  0.0002
 female no_pain - male pain     -0.0484 0.461 107  -0.105  0.9996
 male no_pain - female pain      0.9784 0.461 107   2.121  0.1531
 male no_pain - male pain        0.2306 0.160  95   1.440  0.4779
 female pain - male pain        -0.7478 0.452  95  -1.653  0.3541

Results are averaged over the levels of: Group 
Degrees-of-freedom method: kenward-roger 
P value adjustment: tukey method for comparing a family of 4 estimates 

____________________________________________________________
$emmeans
 Group      Sex    Stimulus emmean    SE df lower.CL upper.CL
 vulnerable female no_pain    3.28 0.467 95     2.35     4.21
 control    female no_pain    4.30 0.467 95     3.38     5.23
 vulnerable male   no_pain    4.02 0.477 95     3.07     4.96
 control    male   no_pain    4.12 0.467 95     3.19     5.05
 vulnerable female pain       2.83 0.450 95     1.94     3.72
 control    female pain       3.35 0.450 95     2.46     4.25
 vulnerable male   pain       3.48 0.459 95     2.57     4.39
 control    male   pain       4.20 0.450 95     3.31     5.09

Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast                                            estimate    SE  df t.ratio p.value
 vulnerable female no_pain - control female no_pain   -1.0272 0.661  95  -1.554  0.7760
 vulnerable female no_pain - vulnerable male no_pain  -0.7393 0.668  95  -1.107  0.9539
 vulnerable female no_pain - control male no_pain     -0.8459 0.661  95  -1.279  0.9042
 vulnerable female no_pain - vulnerable female pain    0.4485 0.224  95   2.001  0.4869
 vulnerable female no_pain - control female pain      -0.0769 0.649 107  -0.119  1.0000
 vulnerable female no_pain - vulnerable male pain     -0.2001 0.655 107  -0.305  1.0000
 vulnerable female no_pain - control male pain        -0.9239 0.649 107  -1.424  0.8443
 control female no_pain - vulnerable male no_pain      0.2879 0.668  95   0.431  0.9999
 control female no_pain - control male no_pain         0.1814 0.661  95   0.274  1.0000
 control female no_pain - vulnerable female pain       1.4757 0.649 107   2.274  0.3174
 control female no_pain - control female pain          0.9503 0.224  95   4.240  0.0013
 control female no_pain - vulnerable male pain         0.8271 0.655 107   1.262  0.9106
 control female no_pain - control male pain            0.1034 0.649 107   0.159  1.0000
 vulnerable male no_pain - control male no_pain       -0.1066 0.668  95  -0.160  1.0000
 vulnerable male no_pain - vulnerable female pain      1.1878 0.656 107   1.811  0.6140
 vulnerable male no_pain - control female pain         0.6624 0.656 107   1.010  0.9720
 vulnerable male no_pain - vulnerable male pain        0.5392 0.229  95   2.357  0.2748
 vulnerable male no_pain - control male pain          -0.1846 0.656 107  -0.281  1.0000
 control male no_pain - vulnerable female pain         1.2944 0.649 107   1.995  0.4902
 control male no_pain - control female pain            0.7690 0.649 107   1.185  0.9345
 control male no_pain - vulnerable male pain           0.6458 0.655 107   0.985  0.9756
 control male no_pain - control male pain             -0.0780 0.224  95  -0.348  1.0000
 vulnerable female pain - control female pain         -0.5254 0.636  95  -0.826  0.9912
 vulnerable female pain - vulnerable male pain        -0.6486 0.643  95  -1.009  0.9721
 vulnerable female pain - control male pain           -1.3724 0.636  95  -2.157  0.3872
 control female pain - vulnerable male pain           -0.1232 0.643  95  -0.192  1.0000
 control female pain - control male pain              -0.8470 0.636  95  -1.331  0.8847
 vulnerable male pain - control male pain             -0.7238 0.643  95  -1.126  0.9495

Degrees-of-freedom method: kenward-roger 
P value adjustment: tukey method for comparing a family of 8 estimates 

Late Centro-parietal: LPP

(a) Control V2
(b) Vulnerable V2
Figure 16: Centro-parietal ROI

LPP, average from [550 750] ms interval

Electrodes CP1, Cz, CP2

Figure 17: LPP measurement window (voltages averaged over sex)
Code
painEmpathy_lpp_lmer <- lmer(Amplitude ~ Group*Sex*Stimulus + (Stimulus|num_id) + (1|num_id:Electrode), lpp_data)
afex_plot(
  painEmpathy_lpp_lmer,
  x     = 'Stimulus',
  trace = 'Group',
  panel = 'Sex',
  id    = 'num_id',
  error_arg = list(width = .25),
  dodge     = my_dodge,
  data_arg  = list(
    position = 
      position_jitterdodge(
        jitter.width  = my_jitter, 
        jitter.height = 0, 
        dodge.width   = my_dodge  ## needs to be same as dodge
      )),
  mapping   = c('color'),
  point_arg = list(size = 3)
)
painEmpathy_lpp_lmer@call
lmer(formula = Amplitude ~ Group * Sex * Stimulus + (Stimulus | 
    num_id) + (1 | num_id:Electrode), data = lpp_data)
Figure 18: LPP means by Group & Stimulus
Code
options(width = 90)
anova(painEmpathy_lpp_lmer)
Type III Analysis of Variance Table with Satterthwaite's method
                    Sum Sq Mean Sq NumDF DenDF  F value  Pr(>F)    
Group               0.6467  0.6467     1    95   3.5266 0.06346 .  
Sex                 0.3750  0.3750     1    95   2.0453 0.15596    
Stimulus           19.3264 19.3264     1    95 105.3939 < 2e-16 ***
Group:Sex           0.0249  0.0249     1    95   0.1359 0.71322    
Group:Stimulus      0.0274  0.0274     1    95   0.1495 0.69990    
Sex:Stimulus        0.0012  0.0012     1    95   0.0066 0.93554    
Group:Sex:Stimulus  0.0226  0.0226     1    95   0.1235 0.72609    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
interpret(omega_squared(painEmpathy_lpp_lmer, alternative = 'two.sided'), rules = 'field2013')
# Effect Size for ANOVA (Type III)

Parameter          | Omega2 (partial) |       95% CI | Interpretation
---------------------------------------------------------------------
Group              |             0.03 | [0.00, 0.12] |          small
Sex                |             0.01 | [0.00, 0.09] |          small
Stimulus           |             0.52 | [0.38, 0.62] |          large
Group:Sex          |             0.00 | [0.00, 0.00] |     very small
Group:Stimulus     |             0.00 | [0.00, 0.00] |     very small
Sex:Stimulus       |             0.00 | [0.00, 0.00] |     very small
Group:Sex:Stimulus |             0.00 | [0.00, 0.00] |     very small

- Interpretation rule: field2013
Code
a_posteriori_lmer(painEmpathy_lpp_lmer)
____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Stimulus emmean     SE df lower.CL upper.CL
 no_pain    1.03 0.0937 95    0.845     1.22
 pain       2.01 0.1060 95    1.800     2.22

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast       estimate     SE df t.ratio p.value
 no_pain - pain   -0.979 0.0954 95 -10.266  <.0001

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 

A deeper look in the back: P3a & P3b

P3a, average from [240 300] ms interval

Electrodes O1, Oz, O2

Figure 19: P3a measurement window (voltages averaged over sex)
Code
painEmpathy_p3a_lmer <- lmer(Amplitude ~ Group*Sex*Stimulus + (Stimulus|num_id) + (1|num_id:Electrode), p3a_data)
afex_plot(
  painEmpathy_p3a_lmer,
  x     = 'Stimulus',
  trace = 'Group',
  panel = 'Sex',
  id    = 'num_id',
  error_arg = list(width = .25),
  dodge     = my_dodge,
  data_arg  = list(
    position = 
      position_jitterdodge(
        jitter.width  = my_jitter, 
        jitter.height = 0, 
        dodge.width   = my_dodge  ## needs to be same as dodge
      )),
  mapping   = c('color'),
  point_arg = list(size = 3)
)
painEmpathy_p3a_lmer@call
lmer(formula = Amplitude ~ Group * Sex * Stimulus + (Stimulus | 
    num_id) + (1 | num_id:Electrode), data = p3a_data)
Figure 20: P3a means by Group, Version & Stimulus
Code
options(width = 110)
anova(painEmpathy_p3a_lmer)
Type III Analysis of Variance Table with Satterthwaite's method
                   Sum Sq Mean Sq NumDF  DenDF F value    Pr(>F)    
Group              1.2233  1.2233     1 95.001  4.8018  0.030876 *  
Sex                0.1229  0.1229     1 95.001  0.4825  0.488997    
Stimulus           4.9139  4.9139     1 95.001 19.2887 2.919e-05 ***
Group:Sex          0.1954  0.1954     1 95.001  0.7669  0.383398    
Group:Stimulus     0.0294  0.0294     1 95.001  0.1156  0.734645    
Sex:Stimulus       0.7831  0.7831     1 95.001  3.0741  0.082775 .  
Group:Sex:Stimulus 2.0638  2.0638     1 95.001  8.1009  0.005421 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
interpret(omega_squared(painEmpathy_p3a_lmer, alternative = 'two.sided'), rules = 'field2013')
# Effect Size for ANOVA (Type III)

Parameter          | Omega2 (partial) |       95% CI | Interpretation
---------------------------------------------------------------------
Group              |             0.04 | [0.00, 0.14] |          small
Sex                |             0.00 | [0.00, 0.00] |     very small
Stimulus           |             0.16 | [0.05, 0.29] |          large
Group:Sex          |             0.00 | [0.00, 0.00] |     very small
Group:Stimulus     |             0.00 | [0.00, 0.00] |     very small
Sex:Stimulus       |             0.02 | [0.00, 0.11] |          small
Group:Sex:Stimulus |             0.07 | [0.00, 0.18] |         medium

- Interpretation rule: field2013
Code
a_posteriori_lmer(painEmpathy_p3a_lmer)
____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Group      emmean    SE df lower.CL upper.CL
 vulnerable   3.22 0.381 95     2.46     3.97
 control      4.39 0.377 95     3.64     5.14

Results are averaged over the levels of: Sex, Stimulus 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast             estimate    SE df t.ratio p.value
 vulnerable - control    -1.17 0.536 95  -2.191  0.0309

Results are averaged over the levels of: Sex, Stimulus 
Degrees-of-freedom method: kenward-roger 

____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 Stimulus emmean    SE df lower.CL upper.CL
 no_pain    4.05 0.279 95     3.49      4.6
 pain       3.56 0.268 95     3.03      4.1

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast       estimate   SE df t.ratio p.value
 no_pain - pain    0.484 0.11 95   4.392  <.0001

Results are averaged over the levels of: Group, Sex 
Degrees-of-freedom method: kenward-roger 

____________________________________________________________
$emmeans
 Group      Sex    Stimulus emmean    SE df lower.CL upper.CL
 vulnerable female no_pain    3.00 0.555 95     1.90     4.10
 control    female no_pain    4.92 0.555 95     3.82     6.02
 vulnerable male   no_pain    3.96 0.566 95     2.84     5.08
 control    male   no_pain    4.31 0.555 95     3.21     5.41
 vulnerable female pain       2.60 0.533 95     1.54     3.66
 control    female pain       3.96 0.533 95     2.91     5.02
 vulnerable male   pain       3.32 0.544 95     2.24     4.40
 control    male   pain       4.37 0.533 95     3.32     5.43

Degrees-of-freedom method: kenward-roger 
Confidence level used: 0.95 

$contrasts
 contrast                                            estimate    SE  df t.ratio p.value
 vulnerable female no_pain - control female no_pain  -1.91892 0.784  95  -2.447  0.2316
 vulnerable female no_pain - vulnerable male no_pain -0.96150 0.792  95  -1.213  0.9260
 vulnerable female no_pain - control male no_pain    -1.31455 0.784  95  -1.676  0.7024
 vulnerable female no_pain - vulnerable female pain   0.40142 0.219  95   1.829  0.6023
 vulnerable female no_pain - control female pain     -0.96454 0.769 103  -1.254  0.9133
 vulnerable female no_pain - vulnerable male pain    -0.31895 0.777 103  -0.411  0.9999
 vulnerable female no_pain - control male pain       -1.37495 0.769 103  -1.787  0.6299
 control female no_pain - vulnerable male no_pain     0.95742 0.792  95   1.208  0.9276
 control female no_pain - control male no_pain        0.60437 0.784  95   0.771  0.9942
 control female no_pain - vulnerable female pain      2.32034 0.769 103   3.016  0.0616
 control female no_pain - control female pain         0.95437 0.219  95   4.348  0.0009
 control female no_pain - vulnerable male pain        1.59997 0.777 103   2.059  0.4480
 control female no_pain - control male pain           0.54397 0.769 103   0.707  0.9966
 vulnerable male no_pain - control male no_pain      -0.35305 0.792  95  -0.446  0.9998
 vulnerable male no_pain - vulnerable female pain     1.36292 0.778 103   1.753  0.6528
 vulnerable male no_pain - control female pain       -0.00305 0.778 103  -0.004  1.0000
 vulnerable male no_pain - vulnerable male pain       0.64255 0.224  95   2.868  0.0909
 vulnerable male no_pain - control male pain         -0.41345 0.778 103  -0.532  0.9995
 control male no_pain - vulnerable female pain        1.71597 0.769 103   2.231  0.3425
 control male no_pain - control female pain           0.35000 0.769 103   0.455  0.9998
 control male no_pain - vulnerable male pain          0.99560 0.777 103   1.281  0.9037
 control male no_pain - control male pain            -0.06040 0.219  95  -0.275  1.0000
 vulnerable female pain - control female pain        -1.36597 0.754  95  -1.812  0.6137
 vulnerable female pain - vulnerable male pain       -0.72037 0.762  95  -0.946  0.9806
 vulnerable female pain - control male pain          -1.77638 0.754  95  -2.356  0.2752
 control female pain - vulnerable male pain           0.64559 0.762  95   0.848  0.9897
 control female pain - control male pain             -0.41041 0.754  95  -0.544  0.9994
 vulnerable male pain - control male pain            -1.05600 0.762  95  -1.386  0.8613

Degrees-of-freedom method: kenward-roger 
P value adjustment: tukey method for comparing a family of 8 estimates 

P3b, average from [340 390] ms interval

Electrodes O1, Oz, O2

Figure 21: P3b measurement window (voltages averaged over sex)
Code
painEmpathy_p3b_lmer <- lmer(Amplitude ~ Group*Sex*Stimulus + (Stimulus|num_id) + (1|num_id:Electrode), p3b_data)
afex_plot(
  painEmpathy_p3b_lmer,
  x     = 'Stimulus',
  trace = 'Group',
  panel = 'Sex',
  id    = 'num_id',
  error_arg = list(width = .25),
  dodge     = my_dodge,
  data_arg  = list(
    position = 
      position_jitterdodge(
        jitter.width  = my_jitter, 
        jitter.height = 0, 
        dodge.width   = my_dodge  ## needs to be same as dodge
      )),
  mapping   = c('color'),
  point_arg = list(size = 3)
)
painEmpathy_p3b_lmer@call
lmer(formula = Amplitude ~ Group * Sex * Stimulus + (Stimulus | 
    num_id) + (1 | num_id:Electrode), data = p3b_data)
Figure 22: P3b means by Group, Version & Stimulus
Code
options(width = 110)
anova(painEmpathy_p3b_lmer)
Type III Analysis of Variance Table with Satterthwaite's method
                    Sum Sq Mean Sq NumDF  DenDF F value Pr(>F)
Group              0.00010 0.00010     1 95.000  0.0004 0.9845
Sex                0.10768 0.10768     1 95.000  0.4266 0.5152
Stimulus           0.64962 0.64962     1 94.999  2.5737 0.1120
Group:Sex          0.05051 0.05051     1 95.000  0.2001 0.6556
Group:Stimulus     0.30469 0.30469     1 94.999  1.2071 0.2747
Sex:Stimulus       0.67173 0.67173     1 94.999  2.6614 0.1061
Group:Sex:Stimulus 0.20362 0.20362     1 94.999  0.8067 0.3714
Code
interpret(omega_squared(painEmpathy_p3b_lmer, alternative = 'two.sided'), rules = 'field2013')
# Effect Size for ANOVA (Type III)

Parameter          | Omega2 (partial) |       95% CI | Interpretation
---------------------------------------------------------------------
Group              |             0.00 | [0.00, 0.00] |     very small
Sex                |             0.00 | [0.00, 0.00] |     very small
Stimulus           |             0.02 | [0.00, 0.10] |          small
Group:Sex          |             0.00 | [0.00, 0.00] |     very small
Group:Stimulus     |         2.13e-03 | [0.00, 0.06] |     very small
Sex:Stimulus       |             0.02 | [0.00, 0.10] |          small
Group:Sex:Stimulus |             0.00 | [0.00, 0.00] |     very small

- Interpretation rule: field2013
Code
a_posteriori_lmer(painEmpathy_p3b_lmer)

Factorial Mass Univariate analysis (FMUT, cluster mass)

Code
n_ctl <- sum(unique(painEmpathy_data$num_id) >= 100)
n_vul <- sum(unique(painEmpathy_data$num_id) <  100)
n_fmut <- min(n_ctl, n_vul)

Using 49 cases by group as FMUT only works with groups of equal size.

Fields and Kuperberg (2020)

max_dist value of 50 corresponds to an approximate distance of 5.24 cm (assuming
a 56 cm great circle circumference head and that your electrode coordinates are
based on an idealized spherical head with radius of 85.000000).

Min/Max distances between all pairs of channels (in chanlocs units):
26.560450/169.891840

Median (semi-IQR) distance between all pairs of channels (in chanlocs units):
119.172654 (30.583399)

Mean (SD) # of neighbors per channel: 2.6 (1.2)
Median (semi-IQR) # of neighbors per channel: 2.0 (1.0)
Min/max # of neighbors per channel: 0 to 4

Version 2

(a) Stimulus by Group interaction
(b) Stimulus effect
(c) Stimulus effect with MASS
(d) Group effect
Figure 23: Full time window FMUT raster Version 2
pev2_painEmpathy_fmut_version_2:

2 significant Stimulus cluster(s) out of 33
cluster 1 F-masss: 626
cluster 1 p-value: 0.0442
cluster 2 F-masss: 17166
cluster 2 p-value: 0.0001


Mass Univariate analysis (MASS, cluster mass), full time window

Using all cases

Groppe, Urbach, and Kutas (2011)

max_dist value of 50 corresponds to an approximate distance of 5.24 cm (assuming
a 56 cm great circle circumference head and that your electrode coordinates are
based on an idealized spherical head with radius of 85.000000).

Min/Max distances between all pairs of channels (in chanlocs units):
26.560450/169.891840

Median (semi-IQR) distance between all pairs of channels (in chanlocs units):
119.172654 (30.583399)

Mean (SD) # of neighbors per channel: 2.6 (1.2)
Median (semi-IQR) # of neighbors per channel: 2.0 (1.0)
Min/max # of neighbors per channel: 0 to 4

Version 2

(a) Control
(b) Vulnerable
Figure 24: Full time window raster Version 2
pev2_painEmpathy_ctl:

1 significant positive cluster(s) out of 17
cluster 1 t-masss: 2096
cluster 1 p-value: 0.0000

1 significant negative cluster(s) out of 28
cluster 1 t-masss: -217
cluster 1 p-value: 0.0352


pev2_painEmpathy_vul:

1 significant positive cluster(s) out of 9
cluster 1 t-masss: 2369
cluster 1 p-value: 0.0000

0 significant negative cluster(s) out of 14


Functional Connectivity: occipital ↔︎ parietal

Multivariate Interaction Measure, MIM (ROIconnect, Pellegrini et al. 2023), beta band (13-30 Hz) 1 sec post-stimulus.

Code
options(width = 80)
summary(connectivity_data)
        ERPset          ID             Group       City            image    
 s001_vul_s:  8   s001   :  8   vulnerable:392   stgo:696   no_pain_v1:396  
 s002_vul_s:  8   s002   :  8   control   :400   viña: 96   pain_v1   :396  
 s003_vul_s:  8   s003   :  8                                               
 s004_vul_s:  8   s004   :  8                                               
 s005_vul_s:  8   s005   :  8                                               
 s006_vul_s:  8   s006   :  8                                               
 (Other)   :744   (Other):744                                               
            region_a              region_b   median_connectivity Version 
 left_occipital :396   parietal_ipsi  :396   Min.   :0.04779     v1:792  
 right_occipital:396   parietal_contra:396   1st Qu.:0.07131             
                                             Median :0.08096             
                                             Mean   :0.08267             
                                             3rd Qu.:0.09109             
                                             Max.   :0.15159             
                                                                         
    Stimulus   log_median_connectivity     num_id           Sex     
 pain   :396   Min.   :-3.041          Min.   :  1.00   female:400  
 no_pain:396   1st Qu.:-2.641          1st Qu.: 28.00   male  :392  
               Median :-2.514          Median :100.00               
               Mean   :-2.512          Mean   : 76.87               
               3rd Qu.:-2.396          3rd Qu.:126.00               
               Max.   :-1.887          Max.   :150.00               
                                                                    
Code
connectivity_data_wide_region_a <- connectivity_data[c('ERPset', 'region_a', 'region_b', 'Stimulus', 'log_median_connectivity')] |>
  pivot_wider(names_from = region_a, values_from = log_median_connectivity)
connectivity_data_wide_region_b <- connectivity_data[c('ERPset', 'region_a', 'region_b', 'Stimulus', 'log_median_connectivity')] |>
  pivot_wider(names_from = region_b, values_from = log_median_connectivity)
connectivity_data_wide_stimulus <- connectivity_data[c('ERPset', 'region_a', 'region_b', 'Stimulus', 'log_median_connectivity')] |>
  pivot_wider(names_from = Stimulus, values_from = log_median_connectivity)
stims <- c('pain', 'no_pain')
region_a_parts <- c(paste0('left_', label_a), paste0('right_', label_a))
region_b_parts <- c(paste0(label_b, '_ipsi'), paste0(label_b, '_contra'))
region_a_pairs <- ggpairs(connectivity_data_wide_region_a,
                            aes(colour = Stimulus, alpha = .5, linewidth = NA),
                            columns  = region_a_parts,
                            lower    = list(continuous = wrap('points', alpha = .4)),
                            progress = FALSE
                            )
region_b_pairs <- ggpairs(connectivity_data_wide_region_b,
                            aes(colour = Stimulus, alpha = .5, linewidth = NA),
                            columns  = region_b_parts,
                            lower    = list(continuous = wrap('points', alpha = .4)),
                            progress = FALSE
                            )
stims_pairs <- ggpairs(connectivity_data_wide_stimulus,
                            aes(colour = region_b, alpha = .5, linewidth = NA),
                            columns  = stims,
                            lower    = list(continuous = wrap('points', alpha = .4)),
                            progress = FALSE
                            )
suppressWarnings(print(region_a_pairs))
suppressWarnings(print(region_b_pairs))
suppressWarnings(print(stims_pairs))
(a) region_a by stim
(b) region_b by stim
(c) stim by region_b
Figure 25: Log median connectivity distributions & correlations

Connectivity ANOVA (glmer):

Code
connectivity_glmer <- glmer(median_connectivity ~ Group*Sex*Stimulus*region_b + (Stimulus*region_b|num_id), family = Gamma(log), connectivity_data)
afex_plot(connectivity_glmer,
          x     = 'region_b',
          trace = 'Stimulus',
          panel = 'Group',
          id    = 'num_id',
          error_arg = list(width = .3, lwd = .75),
          dodge = my_dodge,
          data_arg  = list(
            position = 
              position_jitterdodge(
                jitter.width = my_jitter, 
                dodge.width  = my_dodge  ## needs to be same as dodge
              )),
          mapping   = c('color'),, data_alpha = .3,
          point_arg = list(size = 3)
)
connectivity_glmer@call
glmer(formula = median_connectivity ~ Group * Sex * Stimulus * 
    region_b + (Stimulus * region_b | num_id), data = connectivity_data, 
    family = Gamma(log))
Figure 26: Connectivity median by image & region
Code
options(width = 150)
anova(connectivity_glmer)
Analysis of Variance Table
                            npar  Sum Sq Mean Sq F value
Group                          1 0.13958 0.13958 11.6667
Sex                            1 0.05705 0.05705  4.7686
Stimulus                       1 0.00232 0.00232  0.1938
region_b                       1 0.98862 0.98862 82.6353
Group:Sex                      1 0.01612 0.01612  1.3471
Group:Stimulus                 1 0.00001 0.00001  0.0007
Sex:Stimulus                   1 0.02252 0.02252  1.8824
Group:region_b                 1 0.00265 0.00265  0.2216
Sex:region_b                   1 0.00023 0.00023  0.0194
Stimulus:region_b              1 0.00276 0.00276  0.2305
Group:Sex:Stimulus             1 0.00002 0.00002  0.0015
Group:Sex:region_b             1 0.00245 0.00245  0.2048
Group:Stimulus:region_b        1 0.00030 0.00030  0.0255
Sex:Stimulus:region_b          1 0.00025 0.00025  0.0210
Group:Sex:Stimulus:region_b    1 0.00034 0.00034  0.0282
Code
a_posteriori_glmer(connectivity_glmer)
Analysis of Deviance Table (Type II Wald chisquare tests)

Response: median_connectivity
                               Chisq Df Pr(>Chisq)    
Group                         2.8191  1    0.09315 .  
Sex                           1.2193  1    0.26950    
Stimulus                      0.0885  1    0.76605    
region_b                    117.1079  1    < 2e-16 ***
Group:Sex                     0.3376  1    0.56121    
Group:Stimulus                0.0018  1    0.96651    
Sex:Stimulus                  0.8227  1    0.36438    
Group:region_b                0.3072  1    0.57939    
Sex:region_b                  0.0294  1    0.86390    
Stimulus:region_b             0.3409  1    0.55931    
Group:Sex:Stimulus            0.0000  1    0.99646    
Group:Sex:region_b            0.2983  1    0.58494    
Group:Stimulus:region_b       0.0384  1    0.84459    
Sex:Stimulus:region_b         0.0310  1    0.86019    
Group:Sex:Stimulus:region_b   0.0418  1    0.83802    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
____________________________________________________________
NOTE: Results may be misleading due to involvement in interactions
$emmeans
 region_b        emmean     SE  df asymp.LCL asymp.UCL
 parietal_ipsi    -2.55 0.0199 Inf     -2.59     -2.51
 parietal_contra  -2.48 0.0200 Inf     -2.52     -2.44

Results are averaged over the levels of: Group, Sex, Stimulus 
Results are given on the log (not the response) scale. 
Confidence level used: 0.95 

$contrasts
 contrast                        estimate      SE  df z.ratio p.value
 parietal_ipsi - parietal_contra  -0.0732 0.00675 Inf -10.845  <.0001

Results are averaged over the levels of: Group, Sex, Stimulus 
Results are given on the log (not the response) scale. 

Connectivity Assumptions:

Code
check_model(connectivity_glmer)
Figure 27: Connectivity ANOVA assumptions

References

Delorme, Arnaud, and Scott Makeig. 2004. “EEGLAB: An Open Source Toolbox for Analysis of Single-Trial EEG Dynamics Including Independent Component Analysis.” Journal of Neuroscience Methods 134 (March): 9–21. https://doi.org/10.1016/J.JNEUMETH.2003.10.009.
Dong, Li, Fali Li, Qiang Liu, Xin Wen, Yongxiu Lai, Peng Xu, and Dezhong Yao. 2017. “MATLAB Toolboxes for Reference Electrode Standardization Technique (REST) of Scalp EEG.” Frontiers in Neuroscience 11 (October): 601. https://doi.org/10.3389/fnins.2017.00601.
Fields, Eric C., and Gina R. Kuperberg. 2020. “Having Your Cake and Eating It Too: Flexibility and Power with Mass Univariate Statistics for ERP Data.” Psychophysiology 57 (February): e13468. https://doi.org/10.1111/PSYP.13468.
Groppe, David M., Thomas P. Urbach, and Marta Kutas. 2011. “Mass Univariate Analysis of Event-Related Brain Potentials/Fields i: A Critical Tutorial Review.” Psychophysiology 48 (December): 1711–25. https://doi.org/10.1111/J.1469-8986.2011.01273.X.
Lopez-Calderon, Javier, and Steven J. Luck. 2014. “ERPLAB: An Open-Source Toolbox for the Analysis of Event-Related Potentials.” Frontiers in Human Neuroscience 8 (April): 75729. https://doi.org/10.3389/FNHUM.2014.00213/BIBTEX.
Pellegrini, Franziska, Arnaud Delorme, Vadim Nikulin, and Stefan Haufe. 2023. “Identifying Good Practices for Detecting Inter-Regional Linear Functional Connectivity from EEG.” NeuroImage 277 (August): 120218. https://doi.org/10.1016/J.NEUROIMAGE.2023.120218.
Pion-Tonachini, Luca, Ken Kreutz-Delgado, and Scott Makeig. 2019. “ICLabel: An Automated Electroencephalographic Independent Component Classifier, Dataset, and Website.” NeuroImage 198: 181–97. https://doi.org/10.1016/j.neuroimage.2019.05.026.