まずはホームディレクトリを設定します。

home <- [配布したフォルダをコピーしたパス]
setwd(home)
library(data.table)
Warning message:
In scan(file = file, what = what, sep = sep, quote = quote, dec = dec,  :
  EOF within quoted string

t検定について説明します。以下のように、10個の遺伝子に対して二つの条件下(例えば、Tumor / Normal)で5サンプルずつの遺伝子発現データ考えます。目標は、条件間で発現量の異なる遺伝子群を同定することです。

set.seed(100)
n <- 10
p <- 5
cond1 <- matrix(rnbinom(n*p,2,mu = 300),ncol=p,dimnames=list(paste0("Gene",1:n),paste0("Condition",rep(1,p))))
cond2 <- matrix(rnbinom(n*p,2,mu = 100),ncol=p,dimnames=list(paste0("Gene",1:n),paste0("Condition",rep(2,p))))
data_example <- cbind(cond1,cond2)
Condition1 Condition1 Condition1 Condition1 Condition1 Condition2 Condition2 Condition2 Condition2 Condition2
Gene1 123 91 178 86 327 92 86 75 46 329
Gene2 419 250 648 210 264 210 93 43 89 62
Gene3 277 119 397 148 538 87 58 87 46 33
Gene4 306 198 530 139 428 163 246 54 96 135
Gene5 243 211 172 152 47 102 3 233 58 49
Gene6 205 299 620 202 206 127 64 128 52 284
Gene7 125 56 361 549 80 345 62 189 39 45
Gene8 513 14 217 451 179 89 37 294 125 169
Gene9 71 525 36 276 83 24 141 70 29 166
Gene10 288 151 1005 108 275 37 96 228 7 195

二つの条件間の違いを見る方法はいくつか考えられます。一つは、log fold change (LFC)を計算することです。遺伝子\(i\)に対するLFCとは

\[\mbox{logFC}_i=\mbox{log2}(M_{i,1} / M_{i,2})\]

(\(M_{i,j}\)は遺伝子\(i\)条件\(j\)の発現量の平均です。

M1 <- apply(cond1,1,function(x)mean(x))
M2 <- apply(cond2,1,function(x)mean(x))
(logFC <- log2((M1 + 1) / (M2 + 1)))
    Gene1     Gene2     Gene3     Gene4     Gene5     Gene6     Gene7     Gene8     Gene9    Gene10 
0.3557164 1.8390281 2.2314946 1.2001075 0.8831863 1.2195792 0.7797122 0.9395588 1.1951303 1.6894567 

LFCはどの程度、違うかを表す指標ですが、どの閾値以上であれば差があるかの明確な基準はありません。また遺伝子ごとにデータのばらつき方は異なり、得られたLFCが本当に偶然かどうかも見定める必要がありますがそれはできません。そのために、統計的仮説検定という枠組みを用いて、ばらつきを確率的に考えて、本当にその差があるのかを評価します。t-検定は、二群間の平均の差を検定する代表的な検定手法です。

早速、t-検定を実行してみましょう。遺伝子1に対してt-検定を実行してみます。

x <- cond1[1,]
y <- cond2[1,]
(result_t <- t.test(x,y,var.equal = TRUE))

    Two Sample t-test

data:  x and y
t = 0.51975, df = 8, p-value = 0.6173
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -121.6617  192.4617
sample estimates:
mean of x mean of y 
    161.0     125.6 

p値はいくらかというと、

result_t$p.value
[1] 0.6173102

となり、有意水準5%で考えると有意ではありません。Rでt-検定を行うのは非常に簡単です。ただし、その仕組みを知っていないと、あまり意味も分からずにp値を振り回したり、振り回されてしまいます。さきほどの数行で何をやったのかの意味を理解してみようと思います。

 統計的仮説検定では、まず帰無仮説と対立仮説を立てます。帰無仮説とは最終的に否定したい事柄を、対立仮説にはそれと対比をなす事柄を考えます。今回の場合だと、条件1と条件2で、発現量が異なる遺伝子群を同定したいので、仮説を以下のようにします。 \[\mbox{帰無仮説}:M_{i,1}=M_{i,2}\] \[\mbox{対立仮説}:M_{i,1}\neq M_{i,2}\]

次に、帰無仮説が本当ではないことを確かめるために、帰無仮説を定量化した検定統計量を求めます。

t-統計量

\[\mbox{t-統計量} = \frac{\mbox{群間の平均の違い}}{\mbox{各群のばらつき}}\]

先ほどのt統計量は、

result_t$statistic
        t 
0.5197481 

です。

このt-統計量は単なる数値ではありません。自分の確率的なばらつきかたを表す確率分布を背負っています。特に帰無仮説の確率分布なので、帰無分布と呼びます。仮説検定のポイントはこの帰無分布を正しく理解することです。t統計量の従う分布はt分布という名前がついており、その形はサンプル数のみによって決まります。Rでは簡単にt分布からデータを生成させることができるので、実際に見てみましょう。

data_t <- rt(10000,df = n - 2)
hist(data_t,freq = F,xlab="t",ylab="Probability")

上図はt分布からt統計量を10000個、仮想的に生成したときの頻度分布です。全ての頻度の和を取ると、1になるように正規化しています。これが先ほど実行したt検定の帰無分布です。帰無仮説は二群間の平均の違い=0、すなわち帰無仮説に対応するt統計量が0なので、理論上はゼロになるはずですが、分布上は、確率的なばらつきを持っています。別の言い方をすると、もしも、10000回(実際にはそんなことはできませんが)、繰り返しt統計量を計算した時のばらつき方を表しています。

繰り返しになりますが、この分布は帰無仮説に対応したt統計量のばらつきを表しています。では、対立仮説に対応するt統計量の値(t=-2.026503)はどのあたりかというと、

hist(data_t,freq = F,xlab="t",ylab="Probability")
abline(v=result_t$statistic,col="red")

確かに帰無仮説に対応する0ではないですが、誤差の範囲内と言えそうです。これが確率的に誤差の範囲かどうかを判定するには、有意水準という閾値を設けます。具体的に有意水準5%といったときには、

図中青色の線が有意水準に対応する閾値を表しており、その両側に対応する確率の和が有意水準に対応する5%となっています。有意水準5%とは、偶然0ではない(帰無仮説が正しい)とする閾値以上となる確率が高々5%であると言っています。仮に間違って帰無仮説が間違っているといったとしても、100回中5回程度だということです。裏を返せば、もしもその閾値を越えていれば、それは帰無仮説の下では、滅多に起こりえないことが起こったということになります。したがって、5%という誤差はあるけれども、今回の帰無仮説は成り立たないすなわち有意ではないと考えるわけです。

今回は、5%の有意水準を越えていないので、帰無仮説は5%の有意水準で棄却できません。

ではp値とは何かというと、図中の赤色の線の右側の確率の和です(もし負であれば左側)。先ほど、p値は0.613でしたが、右側だけの有意水準に対応する領域は0.025(2.5%)なので、この値を用いても先ほどと同様に赤色の線が青色の線を越えていないということができます。つまり、p値は有意水準に対応する閾値を越えているかを判断するための値です。

全ての遺伝子に対して、検定してみましょう。

pvals <- NULL
for(i in 1:n){
x <- cond1[i,]
y <- cond2[i,]
result_t <- t.test(x,y,var.equal = TRUE)
pvals[i] <- result_t$p.value
}
pvals
 [1] 0.61731016 0.01664043 0.01819819 0.05069772 0.17883478 0.08861926 0.40741858 0.22987814 0.27743056 0.17355748

次に有意水準5%の説明が本当かどうかを確かめてみましょう。確かめ方は簡単です。同じ確率分布から二群の遺伝子発現量を生成させて、5%有意水準でのt検定を10000回繰り返したときに、間違って帰無仮説を棄却する回数がおよそ500回であれば5%の意味は正しいと言えます。

set.seed(100)
n <- 10000
p <- 5
cond1_many <- matrix(rnbinom(n*p,2,mu = 100),ncol=p,dimnames=list(paste0("Gene",1:n),paste0("Condition",rep(1,p))))
cond2_many <- matrix(rnbinom(n*p,2,mu = 100),ncol=p,dimnames=list(paste0("Gene",1:n),paste0("Condition",rep(2,p))))
pvals_many <- NULL
for(i in 1:n){
  x <- cond1_many[i,]
  y <- cond2_many[i,]
  result_t <- t.test(x,y,alternative = "two.sided",var.equal = TRUE)
  pvals_many[i] <- result_t$p.value
}
sum(pvals_many <= 0.05) / n
[1] 0.044

確かに、5%くらいの確率で帰無仮説を誤って棄却しているようです。

今回は、両側検定と呼ばれる方法で検定を行いました。それがalternative="two.sidedの部分です。両側の意味は、対立仮説が\(M_{i,1} < M_{i,2}\)\(M_{i,1}> M_{i,2}\)(つまり\(M_{i,1}\neq M_{i,2}\))の両方を含めているということです。片側検定の場合は、どちらかを検定することになります。つまり、

\[\mbox{帰無仮説}:M_{i,1}>M_{i,2}\] \[\mbox{対立仮説}:M_{i,1}\neq M_{i,2}\]

を検定します。このときの注意は、有意水準の考え方です。両側検定で有意水準5%といった場合には、二つのしきい値は、外側の和が5%になるようなしきい値となりますが、片側検定ですと、片方のしきい値しか用いなので、片方のしきい値の外側の和が5%となるようなしきい値となります。

alternative="greater"とすれば、対立仮説は\(M_{i,1} > M_{i,2}\)となり、alternative="less"とすれば対立仮説は\(M_{i,1} < M_{i,2}\)となります。t.test関数の基本設定ではalternative="two.sided"となっています。

x <- cond1[1,]
y <- cond2[1,]
(result_t <- t.test(x,y,greater="greater",var.equal = TRUE))

    Two Sample t-test

data:  x and y
t = 0.51975, df = 8, p-value = 0.6173
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -121.6617  192.4617
sample estimates:
mean of x mean of y 
    161.0     125.6 

var.equalは2群のばらつきを同じと仮定するか否かを設定します。今回は同じと仮定したのでvar.equal=TRUEとしています。もしvar.equal=FALSEとすると、ウェルチの検定という方法になります。状況に応じて使い分けてください。

ところで、有意水準5%で検定を100回繰り返すと、有意水準の定義から、確率的には5回、間違って帰無仮説を棄却することになります。遺伝子数は2万近くありますから、遺伝子ごとに検定を行うと20000回の検定を行うことになり、理論上は$20000\times 0.05=1000$回は間違って、発現の差異がないのに、あると判断してしまうことになります。つまり、擬陽性の遺伝子を1000個程度含んでしまうことになります。統計的仮説検定を繰り返し行うことを多重検定と言い、擬陽性をいかにして減らすかという問題は統計学では多重検定補正といって、重要な問題です。擬陽性率をコントロールして擬陽性を減らすために、いくつかの方法が提案されています。研究論文で広く用いられている方法の一つはBenjamini and HochbergによるFalse discovery rate (FDR)です。FDRとは間違って棄却した帰無仮説のうち、本当は帰無仮説が正しい割合です。FDR=5%といった場合には、本当は発現差異がないのに、あると判断してしまった遺伝子1000個のうち、\(1000\times 0.05=50\)個の遺伝子は本当は発現差異がないという仮定で、p値を補正します。詳しい原理はここでは省略します。FDRによる多重検定補正を行うには、p.adjust関数を用います。まず、10個の遺伝子に対するp値が以下のように与えられたとします。

pvals
 [1] 0.61731016 0.01664043 0.01819819 0.05069772 0.17883478 0.08861926 0.40741858 0.22987814 0.27743056 0.17355748

5%有意な遺伝子は

pvals<=0.05
 [1] FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

です。

これに対して、FDRによる多重検定補正を行うには以下のように実行します。

(qvals <- p.adjust(pvals,method="BH"))
 [1] 0.61731016 0.09099094 0.09099094 0.16899241 0.29805796 0.22154816 0.45268731 0.32839735 0.34678820 0.29805796

FDR5%の結果は、以下のようになります。

qvals <= 0.05
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

p値による結果では有意だったものが、FDRによる多重検定補正で有意ではなくなりました。多重検定補正により有意となる基準が厳しくなるので、実際の解析では擬陽性の遺伝子の数を減らすことができます。

LS0tDQp0aXRsZTogIpOdjHaTSYm8kOCMn5LogWl0LYyfkuiCxpG9j2SMn5LoleKQs4FqIg0KYXV0aG9yOiAiWXVzdWtlIE1hdHN1aSINCmFmZmlsaWF0aW9uOiAilryMw4mukeWKd4NWg1iDZYOAkLaVqIp3laqW7CINCmRhdGU6ICKNxY9JjViQVpP6gUYyMDE3lE41jI4xN5P6Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KgtyCuILNg3qBW4OAg2aDQoOMg06DZ4OKgvCQ3ZLogrWC3IK3gUINCmBgYHtyLGV2YWw9Rn0NCmhvbWUgPC0gW5R6lXqCtYK9g3SDSIOLg1+C8INSg3OBW4K1gr2DcINYXQ0Kc2V0d2QoaG9tZSkNCmBgYA0KDQpgYGB7cix3YXJuaW5nPUZ9DQpsaWJyYXJ5KGRhdGEudGFibGUpDQpgYGANCnSMn5LogsmCwoKigsSQ4Ja+grWC3IK3gUKIyIm6gsyC5oKkgsmBQTEwjMKCzIjik2COcYLJkc6CtYLEk/GCwoLMj/CMj4m6gWmX4YKmgs6BQVR1bW9yIC8gTm9ybWFsgWqCxTWDVIOTg3aDi4K4gsKCzIjik2COcZStjLuDZoFbg16NbIKmgtyCt4FCltqVV4LNgUGP8IyPitSCxZStjLuXyoLMiNmCyILpiOKTYI5xjFGC8JOvkuiCt4LpgrGCxoLFgreBQg0KYGBge3J9DQpzZXQuc2VlZCgxMDApDQpuIDwtIDEwDQpwIDwtIDUNCmNvbmQxIDwtIG1hdHJpeChybmJpbm9tKG4qcCwyLG11ID0gMzAwKSxuY29sPXAsZGltbmFtZXM9bGlzdChwYXN0ZTAoIkdlbmUiLDE6bikscGFzdGUwKCJDb25kaXRpb24iLHJlcCgxLHApKSkpDQpjb25kMiA8LSBtYXRyaXgocm5iaW5vbShuKnAsMixtdSA9IDEwMCksbmNvbD1wLGRpbW5hbWVzPWxpc3QocGFzdGUwKCJHZW5lIiwxOm4pLHBhc3RlMCgiQ29uZGl0aW9uIixyZXAoMixwKSkpKQ0KZGF0YV9leGFtcGxlIDwtIGNiaW5kKGNvbmQxLGNvbmQyKQ0KYGBgDQoNCmBgYHtyLGVjaG89Rn0NCmthYmxlKGRhdGFfZXhhbXBsZSkNCmBgYA0Kk/GCwoLMj/CMj4rUgsyI4YKigvCMqYLplfuWQILNgqKCrYLCgqmNbIKmgueC6oLcgreBQojqgsKCzYFBbG9nIGZvbGQgY2hhbmdlIChMRkMpgvCMdo5agreC6YKxgsaCxYK3gUKI4pNgjnEkaSSCyZHOgreC6UxGQ4LGgs0NCg0KXFtcbWJveHtsb2dGQ31faT1cbWJveHtsb2cyfShNX3tpLDF9IC8gTV97aSwyfSlcXQ0KDQooJE1fe2ksan0kgs2I4pNgjnEkaSSP8IyPJGokgsyUrYy7l8qCzJW9i8+CxYK3gUINCg0KYGBge3J9DQpNMSA8LSBhcHBseShjb25kMSwxLGZ1bmN0aW9uKHgpbWVhbih4KSkNCk0yIDwtIGFwcGx5KGNvbmQyLDEsZnVuY3Rpb24oeCltZWFuKHgpKQ0KKGxvZ0ZDIDwtIGxvZzIoKE0xICsgMSkgLyAoTTIgKyAxKSkpDQpgYGANCg0KTEZDgs2Cx4LMkvaTeIFBiOGCpIKpgvCVXIK3jneVV4LFgreCqoFBgseCzOiHkmyIyI/jgsWCoILqgs5gjbeCqoKggulggqmCzJa+im2CyIruj4CCzYKgguiC3IK5gvGBQoLcgr2I4pNgjnGCsoLGgsmDZoFbg16CzILOgueCwoKrlfuCzYjZgsiC6IFBk76C54Lqgr1MRkOCqpZ7k5aCyYv0kVKCqYLHgqSCqYLgjKmS6ILfgumVS5d2gqqCoILogtyCt4KqgruC6oLNgsWCq4LcgrmC8YFCgruCzIK9gt+CyYFBk52MdpNJibyQ4IyfkuiCxoKigqSYZ5Fngt2C8JdwgqKCxIFBgs6C54LCgquC8Iptl6aTSYLJjWyCpoLEgUGWe5OWgsmCu4LMjbeCqoKggumCzIKpgvCVXYm/grWC3IK3gUJ0LYyfkuiCzYFBk/GMUYrUgsyVvYvPgsyNt4LwjJ+S6IK3gumR45Vck0mCyIyfkuiO6JZAgsWCt4FCDQoNCpGBkayBQXQtjJ+S6ILwjsCNc4K1gsSC3YLcgrWC5YKkgUKI4pNgjnExgsmRzoK1gsR0LYyfkuiC8I7AjXOCtYLEgt2C3IK3gUINCg0KYGBge3J9DQp4IDwtIGNvbmQxWzEsXQ0KeSA8LSBjb25kMlsxLF0NCihyZXN1bHRfdCA8LSB0LnRlc3QoeCx5LHZhci5lcXVhbCA9IFRSVUUpKQ0KYGBgDQoNCnCSbILNgqKCrYLngqmCxoKigqSCxoFBDQpgYGB7cn0NCnJlc3VsdF90JHAudmFsdWUNCmBgYA0KgsaCyILogUGXTIjTkIWPgDUlgsWNbIKmgumCxpdMiNOCxYLNgqCC6ILcgrmC8YFCUoLFdC2Mn5LogvCNc4KkgsyCzZTxj+2CyYrIklCCxYK3gUKCvYK+grWBQYK7gsyOZJFngt2C8JJtgsGCxIKigsiCooLGgUGCoILcguiI05ahguCVqoKpgueCuILJcJJsgvCQVYLoifGCtYK9guiBQZBVguiJ8YKzguqCxIK1gtyCooLcgreBQoKzgquC2YLHgsyQlI1zgsWJvYLwguKCwYK9gsyCqYLMiNOWoYLwl52J8IK1gsSC3YLmgqSCxo52gqKC3IK3gUINCg0KDQqBQJOdjHaTSYm8kOCMn5LogsWCzYFBgtyCuItBlrOJvJDggsaRzpenibyQ4ILwl6eCxILcgreBQotBlrOJvJDggsaCzY3Fj0mTSYLJYJTbkuhggrWCvYKijpaVv4LwgUGRzpenibyQ4ILJgs2Cu4LqgsaRzpTkgvCCyIK3jpaVv4LwjWyCpoLcgreBQo2hifGCzI/qjYeCvoLGgUGP8IyPMYLGj/CMjzKCxYFBlK2Mu5fKgqpgiNmCyILpYIjik2COcYxRgvCTr5LogrWCvYKigsyCxYFBibyQ4ILwiMiJuoLMguaCpILJgrWC3IK3gUINClxbXG1ib3h7i0GWs4m8kOB9Ok1fe2ksMX09TV97aSwyfVxdDQpcW1xtYm94e5HOl6eJvJDgfTpNX3tpLDF9XG5lcSBNX3tpLDJ9XF0NCg0Kjp+CyYFBi0GWs4m8kOCCqpZ7k5aCxYLNgsiCooKxgsaC8IptgqmC34Lpgr2C34LJgUGLQZazibyQ4ILwkuiXyom7grWCvWCMn5Lok52MdpfKYILwi4GC34LcgreBQg0KDQojIyMjdC2TnYx2l8oNClxbXG1ib3h7dC2TnYx2l8p9ID0gXGZyYWN7XG1ib3h7jFGK1ILMlb2Lz4LMiOGCon19e1xtYm94e4pljFGCzILOgueCwoKrfX1cXQ0KDQqQ5oLZgseCzHSTnYx2l8qCzYFBDQpgYGB7cn0NCnJlc3VsdF90JHN0YXRpc3RpYw0KYGBgDQqCxYK3gUINCg0KgrGCzHQtk52MdpfKgs2SUILIgumQlJJsgsWCzYKgguiC3IK5gvGBQo6plaqCzIptl6aTSYLIgs6C54LCgquCqYK9gvCVXIK3YIptl6aVqpV6YILwlHeViYLBgsSCooLcgreBQpPBgsmLQZazibyQ4ILMim2XppWqlXqCyILMgsWBQWCLQZazlaqVemCCxozEgtGC3IK3gUKJvJDgjJ+S6ILMg3yDQ4OTg2eCzYKxgsyLQZazlaqVeoLwkLOCtYKtl52J8IK3gumCsYLGgsWCt4FCdJOdjHaXyoLMj12CpJWqlXqCzXSVqpV6gsaCooKklryRT4KqgsKCooLEgqiC6IFBgruCzIxggs2DVIOTg3aDi5CUgsyC3YLJguaCwYLEjIiC3ILogtyCt4FCUoLFgs2KyJJQgsl0laqVeoKpgueDZoFbg16C8JC2kKyCs4K5gumCsYLGgqqCxYKrgumCzILFgUGOwI3bgsmMqYLEgt2C3IK1guWCpIFCDQoNCmBgYHtyfQ0KZGF0YV90IDwtIHJ0KDEwMDAwLGRmID0gbiAtIDIpDQpoaXN0KGRhdGFfdCxmcmVxID0gRix4bGFiPSJ0Iix5bGFiPSJQcm9iYWJpbGl0eSIpDQpgYGANCo/jkH2CzXSVqpV6gqmC53STnYx2l8qC8DEwMDAwjMKBQYm8kXqTSYLJkLaQrIK1gr2CxoKrgsyVcJN4laqVeoLFgreBQpFTgsSCzJVwk3iCzJhhgvCO5oLpgsaBQTGCyYLIgumC5oKkgsmQs4tLibuCtYLEgqKC3IK3gUKCsYLqgqqQ5oLZgseOwI1zgrWCvXSMn5LogsyLQZazlaqVeoLFgreBQotBlrOJvJDggs2T8YxRitSCzJW9i8+CzIjhgqI9MIFBgreCyILtgr+LQZazibyQ4ILJkc6JnoK3gul0k52MdpfKgqowgsiCzILFgUGXnZhfj+OCzYNbg42CyYLIgumCzYK4gsWCt4KqgUGVqpV6j+OCzYFBim2XppNJgsiCzoLngsKCq4Lwjp2CwYLEgqKC3IK3gUKVyoLMjL6CopX7gvCCt4LpgsaBQYLggrWC4IFBMTAwMDCJ8YFpjsCN24LJgs2Cu4LxgsiCsYLGgs2CxYKrgtyCuYLxgqqBaoFBjEqC6JXUgrV0k52MdpfKgvCMdo5agrWCvY6egsyCzoLngsKCq5X7gvCVXIK1gsSCooLcgreBQg0KDQqMSoLoldSCtYLJgsiC6ILcgreCqoFBgrGCzJWqlXqCzYtBlrOJvJDggsmRzomegrWCvXSTnYx2l8qCzILOgueCwoKrgvCVXIK1gsSCooLcgreBQoLFgs2BQZHOl6eJvJDggsmRzomegreC6XSTnYx2l8qCzJJsKHQ9LTIuMDI2NTAzKYLNgseCzIKggr2C6IKpgsaCooKkgsaBQQ0KDQpgYGB7cn0NCmhpc3QoZGF0YV90LGZyZXEgPSBGLHhsYWI9InQiLHlsYWI9IlByb2JhYmlsaXR5IikNCmFibGluZSh2PXJlc3VsdF90JHN0YXRpc3RpYyxjb2w9InJlZCIpDQpgYGANCg0Kim2CqYLJi0GWs4m8kOCCyZHOiZ6Ct4LpMILFgs2CyIKigsWCt4KqgUGM6423gsyUzYjNk+CCxoy+gqaCu4KkgsWCt4FCgrGC6oKqYIptl6aTSYLJYIzrjbeCzJTNiM2CqYLHgqSCqYLwlLuS6IK3gumCyYLNgUFgl0yI05CFj4BggsaCooKk6IeSbILwkN2Cr4LcgreBQovvkcyTSYLJl0yI05CFj4A1JYLGgqKCwYK9gsaCq4LJgs2BQQ0KDQpgYGB7cixlY2hvPUZ9DQp0aHIxIDwtIHF0KHAgPSAwLjAyNSxkZiA9IG4gLSAyKQ0KdGhyMiA8LSBxdChwID0gMC45NzUsZGYgPSBuIC0gMikNCiNoIDwtIGhpc3QoZGF0YV90LGZyZXEgPSBGLHhsYWI9InQiLHlsYWI9IlByb2JhYmlsaXR5IikNCiNjdXRzIDwtIGN1dChoJGJyZWFrcywgYygtSW5mLHRocjEsdGhyMixJbmYpKQ0KI3Bsb3QoaCxmcmVxPUZBTFNFLHhsYWI9InQiLHlsYWI9IlByb2JhYmlsaXR5IiwgY29sID0gYygiZ3JlZW4iLCJ3aGl0ZSIsImdyZWVuIilbY3V0c10pDQpoaXN0KGRhdGFfdCxmcmVxID0gRix4bGFiPSJ0Iix5bGFiPSJQcm9iYWJpbGl0eSIpDQphYmxpbmUodj10aHIxLGNvbD0iYmx1ZSIpDQphYmxpbmUodj10aHIyLGNvbD0iYmx1ZSIpDQpgYGANCg0KkH2ShpDCkEaCzJD8gqqXTIjTkIWPgILJkc6JnoK3gunoh5JsgvCVXIK1gsSCqILogUGCu4LMl7yRpILJkc6JnoK3gumKbZemgsyYYYKql0yI05CFj4CCyZHOiZ6Ct4LpNSWCxoLIgsGCxIKigtyCt4FCl0yI05CFj4A1JYLGgs2BQYv0kVIwgsWCzYLIgqKBaYtBlrOJvJDggqqQs4K1gqKBaoLGgreC6eiHkmyIyI/jgsaCyILpim2XpoKqjYKBWDUlgsWCoILpgsaMvoLBgsSCooLcgreBQom8gsmK1IjhgsGCxItBlrOJvJDggqqK1IjhgsGCxIKigumCxoKigsGCvYLGgrWCxILggUExMDCJ8ZKGNYnxkvaTeIK+gsaCooKkgrGCxoLFgreBQpeggvCV1IK5gs6BQYLggrWC4IK7gszoh5JsgvCJeoKmgsSCooLqgs6BQYK7guqCzYtBlrOJvJDggsyJuoLFgs2BQZbFkb2CyYtOgrGC6IKmgsiCooKxgsaCqotOgrGCwYK9gsaCooKkgrGCxoLJgsiC6ILcgreBQoK1gr2CqoLBgsSBQTUlgsaCooKkjOuNt4LNgqCC6YKvguqCx4LggUGNoYnxgsyLQZazibyQ4ILNYJCsguiXp4K9gsiComCCt4LIgu2Cv5dMiNOCxYLNgsiCooLGjWyCpoLpgu2Cr4LFgreBQg0KDQqNoYnxgs2BQTUlgsyXTIjTkIWPgILwiXqCpoLEgqKCyIKigsyCxYFBi0GWs4m8kOCCzWA1JYLMl0yI05CFj4CCxYr8i3BggsWCq4LcgrmC8YFCDQpgYGB7cixlY2hvPUZ9DQp0aHIxIDwtIHF0KHAgPSAwLjAyNSxkZiA9IG4gLSAyKQ0KdGhyMiA8LSBxdChwID0gMC45NzUsZGYgPSBuIC0gMikNCiNoIDwtIGhpc3QoZGF0YV90LGZyZXEgPSBGLHhsYWI9InQiLHlsYWI9IlByb2JhYmlsaXR5IikNCiNjdXRzIDwtIGN1dChoJGJyZWFrcywgYygtSW5mLHRocjEsdGhyMixJbmYpKQ0KI3Bsb3QoaCxmcmVxPUZBTFNFLHhsYWI9InQiLHlsYWI9IlByb2JhYmlsaXR5IiwgY29sID0gYygiZ3JlZW4iLCJ3aGl0ZSIsImdyZWVuIilbY3V0c10pDQpoaXN0KGRhdGFfdCxmcmVxID0gRix4bGFiPSJ0Iix5bGFiPSJQcm9iYWJpbGl0eSIpDQphYmxpbmUodj10aHIxLGNvbD0iYmx1ZSIpDQphYmxpbmUodj10aHIyLGNvbD0iYmx1ZSIpDQphYmxpbmUodj1yZXN1bHRfdCRzdGF0aXN0aWMsY29sPSJyZWQiKQ0KYGBgDQoNCoLFgs1wkmyCxoLNib2CqYLGgqKCpILGgUGQfZKGgsyQ1JBGgsyQ/ILMiUWRpILMim2XpoLMmGGCxYK3gWmC4IK1lYmCxYKgguqCzo22kaSBaoFCkOaC2YLHgUFwkmyCzTAuNjEzgsWCtYK9gqqBQYlFkaSCvoKvgsyXTIjTkIWPgILJkc6JnoK3gumXzIjmgs0wLjAyNSgyLjUlKYLIgsyCxYFBgrGCzJJsgvCXcIKigsSC4JDmgtmCx4LGk6+XbILJkNSQRoLMkPyCqpDCkEaCzJD8gvCJeoKmgsSCooLIgqKCxoKigqSCsYLGgqqCxYKrgtyCt4FCgsKC3ILogUFwkmyCzZdMiNOQhY+AgsmRzomegreC6eiHkmyC8Il6gqaCxIKigumCqYLwlLuSZoK3gumCvYLfgsySbILFgreBQg0KDQqRU4LEgsyI4pNgjnGCyZHOgrWCxIFBjJ+S6IK1gsSC3YLcgrWC5YKkgUINCg0KYGBge3J9DQpwdmFscyA8LSBOVUxMDQpmb3IoaSBpbiAxOm4pew0KeCA8LSBjb25kMVtpLF0NCnkgPC0gY29uZDJbaSxdDQpyZXN1bHRfdCA8LSB0LnRlc3QoeCx5LHZhci5lcXVhbCA9IFRSVUUpDQpwdmFsc1tpXSA8LSByZXN1bHRfdCRwLnZhbHVlDQp9DQpwdmFscw0KYGBgDQoNCo6fgsmXTIjTkIWPgDUlgsyQ4Ja+gqqWe5OWgqmCx4KkgqmC8IptgqmC34LEgt2C3IK1guWCpIFCim2CqYLflfuCzYrIklCCxYK3gUKTr4K2im2XppWqlXqCqYLnk/GMUYLMiOKTYI5xlK2Mu5fKgvCQtpCsgrOCuYLEgUE1JZdMiNOQhY+AgsWCzHSMn5LogvAxMDAwMInxjEqC6JXUgrWCvYLGgquCyYFBitSI4YLBgsSLQZazibyQ4ILwYIr8i3BggreC6YnxkJSCqoKoguaCuzUwMInxgsWCoILqgs41JYLMiNOWoYLNkLOCtYKigsaMvoKmgtyCt4FCDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTAwKQ0KbiA8LSAxMDAwMA0KcCA8LSA1DQpjb25kMV9tYW55IDwtIG1hdHJpeChybmJpbm9tKG4qcCwyLG11ID0gMTAwKSxuY29sPXAsZGltbmFtZXM9bGlzdChwYXN0ZTAoIkdlbmUiLDE6bikscGFzdGUwKCJDb25kaXRpb24iLHJlcCgxLHApKSkpDQpjb25kMl9tYW55IDwtIG1hdHJpeChybmJpbm9tKG4qcCwyLG11ID0gMTAwKSxuY29sPXAsZGltbmFtZXM9bGlzdChwYXN0ZTAoIkdlbmUiLDE6bikscGFzdGUwKCJDb25kaXRpb24iLHJlcCgyLHApKSkpDQpwdmFsc19tYW55IDwtIE5VTEwNCmZvcihpIGluIDE6bil7DQogIHggPC0gY29uZDFfbWFueVtpLF0NCiAgeSA8LSBjb25kMl9tYW55W2ksXQ0KICByZXN1bHRfdCA8LSB0LnRlc3QoeCx5LGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsdmFyLmVxdWFsID0gVFJVRSkNCiAgcHZhbHNfbWFueVtpXSA8LSByZXN1bHRfdCRwLnZhbHVlDQp9DQpzdW0ocHZhbHNfbWFueSA8PSAwLjA1KSAvIG4NCmBgYA0Kim2CqYLJgUE1JYKtgueCooLMim2XpoLFi0GWs4m8kOCC8IzrgsGCxGCK/ItwYIK1gsSCooLpguaCpILFgreBQg0KDQqNoYnxgs2BQWCXvJGkYIyfkuiCxozEgs6C6oLplfuWQILFjJ+S6ILwjXOCooLcgrWCvYFCgruC6oKqYGFsdGVybmF0aXZlPSJ0d28uc2lkZWRggsyVlJWqgsWCt4FCl7yRpILMiNOWoYLNgUGRzpenibyQ4IKqJE1fe2ksMX0gPCBNX3tpLDJ9JILGJE1fe2ksMX0+IE1fe2ksMn0kKILCgtyC6CRNX3tpLDF9XG5lcSBNX3tpLDJ9JCmCzJe8lfuC8Ircgt+CxIKigumCxoKigqSCsYLGgsWCt4FCldCRpIyfkuiCzI/qjYeCzYFBgseCv4LngqmC8IyfkuiCt4LpgrGCxoLJgsiC6ILcgreBQoLCgtyC6IFBDQoNCg0KXFtcbWJveHuLQZazibyQ4H06TV97aSwxfT5NX3tpLDJ9XF0NClxbXG1ib3h7kc6Xp4m8kOB9Ok1fe2ksMX1cbmVxIE1fe2ksMn1cXQ0KDQqC8IyfkuiCtYLcgreBQoKxgsyCxoKrgsySjYjTgs2BQZdMiNOQhY+AgsyNbIKmlfuCxYK3gUKXvJGkjJ+S6ILFl0yI05CFj4A1JYLGgqKCwYK9j+qNh4LJgs2BQZPxgsKCzIK1gquCopJsgs2BQYpPkaSCzJhhgqo1JYLJgsiC6YLmgqSCyIK1gquCopJsgsaCyILogtyCt4KqgUGV0JGkjJ+S6ILFgreCxoFBldCV+4LMgrWCq4KikmyCtYKpl3CCooLIgsyCxYFBldCV+4LMgrWCq4KikmyCzIpPkaSCzJhhgqo1JYLGgsiC6YLmgqSCyIK1gquCopJsgsaCyILogtyCt4FCDQoNCmBgYHtyLGVjaG89Rn0NCnggPC0gY29uZDFbMSxdDQp5IDwtIGNvbmQyWzEsXQ0KcmVzdWx0X3QgPC0gdC50ZXN0KHgseSx2YXIuZXF1YWwgPSBUUlVFKQ0KdGhyIDwtIHF0KHAgPSAwLjk1LGRmID0gbiAtIDIpDQojaCA8LSBoaXN0KGRhdGFfdCxmcmVxID0gRix4bGFiPSJ0Iix5bGFiPSJQcm9iYWJpbGl0eSIpDQojY3V0cyA8LSBjdXQoaCRicmVha3MsIGMoLUluZix0aHIxLHRocjIsSW5mKSkNCiNwbG90KGgsZnJlcT1GQUxTRSx4bGFiPSJ0Iix5bGFiPSJQcm9iYWJpbGl0eSIsIGNvbCA9IGMoImdyZWVuIiwid2hpdGUiLCJncmVlbiIpW2N1dHNdKQ0KaGlzdChkYXRhX3QsZnJlcSA9IEYseGxhYj0idCIseWxhYj0iUHJvYmFiaWxpdHkiKQ0KYWJsaW5lKHY9dGhyLGNvbD0iYmx1ZSIpDQphYmxpbmUodj1yZXN1bHRfdCRzdGF0aXN0aWMsY29sPSJyZWQiKQ0KYGBgDQoNCmBhbHRlcm5hdGl2ZT0iZ3JlYXRlciJggsaCt4Lqgs6BQZHOl6eJvJDggs0kTV97aSwxfSA+IE1fe2ksMn0kgsaCyILogUFgYWx0ZXJuYXRpdmU9Imxlc3MiYILGgreC6oLOkc6Xp4m8kOCCzSRNX3tpLDF9IDwgTV97aSwyfSSCxoLIguiC3IK3gUJgdC50ZXN0YIrWkJSCzIrulnuQ3ZLogsWCzWBhbHRlcm5hdGl2ZT0idHdvLnNpZGVkImCCxoLIgsGCxIKigtyCt4FCDQpgYGB7cn0NCnggPC0gY29uZDFbMSxdDQp5IDwtIGNvbmQyWzEsXQ0KKHJlc3VsdF90IDwtIHQudGVzdCh4LHksZ3JlYXRlcj0iZ3JlYXRlciIsdmFyLmVxdWFsID0gVFJVRSkpDQpgYGANCg0KYHZhci5lcXVhbGCCzTKMUYLMgs6C54LCgquC8JOvgraCxom8kuiCt4LpgqmU24KpgvCQ3ZLogrWC3IK3gUKNoYnxgs2Tr4K2gsaJvJLogrWCvYLMgsVgdmFyLmVxdWFsPVRSVUVggsaCtYLEgqKC3IK3gUKC4IK1YHZhci5lcXVhbD1GQUxTRWCCxoK3gumCxoFBg0WDRoOLg2CCzIyfkuiCxoKigqSV+5ZAgsmCyILogtyCt4FCj/OLtYLJiZ6CtoLEjmeCopWqgq+CxIKtgr6Cs4KigUINCg0KgsaCsYLrgsWBQZdMiNOQhY+ANSWCxYyfkuiC8DEwMInxjEqC6JXUgreCxoFBl0yI05CFj4CCzJLoi2CCqYLngUGKbZemk0mCyYLNNYnxgUGK1IjhgsGCxItBlrOJvJDggvCK/ItwgreC6YKxgsaCyYLIguiC3IK3gUKI4pNgjnGQlILNglGWnIvfgq2CoILogtyCt4KpgueBQYjik2COcYKygsaCyYyfkuiC8I1zgqSCxjIwMDAwifGCzIyfkuiC8I1zgqSCsYLGgsmCyILogUGXnZhfj+OCzWAkMjAwMDBcdGltZXMgMC4wNT0xMDAwJGCJ8YLNitSI4YLBgsSBQZStjLuCzI23iNmCqoLIgqKCzILJgUGCoILpgsaUu5JmgrWCxIK1gtyCpIKxgsaCyYLIguiC3IK3gUKCwoLcguiBQYtbl3qQq4LMiOKTYI5xgvAxMDAwjMKS9pN4ityC8YLFgrWC3IKkgrGCxoLJgsiC6ILcgreBQpOdjHaTSYm8kOCMn5LogvCMSoLoldSCtY1zgqSCsYLGgvBgkb2PZIyfkuhggsaMvoKigUGLW5d6kKuC8IKigqmCyYK1gsSMuILngreCqYLGgqKCpJbikeiCzZOdjHaKd4LFgs1gkb2PZIyfkuiV4pCzYILGgqKCwYLEgUGPZJd2gsiW4pHogsWCt4FCi1uXepCrl6aC8INSg5ODZ4ONgVuDi4K1gsSLW5d6kKuC8Iy4gueCt4K9gt+CyYFBgqKCrYLCgqmCzJX7lkCCqpLxiMSCs4LqgsSCooLcgreBQoyki4aYX5W2gsWNTIKtl3CCooLnguqCxIKigumV+5ZAgsyI6oLCgs1CZW5qYW1pbmkgYW5kIEhvY2hiZXJngsmC5oLpRmFsc2UgZGlzY292ZXJ5IHJhdGUgKEZEUimCxYK3gUJGRFKCxoLNitSI4YLBgsSK/ItwgrWCvYtBlrOJvJDggsyCpIK/gUGWe5OWgs2LQZazibyQ4IKqkLOCtYKiioSNh4LFgreBQkZEUj01JYLGgqKCwYK9j+qNh4LJgs2BQZZ7k5aCzZStjLuNt4jZgqqCyIKigsyCyYFBgqCC6YLGlLuSZoK1gsSCtYLcgsGCvYjik2COcTEwMDCMwoLMgqSCv4FBJDEwMDBcdGltZXMgMC4wNT01MCSMwoLMiOKTYI5xgs2We5OWgs2UrYy7jbeI2YKqgsiCooLGgqKCpIm8kuiCxYFBcJJsgvCV4pCzgrWC3IK3gUKP2oK1gqKMtJedgs2CsYKxgsWCzY/Il6qCtYLcgreBQkZEUoLJguaC6ZG9j2SMn5LoleKQs4LwjXOCpILJgs2BQWBwLmFkanVzdGCK1pCUgvCXcIKigtyCt4FCgtyCuIFBMTCMwoLMiOKTYI5xgsmRzoK3gulwkmyCqojIibqCzILmgqSCyZdegqaC54Lqgr2CxoK1gtyCt4FCDQpgYGB7cn0NCnB2YWxzDQpgYGANCg0KNSWXTIjTgsiI4pNgjnGCzQ0KYGBge3J9DQpwdmFscyA8PSAwLjA1DQpgYGANCoLFgreBQg0KDQqCsYLqgsmRzoK1gsSBQUZEUoLJguaC6ZG9j2SMn5LoleKQs4LwjXOCpILJgs2IyIm6gsyC5oKkgsmOwI1zgrWC3IK3gUINCmBgYHtyfQ0KKHF2YWxzIDwtIHAuYWRqdXN0KHB2YWxzLG1ldGhvZD0iQkgiKSkNCmBgYA0KRkRSNSWCzIyLicqCzYFBiMiJuoLMguaCpILJgsiC6ILcgreBQg0KYGBge3J9DQpxdmFscyA8PSAwLjA1DQpgYGANCnCSbILJguaC6YyLicqCxYLNl0yI04K+gsGCvYLggsyCqoFBRkRSgsmC5oLpkb2PZIyfkuiV4pCzgsWXTIjTgsWCzYLIgq2CyILogtyCtYK9gUKRvY9kjJ+S6JXikLOCyYLmguiXTIjTgsaCyILpiu6PgIKqjLWCtYKtgsiC6YLMgsWBQY7AjduCzInwkM2CxYLNi1uXepCrgsyI4pNgjnGCzJCUgvCMuILngreCsYLGgqqCxYKrgtyCt4FCDQo=