1 Load & Process data

savepath <- '../../Analysis/ROI_estimates/'
behavpath <- '../../Data/Behavioral/summary/'
## Load data from csv
### Activation estimates
actdata<-read.csv(paste0(savepath,'cons_ashs_ItemSourceDM_rf_new.csv')) # created with output_roi_cons script in Matlab
### ROI metadata
roidata<-read.csv('../../Analysis/ROI_estimates/roi_info.csv') # contains various labeling schemes for ROIs
actdata <- merge(actdata,roidata,by="roi_file")
rm(roidata)
### Clean up data
# first deal with s21, who had to have EmoK subbed in for EmoM (no EmoM trials)
actdata <- unique(actdata) # remove doubled-up EmoK
tmp <-subset(actdata,subject=="s21" & contrast=="EmoK") # get the EmoK for relabel -> these trial types get averaged anyway
tmp$contrast <- "EmoM"
actdata <- rbind(actdata,tmp) # pull back into main dataframe
### Define new variables
actdata$Emotion <- factor(sapply(actdata$contrast,simplify=TRUE,
                                 function(x) ifelse(grepl('Emo',x),'Emo',
                                                    ifelse(grepl('Neu',x),'Neu',NA))))
actdata <- subset(actdata,!is.na(actdata$Emotion)) # get rid of all other contrasts
actdata$RecMem <- factor(sapply(actdata$contrast,simplify=TRUE,
                                      function(x) ifelse(grepl('R',x),'Rec',
                                                         ifelse(grepl('K',x),'Non-Rec',
                                                                ifelse(grepl('M',x),'Non-Rec',NA)))),
                               levels=c("Rec","Non-Rec"))
actdata$SourceMem <- factor(sapply(actdata$contrast,simplify=TRUE,
                                   function(x) ifelse(grepl('SC',x),'Corr',
                                                      ifelse(grepl('SI',x),'Incorr',NA))))
actdata$BothMem <- factor(ifelse(actdata$RecMem=="Rec" & actdata$SourceMem=="Corr","R+S",
                                 ifelse(actdata$RecMem=="Rec" & actdata$SourceMem=="Incorr","R-S",
                                        ifelse(actdata$RecMem=="Non-Rec","NR",NA))),
                          levels=c("R+S","R-S","NR"))
str(actdata)
'data.frame':   4928 obs. of  15 variables:
 $ roi_file     : Factor w/ 28 levels "AMY_L","AMY_R",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ subject      : Factor w/ 22 levels "s04","s05","s06",..: 1 1 1 1 1 1 1 1 2 2 ...
 $ contrast     : Factor w/ 9 levels "ALL","EmoK","EmoM",..: 4 5 2 3 8 9 6 7 4 5 ...
 $ activity     : num  1.582 0.652 1.389 1.901 0.687 ...
 $ numvox       : int  520 520 520 520 520 520 520 520 517 517 ...
 $ Region       : Factor w/ 12 levels "Amyg","BasolatAmyg",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Hemisphere   : Factor w/ 2 levels "L","R": 1 1 1 1 1 1 1 1 1 1 ...
 $ MainRegion   : Factor w/ 3 levels "Amyg","CorticalMTL",..: NA NA NA NA NA NA NA NA NA NA ...
 $ AP           : Factor w/ 3 levels "body","head",..: NA NA NA NA NA NA NA NA NA NA ...
 $ full_filename: Factor w/ 40 levels "rseg_AMY_L.nii",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ RegionAP     : Factor w/ 21 levels "Amyg","BasolatAmyg",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Emotion      : Factor w/ 2 levels "Emo","Neu": 1 1 1 1 2 2 2 2 1 1 ...
 $ RecMem       : Factor w/ 2 levels "Rec","Non-Rec": 1 1 2 2 1 1 2 2 1 1 ...
 $ SourceMem    : Factor w/ 2 levels "Corr","Incorr": 1 2 NA NA 1 2 NA NA 1 2 ...
 $ BothMem      : Factor w/ 3 levels "R+S","R-S","NR": 1 2 3 3 1 2 3 3 1 2 ...
kable(table(actdata$BothMem,actdata$subject))

s04 s05 s06 s07 s08 s09 s10 s11 s13 s14 s16 s17 s18 s19 s20 s21 s22 s23 s25 s26 s27 s28
R+S 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56
R-S 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56
NR 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112

## Create dataframe with 'baseline-corrected' scores, i.e., recollection trial types minus non-recollection
nrbaseline <-
  group_by(actdata,subject,Emotion,roi_file) %>%
  summarize(nr.baseline = mean(activity[RecMem=="Non-Rec"],na.rm=TRUE)) # average over Fam & Miss
actdata.rec <-
  filter(actdata,RecMem=="Rec") %>%
  left_join(nrbaseline)  %>%
  mutate(activity = activity - nr.baseline) # values in actdata.rec are now recollection-related activity
Joining, by = c("roi_file", "subject", "Emotion")
  
## Clean up and save
save(actdata,file=paste0(savepath,'MemoHR_AnatROI_Data_ItemSource.Rdata'))

1.1 Report number of voxels in each ROI

vox <- group_by(actdata,RegionAP) %>%
  summarize(meanvox=mean(numvox),
            minvox=min(numvox),
            maxvox=max(numvox))
kable(vox)
RegionAP meanvox minvox maxvox
Amyg 558.7 397 726
BasolatAmyg 312.5 210 492
CA1.body 194.6 166 237
CA23DG.body 140.3 91 202
CentralAmyg 38.3 13 68
CorticalAmyg 116.5 46 179
MedialAmyg 91.4 51 151
PHC 429.2 271 619
PRC 465.7 247 846
subiculum.body 43.7 29 61
wholeHipp 843.0 600 1071
wholeHipp.body 378.6 312 478
wholeHipp.head 425.9 229 683
wholeHipp.tail 38.6 0 91

2 Plots

2.1 Calculate summary values first

summarydata.all <- group_by(actdata,subject,Emotion,RecMem,SourceMem,Region,RegionAP,MainRegion,AP) %>%
  summarize(activity=mean(activity)) # This part averages across hemispheres, and fam/miss are averaged into non-rec
meandata.all <- group_by(summarydata.all,Region,RegionAP,MainRegion,AP,Emotion) %>%
  group_by(Emotion,RecMem,SourceMem,Region,RegionAP,MainRegion,AP) %>%
  summarize(meanval=mean(activity,na.rm=TRUE),sdval=sd(activity,na.rm=TRUE),
            sem=sdval/sqrt(length(activity)),
            semmin=meanval-sem,
            semmax=meanval+sem,
            nsubj=length(activity))
meandata.all$EmoMem <- interaction(meandata.all$RecMem,meandata.all$Emotion)
meandata.all$MemMem <- interaction(meandata.all$RecMem,meandata.all$SourceMem)
meandata.all$MemMem <- factor(meandata.all$MemMem,levels=c("Rec.Corr","Rec.Incorr","Non-Rec"))
meandata.all$MemMem[is.na(meandata.all$MemMem)] <- "Non-Rec"
summarydata.rec <- group_by(actdata.rec,subject,Emotion,RecMem,SourceMem,Region,RegionAP,MainRegion,AP) %>%
  summarize(activity=mean(activity))  # This part averages across hemispheres
meandata.rec <- group_by(summarydata.rec,Region,RegionAP,MainRegion,AP,Emotion) %>%
  group_by(Emotion,RecMem,SourceMem,Region,RegionAP,MainRegion,AP) %>%
  summarize(meanval=mean(activity,na.rm=TRUE),sdval=sd(activity,na.rm=TRUE),
            sem=sdval/sqrt(length(activity)),
            semmin=meanval-sem,
            semmax=meanval+sem,
            nsubj=length(activity))
meandata.rec$EmoMem <- interaction(meandata.rec$RecMem,meandata.rec$Emotion)
meandata.rec$MemMem <- interaction(meandata.rec$RecMem,meandata.rec$SourceMem)
meandata.rec$MemMem <- factor(meandata.rec$MemMem,levels=c("Rec.Corr","Rec.Incorr","Non-Rec"))
meandata.rec$MemMem[is.na(meandata.rec$MemMem)] <- "Non-Rec"

2.2 Plots with all bars

2.2.1 Main regions

# All regions
plotcolors <- c('#d01c8b','#f1b6da',"gray70",'#4dac26','#b8e186',"gray70")
meandata.all %>%
  filter(RegionAP=="Amyg" | RegionAP=="wholeHipp") %>%
  ungroup() %>%
  mutate(RegionAP = factor(RegionAP,levels=c("Amyg","wholeHipp")),
         RegionLabel = factor(ifelse(RegionAP=="wholeHipp","Hipp","Amyg"),
                              levels=c("Amyg","Hipp")),
         MemoryCond = factor(ifelse(MemMem=="Rec.Corr","Rec + Src",ifelse(MemMem=="Rec.Incorr","Rec - Src","Non-Rec")),
                             levels=c("Rec + Src","Rec - Src","Non-Rec")),
         EmoMem = interaction(MemoryCond,Emotion)) %>%
  ggplot(.,aes(x=MemoryCond,y=meanval)) + geom_bar(stat="identity",position="dodge",aes(fill=EmoMem)) +
  geom_errorbar(aes(ymin=meanval-sem,ymax=meanval+sem,width=.25)) + theme_minimal(18) +
  theme(axis.title.x=element_blank()) + facet_grid(.~RegionLabel+Emotion) +
  xlab("Mean activity (au)") + scale_fill_manual(values=plotcolors) +  guides(color=FALSE, fill=FALSE) + 
  theme(axis.text.x = element_text(angle = 30, hjust = 1))

