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))
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'))
Report number of voxels in each ROI
vox <- group_by(actdata,RegionAP) %>%
summarize(meanvox=mean(numvox),
minvox=min(numvox),
maxvox=max(numvox))
kable(vox)
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 |
Plots
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"
Plots with all bars
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))
Plots with bars subtracting non-recollection
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')
Follow-up tests
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)
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)
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)
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)
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)
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)
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)
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)
}
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)
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")
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==