タンパク質相互作用ネットワークを題材に中心性指標とタンパク質の必須性の関係を調査します。具体的に,次のことを行います。

必須タンパク質と非必須タンパク質を中心性指標の比較

igraphパッケージの読み込み

library(igraph)

大腸菌のタンパク質相互作用ネットワークの読み込み

  • ../data/ecoli_ppi_Hu_etal_2009.txt
  • エッジリスト形式
  • Hu P, Janga SC, Babu M, Díaz-Mejía JJ, Butland G, et al. Global functional atlas of Escherichia coli encompassing previously uncharacterized proteins. PLoS Biol. 2009 Apr 28;7(4):e96. doi: 10.1371/journal.pbio.1000096.
# エッジリストの読み込み
d <- read.table("../data/ecoli_ppi_Hu_etal_2009.txt")
# グラフオブジェクトの作成
g <- simplify(graph.data.frame(d,directed=F),remove.multiple=T,remove.loops=T)

# 最大連結成分の取得
cls <- clusters(g,"weak")
g <- induced_subgraph(g, V(g)$name[cls$membership==which(cls$csize==max(cls$csize))[[1]]])

中心性指標の計算

# 次数中心性(degree centrality)
degree <- degree(g)
# 固有ベクトル中心性(eigenvector centraliry)
eigen <- evcent(g)$vector
# PageRank
page <- page.rank(g)$vector
# 近接中心性(closeness centrality)
closen <- closeness(g)
# 媒介中心性(betweenness centrality)
between <- betweenness(g)
# サブグラフ中心性(subgraph centrality)
subgraph <- subgraph.centrality(g)
# データフレームにまとめる
nprop <- data.frame(V(g)$name,degree,eigen,page,closen,between,subgraph)
names(nprop)[[1]] <- "gene"

タンパク質の必須性のデータを読み込む

Baba T, Ara T, Hasegawa M, Takai Y, Okumura Y, Baba M, Datsenko KA, Tomita M, Wanner BL, Mori H. Construction of Escherichia coli K-12 in-frame, single-gene knockout mutants: the Keio collection. Mol Syst Biol. 2006;2:2006.0008. Epub 2006 Feb 21. doi: 10.1038/msb4100050

ess <- read.table("../data/ecoli_proteins_essentiality_Baba2006MSB.txt",header=T)
# 必須(E),非必須(N),不明(u)
# 中心性指標のデータと必須性のデータをマージする
d <- merge(ess, nprop,by="gene")
# unknownの遺伝子を除外する。
d <- d[d$essential!="u",]

Boxplotの表示

layout(matrix(1:6, ncol=3))
# 次数中心性(degree centrality)
boxplot(log(d$degree)~d$essential,xlab="Essentiality",ylab="Degree")
# 固有ベクトル中心性(eigenvector centraliry)
boxplot(log(d$eigen)~d$essential,xlab="Essentiality",ylab="Eigenvector")
# PageRank
boxplot(log(d$page)~d$essential,xlab="Essentiality",ylab="PageRank")
# 近接中心性(closeness centrality)
boxplot(d$closen~d$essential,xlab="Essentiality",ylab="Closeness")
# 媒介中心性(betweenness centrality)
boxplot(log(d$between+1)~d$essential,xlab="Essentiality",ylab="Betweenness")
# サブグラフ中心性(subgraph centrality)
boxplot(log(d$subgraph)~d$essential,xlab="Essentiality",ylab="Subgraph")

必須タンパク質と非必須タンパク質の中心性指標の差の検定

前準備

# 必須タンパク質の中心性指標
ess_nprop <- d[d$essential=="E",]
# 非必須タンパク質の中心性指標
noness_nprop <- d[d$essential=="N",]

Wilcoxon検定