meandata.all %>%
  filter(RegionAP=="PHC" | RegionAP=="PRC") %>%
  ungroup() %>%
  mutate(RegionAP = factor(RegionAP,levels=c("PRC","PHC")),
         MemoryCond = factor(ifelse(MemMem=="Rec.Corr","Rec + Src",ifelse(MemMem=="Rec.Incorr","Rec - Src","Non-Rec")),
                             levels=c("Rec + Src","Rec - Src","Non-Rec")),
         EmoMem = interaction(MemoryCond,Emotion)) %>%
  ggplot(.,aes(x=MemoryCond,y=meanval)) + geom_bar(stat="identity",position="dodge",aes(fill=EmoMem)) +
  geom_errorbar(aes(ymin=meanval-sem,ymax=meanval+sem,width=.25)) + theme_minimal(18) +
  theme(axis.text.x=element_blank(),axis.title.x=element_blank()) + facet_grid(.~RegionAP+Emotion) +
  xlab("Mean activity (au)") + scale_fill_manual(values=plotcolors) +  guides(color=FALSE, fill=FALSE) + 
  theme(axis.text.x = element_text(angle = 30, hjust = 1))

2.3 Plots with bars subtracting non-recollection

2.3.1 Single Plots

plotcolors <- c('#d01c8b','#f1b6da','#4dac26','#b8e186')
singlePlotROI <- function(roi) {
  meandata.rec %>%
  filter(RegionAP==roi) %>%
  ungroup() %>%
  mutate(MemoryCond = factor(ifelse(MemMem=="Rec.Corr","Rec + Src",ifelse(MemMem=="Rec.Incorr","Rec - Src","Non-Rec")),
                             levels=c("Rec + Src","Rec - Src","Non-Rec")),
         EmoMem = interaction(MemoryCond,Emotion)) %>%
  ggplot(.,aes(x=MemoryCond,y=meanval)) + geom_bar(stat="identity",position="dodge",aes(fill=EmoMem)) +
  geom_errorbar(aes(ymin=meanval-sem,ymax=meanval+sem,width=.25)) + theme_minimal(18) +
  theme(axis.text.x=element_blank(),axis.title.x=element_blank()) + facet_grid(.~Emotion,switch="x") +
  ylab("Recollection-related activity") + scale_fill_manual(values=plotcolors) + guides(color=FALSE) +
    ggtitle(roi) 
}
singlePlotROI_fixedLim <- function(roi,limits) { # fix limits for some plots for better visualization
  singlePlotROI(roi) + ylim(limits)
}
# Plot all regions
singlePlotROI_fixedLim('Amyg',c(-.25,1))

singlePlotROI_fixedLim('wholeHipp',c(-.25,1))

singlePlotROI('PRC')

singlePlotROI('PHC')

3 Stats

3.1 All regions

statdata1 <- subset(actdata.rec,RegionAP=="wholeHipp" | Region=="Amyg"  | Region=="PRC"  | Region=="PHC") 
summary(droplevels(statdata1$Region)) # Note that hemisphere is still included but ezANOVA will average them
     Amyg       PHC       PRC wholeHipp 
      176       176       176       176 
anova_mod1<-ezANOVA(statdata1,dv=activity,wid=subject,within=list(BothMem,Emotion,Region),type=3,detailed=TRUE)
print(anova_mod1)
$ANOVA
                  Effect DFn DFd    SSn  SSd      F         p p<.05     ges
1            (Intercept)   1  21 70.806 57.0 26.070 0.0000467     * 0.22872
2                BothMem   1  21  8.005 19.0  8.835 0.0072650     * 0.03244
3                Emotion   1  21  1.515 36.8  0.865 0.3629812       0.00631
4                 Region   3  63  6.031 45.4  2.790 0.0476819     * 0.02464
5        BothMem:Emotion   1  21  0.283 18.5  0.322 0.5766273       0.00118
6         BothMem:Region   3  63  6.078 16.4  7.791 0.0001671     * 0.02483
7         Emotion:Region   3  63  7.185 31.5  4.782 0.0045822     * 0.02921
8 BothMem:Emotion:Region   3  63  0.297 14.1  0.442 0.7234704       0.00124

$`Mauchly's Test for Sphericity`
                  Effect     W      p p<.05
4                 Region 0.517 0.0236     *
6         BothMem:Region 0.515 0.0229     *
7         Emotion:Region 0.645 0.1243      
8 BothMem:Emotion:Region 0.432 0.0055     *

$`Sphericity Corrections`
                  Effect   GGe   p[GG] p[GG]<.05   HFe    p[HF] p[HF]<.05
4                 Region 0.721 0.06791           0.807 0.060881          
6         BothMem:Region 0.699 0.00108         * 0.778 0.000661         *
7         Emotion:Region 0.818 0.00822         * 0.935 0.005648         *
8 BothMem:Emotion:Region 0.655 0.64192           0.722 0.660713          
rm(statdata1,anova_mod1)

4 Follow-up tests

4.1 Amygdala vs PRC

statdata1 <- subset(actdata.rec,RegionAP=="PRC" | Region=="Amyg") 
summary(droplevels(statdata1$Region)) # Note that hemisphere is still included but ezANOVA will average them
Amyg  PRC 
 176  176 
anova_mod1<-ezANOVA(statdata1,dv=activity,wid=subject,within=list(BothMem,Emotion,Region),type=3,detailed=TRUE)
print(anova_mod1$ANOVA)
statdata2 <- subset(actdata.rec,RegionAP=="PRC" )
anova_mod2<-ezANOVA(statdata2,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod2$ANOVA)
statdata3 <- subset(actdata.rec,Region=="Amyg")
anova_mod3<-ezANOVA(statdata3,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod3$ANOVA)
rm(statdata1,statdata2,statdata3,anova_mod1,anova_mod2,anova_mod3)

4.2 PHC vs whole hippocampus

statdata1 <- subset(actdata.rec,RegionAP=="wholeHipp" | Region=="PHC") 
summary(droplevels(statdata1$Region)) # Note that hemisphere is still included but ezANOVA will average them
      PHC wholeHipp 
      176       176 
anova_mod1<-ezANOVA(statdata1,dv=activity,wid=subject,within=list(BothMem,Emotion,Region),type=3,detailed=TRUE)
print(anova_mod1$ANOVA)
statdata2 <- subset(actdata.rec,RegionAP=="wholeHipp" )
anova_mod2<-ezANOVA(statdata2,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod2$ANOVA)
statdata3 <- subset(actdata.rec,Region=="PHC")
anova_mod3<-ezANOVA(statdata3,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod3$ANOVA)
rm(statdata1,statdata2,statdata3,anova_mod1,anova_mod2,anova_mod3)

4.3 Amygdala vs whole hippocampus

statdata1 <- subset(actdata.rec,RegionAP=="wholeHipp" | Region=="Amyg") 
summary(droplevels(statdata1$Region)) # Note that hemisphere is still included but ezANOVA will average them
     Amyg wholeHipp 
      176       176 
anova_mod1<-ezANOVA(statdata1,dv=activity,wid=subject,within=list(BothMem,Emotion,Region),type=3,detailed=TRUE)
print(anova_mod1$ANOVA)
statdata2 <- subset(actdata.rec,RegionAP=="wholeHipp" )
anova_mod2<-ezANOVA(statdata2,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod2$ANOVA)
statdata3 <- subset(actdata.rec,Region=="Amyg")
anova_mod3<-ezANOVA(statdata3,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod3$ANOVA)
rm(statdata1,statdata2,statdata3,anova_mod1,anova_mod2,anova_mod3)

4.4 Subregions within amygdala

statdata1 <- subset(actdata.rec,MainRegion=="Amyg")
summary(droplevels(statdata1$Region))
 BasolatAmyg  CentralAmyg CorticalAmyg   MedialAmyg 
         176          176          176          176 
anova_mod1<-ezANOVA(statdata1,dv=activity,wid=subject,within=list(BothMem,Emotion,Region),type=3,detailed=TRUE)
print(anova_mod1)
$ANOVA
                  Effect DFn DFd      SSn   SSd       F        p p<.05      ges
1            (Intercept)   1  21 128.3956 125.0 21.5705 0.000139     * 0.151510
2                BothMem   1  21   0.0438  48.3  0.0191 0.891486       0.000061
3                Emotion   1  21  31.9045 108.7  6.1660 0.021548     * 0.042486
4                 Region   3  63  27.5015 174.9  3.3028 0.025861     * 0.036838
5        BothMem:Emotion   1  21   0.3365  36.5  0.1937 0.664322       0.000468
6         BothMem:Region   3  63   0.4582  54.1  0.1778 0.911030       0.000637
7         Emotion:Region   3  63   3.6340 131.8  0.5789 0.631021       0.005028
8 BothMem:Emotion:Region   3  63   1.5538  39.8  0.8190 0.488233       0.002156

$`Mauchly's Test for Sphericity`
                  Effect     W       p p<.05
4                 Region 0.681 0.18170      
6         BothMem:Region 0.421 0.00446     *
7         Emotion:Region 0.794 0.47438      
8 BothMem:Emotion:Region 0.774 0.41049      

$`Sphericity Corrections`
                  Effect   GGe  p[GG] p[GG]<.05   HFe  p[HF] p[HF]<.05
4                 Region 0.842 0.0341         * 0.967 0.0274         *
6         BothMem:Region 0.625 0.8244           0.685 0.8431          
7         Emotion:Region 0.869 0.6081           1.004 0.6310          
8 BothMem:Emotion:Region 0.880 0.4756           1.018 0.4882          
statdata2 <- subset(actdata.rec,Region=="BasolatAmyg")
anova_mod2<-ezANOVA(statdata2,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod2$ANOVA)
statdata3 <- subset(actdata.rec,Region=="CentralAmyg")
anova_mod3<-ezANOVA(statdata3,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod3$ANOVA)
statdata4 <- subset(actdata.rec,Region=="CorticalAmyg")
anova_mod4<-ezANOVA(statdata4,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod4$ANOVA)
statdata5 <- subset(actdata.rec,Region=="MedialAmyg")
anova_mod5<-ezANOVA(statdata5,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod5$ANOVA)
rm(statdata1,statdata2,statdata3,statdata4,statdata5,anova_mod1,anova_mod2,anova_mod3,anova_mod4,anova_mod5)

4.5 Posterior vs anterior hippocampus

statdata1 <- subset(actdata.rec,(RegionAP=="wholeHipp.head" | RegionAP=="wholeHipp.body"))
summary(droplevels(statdata1$RegionAP))
wholeHipp.body wholeHipp.head 
           176            176 
