04_Actives Ori
suppressMessages(library(GenomicRanges))
suppressMessages(library(tidyverse))
suppressMessages(library(rtracklayer))
`%+%`<-paste0
seqinfSY <- readRDS("Data/seqinfSY.rds")
seqinfBY <- readRDS("Data/seqinfBY.rds")
maskedTy_SY <- readRDS("Data/maskedTy_SY.rds")
rDNA_SY <- GRanges("CP029160.1",IRanges(3879940,3934000),"*",seqinfo=seqinfSY)
Loading init coordinates
initerSY <- readRDS("Data/initer_SYSY.rds") %>%
mutate(strain="SY")
initerBY <- readRDS("Data/initer_BYBYSY.rds") %>%
mutate(strain="BY")
In order to identify active Ori in BY and/or SY datasets, we filtered
initiation event to keep those with a minimal width of 100 (to avoid
ponctual detection/transposition artifact) and with a maximum width of
10kb to reduce the probability to keep initiation events coming from
fused replication bubbles. Initiations event mapping on rDNA and on the
problematic Ty from chrIII and chrXVI were also excluded.
initSY <-initerSY %>%
filter(type=="Init") %>%
filter(between(x1-x0,100,10000)) %>%
select(chrom,center,x0,x1,exp,strain,strand)
initSY.gr <- with(initSY,GRanges(seqnames=chrom,ranges=IRanges(x0,x1),strand="*",seqinfo=seqinfSY))
initSY2 <- initSY[!overlapsAny(initSY.gr,c(rDNA_SY,maskedTy_SY)),]
initBY <-initerBY %>%
filter(type=="Init") %>%
filter(between(wid,100,10000)) %>%
select(chrom=chromSY,center=centerSY,x0=x0nSY,x1=x1nSY,exp,strain,strand) %>%
mutate(strain="BY")
initBY.gr <- with(initBY,GRanges(seqnames=chrom,ranges=IRanges(x0,x1),strand="*",seqinfo=seqinfSY))
initBY2 <- initBY[!overlapsAny(initBY.gr,c(rDNA_SY,maskedTy_SY)),] %>% arrange(center)
Then initiation events were clustered like in the Forkseq paper using
a clustering distance of 1.5kb
function.cluster2 <- function(input,clust.dist0=clust.dist)
# input is a tibble of genomic objects with a width of 1
{
require(tidygenomics)
test <- genome_cluster(input, by=c("chrom", "center", "center"),max_distance=clust.dist0)
test2 <- test %>%
group_by(cluster_id) %>%
nest %>%
mutate(eff=map_int(data,nrow)) %>%
mutate(cl.med=map_dbl(data,function(x) median(x$center))) %>%
mutate(cl.start=map_dbl(data,function(x) min(x$center)))%>%
mutate(cl.end=map_dbl(data,function(x) max(x$center)))%>%
mutate(cl.mad=map_dbl(data,function(x) mad(x$center)))%>%
unnest(cols=c(data))
test3 <- test2 %>% select(chrom,cl.med,cl.start,cl.end,eff,cl.mad,cluster_id) %>% group_by(cluster_id) %>% dplyr::slice(1)
res <- list(test2,test3)
return(res)
}
clust_dist <- 1500
# SY
iniforks.clustSY <- function.cluster2(initSY2, clust.dist0=clust_dist)
ini.clustSY <- iniforks.clustSY[[2]] %>% mutate(cl.width=1+cl.end-cl.start)
ini.clSY <- with(ini.clustSY,GRanges(seqnames=chrom, ranges=IRanges(start=cl.med, width=1),seqinfo=seqinfSY,eff=eff))
# BYSY
iniforks.clustBY <- function.cluster2(initBY2, clust.dist0=clust_dist)
ini.clustBY <- iniforks.clustBY[[2]] %>% mutate(cl.width=1+cl.end-cl.start)
ini.clBY <- with(ini.clustBY,GRanges(seqnames=chrom, ranges=IRanges(start=cl.med, width=1),seqinfo=seqinfSY,eff=eff))
We then decide to keep only the cluster for which at least 2
initiation events have been observed in SY or BY data
### keep cluster>=2
iniSY2keep <- ini.clSY[ini.clSY$eff>=2]
iniBY2keep <- ini.clBY[ini.clBY$eff>=2]
Using this information we defined as “active origin” the known ARS
for which these “efficient” inititiation clusters were localised at less
than 1.5kb for the ARS center
ars <- import("Genome_annotations/ARS_BYonSY.bed")
dist2ars <- 1500
dtnSY <- as_tibble(distanceToNearest(iniSY2keep,resize(ars,fix="center",width=1)))
dtnBY <- as_tibble(distanceToNearest(iniBY2keep,resize(ars,fix="center",width=1)))
ars2keep <- ars[unique(c(dtnSY %>% filter(distance<dist2ars) %>% pull(subjectHits),dtnBY %>% filter(distance<dist2ars) %>% pull(subjectHits)))] %>% sort
export(ars2keep,con="Data/ars2keep_lim10k_cl1500_2_dtac1500.bed")
export(iniSY2keep,con="Data/iniSY2keep_lim10k_cl1500_2.bed")
export(iniBY2keep,con="Data/iniBY2keep_lim10k_cl1500_2.bed")
From these data, dispersive initiations can be defined as initiation
events that do not overlap with active ori in the SY/BY system.
This can be computed with the 10kb width limit
initSY2.gr <- initSY.gr[!overlapsAny(initSY.gr,c(rDNA_SY,maskedTy_SY)),]
length(initSY2.gr[!overlapsAny(initSY2.gr,ars2keep)])/length(initSY2.gr)
[1] 0.04061074
initBY2.gr <- initBY.gr[!overlapsAny(initBY.gr,c(rDNA_SY,maskedTy_SY)),]
length(initBY2.gr[!overlapsAny(initBY2.gr,ars2keep)])/length(initBY2.gr)
[1] 0.02908833
and without the 10kb limit
initSYb <-initerSY %>%
filter(type=="Init") %>%
filter(x1-x0>100) %>%
select(chrom,center,x0,x1,exp,strain,strand)
initSYb.gr <- with(initSYb,GRanges(seqnames=chrom,ranges=IRanges(x0,x1),strand="*",seqinfo=seqinfSY))
initSY2b.gr <- initSYb.gr[!overlapsAny(initSYb.gr,c(rDNA_SY,maskedTy_SY)),]
length(initSY2b.gr[!overlapsAny(initSY2b.gr,ars2keep)])/length(initSY2b.gr)
[1] 0.02111955
initBYb <-initerBY %>%
filter(type=="Init") %>%
filter(x1-x0>100) %>%
select(chrom=chromSY,center=centerSY,x0=x0nSY,x1=x1nSY,exp,strain,strand)
initBYb.gr <- with(initBYb,GRanges(seqnames=chrom,ranges=IRanges(x0,x1),strand="*",seqinfo=seqinfSY))
initBY2b.gr <- initBYb.gr[!overlapsAny(initBYb.gr,c(rDNA_SY,maskedTy_SY)),]
length(initBY2b.gr[!overlapsAny(initBY2b.gr,ars2keep)])/length(initBY2b.gr)
[1] 0.01552882
Or it could be defined from the clustering
length(ini.clSY[ini.clSY$eff==1])/length(initSY2.gr)
[1] 0.03242563
length(ini.clBY[ini.clBY$eff==1])/length(initBY2.gr)
[1] 0.02855623
OR define it on all ARS_BYonSY without the 10kb limit
ars <- import("Genome_annotations/ARS_BYonSY.bed")
initSYb <-initerSY %>%
filter(type=="Init") %>%
filter(x1-x0>100) %>%
select(chrom,center,x0,x1,exp,strain,strand)
initSYb.gr <- with(initSYb,GRanges(seqnames=chrom,ranges=IRanges(x0,x1),strand="*",seqinfo=seqinfSY))
initSY2b.gr <- initSYb.gr[!overlapsAny(initSYb.gr,c(rDNA_SY,maskedTy_SY)),]
length(initSY2b.gr[!overlapsAny(initSY2b.gr,ars)])/length(initSY2b.gr)
[1] 0.01034427
initBYb <-initerBY %>%
filter(type=="Init") %>%
filter(x1-x0>100) %>%
select(chrom=chromSY,center=centerSY,x0=x0nSY,x1=x1nSY,exp,strain,strand)
initBYb.gr <- with(initBYb,GRanges(seqnames=chrom,ranges=IRanges(x0,x1),strand="*",seqinfo=seqinfSY))
initBY2b.gr <- initBYb.gr[!overlapsAny(initBYb.gr,c(rDNA_SY,maskedTy_SY)),]
length(initBY2b.gr[!overlapsAny(initBY2b.gr,ars)])/length(initBY2b.gr)
[1] 0.00776441
LS0tCnRpdGxlOiAiQllTWSBwcm9qZWN0IE5vdGVib29rIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tICAKIyAwNF9BY3RpdmVzIE9yaSAgCgoqKiogIAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KEdlbm9taWNSYW5nZXMpKQpzdXBwcmVzc01lc3NhZ2VzKGxpYnJhcnkodGlkeXZlcnNlKSkKc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KHJ0cmFja2xheWVyKSkKYCUrJWA8LXBhc3RlMApzZXFpbmZTWSA8LSByZWFkUkRTKCJEYXRhL3NlcWluZlNZLnJkcyIpCnNlcWluZkJZIDwtIHJlYWRSRFMoIkRhdGEvc2VxaW5mQlkucmRzIikKbWFza2VkVHlfU1kgPC0gcmVhZFJEUygiRGF0YS9tYXNrZWRUeV9TWS5yZHMiKQpyRE5BX1NZIDwtIEdSYW5nZXMoIkNQMDI5MTYwLjEiLElSYW5nZXMoMzg3OTk0MCwzOTM0MDAwKSwiKiIsc2VxaW5mbz1zZXFpbmZTWSkKYGBgCkxvYWRpbmcgaW5pdCBjb29yZGluYXRlcwoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KaW5pdGVyU1kgPC0gcmVhZFJEUygiRGF0YS9pbml0ZXJfU1lTWS5yZHMiKSAlPiUKCW11dGF0ZShzdHJhaW49IlNZIikKaW5pdGVyQlkgPC0gcmVhZFJEUygiRGF0YS9pbml0ZXJfQllCWVNZLnJkcyIpICU+JQoJbXV0YXRlKHN0cmFpbj0iQlkiKQpgYGAKSW4gb3JkZXIgdG8gaWRlbnRpZnkgYWN0aXZlIE9yaSBpbiBCWSBhbmQvb3IgU1kgZGF0YXNldHMsIHdlIGZpbHRlcmVkIGluaXRpYXRpb24gZXZlbnQgdG8ga2VlcCB0aG9zZSB3aXRoIGEgbWluaW1hbCB3aWR0aCBvZiAxMDAgKHRvIGF2b2lkIHBvbmN0dWFsIGRldGVjdGlvbi90cmFuc3Bvc2l0aW9uIGFydGlmYWN0KSBhbmQgd2l0aCBhIG1heGltdW0gd2lkdGggb2YgMTBrYiB0byByZWR1Y2UgdGhlIHByb2JhYmlsaXR5IHRvIGtlZXAgaW5pdGlhdGlvbiBldmVudHMgY29taW5nIGZyb20gZnVzZWQgcmVwbGljYXRpb24gYnViYmxlcy4gSW5pdGlhdGlvbnMgZXZlbnQgbWFwcGluZyBvbiByRE5BIGFuZCBvbiB0aGUgcHJvYmxlbWF0aWMgVHkgZnJvbSBjaHJJSUkgYW5kIGNoclhWSSB3ZXJlIGFsc28gZXhjbHVkZWQuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQppbml0U1kgPC1pbml0ZXJTWSAlPiUgCglmaWx0ZXIodHlwZT09IkluaXQiKSAgJT4lCglmaWx0ZXIoYmV0d2Vlbih4MS14MCwxMDAsMTAwMDApKSAlPiUKCXNlbGVjdChjaHJvbSxjZW50ZXIseDAseDEsZXhwLHN0cmFpbixzdHJhbmQpCmluaXRTWS5nciA8LSB3aXRoKGluaXRTWSxHUmFuZ2VzKHNlcW5hbWVzPWNocm9tLHJhbmdlcz1JUmFuZ2VzKHgwLHgxKSxzdHJhbmQ9IioiLHNlcWluZm89c2VxaW5mU1kpKQppbml0U1kyIDwtIGluaXRTWVshb3ZlcmxhcHNBbnkoaW5pdFNZLmdyLGMockROQV9TWSxtYXNrZWRUeV9TWSkpLF0KCmluaXRCWSA8LWluaXRlckJZICU+JSAKCWZpbHRlcih0eXBlPT0iSW5pdCIpICAlPiUKCWZpbHRlcihiZXR3ZWVuKHdpZCwxMDAsMTAwMDApKSAlPiUKCXNlbGVjdChjaHJvbT1jaHJvbVNZLGNlbnRlcj1jZW50ZXJTWSx4MD14MG5TWSx4MT14MW5TWSxleHAsc3RyYWluLHN0cmFuZCkgJT4lCgltdXRhdGUoc3RyYWluPSJCWSIpCmluaXRCWS5nciA8LSB3aXRoKGluaXRCWSxHUmFuZ2VzKHNlcW5hbWVzPWNocm9tLHJhbmdlcz1JUmFuZ2VzKHgwLHgxKSxzdHJhbmQ9IioiLHNlcWluZm89c2VxaW5mU1kpKQppbml0QlkyIDwtIGluaXRCWVshb3ZlcmxhcHNBbnkoaW5pdEJZLmdyLGMockROQV9TWSxtYXNrZWRUeV9TWSkpLF0gJT4lIGFycmFuZ2UoY2VudGVyKQpgYGAKVGhlbiBpbml0aWF0aW9uIGV2ZW50cyB3ZXJlIGNsdXN0ZXJlZCBsaWtlIGluIHRoZSBGb3Jrc2VxIHBhcGVyIHVzaW5nIGEgY2x1c3RlcmluZyBkaXN0YW5jZSBvZiAxLjVrYgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZnVuY3Rpb24uY2x1c3RlcjIgPC0gZnVuY3Rpb24oaW5wdXQsY2x1c3QuZGlzdDA9Y2x1c3QuZGlzdCkKCSMgaW5wdXQgaXMgYSB0aWJibGUgb2YgZ2Vub21pYyBvYmplY3RzIHdpdGggYSB3aWR0aCBvZiAxCnsKCXJlcXVpcmUodGlkeWdlbm9taWNzKQoJdGVzdCA8LSBnZW5vbWVfY2x1c3RlcihpbnB1dCwgYnk9YygiY2hyb20iLCAiY2VudGVyIiwgImNlbnRlciIpLG1heF9kaXN0YW5jZT1jbHVzdC5kaXN0MCkKCXRlc3QyIDwtIHRlc3QgJT4lCgkJZ3JvdXBfYnkoY2x1c3Rlcl9pZCkgJT4lCgkJbmVzdCAlPiUKCQltdXRhdGUoZWZmPW1hcF9pbnQoZGF0YSxucm93KSkgJT4lCgkJbXV0YXRlKGNsLm1lZD1tYXBfZGJsKGRhdGEsZnVuY3Rpb24oeCkgbWVkaWFuKHgkY2VudGVyKSkpICU+JQoJCW11dGF0ZShjbC5zdGFydD1tYXBfZGJsKGRhdGEsZnVuY3Rpb24oeCkgbWluKHgkY2VudGVyKSkpJT4lCgkJbXV0YXRlKGNsLmVuZD1tYXBfZGJsKGRhdGEsZnVuY3Rpb24oeCkgbWF4KHgkY2VudGVyKSkpJT4lCgkJbXV0YXRlKGNsLm1hZD1tYXBfZGJsKGRhdGEsZnVuY3Rpb24oeCkgbWFkKHgkY2VudGVyKSkpJT4lCgkJdW5uZXN0KGNvbHM9YyhkYXRhKSkKCXRlc3QzIDwtIHRlc3QyICU+JSBzZWxlY3QoY2hyb20sY2wubWVkLGNsLnN0YXJ0LGNsLmVuZCxlZmYsY2wubWFkLGNsdXN0ZXJfaWQpICU+JSBncm91cF9ieShjbHVzdGVyX2lkKSAlPiUgZHBseXI6OnNsaWNlKDEpCglyZXMgPC0gbGlzdCh0ZXN0Mix0ZXN0MykKCXJldHVybihyZXMpCn0KY2x1c3RfZGlzdCA8LSAxNTAwCgojIFNZCmluaWZvcmtzLmNsdXN0U1kgPC0gZnVuY3Rpb24uY2x1c3RlcjIoaW5pdFNZMiwgY2x1c3QuZGlzdDA9Y2x1c3RfZGlzdCkKaW5pLmNsdXN0U1kgPC0gaW5pZm9ya3MuY2x1c3RTWVtbMl1dICU+JSBtdXRhdGUoY2wud2lkdGg9MStjbC5lbmQtY2wuc3RhcnQpCmluaS5jbFNZIDwtIHdpdGgoaW5pLmNsdXN0U1ksR1JhbmdlcyhzZXFuYW1lcz1jaHJvbSwgcmFuZ2VzPUlSYW5nZXMoc3RhcnQ9Y2wubWVkLCB3aWR0aD0xKSxzZXFpbmZvPXNlcWluZlNZLGVmZj1lZmYpKQoKIyBCWVNZCmluaWZvcmtzLmNsdXN0QlkgPC0gZnVuY3Rpb24uY2x1c3RlcjIoaW5pdEJZMiwgY2x1c3QuZGlzdDA9Y2x1c3RfZGlzdCkKaW5pLmNsdXN0QlkgPC0gaW5pZm9ya3MuY2x1c3RCWVtbMl1dICU+JSBtdXRhdGUoY2wud2lkdGg9MStjbC5lbmQtY2wuc3RhcnQpCmluaS5jbEJZIDwtIHdpdGgoaW5pLmNsdXN0QlksR1JhbmdlcyhzZXFuYW1lcz1jaHJvbSwgcmFuZ2VzPUlSYW5nZXMoc3RhcnQ9Y2wubWVkLCB3aWR0aD0xKSxzZXFpbmZvPXNlcWluZlNZLGVmZj1lZmYpKQpgYGAKV2UgdGhlbiBkZWNpZGUgdG8ga2VlcCBvbmx5IHRoZSBjbHVzdGVyIGZvciB3aGljaCBhdCBsZWFzdCAyIGluaXRpYXRpb24gZXZlbnRzIGhhdmUgYmVlbiBvYnNlcnZlZCBpbiBTWSBvciBCWSBkYXRhCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIyBrZWVwIGNsdXN0ZXI+PTIKaW5pU1kya2VlcCA8LSBpbmkuY2xTWVtpbmkuY2xTWSRlZmY+PTJdCmluaUJZMmtlZXAgPC0gaW5pLmNsQllbaW5pLmNsQlkkZWZmPj0yXQpgYGAKVXNpbmcgdGhpcyBpbmZvcm1hdGlvbiB3ZSBkZWZpbmVkIGFzICJhY3RpdmUgb3JpZ2luIiB0aGUga25vd24gQVJTIGZvciB3aGljaCB0aGVzZSAiZWZmaWNpZW50IiBpbml0aXRpYXRpb24gY2x1c3RlcnMgd2VyZSBsb2NhbGlzZWQgYXQgbGVzcyB0aGFuIDEuNWtiIGZvciB0aGUgQVJTIGNlbnRlcgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQphcnMgPC0gaW1wb3J0KCJHZW5vbWVfYW5ub3RhdGlvbnMvQVJTX0JZb25TWS5iZWQiKQpkaXN0MmFycyA8LSAxNTAwCgpkdG5TWSA8LSBhc190aWJibGUoZGlzdGFuY2VUb05lYXJlc3QoaW5pU1kya2VlcCxyZXNpemUoYXJzLGZpeD0iY2VudGVyIix3aWR0aD0xKSkpCmR0bkJZIDwtIGFzX3RpYmJsZShkaXN0YW5jZVRvTmVhcmVzdChpbmlCWTJrZWVwLHJlc2l6ZShhcnMsZml4PSJjZW50ZXIiLHdpZHRoPTEpKSkKYXJzMmtlZXAgPC0gYXJzW3VuaXF1ZShjKGR0blNZICU+JSBmaWx0ZXIoZGlzdGFuY2U8ZGlzdDJhcnMpICU+JSBwdWxsKHN1YmplY3RIaXRzKSxkdG5CWSAlPiUgZmlsdGVyKGRpc3RhbmNlPGRpc3QyYXJzKSAlPiUgcHVsbChzdWJqZWN0SGl0cykpKV0gJT4lIHNvcnQKCmV4cG9ydChhcnMya2VlcCxjb249IkRhdGEvYXJzMmtlZXBfbGltMTBrX2NsMTUwMF8yX2R0YWMxNTAwLmJlZCIpCmV4cG9ydChpbmlTWTJrZWVwLGNvbj0iRGF0YS9pbmlTWTJrZWVwX2xpbTEwa19jbDE1MDBfMi5iZWQiKQpleHBvcnQoaW5pQlkya2VlcCxjb249IkRhdGEvaW5pQlkya2VlcF9saW0xMGtfY2wxNTAwXzIuYmVkIikKYGBgCgpGcm9tIHRoZXNlIGRhdGEsIGRpc3BlcnNpdmUgaW5pdGlhdGlvbnMgY2FuIGJlIGRlZmluZWQgYXMgaW5pdGlhdGlvbiBldmVudHMgdGhhdCBkbyBub3Qgb3ZlcmxhcCB3aXRoIGFjdGl2ZSBvcmkgaW4gdGhlIFNZL0JZIHN5c3RlbS4gIApUaGlzIGNhbiBiZSBjb21wdXRlZCB3aXRoIHRoZSAxMGtiIHdpZHRoIGxpbWl0CgpgYGB7cn0KaW5pdFNZMi5nciA8LSBpbml0U1kuZ3JbIW92ZXJsYXBzQW55KGluaXRTWS5ncixjKHJETkFfU1ksbWFza2VkVHlfU1kpKSxdCmxlbmd0aChpbml0U1kyLmdyWyFvdmVybGFwc0FueShpbml0U1kyLmdyLGFyczJrZWVwKV0pL2xlbmd0aChpbml0U1kyLmdyKQppbml0QlkyLmdyIDwtIGluaXRCWS5nclshb3ZlcmxhcHNBbnkoaW5pdEJZLmdyLGMockROQV9TWSxtYXNrZWRUeV9TWSkpLF0KbGVuZ3RoKGluaXRCWTIuZ3JbIW92ZXJsYXBzQW55KGluaXRCWTIuZ3IsYXJzMmtlZXApXSkvbGVuZ3RoKGluaXRCWTIuZ3IpCmBgYAphbmQgd2l0aG91dCB0aGUgMTBrYiBsaW1pdAoKYGBge3J9CmluaXRTWWIgPC1pbml0ZXJTWSAlPiUgCglmaWx0ZXIodHlwZT09IkluaXQiKSAgJT4lCglmaWx0ZXIoeDEteDA+MTAwKSAlPiUKCXNlbGVjdChjaHJvbSxjZW50ZXIseDAseDEsZXhwLHN0cmFpbixzdHJhbmQpCmluaXRTWWIuZ3IgPC0gd2l0aChpbml0U1liLEdSYW5nZXMoc2VxbmFtZXM9Y2hyb20scmFuZ2VzPUlSYW5nZXMoeDAseDEpLHN0cmFuZD0iKiIsc2VxaW5mbz1zZXFpbmZTWSkpCmluaXRTWTJiLmdyIDwtIGluaXRTWWIuZ3JbIW92ZXJsYXBzQW55KGluaXRTWWIuZ3IsYyhyRE5BX1NZLG1hc2tlZFR5X1NZKSksXQpsZW5ndGgoaW5pdFNZMmIuZ3JbIW92ZXJsYXBzQW55KGluaXRTWTJiLmdyLGFyczJrZWVwKV0pL2xlbmd0aChpbml0U1kyYi5ncikKaW5pdEJZYiA8LWluaXRlckJZICU+JSAKCWZpbHRlcih0eXBlPT0iSW5pdCIpICAlPiUKCWZpbHRlcih4MS14MD4xMDApICU+JQoJc2VsZWN0KGNocm9tPWNocm9tU1ksY2VudGVyPWNlbnRlclNZLHgwPXgwblNZLHgxPXgxblNZLGV4cCxzdHJhaW4sc3RyYW5kKQppbml0QlliLmdyIDwtIHdpdGgoaW5pdEJZYixHUmFuZ2VzKHNlcW5hbWVzPWNocm9tLHJhbmdlcz1JUmFuZ2VzKHgwLHgxKSxzdHJhbmQ9IioiLHNlcWluZm89c2VxaW5mU1kpKQppbml0QlkyYi5nciA8LSBpbml0QlliLmdyWyFvdmVybGFwc0FueShpbml0QlliLmdyLGMockROQV9TWSxtYXNrZWRUeV9TWSkpLF0KbGVuZ3RoKGluaXRCWTJiLmdyWyFvdmVybGFwc0FueShpbml0QlkyYi5ncixhcnMya2VlcCldKS9sZW5ndGgoaW5pdEJZMmIuZ3IpCmBgYApPciBpdCBjb3VsZCBiZSBkZWZpbmVkIGZyb20gdGhlIGNsdXN0ZXJpbmcKYGBge3J9Cmxlbmd0aChpbmkuY2xTWVtpbmkuY2xTWSRlZmY9PTFdKS9sZW5ndGgoaW5pdFNZMi5ncikKbGVuZ3RoKGluaS5jbEJZW2luaS5jbEJZJGVmZj09MV0pL2xlbmd0aChpbml0QlkyLmdyKQpgYGAKT1IgZGVmaW5lIGl0IG9uIGFsbCBBUlNfQllvblNZIHdpdGhvdXQgdGhlIDEwa2IgbGltaXQKCmBgYHtyfQphcnMgPC0gaW1wb3J0KCJHZW5vbWVfYW5ub3RhdGlvbnMvQVJTX0JZb25TWS5iZWQiKQppbml0U1liIDwtaW5pdGVyU1kgJT4lIAoJZmlsdGVyKHR5cGU9PSJJbml0IikgICU+JQoJZmlsdGVyKHgxLXgwPjEwMCkgJT4lCglzZWxlY3QoY2hyb20sY2VudGVyLHgwLHgxLGV4cCxzdHJhaW4sc3RyYW5kKQppbml0U1liLmdyIDwtIHdpdGgoaW5pdFNZYixHUmFuZ2VzKHNlcW5hbWVzPWNocm9tLHJhbmdlcz1JUmFuZ2VzKHgwLHgxKSxzdHJhbmQ9IioiLHNlcWluZm89c2VxaW5mU1kpKQppbml0U1kyYi5nciA8LSBpbml0U1liLmdyWyFvdmVybGFwc0FueShpbml0U1liLmdyLGMockROQV9TWSxtYXNrZWRUeV9TWSkpLF0KbGVuZ3RoKGluaXRTWTJiLmdyWyFvdmVybGFwc0FueShpbml0U1kyYi5ncixhcnMpXSkvbGVuZ3RoKGluaXRTWTJiLmdyKQppbml0QlliIDwtaW5pdGVyQlkgJT4lIAoJZmlsdGVyKHR5cGU9PSJJbml0IikgICU+JQoJZmlsdGVyKHgxLXgwPjEwMCkgJT4lCglzZWxlY3QoY2hyb209Y2hyb21TWSxjZW50ZXI9Y2VudGVyU1kseDA9eDBuU1kseDE9eDFuU1ksZXhwLHN0cmFpbixzdHJhbmQpCmluaXRCWWIuZ3IgPC0gd2l0aChpbml0QlliLEdSYW5nZXMoc2VxbmFtZXM9Y2hyb20scmFuZ2VzPUlSYW5nZXMoeDAseDEpLHN0cmFuZD0iKiIsc2VxaW5mbz1zZXFpbmZTWSkpCmluaXRCWTJiLmdyIDwtIGluaXRCWWIuZ3JbIW92ZXJsYXBzQW55KGluaXRCWWIuZ3IsYyhyRE5BX1NZLG1hc2tlZFR5X1NZKSksXQpsZW5ndGgoaW5pdEJZMmIuZ3JbIW92ZXJsYXBzQW55KGluaXRCWTJiLmdyLGFycyldKS9sZW5ndGgoaW5pdEJZMmIuZ3IpCmBgYAoK