cat("次数中心性(degree centrality)
    中央値 必須:",median(ess_nprop$degree),"非必須:",median(noness_nprop$degree),"\n")
次数中心性(degree centrality)
    中央値 必須: 9 非必須: 2 
wilcox.test(ess_nprop$degree, noness_nprop$degree)

    Wilcoxon rank sum test with continuity correction

data:  ess_nprop$degree and noness_nprop$degree
W = 171775, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0
cat("固有ベクトル中心性(eigenvector centraliry)
    中央値 必須:",median(ess_nprop$eigen),"非必須:",median(noness_nprop$eigen),"\n")
固有ベクトル中心性(eigenvector centraliry)
    中央値 必須: 0.04040747 非必須: 0.00491207 
wilcox.test(ess_nprop$eigen, noness_nprop$eigen)

    Wilcoxon rank sum test with continuity correction

data:  ess_nprop$eigen and noness_nprop$eigen
W = 173693, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0
cat("PageRank
    中央値 必須:",median(ess_nprop$page),"非必須:",median(noness_nprop$page),"\n")
PageRank
    中央値 必須: 0.0008231837 非必須: 0.0002878847 
wilcox.test(ess_nprop$page, noness_nprop$page)

    Wilcoxon rank sum test with continuity correction

data:  ess_nprop$page and noness_nprop$page
W = 168277, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0
cat("近接中心性(closeness centrality)
    中央値 必須:",median(ess_nprop$closen),"非必須:",median(noness_nprop$closen),"\n")
近接中心性(closeness centrality)
    中央値 必須: 0.0001693338 非必須: 0.0001446132 
wilcox.test(ess_nprop$closen, noness_nprop$closen)

    Wilcoxon rank sum test with continuity correction

data:  ess_nprop$closen and noness_nprop$closen
W = 173098, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0
cat("媒介中心性(betweenness centrality)
    中央値 必須:",median(ess_nprop$between),"非必須:",median(noness_nprop$between),"\n")
媒介中心性(betweenness centrality)
    中央値 必須: 2453.932 非必須: 47.76135 
wilcox.test(ess_nprop$between, noness_nprop$between)

    Wilcoxon rank sum test with continuity correction

data:  ess_nprop$between and noness_nprop$between
W = 166378, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0
cat("サブグラフ中心性(subgraph centrality)
    中央値 必須:",median(ess_nprop$subgraph),"非必須:",median(noness_nprop$subgraph),"\n")
サブグラフ中心性(subgraph centrality)
    中央値 必須: 6.05615e+11 非必須: 8949452569 
wilcox.test(ess_nprop$subgraph, noness_nprop$subgraph)

    Wilcoxon rank sum test with continuity correction

data:  ess_nprop$subgraph and noness_nprop$subgraph
W = 173687, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0

単一の中心性指標を用いて必須タンパク質を判別する

前準備

# 必須なら1,非必須なら0とする。
ess_score <- ifelse(d$essential == "E",1,0)
# ROCカーブを書くためのパッケージを読み込む
library(pROC)

ROCカーブのプロット

layout(matrix(1:6, ncol=3))
# 次数中心性(degree centrality)
plot.roc(ess_score,d$degree,print.auc=T,main="Degree")
Setting levels: control = 0, case = 1
Setting direction: controls < cases
# 固有ベクトル中心性(eigenvector centraliry)
plot.roc(ess_score,d$eigen,print.auc=T,main="Eigenvector")
Setting levels: control = 0, case = 1
Setting direction: controls < cases
# PageRank
plot.roc(ess_score,d$page,print.auc=T,main="PageRank")
Setting levels: control = 0, case = 1
Setting direction: controls < cases
# 近接中心性(closeness centrality)
plot.roc(ess_score,d$closen,print.auc=T,main="Closeness")
Setting levels: control = 0, case = 1
Setting direction: controls < cases
# 媒介中心性(betweenness centrality)
plot.roc(ess_score,d$between,print.auc=T,main="Betweenness")
Setting levels: control = 0, case = 1
Setting direction: controls < cases
# サブグラフ中心性(Subgraph centrality)
plot.roc(ess_score,d$subgraph,print.auc=T,main="Subgraph")
Setting levels: control = 0, case = 1
Setting direction: controls < cases

やってみよう

酵母のデータ

  • 出芽酵母のタンパク質相互作用ネットワーク
    • ../data/yeast_ppi_Batada_etal_2006.txt
    • エッジリスト形式
    • Batada NN et al. (2006) Stratus not altocumulus: a new view of the yeast protein interaction network. PLoS Biol 4, e317. doi: 10.1371/journal.pbio.0040317
  • 出芽酵母タンパク質(遺伝子)の必須性
    • ../data/yeast_proteins_essentiality_OGEE.txt
    • 必須(E),非必須(N)
    • Chen WH, Minguez P, Lercher MJ, Bork P (2012) OGEE: an online gene essentiality database. Nucleic Acids Res 40, D901-906. doi: 10.1093/nar/gkr986.
LS0tCnRpdGxlOiAi5Lit5b+D5oCn6Kej5p6Q77yIQ2VudHJhbGl0eSBhbmFseXNpc++8iSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoK44K/44Oz44OR44Kv6LOq55u45LqS5L2c55So44ON44OD44OI44Ov44O844Kv44KS6aGM5p2Q44Gr5Lit5b+D5oCn5oyH5qiZ44Go44K/44Oz44OR44Kv6LOq44Gu5b+F6aCI5oCn44Gu6Zai5L+C44KS6Kq/5p+744GX44G+44GZ44CC5YW35L2T55qE44Gr77yM5qyh44Gu44GT44Go44KS6KGM44GE44G+44GZ44CCCgogICsg44K/44Oz44OR44Kv6LOq55u45LqS5L2c55So44ON44OD44OI44Ov44O844Kv44Gu5Lit5b+D5oCn5oyH5qiZ44KS6KiI566X44GZ44KL44GT44Go44Gn6YeN6KaB44Gq44K/44Oz44OR44Kv6LOq44KS5ZCM5a6a44GX44G+44GZ44CCCiAgKyDlv4XpoIjjgr/jg7Pjg5Hjgq/os6rjgajpnZ7lv4XpoIjjgr/jg7Pjg5Hjgq/os6rjgpLkuK3lv4PmgKfmjIfmqJnjgpLmr5TovIPjgZfvvIzlt67jga7ntbHoqIjliIbmnpDjgpLooYzjgYTjgb7jgZnjgIIKICArIOWNmOS4gOOBruS4reW/g+aAp+aMh+aomeOCkueUqOOBhOOBpuW/hemgiOOCv+ODs+ODkeOCr+izquOCkuWIpOWIpeOBl+OBvuOBmeOAggoKIyDlv4XpoIjjgr/jg7Pjg5Hjgq/os6rjgajpnZ7lv4XpoIjjgr/jg7Pjg5Hjgq/os6rjgpLkuK3lv4PmgKfmjIfmqJnjga7mr5TovIMKIyMjIGlncmFwaOODkeODg+OCseODvOOCuOOBruiqreOBv+i+vOOBvwpgYGB7cn0KbGlicmFyeShpZ3JhcGgpCmBgYAoKIyMjIOWkp+iFuOiPjOOBruOCv+ODs+ODkeOCr+izquebuOS6kuS9nOeUqOODjeODg+ODiOODr+ODvOOCr+OBruiqreOBv+i+vOOBvwogICsgYC4uL2RhdGEvZWNvbGlfcHBpX0h1X2V0YWxfMjAwOS50eHRgCiAgKyDjgqjjg4Pjgrjjg6rjgrnjg4jlvaLlvI8KICArIEh1IFAsIEphbmdhIFNDLCBCYWJ1IE0sIETDrWF6LU1lasOtYSBKSiwgQnV0bGFuZCBHLCBldCBhbC4gR2xvYmFsIGZ1bmN0aW9uYWwgYXRsYXMgb2YgRXNjaGVyaWNoaWEgY29saSBlbmNvbXBhc3NpbmcgcHJldmlvdXNseSB1bmNoYXJhY3Rlcml6ZWQgcHJvdGVpbnMuIFBMb1MgQmlvbC4gMjAwOSBBcHIgMjg7Nyg0KTplOTYuIGRvaTogMTAuMTM3MS9qb3VybmFsLnBiaW8uMTAwMDA5Ni4KYGBge3J9CiMg44Ko44OD44K444Oq44K544OI44Gu6Kqt44G/6L6844G/CmQgPC0gcmVhZC50YWJsZSgiLi4vZGF0YS9lY29saV9wcGlfSHVfZXRhbF8yMDA5LnR4dCIpCiMg44Kw44Op44OV44Kq44OW44K444Kn44Kv44OI44Gu5L2c5oiQCmcgPC0gc2ltcGxpZnkoZ3JhcGguZGF0YS5mcmFtZShkLGRpcmVjdGVkPUYpLHJlbW92ZS5tdWx0aXBsZT1ULHJlbW92ZS5sb29wcz1UKQoKIyDmnIDlpKfpgKPntZDmiJDliIbjga7lj5blvpcKY2xzIDwtIGNsdXN0ZXJzKGcsIndlYWsiKQpnIDwtIGluZHVjZWRfc3ViZ3JhcGgoZywgVihnKSRuYW1lW2NscyRtZW1iZXJzaGlwPT13aGljaChjbHMkY3NpemU9PW1heChjbHMkY3NpemUpKVtbMV1dXSkKYGBgCgojIyMg5Lit5b+D5oCn5oyH5qiZ44Gu6KiI566XCmBgYHtyfQojIOasoeaVsOS4reW/g+aAp++8iGRlZ3JlZSBjZW50cmFsaXR577yJCmRlZ3JlZSA8LSBkZWdyZWUoZykKIyDlm7rmnInjg5njgq/jg4jjg6vkuK3lv4PmgKfvvIhlaWdlbnZlY3RvciBjZW50cmFsaXJ577yJCmVpZ2VuIDwtIGV2Y2VudChnKSR2ZWN0b3IKIyBQYWdlUmFuawpwYWdlIDwtIHBhZ2UucmFuayhnKSR2ZWN0b3IKIyDov5HmjqXkuK3lv4PmgKfvvIhjbG9zZW5lc3MgY2VudHJhbGl0ee+8iQpjbG9zZW4gPC0gY2xvc2VuZXNzKGcpCiMg5aqS5LuL5Lit5b+D5oCn77yIYmV0d2Vlbm5lc3MgY2VudHJhbGl0ee+8iQpiZXR3ZWVuIDwtIGJldHdlZW5uZXNzKGcpCiMg44K144OW44Kw44Op44OV5Lit5b+D5oCn77yIc3ViZ3JhcGggY2VudHJhbGl0ee+8iQpzdWJncmFwaCA8LSBzdWJncmFwaC5jZW50cmFsaXR5KGcpCmBgYAoKYGBge3J9CiMg44OH44O844K/44OV44Os44O844Og44Gr44G+44Go44KB44KLCm5wcm9wIDwtIGRhdGEuZnJhbWUoVihnKSRuYW1lLGRlZ3JlZSxlaWdlbixwYWdlLGNsb3NlbixiZXR3ZWVuLHN1YmdyYXBoKQpuYW1lcyhucHJvcClbWzFdXSA8LSAiZ2VuZSIKYGBgCgojIyMg44K/44Oz44OR44Kv6LOq44Gu5b+F6aCI5oCn44Gu44OH44O844K/44KS6Kqt44G/6L6844KACkJhYmEgVCwgQXJhIFQsIEhhc2VnYXdhIE0sIFRha2FpIFksIE9rdW11cmEgWSwgQmFiYSBNLCBEYXRzZW5rbyBLQSwgVG9taXRhIE0sIFdhbm5lciBCTCwgTW9yaSBILiBDb25zdHJ1Y3Rpb24gb2YgRXNjaGVyaWNoaWEgY29saSBLLTEyIGluLWZyYW1lLCBzaW5nbGUtZ2VuZSBrbm9ja291dCBtdXRhbnRzOiB0aGUgS2VpbyBjb2xsZWN0aW9uLiBNb2wgU3lzdCBCaW9sLiAyMDA2OzI6MjAwNi4wMDA4LiBFcHViIDIwMDYgRmViIDIxLiBkb2k6IDEwLjEwMzgvbXNiNDEwMDA1MApgYGB7cn0KZXNzIDwtIHJlYWQudGFibGUoIi4uL2RhdGEvZWNvbGlfcHJvdGVpbnNfZXNzZW50aWFsaXR5X0JhYmEyMDA2TVNCLnR4dCIsaGVhZGVyPVQpCiMg5b+F6aCI77yIRe+8ie+8jOmdnuW/hemgiO+8iE7vvInvvIzkuI3mmI7vvIh177yJCmBgYAoKYGBge3J9CiMg5Lit5b+D5oCn5oyH5qiZ44Gu44OH44O844K/44Go5b+F6aCI5oCn44Gu44OH44O844K/44KS44Oe44O844K444GZ44KLCmQgPC0gbWVyZ2UoZXNzLCBucHJvcCxieT0iZ2VuZSIpCiMgdW5rbm93buOBrumBuuS8neWtkOOCkumZpOWkluOBmeOCi+OAggpkIDwtIGRbZCRlc3NlbnRpYWwhPSJ1IixdCmBgYAoKIyMjIEJveHBsb3Tjga7ooajnpLoKYGBge3J9CmxheW91dChtYXRyaXgoMTo2LCBuY29sPTMpKQojIOasoeaVsOS4reW/g+aAp++8iGRlZ3JlZSBjZW50cmFsaXR577yJCmJveHBsb3QobG9nKGQkZGVncmVlKX5kJGVzc2VudGlhbCx4bGFiPSJFc3NlbnRpYWxpdHkiLHlsYWI9IkRlZ3JlZSIpCiMg5Zu65pyJ44OZ44Kv44OI44Or5Lit5b+D5oCn77yIZWlnZW52ZWN0b3IgY2VudHJhbGlyee+8iQpib3hwbG90KGxvZyhkJGVpZ2VuKX5kJGVzc2VudGlhbCx4bGFiPSJFc3NlbnRpYWxpdHkiLHlsYWI9IkVpZ2VudmVjdG9yIikKIyBQYWdlUmFuawpib3hwbG90KGxvZyhkJHBhZ2UpfmQkZXNzZW50aWFsLHhsYWI9IkVzc2VudGlhbGl0eSIseWxhYj0iUGFnZVJhbmsiKQojIOi/keaOpeS4reW/g+aAp++8iGNsb3NlbmVzcyBjZW50cmFsaXR577yJCmJveHBsb3QoZCRjbG9zZW5+ZCRlc3NlbnRpYWwseGxhYj0iRXNzZW50aWFsaXR5Iix5bGFiPSJDbG9zZW5lc3MiKQojIOWqkuS7i+S4reW/g+aAp++8iGJldHdlZW5uZXNzIGNlbnRyYWxpdHnvvIkKYm94cGxvdChsb2coZCRiZXR3ZWVuKzEpfmQkZXNzZW50aWFsLHhsYWI9IkVzc2VudGlhbGl0eSIseWxhYj0iQmV0d2Vlbm5lc3MiKQojIOOCteODluOCsOODqeODleS4reW/g+aAp++8iHN1YmdyYXBoIGNlbnRyYWxpdHnvvIkKYm94cGxvdChsb2coZCRzdWJncmFwaCl+ZCRlc3NlbnRpYWwseGxhYj0iRXNzZW50aWFsaXR5Iix5bGFiPSJTdWJncmFwaCIpCmBgYAoKIyDlv4XpoIjjgr/jg7Pjg5Hjgq/os6rjgajpnZ7lv4XpoIjjgr/jg7Pjg5Hjgq/os6rjga7kuK3lv4PmgKfmjIfmqJnjga7lt67jga7mpJzlrpoKIyMjIOWJjea6luWCmQpgYGB7cn0KIyDlv4XpoIjjgr/jg7Pjg5Hjgq/os6rjga7kuK3lv4PmgKfmjIfmqJkKZXNzX25wcm9wIDwtIGRbZCRlc3NlbnRpYWw9PSJFIixdCiMg6Z2e5b+F6aCI44K/44Oz44OR44Kv6LOq44Gu5Lit5b+D5oCn5oyH5qiZCm5vbmVzc19ucHJvcCA8LSBkW2QkZXNzZW50aWFsPT0iTiIsXQpgYGAKCiMjIyBXaWxjb3hvbuaknOWumgpgYGB7cn0KY2F0KCLmrKHmlbDkuK3lv4PmgKfvvIhkZWdyZWUgY2VudHJhbGl0ee+8iQogICAg5Lit5aSu5YCk44CA5b+F6aCI77yaIixtZWRpYW4oZXNzX25wcm9wJGRlZ3JlZSksIumdnuW/hemgiO+8miIsbWVkaWFuKG5vbmVzc19ucHJvcCRkZWdyZWUpLCJcbiIpCndpbGNveC50ZXN0KGVzc19ucHJvcCRkZWdyZWUsIG5vbmVzc19ucHJvcCRkZWdyZWUpCmBgYAoKYGBge3J9CmNhdCgi5Zu65pyJ44OZ44Kv44OI44Or5Lit5b+D5oCn77yIZWlnZW52ZWN0b3IgY2VudHJhbGlyee+8iQogICAg5Lit5aSu5YCk44CA5b+F6aCI77yaIixtZWRpYW4oZXNzX25wcm9wJGVpZ2VuKSwi6Z2e5b+F6aCI77yaIixtZWRpYW4obm9uZXNzX25wcm9wJGVpZ2VuKSwiXG4iKQp3aWxjb3gudGVzdChlc3NfbnByb3AkZWlnZW4sIG5vbmVzc19ucHJvcCRlaWdlbikKCmNhdCgiUGFnZVJhbmsKICAgIOS4reWkruWApOOAgOW/hemgiO+8miIsbWVkaWFuKGVzc19ucHJvcCRwYWdlKSwi6Z2e5b+F6aCI77yaIixtZWRpYW4obm9uZXNzX25wcm9wJHBhZ2UpLCJcbiIpCndpbGNveC50ZXN0KGVzc19ucHJvcCRwYWdlLCBub25lc3NfbnByb3AkcGFnZSkKCmNhdCgi6L+R5o6l5Lit5b+D5oCn77yIY2xvc2VuZXNzIGNlbnRyYWxpdHnvvIkKICAgIOS4reWkruWApOOAgOW/hemgiO+8miIsbWVkaWFuKGVzc19ucHJvcCRjbG9zZW4pLCLpnZ7lv4XpoIjvvJoiLG1lZGlhbihub25lc3NfbnByb3AkY2xvc2VuKSwiXG4iKQp3aWxjb3gudGVzdChlc3NfbnByb3AkY2xvc2VuLCBub25lc3NfbnByb3AkY2xvc2VuKQoKY2F0KCLlqpLku4vkuK3lv4PmgKfvvIhiZXR3ZWVubmVzcyBjZW50cmFsaXR577yJCiAgICDkuK3lpK7lgKTjgIDlv4XpoIjvvJoiLG1lZGlhbihlc3NfbnByb3AkYmV0d2VlbiksIumdnuW/hemgiO+8miIsbWVkaWFuKG5vbmVzc19ucHJvcCRiZXR3ZWVuKSwiXG4iKQp3aWxjb3gudGVzdChlc3NfbnByb3AkYmV0d2Vlbiwgbm9uZXNzX25wcm9wJGJldHdlZW4pCgpjYXQoIuOCteODluOCsOODqeODleS4reW/g+aAp++8iHN1YmdyYXBoIGNlbnRyYWxpdHnvvIkKICAgIOS4reWkruWApOOAgOW/hemgiO+8miIsbWVkaWFuKGVzc19ucHJvcCRzdWJncmFwaCksIumdnuW/hemgiO+8miIsbWVkaWFuKG5vbmVzc19ucHJvcCRzdWJncmFwaCksIlxuIikKd2lsY294LnRlc3QoZXNzX25wcm9wJHN1YmdyYXBoLCBub25lc3NfbnByb3Akc3ViZ3JhcGgpCmBgYAoKIyDljZjkuIDjga7kuK3lv4PmgKfmjIfmqJnjgpLnlKjjgYTjgablv4XpoIjjgr/jg7Pjg5Hjgq/os6rjgpLliKTliKXjgZnjgosKCiMjIyDliY3mupblgpkKYGBge3J9CiMg5b+F6aCI44Gq44KJMe+8jOmdnuW/hemgiOOBquOCiTDjgajjgZnjgovjgIIKZXNzX3Njb3JlIDwtIGlmZWxzZShkJGVzc2VudGlhbCA9PSAiRSIsMSwwKQojIFJPQ+OCq+ODvOODluOCkuabuOOBj+OBn+OCgeOBruODkeODg+OCseODvOOCuOOCkuiqreOBv+i+vOOCgApsaWJyYXJ5KHBST0MpCmBgYAoKIyMjIFJPQ+OCq+ODvOODluOBruODl+ODreODg+ODiApgYGB7cn0KbGF5b3V0KG1hdHJpeCgxOjYsIG5jb2w9MykpCiMg5qyh5pWw5Lit5b+D5oCn77yIZGVncmVlIGNlbnRyYWxpdHnvvIkKcGxvdC5yb2MoZXNzX3Njb3JlLGQkZGVncmVlLHByaW50LmF1Yz1ULG1haW49IkRlZ3JlZSIpCiMg5Zu65pyJ44OZ44Kv44OI44Or5Lit5b+D5oCn77yIZWlnZW52ZWN0b3IgY2VudHJhbGlyee+8iQpwbG90LnJvYyhlc3Nfc2NvcmUsZCRlaWdlbixwcmludC5hdWM9VCxtYWluPSJFaWdlbnZlY3RvciIpCiMgUGFnZVJhbmsKcGxvdC5yb2MoZXNzX3Njb3JlLGQkcGFnZSxwcmludC5hdWM9VCxtYWluPSJQYWdlUmFuayIpCiMg6L+R5o6l5Lit5b+D5oCn77yIY2xvc2VuZXNzIGNlbnRyYWxpdHnvvIkKcGxvdC5yb2MoZXNzX3Njb3JlLGQkY2xvc2VuLHByaW50LmF1Yz1ULG1haW49IkNsb3NlbmVzcyIpCiMg5aqS5LuL5Lit5b+D5oCn77yIYmV0d2Vlbm5lc3MgY2VudHJhbGl0ee+8iQpwbG90LnJvYyhlc3Nfc2NvcmUsZCRiZXR3ZWVuLHByaW50LmF1Yz1ULG1haW49IkJldHdlZW5uZXNzIikKIyDjgrXjg5bjgrDjg6njg5XkuK3lv4PmgKfvvIhTdWJncmFwaCBjZW50cmFsaXR577yJCnBsb3Qucm9jKGVzc19zY29yZSxkJHN1YmdyYXBoLHByaW50LmF1Yz1ULG1haW49IlN1YmdyYXBoIikKYGBgCgojIOOChOOBo+OBpuOBv+OCiOOBhgogICsg44GT44GuTm90ZWJvb2vjgpLlj4LogIPjgavjgZfjgabvvIzphbXmr43jga7jg4fjg7zjgr/jgpLop6PmnpDjgZfjgabjgb/jgojjgYbjgIIKICArIE5vdGVib29r44KS5Y+C6ICD44Gr6Ieq5YiG44Gu44OH44O844K/44KS6Kej5p6Q44GX44Gm44G/44KI44GG44CCCgojIyMg6YW15q+N44Gu44OH44O844K/CiAgKyDlh7roir3phbXmr43jga7jgr/jg7Pjg5Hjgq/os6rnm7jkupLkvZznlKjjg43jg4Pjg4jjg6/jg7zjgq8KICAgICArIGBgLi4vZGF0YS95ZWFzdF9wcGlfQmF0YWRhX2V0YWxfMjAwNi50eHRgYAogICAgICsg44Ko44OD44K444Oq44K544OI5b2i5byPCiAgICAgKyBCYXRhZGEgTk4gZXQgYWwuICgyMDA2KSBTdHJhdHVzIG5vdCBhbHRvY3VtdWx1czogYSBuZXcgdmlldyBvZiB0aGUgeWVhc3QgcHJvdGVpbiBpbnRlcmFjdGlvbiBuZXR3b3JrLiBQTG9TIEJpb2wgNCwgZTMxNy4gZG9pOiAxMC4xMzcxL2pvdXJuYWwucGJpby4wMDQwMzE3CiAgKyDlh7roir3phbXmr43jgr/jg7Pjg5Hjgq/os6rvvIjpgbrkvJ3lrZDvvInjga7lv4XpoIjmgKcKICAgICArIGBgLi4vZGF0YS95ZWFzdF9wcm90ZWluc19lc3NlbnRpYWxpdHlfT0dFRS50eHRgYAogICAgICsg5b+F6aCI77yIRe+8ie+8jOmdnuW/hemgiO+8iE7vvIkKICAgICArIENoZW4gV0gsIE1pbmd1ZXogUCwgTGVyY2hlciBNSiwgQm9yayBQICgyMDEyKSBPR0VFOiBhbiBvbmxpbmUgZ2VuZSBlc3NlbnRpYWxpdHkgZGF0YWJhc2UuIE51Y2xlaWMgQWNpZHMgUmVzIDQwLCBEOTAxLTkwNi4gZG9pOiAxMC4xMDkzL25hci9na3I5ODYu