anova_mod1<-ezANOVA(statdata1,dv=activity,wid=subject,within=list(BothMem,Emotion,RegionAP),type=3,detailed=TRUE)
print(anova_mod1$ANOVA)
statdata2 <- subset(actdata.rec,(RegionAP=="wholeHipp.head") )
anova_mod2<-ezANOVA(statdata2,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod2$ANOVA)
statdata3 <- subset(actdata.rec,(RegionAP=="wholeHipp.body" ) )
anova_mod3<-ezANOVA(statdata3,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod3$ANOVA)
rm(statdata1,statdata2,statdata3,anova_mod1,anova_mod2,anova_mod3)

4.6 Subregions within posterior hippocampus

statdata1 <- subset(actdata.rec,MainRegion=="Hipp")
summary(droplevels(statdata1$Region))
      CA1    CA23DG subiculum 
      176       176       176 
anova_mod<-ezANOVA(statdata1,dv=activity,wid=subject,within=list(BothMem,Emotion,Region),type=3,detailed=TRUE)
print(anova_mod)
$ANOVA
                  Effect DFn DFd     SSn   SSd       F       p p<.05       ges
1            (Intercept)   1  21  9.9296 113.3 1.83974 0.18939       0.0216324
2                BothMem   1  21 14.2476  30.6 9.76278 0.00512     * 0.0307503
3                Emotion   1  21  0.1385  83.5 0.03484 0.85372       0.0003084
4                 Region   2  42  5.9476  77.0 1.62135 0.20976       0.0130708
5        BothMem:Emotion   1  21  0.5762  29.4 0.41086 0.52847       0.0012814
6         BothMem:Region   2  42  0.2287  28.4 0.16916 0.84495       0.0005089
7         Emotion:Region   2  42  0.0276  58.2 0.00994 0.99011       0.0000614
8 BothMem:Emotion:Region   2  42  0.6745  28.5 0.49711 0.61182       0.0014997

$`Mauchly's Test for Sphericity`
                  Effect     W      p p<.05
4                 Region 0.717 0.0361     *
6         BothMem:Region 0.715 0.0351     *
7         Emotion:Region 0.832 0.1585      
8 BothMem:Emotion:Region 0.631 0.0101     *

$`Sphericity Corrections`
                  Effect   GGe p[GG] p[GG]<.05   HFe p[HF] p[HF]<.05
4                 Region 0.780 0.215           0.831 0.214          
6         BothMem:Region 0.778 0.791           0.829 0.805          
7         Emotion:Region 0.856 0.982           0.925 0.987          
8 BothMem:Emotion:Region 0.731 0.555           0.772 0.565          
statdata2 <- subset(actdata.rec,Region=="CA1")
anova_mod2<-ezANOVA(statdata2,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod2$ANOVA)
statdata3 <- subset(actdata.rec,Region=="CA23DG")
anova_mod3<-ezANOVA(statdata3,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod3$ANOVA)
statdata4 <- subset(actdata.rec,Region=="subiculum")
anova_mod4<-ezANOVA(statdata4,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod4$ANOVA)
rm(statdata1,anova_mod,statdata2,statdata3,statdata4,anova_mod2,anova_mod3,anova_mod4)

4.7 PRC vs PHC

statdata1 <- subset(actdata.rec,(Region=="PRC" | Region=="PHC") )
anova_mod<-ezANOVA(statdata1,dv=activity,wid=subject,within=list(BothMem,Emotion,Region),type=3,detailed=TRUE)
print(anova_mod$ANOVA)
statdata2 <- subset(actdata.rec,(Region=="PRC") )
anova_mod2<-ezANOVA(statdata2,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod2$ANOVA)
statdata3 <- subset(actdata.rec,Region=="PHC" )
anova_mod3<-ezANOVA(statdata3,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
print(anova_mod3$ANOVA)
rm(statdata1,statdata2,statdata3,anova_mod1,anova_mod2,anova_mod3)

5 ROI maps

plotROImap <- function(values,colornames) {
  
  ids <- factor(c("Amyg","PRC","PHC","wholeHipp.head","wholeHipp.body","subiculum.body","CA1.body","CA23DG.body","CorticalAmyg","CentralAmyg","MedialAmyg","BasolatAmyg"))
  nid <- length(ids)
  
  # Define polygon coordinates (in this case, 4 each for a rectangle)
  positions <- data.frame(
    id = rep(ids, each = 4),
    order = rep(c(1,2,3,4),nid),
    x = c(1,2,2,1,
          1.5,3,3,1.5,
          3,4,4,3,
          2,3,3,2,
          3,4,4,3,
          3,4,4,3,
          3,4,4,3,
          3,4,4,3,
          1,2,2,1,
          1,2,2,1,
          1,2,2,1,
          1,2,2,1),
    y = c(2,2,3,3,
          1,1,2,2,
          1,1,2,2,
          2,2,3,3,
          2,2,3,3,
          2,2,2.3333,2.3333,
          2.3333,2.3333,2.6666,2.6666,
          2.6666,2.6666,3,3,
          2,2,2.25,2.25,
          2.25,2.25,2.5,2.5,
          2.5,2.5,2.75,2.75,
          2.75,2.75,3,3)
  )
  
  # Calculate midpoint of each poly for label
  positions %>%
    group_by(id) %>%
    summarize(label_x = mean(x),
              label_y = mean(y)) %>%
    left_join(values) %>%
    filter(!is.na(value) & !is.null(value) & value!="NULL") -> values
  
  # Merge id & label info with positions
  datapoly <- merge(values, positions, by=c("id")) %>%
    arrange(id,order) %>%
    ungroup()
  
  # Prettier labels
  values$id[values$id=="wholeHipp.head"] <- "Hipp.ant"
  values$id[values$id=="wholeHipp.body"] <- "Hipp.post"
  
  values$id[values$id=="BasolatAmyg"] <- "Amyg.basolateral"
  values$id[values$id=="MedialAmyg"] <- "Amyg.basomedial"
  values$id[values$id=="CentralAmyg"] <- "Amyg.centromedial"
  values$id[values$id=="CorticalAmyg"] <- "Amyg.cortical"
  # Plot polygons with values coding fill color
  p <- ggplot(datapoly, aes(x=x, y=y)) + geom_polygon(colour="black",aes(fill=value, group=id)) +
    theme_minimal(20) + 
    theme(axis.text = element_blank(),axis.ticks = element_blank()) +
    theme(panel.grid.major = element_blank(),panel.grid.minor=element_blank()) + 
    xlab('') + ylab('') + 
    scale_fill_gradient(low=colornames[1],high=colornames[2],limits=c(0,NA),na.value="gray60",name="effect size") + 
    geom_text(data=values,size=8,aes(label=id,x=label_x,y=label_y))
  return(p)
}

5.1 Get stats summary info for plots

getAnovaEffectSize <- function(df,effectrow) {
  df <- data.frame(df) # bc ezANOVA hates grouped dataframes
  anova_mod <- ezANOVA(df,dv=activity,wid=subject,within=list(BothMem,Emotion),type=3,detailed=TRUE)
  effectsize <- anova_mod$ANOVA[9][[1]][effectrow]
  return(effectsize)
}
actdata.rec %>%
  filter(RegionAP %in% c("Amyg","wholeHipp.head","wholeHipp.body","PHC","PRC")) %>%
  group_by(RegionAP) %>%
  do(memory = getAnovaEffectSize(.,1),
     source = getAnovaEffectSize(.,2),
     emotion = getAnovaEffectSize(.,3)) %>%
  unnest() -> effectsizes.roi
actdata.rec %>%
  filter(RegionAP %in% c("CorticalAmyg","CentralAmyg","MedialAmyg","BasolatAmyg","CA1.body","CA23DG.body","subiculum.body","wholeHipp.head","PHC","PRC")) %>%
  group_by(RegionAP) %>%
  do(memory = getAnovaEffectSize(.,1),
     source = getAnovaEffectSize(.,2),
     emotion = getAnovaEffectSize(.,3)) %>%
  unnest() -> effectsizes.roi.subreg
print(effectsizes.roi)
print(effectsizes.roi.subreg)

5.2 Major subdivisions

map.mem <- data.frame(id=as.character(effectsizes.roi$RegionAP),value=as.numeric(effectsizes.roi$memory))
plotROImap(map.mem,c('white','orange')) + ggtitle("Recollection-related activity")

map.emo <- data.frame(id=as.character(effectsizes.roi$RegionAP),value=as.numeric(effectsizes.roi$emotion))
plotROImap(map.emo,c('white','tomato')) + ggtitle("Effect of emotion on recollection-related activity")

map.src <- data.frame(id=as.character(effectsizes.roi$RegionAP),value=as.numeric(effectsizes.roi$source))
plotROImap(map.src,c('white','skyblue1')) + ggtitle("Effect of context encoding on recollection-related activity")

5.3 With subregions

map.mem2 <- data.frame(id=as.character(effectsizes.roi.subreg$RegionAP),value=as.numeric(effectsizes.roi.subreg$memory))
plotROImap(map.mem2,c('white','orange')) + ggtitle("Recollection-related activity")

map.emo2 <- data.frame(id=as.character(effectsizes.roi.subreg$RegionAP),value=as.numeric(effectsizes.roi.subreg$emotion))
plotROImap(map.emo2,c('white','tomato')) + ggtitle("Effect of emotion on recollection-related activity")

map.src2 <- data.frame(id=as.character(effectsizes.roi.subreg$RegionAP),value=as.numeric(effectsizes.roi.subreg$source))
plotROImap(map.src2,c('white','skyblue1')) + ggtitle("Effect of context encoding on recollection-related activity")

LS0tCnRpdGxlOiAiTWVtb0hSIGZNUkkgUk9JIEFjdGl2YXRpb24gRGF0YSIKYXV0aG9yOiAiTWF1cmVlbiBSaXRjaGV5IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwotLS0KCmBgYHtyIGluaXQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoJ2dncGxvdDInKQpsaWJyYXJ5KCdkcGx5cicpIApsaWJyYXJ5KCd0aWR5cicpCmxpYnJhcnkoJ2tuaXRyJykKbGlicmFyeSgnZXonKQpvcHRpb25zKGRpZ2l0cz0zKQpvcHRpb25zKHNjaXBlbiA9IDk5OSkKYGBgCgoKIyBMb2FkICYgUHJvY2VzcyBkYXRhCmBgYHtyfQoKc2F2ZXBhdGggPC0gJy4uLy4uL0FuYWx5c2lzL1JPSV9lc3RpbWF0ZXMvJwpiZWhhdnBhdGggPC0gJy4uLy4uL0RhdGEvQmVoYXZpb3JhbC9zdW1tYXJ5LycKCiMjIExvYWQgZGF0YSBmcm9tIGNzdgojIyMgQWN0aXZhdGlvbiBlc3RpbWF0ZXMKYWN0ZGF0YTwtcmVhZC5jc3YocGFzdGUwKHNhdmVwYXRoLCdjb25zX2FzaHNfSXRlbVNvdXJjZURNX3JmX25ldy5jc3YnKSkgIyBjcmVhdGVkIHdpdGggb3V0cHV0X3JvaV9jb25zIHNjcmlwdCBpbiBNYXRsYWIKCiMjIyBST0kgbWV0YWRhdGEKcm9pZGF0YTwtcmVhZC5jc3YoJy4uLy4uL0FuYWx5c2lzL1JPSV9lc3RpbWF0ZXMvcm9pX2luZm8uY3N2JykgIyBjb250YWlucyB2YXJpb3VzIGxhYmVsaW5nIHNjaGVtZXMgZm9yIFJPSXMKYWN0ZGF0YSA8LSBtZXJnZShhY3RkYXRhLHJvaWRhdGEsYnk9InJvaV9maWxlIikKcm0ocm9pZGF0YSkKCiMjIyBDbGVhbiB1cCBkYXRhCiMgZmlyc3QgZGVhbCB3aXRoIHMyMSwgd2hvIGhhZCB0byBoYXZlIEVtb0sgc3ViYmVkIGluIGZvciBFbW9NIChubyBFbW9NIHRyaWFscykKYWN0ZGF0YSA8LSB1bmlxdWUoYWN0ZGF0YSkgIyByZW1vdmUgZG91YmxlZC11cCBFbW9LCnRtcCA8LXN1YnNldChhY3RkYXRhLHN1YmplY3Q9PSJzMjEiICYgY29udHJhc3Q9PSJFbW9LIikgIyBnZXQgdGhlIEVtb0sgZm9yIHJlbGFiZWwgLT4gdGhlc2UgdHJpYWwgdHlwZXMgZ2V0IGF2ZXJhZ2VkIGFueXdheQp0bXAkY29udHJhc3QgPC0gIkVtb00iCmFjdGRhdGEgPC0gcmJpbmQoYWN0ZGF0YSx0bXApICMgcHVsbCBiYWNrIGludG8gbWFpbiBkYXRhZnJhbWUKCiMjIyBEZWZpbmUgbmV3IHZhcmlhYmxlcwphY3RkYXRhJEVtb3Rpb24gPC0gZmFjdG9yKHNhcHBseShhY3RkYXRhJGNvbnRyYXN0LHNpbXBsaWZ5PVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIGlmZWxzZShncmVwbCgnRW1vJyx4KSwnRW1vJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShncmVwbCgnTmV1Jyx4KSwnTmV1JyxOQSkpKSkKYWN0ZGF0YSA8LSBzdWJzZXQoYWN0ZGF0YSwhaXMubmEoYWN0ZGF0YSRFbW90aW9uKSkgIyBnZXQgcmlkIG9mIGFsbCBvdGhlciBjb250cmFzdHMKCgphY3RkYXRhJFJlY01lbSA8LSBmYWN0b3Ioc2FwcGx5KGFjdGRhdGEkY29udHJhc3Qsc2ltcGxpZnk9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KSBpZmVsc2UoZ3JlcGwoJ1InLHgpLCdSZWMnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZ3JlcGwoJ0snLHgpLCdOb24tUmVjJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShncmVwbCgnTScseCksJ05vbi1SZWMnLE5BKSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscz1jKCJSZWMiLCJOb24tUmVjIikpCmFjdGRhdGEkU291cmNlTWVtIDwtIGZhY3RvcihzYXBwbHkoYWN0ZGF0YSRjb250cmFzdCxzaW1wbGlmeT1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIGlmZWxzZShncmVwbCgnU0MnLHgpLCdDb3JyJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGdyZXBsKCdTSScseCksJ0luY29ycicsTkEpKSkpCgphY3RkYXRhJEJvdGhNZW0gPC0gZmFjdG9yKGlmZWxzZShhY3RkYXRhJFJlY01lbT09IlJlYyIgJiBhY3RkYXRhJFNvdXJjZU1lbT09IkNvcnIiLCJSK1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoYWN0ZGF0YSRSZWNNZW09PSJSZWMiICYgYWN0ZGF0YSRTb3VyY2VNZW09PSJJbmNvcnIiLCJSLVMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGFjdGRhdGEkUmVjTWVtPT0iTm9uLVJlYyIsIk5SIixOQSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygiUitTIiwiUi1TIiwiTlIiKSkKCnN0cihhY3RkYXRhKQprYWJsZSh0YWJsZShhY3RkYXRhJEJvdGhNZW0sYWN0ZGF0YSRzdWJqZWN0KSkKCiMjIENyZWF0ZSBkYXRhZnJhbWUgd2l0aCAnYmFzZWxpbmUtY29ycmVjdGVkJyBzY29yZXMsIGkuZS4sIHJlY29sbGVjdGlvbiB0cmlhbCB0eXBlcyBtaW51cyBub24tcmVjb2xsZWN0aW9uCm5yYmFzZWxpbmUgPC0KICBncm91cF9ieShhY3RkYXRhLHN1YmplY3QsRW1vdGlvbixyb2lfZmlsZSkgJT4lCiAgc3VtbWFyaXplKG5yLmJhc2VsaW5lID0gbWVhbihhY3Rpdml0eVtSZWNNZW09PSJOb24tUmVjIl0sbmEucm09VFJVRSkpICMgYXZlcmFnZSBvdmVyIEZhbSAmIE1pc3MKYWN0ZGF0YS5yZWMgPC0KICBmaWx0ZXIoYWN0ZGF0YSxSZWNNZW09PSJSZWMiKSAlPiUKICBsZWZ0X2pvaW4obnJiYXNlbGluZSkgICU+JQogIG11dGF0ZShhY3Rpdml0eSA9IGFjdGl2aXR5IC0gbnIuYmFzZWxpbmUpICMgdmFsdWVzIGluIGFjdGRhdGEucmVjIGFyZSBub3cgcmVjb2xsZWN0aW9uLXJlbGF0ZWQgYWN0aXZpdHkKICAKIyMgQ2xlYW4gdXAgYW5kIHNhdmUKc2F2ZShhY3RkYXRhLGZpbGU9cGFzdGUwKHNhdmVwYXRoLCdNZW1vSFJfQW5hdFJPSV9EYXRhX0l0ZW1Tb3VyY2UuUmRhdGEnKSkKCmBgYAoKIyMgUmVwb3J0IG51bWJlciBvZiB2b3hlbHMgaW4gZWFjaCBST0kKYGBge3IgbnVtVm94fQp2b3ggPC0gZ3JvdXBfYnkoYWN0ZGF0YSxSZWdpb25BUCkgJT4lCiAgc3VtbWFyaXplKG1lYW52b3g9bWVhbihudW12b3gpLAogICAgICAgICAgICBtaW52b3g9bWluKG51bXZveCksCiAgICAgICAgICAgIG1heHZveD1tYXgobnVtdm94KSkKa2FibGUodm94KQpgYGAKCiMgUGxvdHMKIyMgQ2FsY3VsYXRlIHN1bW1hcnkgdmFsdWVzIGZpcnN0CmBgYHtyIGNhbGNTdW1tYXJ5fQpzdW1tYXJ5ZGF0YS5hbGwgPC0gZ3JvdXBfYnkoYWN0ZGF0YSxzdWJqZWN0LEVtb3Rpb24sUmVjTWVtLFNvdXJjZU1lbSxSZWdpb24sUmVnaW9uQVAsTWFpblJlZ2lvbixBUCkgJT4lCiAgc3VtbWFyaXplKGFjdGl2aXR5PW1lYW4oYWN0aXZpdHkpKSAjIFRoaXMgcGFydCBhdmVyYWdlcyBhY3Jvc3MgaGVtaXNwaGVyZXMsIGFuZCBmYW0vbWlzcyBhcmUgYXZlcmFnZWQgaW50byBub24tcmVjCm1lYW5kYXRhLmFsbCA8LSBncm91cF9ieShzdW1tYXJ5ZGF0YS5hbGwsUmVnaW9uLFJlZ2lvbkFQLE1haW5SZWdpb24sQVAsRW1vdGlvbikgJT4lCiAgZ3JvdXBfYnkoRW1vdGlvbixSZWNNZW0sU291cmNlTWVtLFJlZ2lvbixSZWdpb25BUCxNYWluUmVnaW9uLEFQKSAlPiUKICBzdW1tYXJpemUobWVhbnZhbD1tZWFuKGFjdGl2aXR5LG5hLnJtPVRSVUUpLHNkdmFsPXNkKGFjdGl2aXR5LG5hLnJtPVRSVUUpLAogICAgICAgICAgICBzZW09c2R2YWwvc3FydChsZW5ndGgoYWN0aXZpdHkpKSwKICAgICAgICAgICAgc2VtbWluPW1lYW52YWwtc2VtLAogICAgICAgICAgICBzZW1tYXg9bWVhbnZhbCtzZW0sCiAgICAgICAgICAgIG5zdWJqPWxlbmd0aChhY3Rpdml0eSkpCm1lYW5kYXRhLmFsbCRFbW9NZW0gPC0gaW50ZXJhY3Rpb24obWVhbmRhdGEuYWxsJFJlY01lbSxtZWFuZGF0YS5hbGwkRW1vdGlvbikKbWVhbmRhdGEuYWxsJE1lbU1lbSA8LSBpbnRlcmFjdGlvbihtZWFuZGF0YS5hbGwkUmVjTWVtLG1lYW5kYXRhLmFsbCRTb3VyY2VNZW0pCm1lYW5kYXRhLmFsbCRNZW1NZW0gPC0gZmFjdG9yKG1lYW5kYXRhLmFsbCRNZW1NZW0sbGV2ZWxzPWMoIlJlYy5Db3JyIiwiUmVjLkluY29yciIsIk5vbi1SZWMiKSkKbWVhbmRhdGEuYWxsJE1lbU1lbVtpcy5uYShtZWFuZGF0YS5hbGwkTWVtTWVtKV0gPC0gIk5vbi1SZWMiCgpzdW1tYXJ5ZGF0YS5yZWMgPC0gZ3JvdXBfYnkoYWN0ZGF0YS5yZWMsc3ViamVjdCxFbW90aW9uLFJlY01lbSxTb3VyY2VNZW0sUmVnaW9uLFJlZ2lvbkFQLE1haW5SZWdpb24sQVApICU+JQogIHN1bW1hcml6ZShhY3Rpdml0eT1tZWFuKGFjdGl2aXR5KSkgICMgVGhpcyBwYXJ0IGF2ZXJhZ2VzIGFjcm9zcyBoZW1pc3BoZXJlcwptZWFuZGF0YS5yZWMgPC0gZ3JvdXBfYnkoc3VtbWFyeWRhdGEucmVjLFJlZ2lvbixSZWdpb25BUCxNYWluUmVnaW9uLEFQLEVtb3Rpb24pICU+JQogIGdyb3VwX2J5KEVtb3Rpb24sUmVjTWVtLFNvdXJjZU1lbSxSZWdpb24sUmVnaW9uQVAsTWFpblJlZ2lvbixBUCkgJT4lCiAgc3VtbWFyaXplKG1lYW52YWw9bWVhbihhY3Rpdml0eSxuYS5ybT1UUlVFKSxzZHZhbD1zZChhY3Rpdml0eSxuYS5ybT1UUlVFKSwKICAgICAgICAgICAgc2VtPXNkdmFsL3NxcnQobGVuZ3RoKGFjdGl2aXR5KSksCiAgICAgICAgICAgIHNlbW1pbj1tZWFudmFsLXNlbSwKICAgICAgICAgICAgc2VtbWF4PW1lYW52YWwrc2VtLAogICAgICAgICAgICBuc3Viaj1sZW5ndGgoYWN0aXZpdHkpKQptZWFuZGF0YS5yZWMkRW1vTWVtIDwtIGludGVyYWN0aW9uKG1lYW5kYXRhLnJlYyRSZWNNZW0sbWVhbmRhdGEucmVjJEVtb3Rpb24pCm1lYW5kYXRhLnJlYyRNZW1NZW0gPC0gaW50ZXJhY3Rpb24obWVhbmRhdGEucmVjJFJlY01lbSxtZWFuZGF0YS5yZWMkU291cmNlTWVtKQptZWFuZGF0YS5yZWMkTWVtTWVtIDwtIGZhY3RvcihtZWFuZGF0YS5yZWMkTWVtTWVtLGxldmVscz1jKCJSZWMuQ29yciIsIlJlYy5JbmNvcnIiLCJOb24tUmVjIikpCm1lYW5kYXRhLnJlYyRNZW1NZW1baXMubmEobWVhbmRhdGEucmVjJE1lbU1lbSldIDwtICJOb24tUmVjIgpgYGAKCiMjIFBsb3RzIHdpdGggYWxsIGJhcnMKIyMjIE1haW4gcmVnaW9ucwoKYGBge3IsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQoKIyBBbGwgcmVnaW9ucwpwbG90Y29sb3JzIDwtIGMoJyNkMDFjOGInLCcjZjFiNmRhJywiZ3JheTcwIiwnIzRkYWMyNicsJyNiOGUxODYnLCJncmF5NzAiKQoKbWVhbmRhdGEuYWxsICU+JQogIGZpbHRlcihSZWdpb25BUD09IkFteWciIHwgUmVnaW9uQVA9PSJ3aG9sZUhpcHAiKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKFJlZ2lvbkFQID0gZmFjdG9yKFJlZ2lvbkFQLGxldmVscz1jKCJBbXlnIiwid2hvbGVIaXBwIikpLAogICAgICAgICBSZWdpb25MYWJlbCA9IGZhY3RvcihpZmVsc2UoUmVnaW9uQVA9PSJ3aG9sZUhpcHAiLCJIaXBwIiwiQW15ZyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygiQW15ZyIsIkhpcHAiKSksCiAgICAgICAgIE1lbW9yeUNvbmQgPSBmYWN0b3IoaWZlbHNlKE1lbU1lbT09IlJlYy5Db3JyIiwiUmVjICsgU3JjIixpZmVsc2UoTWVtTWVtPT0iUmVjLkluY29yciIsIlJlYyAtIFNyYyIsIk5vbi1SZWMiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzPWMoIlJlYyArIFNyYyIsIlJlYyAtIFNyYyIsIk5vbi1SZWMiKSksCiAgICAgICAgIEVtb01lbSA9IGludGVyYWN0aW9uKE1lbW9yeUNvbmQsRW1vdGlvbikpICU+JQogIGdncGxvdCguLGFlcyh4PU1lbW9yeUNvbmQseT1tZWFudmFsKSkgKyBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb249ImRvZGdlIixhZXMoZmlsbD1FbW9NZW0pKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1tZWFudmFsLXNlbSx5bWF4PW1lYW52YWwrc2VtLHdpZHRoPS4yNSkpICsgdGhlbWVfbWluaW1hbCgxOCkgKwogIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpICsgZmFjZXRfZ3JpZCguflJlZ2lvbkxhYmVsK0Vtb3Rpb24pICsKICB4bGFiKCJNZWFuIGFjdGl2aXR5IChhdSkiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1wbG90Y29sb3JzKSArICBndWlkZXMoY29sb3I9RkFMU0UsIGZpbGw9RkFMU0UpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwgaGp1c3QgPSAxKSkKCm1lYW5kYXRhLmFsbCAlPiUKICBmaWx0ZXIoUmVnaW9uQVA9PSJQSEMiIHwgUmVnaW9uQVA9PSJQUkMiKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKFJlZ2lvbkFQID0gZmFjdG9yKFJlZ2lvbkFQLGxldmVscz1jKCJQUkMiLCJQSEMiKSksCiAgICAgICAgIE1lbW9yeUNvbmQgPSBmYWN0b3IoaWZlbHNlKE1lbU1lbT09IlJlYy5Db3JyIiwiUmVjICsgU3JjIixpZmVsc2UoTWVtTWVtPT0iUmVjLkluY29yciIsIlJlYyAtIFNyYyIsIk5vbi1SZWMiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzPWMoIlJlYyArIFNyYyIsIlJlYyAtIFNyYyIsIk5vbi1SZWMiKSksCiAgICAgICAgIEVtb01lbSA9IGludGVyYWN0aW9uKE1lbW9yeUNvbmQsRW1vdGlvbikpICU+JQogIGdncGxvdCguLGFlcyh4PU1lbW9yeUNvbmQseT1tZWFudmFsKSkgKyBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb249ImRvZGdlIixhZXMoZmlsbD1FbW9NZW0pKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1tZWFudmFsLXNlbSx5bWF4PW1lYW52YWwrc2VtLHdpZHRoPS4yNSkpICsgdGhlbWVfbWluaW1hbCgxOCkgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSArIGZhY2V0X2dyaWQoLn5SZWdpb25BUCtFbW90aW9uKSArCiAgeGxhYigiTWVhbiBhY3Rpdml0eSAoYXUpIikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9cGxvdGNvbG9ycykgKyAgZ3VpZGVzKGNvbG9yPUZBTFNFLCBmaWxsPUZBTFNFKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIGhqdXN0ID0gMSkpCgpgYGAKCiMjIFBsb3RzIHdpdGggYmFycyBzdWJ0cmFjdGluZyBub24tcmVjb2xsZWN0aW9uCgojIyMgU2luZ2xlIFBsb3RzCmBgYHtyfQpwbG90Y29sb3JzIDwtIGMoJyNkMDFjOGInLCcjZjFiNmRhJywnIzRkYWMyNicsJyNiOGUxODYnKQoKc2luZ2xlUGxvdFJPSSA8LSBmdW5jdGlvbihyb2kpIHsKICBtZWFuZGF0YS5yZWMgJT4lCiAgZmlsdGVyKFJlZ2lvbkFQPT1yb2kpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoTWVtb3J5Q29uZCA9IGZhY3RvcihpZmVsc2UoTWVtTWVtPT0iUmVjLkNvcnIiLCJSZWMgKyBTcmMiLGlmZWxzZShNZW1NZW09PSJSZWMuSW5jb3JyIiwiUmVjIC0gU3JjIiwiTm9uLVJlYyIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygiUmVjICsgU3JjIiwiUmVjIC0gU3JjIiwiTm9uLVJlYyIpKSwKICAgICAgICAgRW1vTWVtID0gaW50ZXJhY3Rpb24oTWVtb3J5Q29uZCxFbW90aW9uKSkgJT4lCiAgZ2dwbG90KC4sYWVzKHg9TWVtb3J5Q29uZCx5PW1lYW52YWwpKSArIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj0iZG9kZ2UiLGFlcyhmaWxsPUVtb01lbSkpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPW1lYW52YWwtc2VtLHltYXg9bWVhbnZhbCtzZW0sd2lkdGg9LjI1KSkgKyB0aGVtZV9taW5pbWFsKDE4KSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpICsgZmFjZXRfZ3JpZCgufkVtb3Rpb24sc3dpdGNoPSJ4IikgKwogIHlsYWIoIlJlY29sbGVjdGlvbi1yZWxhdGVkIGFjdGl2aXR5IikgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9cGxvdGNvbG9ycykgKyBndWlkZXMoY29sb3I9RkFMU0UpICsKICAgIGdndGl0bGUocm9pKSAKfQpzaW5nbGVQbG90Uk9JX2ZpeGVkTGltIDwtIGZ1bmN0aW9uKHJvaSxsaW1pdHMpIHsgIyBmaXggbGltaXRzIGZvciBzb21lIHBsb3RzIGZvciBiZXR0ZXIgdmlzdWFsaXphdGlvbgogIHNpbmdsZVBsb3RST0kocm9pKSArIHlsaW0obGltaXRzKQp9CgojIFBsb3QgYWxsIHJlZ2lvbnMKc2luZ2xlUGxvdFJPSV9maXhlZExpbSgnQW15ZycsYygtLjI1LDEpKQpzaW5nbGVQbG90Uk9JX2ZpeGVkTGltKCd3aG9sZUhpcHAnLGMoLS4yNSwxKSkKc2luZ2xlUGxvdFJPSSgnUFJDJykKc2luZ2xlUGxvdFJPSSgnUEhDJykKYGBgCgojIFN0YXRzCgojIyBBbGwgcmVnaW9ucwpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc3RhdGRhdGExIDwtIHN1YnNldChhY3RkYXRhLnJlYyxSZWdpb25BUD09Indob2xlSGlwcCIgfCBSZWdpb249PSJBbXlnIiAgfCBSZWdpb249PSJQUkMiICB8IFJlZ2lvbj09IlBIQyIpIApzdW1tYXJ5KGRyb3BsZXZlbHMoc3RhdGRhdGExJFJlZ2lvbikpICMgTm90ZSB0aGF0IGhlbWlzcGhlcmUgaXMgc3RpbGwgaW5jbHVkZWQgYnV0IGV6QU5PVkEgd2lsbCBhdmVyYWdlIHRoZW0KYW5vdmFfbW9kMTwtZXpBTk9WQShzdGF0ZGF0YTEsZHY9YWN0aXZpdHksd2lkPXN1YmplY3Qsd2l0aGluPWxpc3QoQm90aE1lbSxFbW90aW9uLFJlZ2lvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDEpCgpybShzdGF0ZGF0YTEsYW5vdmFfbW9kMSkKYGBgCgojIEZvbGxvdy11cCB0ZXN0cwojIyBBbXlnZGFsYSB2cyBQUkMKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN0YXRkYXRhMSA8LSBzdWJzZXQoYWN0ZGF0YS5yZWMsUmVnaW9uQVA9PSJQUkMiIHwgUmVnaW9uPT0iQW15ZyIpIApzdW1tYXJ5KGRyb3BsZXZlbHMoc3RhdGRhdGExJFJlZ2lvbikpICMgTm90ZSB0aGF0IGhlbWlzcGhlcmUgaXMgc3RpbGwgaW5jbHVkZWQgYnV0IGV6QU5PVkEgd2lsbCBhdmVyYWdlIHRoZW0KYW5vdmFfbW9kMTwtZXpBTk9WQShzdGF0ZGF0YTEsZHY9YWN0aXZpdHksd2lkPXN1YmplY3Qsd2l0aGluPWxpc3QoQm90aE1lbSxFbW90aW9uLFJlZ2lvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDEkQU5PVkEpCgpzdGF0ZGF0YTIgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbkFQPT0iUFJDIiApCmFub3ZhX21vZDI8LWV6QU5PVkEoc3RhdGRhdGEyLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDIkQU5PVkEpCgpzdGF0ZGF0YTMgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbj09IkFteWciKQphbm92YV9tb2QzPC1lekFOT1ZBKHN0YXRkYXRhMyxkdj1hY3Rpdml0eSx3aWQ9c3ViamVjdCx3aXRoaW49bGlzdChCb3RoTWVtLEVtb3Rpb24pLHR5cGU9MyxkZXRhaWxlZD1UUlVFKQpwcmludChhbm92YV9tb2QzJEFOT1ZBKQoKcm0oc3RhdGRhdGExLHN0YXRkYXRhMixzdGF0ZGF0YTMsYW5vdmFfbW9kMSxhbm92YV9tb2QyLGFub3ZhX21vZDMpCmBgYAoKIyMgUEhDIHZzIHdob2xlIGhpcHBvY2FtcHVzCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzdGF0ZGF0YTEgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbkFQPT0id2hvbGVIaXBwIiB8IFJlZ2lvbj09IlBIQyIpIApzdW1tYXJ5KGRyb3BsZXZlbHMoc3RhdGRhdGExJFJlZ2lvbikpICMgTm90ZSB0aGF0IGhlbWlzcGhlcmUgaXMgc3RpbGwgaW5jbHVkZWQgYnV0IGV6QU5PVkEgd2lsbCBhdmVyYWdlIHRoZW0KYW5vdmFfbW9kMTwtZXpBTk9WQShzdGF0ZGF0YTEsZHY9YWN0aXZpdHksd2lkPXN1YmplY3Qsd2l0aGluPWxpc3QoQm90aE1lbSxFbW90aW9uLFJlZ2lvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDEkQU5PVkEpCgpzdGF0ZGF0YTIgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbkFQPT0id2hvbGVIaXBwIiApCmFub3ZhX21vZDI8LWV6QU5PVkEoc3RhdGRhdGEyLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDIkQU5PVkEpCgpzdGF0ZGF0YTMgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbj09IlBIQyIpCmFub3ZhX21vZDM8LWV6QU5PVkEoc3RhdGRhdGEzLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDMkQU5PVkEpCgpybShzdGF0ZGF0YTEsc3RhdGRhdGEyLHN0YXRkYXRhMyxhbm92YV9tb2QxLGFub3ZhX21vZDIsYW5vdmFfbW9kMykKYGBgCgoKIyMgQW15Z2RhbGEgdnMgd2hvbGUgaGlwcG9jYW1wdXMKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN0YXRkYXRhMSA8LSBzdWJzZXQoYWN0ZGF0YS5yZWMsUmVnaW9uQVA9PSJ3aG9sZUhpcHAiIHwgUmVnaW9uPT0iQW15ZyIpIApzdW1tYXJ5KGRyb3BsZXZlbHMoc3RhdGRhdGExJFJlZ2lvbikpICMgTm90ZSB0aGF0IGhlbWlzcGhlcmUgaXMgc3RpbGwgaW5jbHVkZWQgYnV0IGV6QU5PVkEgd2lsbCBhdmVyYWdlIHRoZW0KYW5vdmFfbW9kMTwtZXpBTk9WQShzdGF0ZGF0YTEsZHY9YWN0aXZpdHksd2lkPXN1YmplY3Qsd2l0aGluPWxpc3QoQm90aE1lbSxFbW90aW9uLFJlZ2lvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDEkQU5PVkEpCgpzdGF0ZGF0YTIgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbkFQPT0id2hvbGVIaXBwIiApCmFub3ZhX21vZDI8LWV6QU5PVkEoc3RhdGRhdGEyLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDIkQU5PVkEpCgpzdGF0ZGF0YTMgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbj09IkFteWciKQphbm92YV9tb2QzPC1lekFOT1ZBKHN0YXRkYXRhMyxkdj1hY3Rpdml0eSx3aWQ9c3ViamVjdCx3aXRoaW49bGlzdChCb3RoTWVtLEVtb3Rpb24pLHR5cGU9MyxkZXRhaWxlZD1UUlVFKQpwcmludChhbm92YV9tb2QzJEFOT1ZBKQoKcm0oc3RhdGRhdGExLHN0YXRkYXRhMixzdGF0ZGF0YTMsYW5vdmFfbW9kMSxhbm92YV9tb2QyLGFub3ZhX21vZDMpCmBgYAoKIyMgU3VicmVnaW9ucyB3aXRoaW4gYW15Z2RhbGEKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN0YXRkYXRhMSA8LSBzdWJzZXQoYWN0ZGF0YS5yZWMsTWFpblJlZ2lvbj09IkFteWciKQpzdW1tYXJ5KGRyb3BsZXZlbHMoc3RhdGRhdGExJFJlZ2lvbikpCmFub3ZhX21vZDE8LWV6QU5PVkEoc3RhdGRhdGExLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbixSZWdpb24pLHR5cGU9MyxkZXRhaWxlZD1UUlVFKQpwcmludChhbm92YV9tb2QxKQoKc3RhdGRhdGEyIDwtIHN1YnNldChhY3RkYXRhLnJlYyxSZWdpb249PSJCYXNvbGF0QW15ZyIpCmFub3ZhX21vZDI8LWV6QU5PVkEoc3RhdGRhdGEyLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDIkQU5PVkEpCgpzdGF0ZGF0YTMgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbj09IkNlbnRyYWxBbXlnIikKYW5vdmFfbW9kMzwtZXpBTk9WQShzdGF0ZGF0YTMsZHY9YWN0aXZpdHksd2lkPXN1YmplY3Qsd2l0aGluPWxpc3QoQm90aE1lbSxFbW90aW9uKSx0eXBlPTMsZGV0YWlsZWQ9VFJVRSkKcHJpbnQoYW5vdmFfbW9kMyRBTk9WQSkKCnN0YXRkYXRhNCA8LSBzdWJzZXQoYWN0ZGF0YS5yZWMsUmVnaW9uPT0iQ29ydGljYWxBbXlnIikKYW5vdmFfbW9kNDwtZXpBTk9WQShzdGF0ZGF0YTQsZHY9YWN0aXZpdHksd2lkPXN1YmplY3Qsd2l0aGluPWxpc3QoQm90aE1lbSxFbW90aW9uKSx0eXBlPTMsZGV0YWlsZWQ9VFJVRSkKcHJpbnQoYW5vdmFfbW9kNCRBTk9WQSkKCnN0YXRkYXRhNSA8LSBzdWJzZXQoYWN0ZGF0YS5yZWMsUmVnaW9uPT0iTWVkaWFsQW15ZyIpCmFub3ZhX21vZDU8LWV6QU5PVkEoc3RhdGRhdGE1LGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDUkQU5PVkEpCgpybShzdGF0ZGF0YTEsc3RhdGRhdGEyLHN0YXRkYXRhMyxzdGF0ZGF0YTQsc3RhdGRhdGE1LGFub3ZhX21vZDEsYW5vdmFfbW9kMixhbm92YV9tb2QzLGFub3ZhX21vZDQsYW5vdmFfbW9kNSkKCmBgYAoKIyMgUG9zdGVyaW9yIHZzIGFudGVyaW9yIGhpcHBvY2FtcHVzCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzdGF0ZGF0YTEgPC0gc3Vic2V0KGFjdGRhdGEucmVjLChSZWdpb25BUD09Indob2xlSGlwcC5oZWFkIiB8IFJlZ2lvbkFQPT0id2hvbGVIaXBwLmJvZHkiKSkKc3VtbWFyeShkcm9wbGV2ZWxzKHN0YXRkYXRhMSRSZWdpb25BUCkpCmFub3ZhX21vZDE8LWV6QU5PVkEoc3RhdGRhdGExLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbixSZWdpb25BUCksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDEkQU5PVkEpCgpzdGF0ZGF0YTIgPC0gc3Vic2V0KGFjdGRhdGEucmVjLChSZWdpb25BUD09Indob2xlSGlwcC5oZWFkIikgKQphbm92YV9tb2QyPC1lekFOT1ZBKHN0YXRkYXRhMixkdj1hY3Rpdml0eSx3aWQ9c3ViamVjdCx3aXRoaW49bGlzdChCb3RoTWVtLEVtb3Rpb24pLHR5cGU9MyxkZXRhaWxlZD1UUlVFKQpwcmludChhbm92YV9tb2QyJEFOT1ZBKQoKc3RhdGRhdGEzIDwtIHN1YnNldChhY3RkYXRhLnJlYywoUmVnaW9uQVA9PSJ3aG9sZUhpcHAuYm9keSIgKSApCmFub3ZhX21vZDM8LWV6QU5PVkEoc3RhdGRhdGEzLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDMkQU5PVkEpCgpybShzdGF0ZGF0YTEsc3RhdGRhdGEyLHN0YXRkYXRhMyxhbm92YV9tb2QxLGFub3ZhX21vZDIsYW5vdmFfbW9kMykKCmBgYAoKIyMgU3VicmVnaW9ucyB3aXRoaW4gcG9zdGVyaW9yIGhpcHBvY2FtcHVzCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzdGF0ZGF0YTEgPC0gc3Vic2V0KGFjdGRhdGEucmVjLE1haW5SZWdpb249PSJIaXBwIikKc3VtbWFyeShkcm9wbGV2ZWxzKHN0YXRkYXRhMSRSZWdpb24pKQphbm92YV9tb2Q8LWV6QU5PVkEoc3RhdGRhdGExLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbixSZWdpb24pLHR5cGU9MyxkZXRhaWxlZD1UUlVFKQpwcmludChhbm92YV9tb2QpCgpzdGF0ZGF0YTIgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbj09IkNBMSIpCmFub3ZhX21vZDI8LWV6QU5PVkEoc3RhdGRhdGEyLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDIkQU5PVkEpCgpzdGF0ZGF0YTMgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbj09IkNBMjNERyIpCmFub3ZhX21vZDM8LWV6QU5PVkEoc3RhdGRhdGEzLGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDMkQU5PVkEpCgpzdGF0ZGF0YTQgPC0gc3Vic2V0KGFjdGRhdGEucmVjLFJlZ2lvbj09InN1YmljdWx1bSIpCmFub3ZhX21vZDQ8LWV6QU5PVkEoc3RhdGRhdGE0LGR2PWFjdGl2aXR5LHdpZD1zdWJqZWN0LHdpdGhpbj1saXN0KEJvdGhNZW0sRW1vdGlvbiksdHlwZT0zLGRldGFpbGVkPVRSVUUpCnByaW50KGFub3ZhX21vZDQkQU5PVkEpCgpybShzdGF0ZGF0YTEsYW5vdmFfbW9kLHN0YXRkYXRhMixzdGF0ZGF0YTMsc3RhdGRhdGE0LGFub3ZhX21vZDIsYW5vdmFfbW9kMyxhbm92YV9tb2Q0KQoKYGBgCgoKIyMgUFJDIHZzIFBIQwpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc3RhdGRhdGExIDwtIHN1YnNldChhY3RkYXRhLnJlYywoUmVnaW9uPT0iUFJDIiB8IFJlZ2lvbj09IlBIQyIpICkKYW5vdmFfbW9kPC1lekFOT1ZBKHN0YXRkYXRhMSxkdj1hY3Rpdml0eSx3aWQ9c3ViamVjdCx3aXRoaW49bGlzdChCb3RoTWVtLEVtb3Rpb24sUmVnaW9uKSx0eXBlPTMsZGV0YWlsZWQ9VFJVRSkKcHJpbnQoYW5vdmFfbW9kJEFOT1ZBKQoKc3RhdGRhdGEyIDwtIHN1YnNldChhY3RkYXRhLnJlYywoUmVnaW9uPT0iUFJDIikgKQphbm92YV9tb2QyPC1lekFOT1ZBKHN0YXRkYXRhMixkdj1hY3Rpdml0eSx3aWQ9c3ViamVjdCx3aXRoaW49bGlzdChCb3RoTWVtLEVtb3Rpb24pLHR5cGU9MyxkZXRhaWxlZD1UUlVFKQpwcmludChhbm92YV9tb2QyJEFOT1ZBKQoKc3RhdGRhdGEzIDwtIHN1YnNldChhY3RkYXRhLnJlYyxSZWdpb249PSJQSEMiICkKYW5vdmFfbW9kMzwtZXpBTk9WQShzdGF0ZGF0YTMsZHY9YWN0aXZpdHksd2lkPXN1YmplY3Qsd2l0aGluPWxpc3QoQm90aE1lbSxFbW90aW9uKSx0eXBlPTMsZGV0YWlsZWQ9VFJVRSkKcHJpbnQoYW5vdmFfbW9kMyRBTk9WQSkKCnJtKHN0YXRkYXRhMSxzdGF0ZGF0YTIsc3RhdGRhdGEzLGFub3ZhX21vZDEsYW5vdmFfbW9kMixhbm92YV9tb2QzKQoKYGBgCgoKCiMgUk9JIG1hcHMKCmBgYHtyIGRlZmluZU1hcEZ1bmN9CnBsb3RST0ltYXAgPC0gZnVuY3Rpb24odmFsdWVzLGNvbG9ybmFtZXMpIHsKICAKICBpZHMgPC0gZmFjdG9yKGMoIkFteWciLCJQUkMiLCJQSEMiLCJ3aG9sZUhpcHAuaGVhZCIsIndob2xlSGlwcC5ib2R5Iiwic3ViaWN1bHVtLmJvZHkiLCJDQTEuYm9keSIsIkNBMjNERy5ib2R5IiwiQ29ydGljYWxBbXlnIiwiQ2VudHJhbEFteWciLCJNZWRpYWxBbXlnIiwiQmFzb2xhdEFteWciKSkKICBuaWQgPC0gbGVuZ3RoKGlkcykKICAKICAjIERlZmluZSBwb2x5Z29uIGNvb3JkaW5hdGVzIChpbiB0aGlzIGNhc2UsIDQgZWFjaCBmb3IgYSByZWN0YW5nbGUpCiAgcG9zaXRpb25zIDwtIGRhdGEuZnJhbWUoCiAgICBpZCA9IHJlcChpZHMsIGVhY2ggPSA0KSwKICAgIG9yZGVyID0gcmVwKGMoMSwyLDMsNCksbmlkKSwKICAgIHggPSBjKDEsMiwyLDEsCiAgICAgICAgICAxLjUsMywzLDEuNSwKICAgICAgICAgIDMsNCw0LDMsCiAgICAgICAgICAyLDMsMywyLAogICAgICAgICAgMyw0LDQsMywKICAgICAgICAgIDMsNCw0LDMsCiAgICAgICAgICAzLDQsNCwzLAogICAgICAgICAgMyw0LDQsMywKICAgICAgICAgIDEsMiwyLDEsCiAgICAgICAgICAxLDIsMiwxLAogICAgICAgICAgMSwyLDIsMSwKICAgICAgICAgIDEsMiwyLDEpLAogICAgeSA9IGMoMiwyLDMsMywKICAgICAgICAgIDEsMSwyLDIsCiAgICAgICAgICAxLDEsMiwyLAogICAgICAgICAgMiwyLDMsMywKICAgICAgICAgIDIsMiwzLDMsCiAgICAgICAgICAyLDIsMi4zMzMzLDIuMzMzMywKICAgICAgICAgIDIuMzMzMywyLjMzMzMsMi42NjY2LDIuNjY2NiwKICAgICAgICAgIDIuNjY2NiwyLjY2NjYsMywzLAogICAgICAgICAgMiwyLDIuMjUsMi4yNSwKICAgICAgICAgIDIuMjUsMi4yNSwyLjUsMi41LAogICAgICAgICAgMi41LDIuNSwyLjc1LDIuNzUsCiAgICAgICAgICAyLjc1LDIuNzUsMywzKQogICkKICAKICAjIENhbGN1bGF0ZSBtaWRwb2ludCBvZiBlYWNoIHBvbHkgZm9yIGxhYmVsCiAgcG9zaXRpb25zICU+JQogICAgZ3JvdXBfYnkoaWQpICU+JQogICAgc3VtbWFyaXplKGxhYmVsX3ggPSBtZWFuKHgpLAogICAgICAgICAgICAgIGxhYmVsX3kgPSBtZWFuKHkpKSAlPiUKICAgIGxlZnRfam9pbih2YWx1ZXMpICU+JQogICAgZmlsdGVyKCFpcy5uYSh2YWx1ZSkgJiAhaXMubnVsbCh2YWx1ZSkgJiB2YWx1ZSE9Ik5VTEwiKSAtPiB2YWx1ZXMKICAKICAjIE1lcmdlIGlkICYgbGFiZWwgaW5mbyB3aXRoIHBvc2l0aW9ucwogIGRhdGFwb2x5IDwtIG1lcmdlKHZhbHVlcywgcG9zaXRpb25zLCBieT1jKCJpZCIpKSAlPiUKICAgIGFycmFuZ2UoaWQsb3JkZXIpICU+JQogICAgdW5ncm91cCgpCiAgCiAgIyBQcmV0dGllciBsYWJlbHMKICB2YWx1ZXMkaWRbdmFsdWVzJGlkPT0id2hvbGVIaXBwLmhlYWQiXSA8LSAiSGlwcC5hbnQiCiAgdmFsdWVzJGlkW3ZhbHVlcyRpZD09Indob2xlSGlwcC5ib2R5Il0gPC0gIkhpcHAucG9zdCIKICAKICB2YWx1ZXMkaWRbdmFsdWVzJGlkPT0iQmFzb2xhdEFteWciXSA8LSAiQW15Zy5iYXNvbGF0ZXJhbCIKICB2YWx1ZXMkaWRbdmFsdWVzJGlkPT0iTWVkaWFsQW15ZyJdIDwtICJBbXlnLmJhc29tZWRpYWwiCiAgdmFsdWVzJGlkW3ZhbHVlcyRpZD09IkNlbnRyYWxBbXlnIl0gPC0gIkFteWcuY2VudHJvbWVkaWFsIgogIHZhbHVlcyRpZFt2YWx1ZXMkaWQ9PSJDb3J0aWNhbEFteWciXSA8LSAiQW15Zy5jb3J0aWNhbCIKCiAgIyBQbG90IHBvbHlnb25zIHdpdGggdmFsdWVzIGNvZGluZyBmaWxsIGNvbG9yCiAgcCA8LSBnZ3Bsb3QoZGF0YXBvbHksIGFlcyh4PXgsIHk9eSkpICsgZ2VvbV9wb2x5Z29uKGNvbG91cj0iYmxhY2siLGFlcyhmaWxsPXZhbHVlLCBncm91cD1pZCkpICsKICAgIHRoZW1lX21pbmltYWwoMjApICsgCiAgICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSxwYW5lbC5ncmlkLm1pbm9yPWVsZW1lbnRfYmxhbmsoKSkgKyAKICAgIHhsYWIoJycpICsgeWxhYignJykgKyAKICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93PWNvbG9ybmFtZXNbMV0saGlnaD1jb2xvcm5hbWVzWzJdLGxpbWl0cz1jKDAsTkEpLG5hLnZhbHVlPSJncmF5NjAiLG5hbWU9ImVmZmVjdCBzaXplIikgKyAKICAgIGdlb21fdGV4dChkYXRhPXZhbHVlcyxzaXplPTgsYWVzKGxhYmVsPWlkLHg9bGFiZWxfeCx5PWxhYmVsX3kpKQoKICByZXR1cm4ocCkKfQpgYGAKCiMjIEdldCBzdGF0cyBzdW1tYXJ5IGluZm8gZm9yIHBsb3RzCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCmdldEFub3ZhRWZmZWN0U2l6ZSA8LSBmdW5jdGlvbihkZixlZmZlY3Ryb3cpIHsKICBkZiA8LSBkYXRhLmZyYW1lKGRmKSAjIGJjIGV6QU5PVkEgaGF0ZXMgZ3JvdXBlZCBkYXRhZnJhbWVzCiAgYW5vdmFfbW9kIDwtIGV6QU5PVkEoZGYsZHY9YWN0aXZpdHksd2lkPXN1YmplY3Qsd2l0aGluPWxpc3QoQm90aE1lbSxFbW90aW9uKSx0eXBlPTMsZGV0YWlsZWQ9VFJVRSkKICBlZmZlY3RzaXplIDwtIGFub3ZhX21vZCRBTk9WQVs5XVtbMV1dW2VmZmVjdHJvd10KICByZXR1cm4oZWZmZWN0c2l6ZSkKfQoKYWN0ZGF0YS5yZWMgJT4lCiAgZmlsdGVyKFJlZ2lvbkFQICVpbiUgYygiQW15ZyIsIndob2xlSGlwcC5oZWFkIiwid2hvbGVIaXBwLmJvZHkiLCJQSEMiLCJQUkMiKSkgJT4lCiAgZ3JvdXBfYnkoUmVnaW9uQVApICU+JQogIGRvKG1lbW9yeSA9IGdldEFub3ZhRWZmZWN0U2l6ZSguLDEpLAogICAgIHNvdXJjZSA9IGdldEFub3ZhRWZmZWN0U2l6ZSguLDIpLAogICAgIGVtb3Rpb24gPSBnZXRBbm92YUVmZmVjdFNpemUoLiwzKSkgJT4lCiAgdW5uZXN0KCkgLT4gZWZmZWN0c2l6ZXMucm9pCgphY3RkYXRhLnJlYyAlPiUKICBmaWx0ZXIoUmVnaW9uQVAgJWluJSBjKCJDb3J0aWNhbEFteWciLCJDZW50cmFsQW15ZyIsIk1lZGlhbEFteWciLCJCYXNvbGF0QW15ZyIsIkNBMS5ib2R5IiwiQ0EyM0RHLmJvZHkiLCJzdWJpY3VsdW0uYm9keSIsIndob2xlSGlwcC5oZWFkIiwiUEhDIiwiUFJDIikpICU+JQogIGdyb3VwX2J5KFJlZ2lvbkFQKSAlPiUKICBkbyhtZW1vcnkgPSBnZXRBbm92YUVmZmVjdFNpemUoLiwxKSwKICAgICBzb3VyY2UgPSBnZXRBbm92YUVmZmVjdFNpemUoLiwyKSwKICAgICBlbW90aW9uID0gZ2V0QW5vdmFFZmZlY3RTaXplKC4sMykpICU+JQogIHVubmVzdCgpIC0+IGVmZmVjdHNpemVzLnJvaS5zdWJyZWcKCnByaW50KGVmZmVjdHNpemVzLnJvaSkKcHJpbnQoZWZmZWN0c2l6ZXMucm9pLnN1YnJlZykKCmBgYAoKIyMgTWFqb3Igc3ViZGl2aXNpb25zCgpgYGB7ciwgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9NiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWFwLm1lbSA8LSBkYXRhLmZyYW1lKGlkPWFzLmNoYXJhY3RlcihlZmZlY3RzaXplcy5yb2kkUmVnaW9uQVApLHZhbHVlPWFzLm51bWVyaWMoZWZmZWN0c2l6ZXMucm9pJG1lbW9yeSkpCnBsb3RST0ltYXAobWFwLm1lbSxjKCd3aGl0ZScsJ29yYW5nZScpKSArIGdndGl0bGUoIlJlY29sbGVjdGlvbi1yZWxhdGVkIGFjdGl2aXR5IikKbWFwLmVtbyA8LSBkYXRhLmZyYW1lKGlkPWFzLmNoYXJhY3RlcihlZmZlY3RzaXplcy5yb2kkUmVnaW9uQVApLHZhbHVlPWFzLm51bWVyaWMoZWZmZWN0c2l6ZXMucm9pJGVtb3Rpb24pKQpwbG90Uk9JbWFwKG1hcC5lbW8sYygnd2hpdGUnLCd0b21hdG8nKSkgKyBnZ3RpdGxlKCJFZmZlY3Qgb2YgZW1vdGlvbiBvbiByZWNvbGxlY3Rpb24tcmVsYXRlZCBhY3Rpdml0eSIpCm1hcC5zcmMgPC0gZGF0YS5mcmFtZShpZD1hcy5jaGFyYWN0ZXIoZWZmZWN0c2l6ZXMucm9pJFJlZ2lvbkFQKSx2YWx1ZT1hcy5udW1lcmljKGVmZmVjdHNpemVzLnJvaSRzb3VyY2UpKQpwbG90Uk9JbWFwKG1hcC5zcmMsYygnd2hpdGUnLCdza3libHVlMScpKSArIGdndGl0bGUoIkVmZmVjdCBvZiBjb250ZXh0IGVuY29kaW5nIG9uIHJlY29sbGVjdGlvbi1yZWxhdGVkIGFjdGl2aXR5IikKCmBgYAoKIyMgV2l0aCBzdWJyZWdpb25zCmBgYHtyLCBmaWcuaGVpZ2h0PTIsIGZpZy53aWR0aD02LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQptYXAubWVtMiA8LSBkYXRhLmZyYW1lKGlkPWFzLmNoYXJhY3RlcihlZmZlY3RzaXplcy5yb2kuc3VicmVnJFJlZ2lvbkFQKSx2YWx1ZT1hcy5udW1lcmljKGVmZmVjdHNpemVzLnJvaS5zdWJyZWckbWVtb3J5KSkKcGxvdFJPSW1hcChtYXAubWVtMixjKCd3aGl0ZScsJ29yYW5nZScpKSArIGdndGl0bGUoIlJlY29sbGVjdGlvbi1yZWxhdGVkIGFjdGl2aXR5IikKbWFwLmVtbzIgPC0gZGF0YS5mcmFtZShpZD1hcy5jaGFyYWN0ZXIoZWZmZWN0c2l6ZXMucm9pLnN1YnJlZyRSZWdpb25BUCksdmFsdWU9YXMubnVtZXJpYyhlZmZlY3RzaXplcy5yb2kuc3VicmVnJGVtb3Rpb24pKQpwbG90Uk9JbWFwKG1hcC5lbW8yLGMoJ3doaXRlJywndG9tYXRvJykpICsgZ2d0aXRsZSgiRWZmZWN0IG9mIGVtb3Rpb24gb24gcmVjb2xsZWN0aW9uLXJlbGF0ZWQgYWN0aXZpdHkiKQptYXAuc3JjMiA8LSBkYXRhLmZyYW1lKGlkPWFzLmNoYXJhY3RlcihlZmZlY3RzaXplcy5yb2kuc3VicmVnJFJlZ2lvbkFQKSx2YWx1ZT1hcy5udW1lcmljKGVmZmVjdHNpemVzLnJvaS5zdWJyZWckc291cmNlKSkKcGxvdFJPSW1hcChtYXAuc3JjMixjKCd3aGl0ZScsJ3NreWJsdWUxJykpICsgZ2d0aXRsZSgiRWZmZWN0IG9mIGNvbnRleHQgZW5jb2Rpbmcgb24gcmVjb2xsZWN0aW9uLXJlbGF0ZWQgYWN0aXZpdHkiKQoKYGBgCg==