演習の概要

注意事項

  • 慶應義塾大学SFCで開講している「環境ガバナンスのデータサイエンス」「空間モデリング特論」の授業履修者向けの演習用ページです。
  • 必ずしも全てのバージョンのRやOSで動作確認を行っていません。この演習用ページを作成している段階では、R3.5.3を使っています。
  • Rの更新などにより、Rコードなどを予告無しに変更する場合があります。

データ分析の準備

データのダウンロード

  • 演習で用いるデータはここからダウンロードしてください。
  • ここでは./直下にgisdataフォルダを作成し、setwd("gisdata")とディレクトリを指定しています

パッケージのインストール

  • install.packages()でパッケージをインストールし、library()でパッケージを呼び出す
  • ここでは以下のパッケージを用います
install.packages("DCluster")
install.packages("spdep")
library(DCluster)
library(spdep)

以下の方法でパイプ %>% の優先順位を高める

needs::prioritize(magrittr)

データの読み込み

都道府県別出生率データを読み込み、出生率の期待値を計算します。

data76 <- read.table("data76.csv", sep=",", header=TRUE, row.names=1)
data76_OE <- data.frame(Observed=data76$n.birth)
data76_OE <- cbind(data76_OE,  
Expected=data76$pop*sum(data76$n.birth)/sum(data76$pop), 
x=data76$Easting, y=data76$Northing)

空間集積性の検定

ピアソンの\(\chi^2\)検定

DClusterパッケージのachisq.stat()関数で\(\chi^2\)統計量を計算し、achisq.test()関数で\(\chi^2\)検定の結果を示す。これにより、ランダム性に関する検定を行う。

achisq.stat(data76_OE, lambda=1)
$T
[1] 1616.169

$df
[1] 79

$pvalue
[1] 3.154174e-285
achisq.test(Observed~offset(log(Expected)), data76_OE, model="poisson", R=100)
Chi-square test for overdispersion 

    Type of boots.: parametric 
    Model used when sampling: Poisson 
    Number of simulations: 100 
    Statistic:  1616.169 
    p-value :  0.00990099 

さらに、boot()関数を用いてブートストラップ法により標本を生成し、\(\chi^2\)検定を行うこともできる。

data76_achb_pb <- boot(data76_OE, statistic=achisq.pboot, sim="parametric", ran.gen=poisson.sim, R=100)
plot(data76_achb_pb)

Potthoff & Whittinghillの検定(過分散の有無に関する検定)

すべての地区において相対リスクが互いに類似しているかどうかを検証する方法です。

pottwhitt.stat(data76_OE)
$T
[1] 3840008393

$asintmean
[1] 3745501200

$asintvat
[1] 591789189600

$pvalue
[1] 0
pottwhitt.test(Observed~offset(log(Expected)), data76_OE, model="poisson", R=100)
Potthoff-Whittinghill's test of overdispersion 

    Type of boots.: parametric 
    Model used when sampling: Poisson 
    Number of simulations: 100 
    Statistic:  3840008393 
    p-value :  0.00990099 

boot()関数を用いてブートストラップ法により標本を生成し、過分散の有無に関する検定を行う。

data76_pw_pb <- boot(data76_OE, statistic=pottwhitt.pboot, sim="parametric", ran.gen=poisson.sim, R=100)
plot(data76_pw_pb)

Stone’s test

各地区の相対リスクが等しいという帰無仮説\(H_0\)に対して、特定の地域からの距離が増加する毎に相対リスク\(\theta\)が減少するという対立仮説\(H_1\)を立て、仮説検定する方法です。

stone.stat(data76_OE, region=which(row.names(data76_OE)=="20"), lambda=1)
             region 
 1.000948 79.000000 
stone.test(Observed~offset(log(Expected)), data76_OE, model="poisson", R=100, region=which(row.names(data76_OE)=="20"), lambda=1)
Stone's Test for raised incidence around locations 

    Type of boots.: parametric 
    Model used when sampling: Poisson 
    Number of simulations: 100 
    Statistic:  1.000948 
    p-value :  0.8910891 

boot()関数を用いてブートストラップ法により標本を生成し、検定を行う。

data76_st_pb <- boot(data76_OE, statistic=stone.pboot, sim="parametric", ran.gen=poisson.sim, R=100, region=which(row.names(data76_OE)=="20"))
plot(data76_st_pb)

Tango’s test

空間オブジェクト同士の隣接性を考慮して空間属性の集積性を仮説検定する方法。

spdepパッケージを使って空間隣接行列と空間重み付け行列を計算する。さらにDClusterパッケージのtango.stat()関数により、Tango統計量\(T\)を用いた集積性の有無を\(\chi^2\)検定する。

data76_OE <- cbind(data76_OE, x=data76$Easting, y=data76$Northing)
coords <- as.matrix(data76_OE[,c("x","y")])
dlist <- dnearneigh(coords, 0, Inf)
dlist <- include.self(dlist)
dlist.d <- nbdists(dlist, coords)
col.W.tango <- nb2listw(dlist, glist=lapply(dlist.d, function(x){exp(-x)}), style="C")
tango.stat(data76_OE, col.W.tango, zero.policy=TRUE)
             [,1]
[1,] 0.0003874411
tango.test(Observed~offset(log(Expected)), data76_OE, model="poisson", R=100, list=col.W.tango, zero.policy=TRUE)
Tango's test of global clustering 

    Type of boots.: parametric 
    Model used when sampling: Poisson 
    Number of simulations: 100 
    Statistic:  0.0003874411 
    p-value :  0.00990099 

boot()関数を用いてブートストラップ法により標本を生成し、検定を行う。

data76_tn_pb <- boot(data76_OE, statistic=tango.pboot, sim="parametric", ran.gen=poisson.sim, R=100, listw=col.W.tango, zero.policy=TRUE)
plot(data76_tn_pb)

Whittermoreの統計量

空間オブジェクト間の距離\(d_ij\)を要素とする距離行列\(D\)を用いて、空間属性の集積性を仮説検定する。

col.W.whitt <- col.W.tango
whittermore.stat(data76_OE, col.W.whitt, zero.policy=TRUE)
           [,1]
[1,] 0.02664723
whittermore.test(Observed~offset(log(Expected)), data76_OE, model="poisson", R=100, list=col.W.whitt, zero.policy=TRUE)
Whittermore's test of global clustering 

    Type of boots.: parametric 
    Model used when sampling: Poisson 
    Number of simulations: 100 
    Statistic:  0.02664723 
    p-value :  0.00990099 

boot()関数を用いてブートストラップ法により標本を生成し、検定を行う。

data76_wt_pb <- boot(data76_OE, statistic=whittermore.pboot, sim="parametric", ran.gen=poisson.sim, R=100, listw=col.W.whitt, zero.policy=TRUE)
plot(data76_wt_pb)

Besag-Newell’s test

空間データの観測値\(O_i\)の発生が非常にまれであり、負の二項分布などに従うような場合に用いられる。

boot()関数を用いてブートストラップ法により標本を生成し、検定を行う。

data76_bn_perboot <- boot(data76_OE, statistic=besagnewell.boot, R=100, k=20)
plot(data76_bn_perboot)

OpenshawのGAM

opgam()関数を用いてOpenshaw のGeographical Analysis Machine(GAM)を計算する。

格子データの交点ではないが、市区町村代表点データ上に、市区町村別出生率を用いてGAM を適用してみる。

thegrid <- as(data76_OE, "data.frame")[,c("x","y")]
data76_opg <- opgam(data=as(data76_OE, "data.frame"), thegrid=thegrid,radius=20000, step=1000, alpha=0.05)
data76_opg
plot(data76_OE$x,data76_OE$y, xlab="Easting", ylab="Northing", cex=2,cex.axis=1.2, cex.lab=1.2)
points(data76_opg$x, data76_opg$y, col="red", pch="*", cex=4)

Kulldorffの空間スキャン統計量

最大尤度比となるウィンドゥをクラスターの候補と考える方法。最大尤度比を求めるために、モンテカルロシミュレーションで求めた値を用いて、統計的有意性を判断する。

kullnagar.stat()関数を用いて以下のように計算できる。

data76_OE <- data.frame(Observed=data76$n.birth)
data76_OE <- cbind(data76_OE,  
Expected=data76$pop*sum(data76$n.birth)/sum(data76$pop), 
x=data76$Easting, y=data76$Northing)
dist <- (data76_OE$x-data76_OE$x[1])^2+(data76_OE$y-data76_OE$y[1])^2
index<-order(dist)
kullnagar.stat(data76_OE[index,], fractpop=.5)
      value        size 
5.33617e+75 3.00000e+01 
LS0tCnRpdGxlOiAi56m66ZaT44Oi44OH44Oq44Oz44KwUua8lOe/kjYiCiNhdXRob3I6ICJUb21veXVraSBGdXJ1dGFuaSIKI2RhdGU6ICIyMDE5LzMvMjkiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAotLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoY2FjaGUgPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoZXJyb3IgPSBUUlVFKQpgYGAKCiMjIOa8lOe/kuOBruamguimgQotIOepuumWk+mbhuepjeaAp+OBruaknOWumuOAgeODlOOCouOCveODs+OBriRcY2hpXjIk5qSc5a6a44CBUG90dGhvZmYgJiBXaGl0dGluZ2hpbGzjga7mpJzlrprjgIFTdG9uZeKAmXMgdGVzdOOAgVRhbmdv4oCZcyB0ZXN044CBV2hpdHRlcm1vcmXjga7ntbHoqIjph4/jgIFCZXNhZy1OZXdlbGzigJlzIHRlc3TjgIFPcGVuc2hhd+OBrkdBTeOAgUt1bGxkb3JmZuOBruepuumWk+OCueOCreODo+ODs+e1seioiOmHjwoKIyMjIOazqOaEj+S6i+mghQotIOaFtuaHiee+qeWhvuWkp+WtplNGQ+OBp+mWi+ism+OBl+OBpuOBhOOCi+OAjOepuumWk+ODouODh+ODquODs+OCsOOAjeOBruaOiOalreWxpeS/ruiAheWQkeOBkeOBrua8lOe/kueUqOODmuODvOOCuOOBp+OBmeOAggotIOW/heOBmuOBl+OCguWFqOOBpuOBruODkOODvOOCuOODp+ODs+OBrlLjgoRPU+OBp+WLleS9nOeiuuiqjeOCkuihjOOBo+OBpuOBhOOBvuOBm+OCk+OAguOBk+OBrua8lOe/kueUqOODmuODvOOCuOOCkuS9nOaIkOOBl+OBpuOBhOOCi+autemajuOBp+OBr+OAgVIzLjUuM+OCkuS9v+OBo+OBpuOBhOOBvuOBmeOAggotIFLjga7mm7TmlrDjgarjganjgavjgojjgorjgIFS44Kz44O844OJ44Gq44Gp44KS5LqI5ZGK54Sh44GX44Gr5aSJ5pu044GZ44KL5aC05ZCI44GM44GC44KK44G+44GZ44CCIAoKIyMg44OH44O844K/5YiG5p6Q44Gu5rqW5YKZCiMjIyDjg4fjg7zjgr/jga7jg4Djgqbjg7Pjg63jg7zjg4kKLSDmvJTnv5LjgafnlKjjgYTjgovjg4fjg7zjgr/jga9b44GT44GTXShodHRwOi8vd2ViLnNmYy5rZWlvLmFjLmpwL35tYXVuei9hc2FrdXJhX3NwL2FzYWt1cmFfc3BfZGF0YV8xMTAxLnppcCnjgYvjgonjg4Djgqbjg7Pjg63jg7zjg4njgZfjgabjgY/jgaDjgZXjgYTjgIIKLSDjgZPjgZPjgafjga9gLi9g55u05LiL44GrYGdpc2RhdGFg44OV44Kp44Or44OA44KS5L2c5oiQ44GX44CBYHNldHdkKCJnaXNkYXRhIilg44Go44OH44Kj44Os44Kv44OI44Oq44KS5oyH5a6a44GX44Gm44GE44G+44GZCgojIyMg44OR44OD44Kx44O844K444Gu44Kk44Oz44K544OI44O844OrCi0gYGluc3RhbGwucGFja2FnZXMoKWDjgafjg5Hjg4PjgrHjg7zjgrjjgpLjgqTjg7Pjgrnjg4jjg7zjg6vjgZfjgIFgbGlicmFyeSgpYOOBp+ODkeODg+OCseODvOOCuOOCkuWRvOOBs+WHuuOBmQotIOOBk+OBk+OBp+OBr+S7peS4i+OBruODkeODg+OCseODvOOCuOOCkueUqOOBhOOBvuOBmQoKYGBge3IgaW5zdGFsbCBwYWNrYWdlcywgZXZhbD1GQUxTRX0KaW5zdGFsbC5wYWNrYWdlcygiRENsdXN0ZXIiKQppbnN0YWxsLnBhY2thZ2VzKCJzcGRlcCIpCmBgYAoKYGBge3IgbGlicmFyeSwgZXZhbD1GQUxTRX0KbGlicmFyeShEQ2x1c3RlcikKbGlicmFyeShzcGRlcCkKYGBgCgrku6XkuIvjga7mlrnms5Xjgafjg5HjgqTjg5cgJT4lIOOBruWEquWFiOmghuS9jeOCkumrmOOCgeOCiwpgYGB7ciBwaXBlX3ByaW9yaXRpemV9Cm5lZWRzOjpwcmlvcml0aXplKG1hZ3JpdHRyKQpgYGAKCiMjIyDjg4fjg7zjgr/jga7oqq3jgb/ovrzjgb8K6YO96YGT5bqc55yM5Yil5Ye655Sf546H44OH44O844K/44KS6Kqt44G/6L6844G/44CB5Ye655Sf546H44Gu5pyf5b6F5YCk44KS6KiI566X44GX44G+44GZ44CCCmBgYHtyIHJlYWRfZGF0YTc2fQpkYXRhNzYgPC0gcmVhZC50YWJsZSgiZGF0YTc2LmNzdiIsIHNlcD0iLCIsIGhlYWRlcj1UUlVFLCByb3cubmFtZXM9MSkKZGF0YTc2X09FIDwtIGRhdGEuZnJhbWUoT2JzZXJ2ZWQ9ZGF0YTc2JG4uYmlydGgpCmRhdGE3Nl9PRSA8LSBjYmluZChkYXRhNzZfT0UsICAKRXhwZWN0ZWQ9ZGF0YTc2JHBvcCpzdW0oZGF0YTc2JG4uYmlydGgpL3N1bShkYXRhNzYkcG9wKSwgCng9ZGF0YTc2JEVhc3RpbmcsIHk9ZGF0YTc2JE5vcnRoaW5nKQpgYGAKCiMjIOepuumWk+mbhuepjeaAp+OBruaknOWumgojIyMg44OU44Ki44K944Oz44GuJFxjaGleMiTmpJzlrpoKYERDbHVzdGVyYOODkeODg+OCseODvOOCuOOBrmBhY2hpc3Euc3RhdCgpYOmWouaVsOOBpyRcY2hpXjIk57Wx6KiI6YeP44KS6KiI566X44GX44CBYGFjaGlzcS50ZXN0KClg6Zai5pWw44GnJFxjaGleMiTmpJzlrprjga7ntZDmnpzjgpLnpLrjgZnjgILjgZPjgozjgavjgojjgorjgIHjg6njg7Pjg4Djg6DmgKfjgavplqLjgZnjgovmpJzlrprjgpLooYzjgYbjgIIKYGBge3Igc3BfYWdnMS0xfQphY2hpc3Euc3RhdChkYXRhNzZfT0UsIGxhbWJkYT0xKQphY2hpc3EudGVzdChPYnNlcnZlZH5vZmZzZXQobG9nKEV4cGVjdGVkKSksIGRhdGE3Nl9PRSwgbW9kZWw9InBvaXNzb24iLCBSPTEwMCkKYGBgCuOBleOCieOBq+OAgWBib290KClg6Zai5pWw44KS55So44GE44Gm44OW44O844OI44K544OI44Op44OD44OX5rOV44Gr44KI44KK5qiZ5pys44KS55Sf5oiQ44GX44CBJFxjaGleMiTmpJzlrprjgpLooYzjgYbjgZPjgajjgoLjgafjgY3jgovjgIIKYGBge3Igc3BfYWdnMS0yfQpkYXRhNzZfYWNoYl9wYiA8LSBib290KGRhdGE3Nl9PRSwgc3RhdGlzdGljPWFjaGlzcS5wYm9vdCwgc2ltPSJwYXJhbWV0cmljIiwgcmFuLmdlbj1wb2lzc29uLnNpbSwgUj0xMDApCnBsb3QoZGF0YTc2X2FjaGJfcGIpCmBgYAoKIyMjIFBvdHRob2ZmICYgV2hpdHRpbmdoaWxs44Gu5qSc5a6a77yI6YGO5YiG5pWj44Gu5pyJ54Sh44Gr6Zai44GZ44KL5qSc5a6a77yJCuOBmeOBueOBpuOBruWcsOWMuuOBq+OBiuOBhOOBpuebuOWvvuODquOCueOCr+OBjOS6kuOBhOOBq+mhnuS8vOOBl+OBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkuaknOiovOOBmeOCi+aWueazleOBp+OBmeOAggpgYGB7ciBzcF9hZ2cyLTF9CnBvdHR3aGl0dC5zdGF0KGRhdGE3Nl9PRSkKcG90dHdoaXR0LnRlc3QoT2JzZXJ2ZWR+b2Zmc2V0KGxvZyhFeHBlY3RlZCkpLCBkYXRhNzZfT0UsIG1vZGVsPSJwb2lzc29uIiwgUj0xMDApCmBgYApgYm9vdCgpYOmWouaVsOOCkueUqOOBhOOBpuODluODvOODiOOCueODiOODqeODg+ODl+azleOBq+OCiOOCiuaomeacrOOCkueUn+aIkOOBl+OAgemBjuWIhuaVo+OBruacieeEoeOBq+mWouOBmeOCi+aknOWumuOCkuihjOOBhuOAggpgYGB7ciBzcF9hZ2cyLTJ9CmRhdGE3Nl9wd19wYiA8LSBib290KGRhdGE3Nl9PRSwgc3RhdGlzdGljPXBvdHR3aGl0dC5wYm9vdCwgc2ltPSJwYXJhbWV0cmljIiwgcmFuLmdlbj1wb2lzc29uLnNpbSwgUj0xMDApCnBsb3QoZGF0YTc2X3B3X3BiKQpgYGAKCiMjIyBTdG9uZSdzIHRlc3QK5ZCE5Zyw5Yy644Gu55u45a++44Oq44K544Kv44GM562J44GX44GE44Go44GE44GG5biw54Sh5Luu6KqsJEhfMCTjgavlr77jgZfjgabjgIHnibnlrprjga7lnLDln5/jgYvjgonjga7ot53pm6LjgYzlopfliqDjgZnjgovmr47jgavnm7jlr77jg6rjgrnjgq8kXHRoZXRhJOOBjOa4m+WwkeOBmeOCi+OBqOOBhOOBhuWvvueri+S7ruiqrCRIXzEk44KS56uL44Gm44CB5Luu6Kqs5qSc5a6a44GZ44KL5pa55rOV44Gn44GZ44CCCgpgYGB7ciBzcF9hZ2czLTF9CnN0b25lLnN0YXQoZGF0YTc2X09FLCByZWdpb249d2hpY2gocm93Lm5hbWVzKGRhdGE3Nl9PRSk9PSIyMCIpLCBsYW1iZGE9MSkKc3RvbmUudGVzdChPYnNlcnZlZH5vZmZzZXQobG9nKEV4cGVjdGVkKSksIGRhdGE3Nl9PRSwgbW9kZWw9InBvaXNzb24iLCBSPTEwMCwgcmVnaW9uPXdoaWNoKHJvdy5uYW1lcyhkYXRhNzZfT0UpPT0iMjAiKSwgbGFtYmRhPTEpCmBgYAoKYGJvb3QoKWDplqLmlbDjgpLnlKjjgYTjgabjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5fms5XjgavjgojjgormqJnmnKzjgpLnlJ/miJDjgZfjgIHmpJzlrprjgpLooYzjgYbjgIIKYGBge3Igc3BfYWdnMy0yfQpkYXRhNzZfc3RfcGIgPC0gYm9vdChkYXRhNzZfT0UsIHN0YXRpc3RpYz1zdG9uZS5wYm9vdCwgc2ltPSJwYXJhbWV0cmljIiwgcmFuLmdlbj1wb2lzc29uLnNpbSwgUj0xMDAsIHJlZ2lvbj13aGljaChyb3cubmFtZXMoZGF0YTc2X09FKT09IjIwIikpCnBsb3QoZGF0YTc2X3N0X3BiKQpgYGAKCiMjIyBUYW5nbydzIHRlc3QK56m66ZaT44Kq44OW44K444Kn44Kv44OI5ZCM5aOr44Gu6Zqj5o6l5oCn44KS6ICD5oWu44GX44Gm56m66ZaT5bGe5oCn44Gu6ZuG56mN5oCn44KS5Luu6Kqs5qSc5a6a44GZ44KL5pa55rOV44CCCgpgc3BkZXBg44OR44OD44Kx44O844K444KS5L2/44Gj44Gm56m66ZaT6Zqj5o6l6KGM5YiX44Go56m66ZaT6YeN44G/5LuY44GR6KGM5YiX44KS6KiI566X44GZ44KL44CC44GV44KJ44GrYERDbHVzdGVyYOODkeODg+OCseODvOOCuOOBrmB0YW5nby5zdGF0KClg6Zai5pWw44Gr44KI44KK44CBVGFuZ2/ntbHoqIjph48kVCTjgpLnlKjjgYTjgZ/pm4bnqY3mgKfjga7mnInnhKHjgpIkXGNoaV4yJOaknOWumuOBmeOCi+OAggoKYGBge3Igc3BfYWdnNC0xfQpkYXRhNzZfT0UgPC0gY2JpbmQoZGF0YTc2X09FLCB4PWRhdGE3NiRFYXN0aW5nLCB5PWRhdGE3NiROb3J0aGluZykKY29vcmRzIDwtIGFzLm1hdHJpeChkYXRhNzZfT0VbLGMoIngiLCJ5IildKQpkbGlzdCA8LSBkbmVhcm5laWdoKGNvb3JkcywgMCwgSW5mKQpkbGlzdCA8LSBpbmNsdWRlLnNlbGYoZGxpc3QpCmRsaXN0LmQgPC0gbmJkaXN0cyhkbGlzdCwgY29vcmRzKQpjb2wuVy50YW5nbyA8LSBuYjJsaXN0dyhkbGlzdCwgZ2xpc3Q9bGFwcGx5KGRsaXN0LmQsIGZ1bmN0aW9uKHgpe2V4cCgteCl9KSwgc3R5bGU9IkMiKQp0YW5nby5zdGF0KGRhdGE3Nl9PRSwgY29sLlcudGFuZ28sIHplcm8ucG9saWN5PVRSVUUpCnRhbmdvLnRlc3QoT2JzZXJ2ZWR+b2Zmc2V0KGxvZyhFeHBlY3RlZCkpLCBkYXRhNzZfT0UsIG1vZGVsPSJwb2lzc29uIiwgUj0xMDAsIGxpc3Q9Y29sLlcudGFuZ28sIHplcm8ucG9saWN5PVRSVUUpCmBgYAoKYGJvb3QoKWDplqLmlbDjgpLnlKjjgYTjgabjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5fms5XjgavjgojjgormqJnmnKzjgpLnlJ/miJDjgZfjgIHmpJzlrprjgpLooYzjgYbjgIIKYGBge3Igc3BfYWdnNC0yfQpkYXRhNzZfdG5fcGIgPC0gYm9vdChkYXRhNzZfT0UsIHN0YXRpc3RpYz10YW5nby5wYm9vdCwgc2ltPSJwYXJhbWV0cmljIiwgcmFuLmdlbj1wb2lzc29uLnNpbSwgUj0xMDAsIGxpc3R3PWNvbC5XLnRhbmdvLCB6ZXJvLnBvbGljeT1UUlVFKQpwbG90KGRhdGE3Nl90bl9wYikKYGBgCiMjIyBXaGl0dGVybW9yZeOBrue1seioiOmHjwrnqbrplpPjgqrjg5bjgrjjgqfjgq/jg4jplpPjga7ot53pm6IkZF9paiTjgpLopoHntKDjgajjgZnjgovot53pm6LooYzliJckRCTjgpLnlKjjgYTjgabjgIHnqbrplpPlsZ7mgKfjga7pm4bnqY3mgKfjgpLku67oqqzmpJzlrprjgZnjgovjgIIKYGBge3Igc3BfYWdnNS0xfQpjb2wuVy53aGl0dCA8LSBjb2wuVy50YW5nbwp3aGl0dGVybW9yZS5zdGF0KGRhdGE3Nl9PRSwgY29sLlcud2hpdHQsIHplcm8ucG9saWN5PVRSVUUpCndoaXR0ZXJtb3JlLnRlc3QoT2JzZXJ2ZWR+b2Zmc2V0KGxvZyhFeHBlY3RlZCkpLCBkYXRhNzZfT0UsIG1vZGVsPSJwb2lzc29uIiwgUj0xMDAsIGxpc3Q9Y29sLlcud2hpdHQsIHplcm8ucG9saWN5PVRSVUUpCmBgYAoKYGJvb3QoKWDplqLmlbDjgpLnlKjjgYTjgabjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5fms5XjgavjgojjgormqJnmnKzjgpLnlJ/miJDjgZfjgIHmpJzlrprjgpLooYzjgYbjgIIKYGBge3Igc3BfYWdnNS0yfQpkYXRhNzZfd3RfcGIgPC0gYm9vdChkYXRhNzZfT0UsIHN0YXRpc3RpYz13aGl0dGVybW9yZS5wYm9vdCwgc2ltPSJwYXJhbWV0cmljIiwgcmFuLmdlbj1wb2lzc29uLnNpbSwgUj0xMDAsIGxpc3R3PWNvbC5XLndoaXR0LCB6ZXJvLnBvbGljeT1UUlVFKQpwbG90KGRhdGE3Nl93dF9wYikKYGBgCgojIyMgQmVzYWctTmV3ZWxsJ3MgdGVzdArnqbrplpPjg4fjg7zjgr/jga7oprPmuKzlgKQkT19pJOOBrueZuueUn+OBjOmdnuW4uOOBq+OBvuOCjOOBp+OBguOCiuOAgeiyoOOBruS6jOmgheWIhuW4g+OBquOBqeOBq+W+k+OBhuOCiOOBhuOBquWgtOWQiOOBq+eUqOOBhOOCieOCjOOCi+OAggoKYGJvb3QoKWDplqLmlbDjgpLnlKjjgYTjgabjg5bjg7zjg4jjgrnjg4jjg6njg4Pjg5fms5XjgavjgojjgormqJnmnKzjgpLnlJ/miJDjgZfjgIHmpJzlrprjgpLooYzjgYbjgIIKYGBge3Igc3BfYWdnNi0yfQpkYXRhNzZfYm5fcGVyYm9vdCA8LSBib290KGRhdGE3Nl9PRSwgc3RhdGlzdGljPWJlc2FnbmV3ZWxsLmJvb3QsIFI9MTAwLCBrPTIwKQpwbG90KGRhdGE3Nl9ibl9wZXJib290KQpgYGAKIyMjIE9wZW5zaGF344GuR0FNCmBvcGdhbSgpYOmWouaVsOOCkueUqOOBhOOBpk9wZW5zaGF3IOOBrkdlb2dyYXBoaWNhbCBBbmFseXNpcyBNYWNoaW5lKEdBTSnjgpLoqIjnrpfjgZnjgovjgIIKCuagvOWtkOODh+ODvOOCv+OBruS6pOeCueOBp+OBr+OBquOBhOOBjOOAgeW4guWMuueUuuadkeS7o+ihqOeCueODh+ODvOOCv+S4iuOBq+OAgeW4guWMuueUuuadkeWIpeWHuueUn+eOh+OCkueUqOOBhOOBpkdBTSDjgpLpgannlKjjgZfjgabjgb/jgovjgIIKCmBgYHtyIHNwX2FnZzctMX0KdGhlZ3JpZCA8LSBhcyhkYXRhNzZfT0UsICJkYXRhLmZyYW1lIilbLGMoIngiLCJ5IildCmRhdGE3Nl9vcGcgPC0gb3BnYW0oZGF0YT1hcyhkYXRhNzZfT0UsICJkYXRhLmZyYW1lIiksIHRoZWdyaWQ9dGhlZ3JpZCxyYWRpdXM9MjAwMDAsIHN0ZXA9MTAwMCwgYWxwaGE9MC4wNSkKZGF0YTc2X29wZwpgYGAKCmBgYHtyIHNwX2FnZzctMn0KcGxvdChkYXRhNzZfT0UkeCxkYXRhNzZfT0UkeSwgeGxhYj0iRWFzdGluZyIsIHlsYWI9Ik5vcnRoaW5nIiwgY2V4PTIsY2V4LmF4aXM9MS4yLCBjZXgubGFiPTEuMikKcG9pbnRzKGRhdGE3Nl9vcGckeCwgZGF0YTc2X29wZyR5LCBjb2w9InJlZCIsIHBjaD0iKiIsIGNleD00KQpgYGAKCiMjIyBLdWxsZG9yZmbjga7nqbrplpPjgrnjgq3jg6Pjg7PntbHoqIjph48K5pyA5aSn5bCk5bqm5q+U44Go44Gq44KL44Km44Kj44Oz44OJ44Kl44KS44Kv44Op44K544K/44O844Gu5YCZ6KOc44Go6ICD44GI44KL5pa55rOV44CC5pyA5aSn5bCk5bqm5q+U44KS5rGC44KB44KL44Gf44KB44Gr44CB44Oi44Oz44OG44Kr44Or44Ot44K344Of44Ol44Os44O844K344On44Oz44Gn5rGC44KB44Gf5YCk44KS55So44GE44Gm44CB57Wx6KiI55qE5pyJ5oSP5oCn44KS5Yik5pat44GZ44KL44CCCgpga3VsbG5hZ2FyLnN0YXQoKWDplqLmlbDjgpLnlKjjgYTjgabku6XkuIvjga7jgojjgYbjgavoqIjnrpfjgafjgY3jgovjgIIKYGBge3Igc3BfYWdnOC0xfQpkYXRhNzZfT0UgPC0gZGF0YS5mcmFtZShPYnNlcnZlZD1kYXRhNzYkbi5iaXJ0aCkKZGF0YTc2X09FIDwtIGNiaW5kKGRhdGE3Nl9PRSwgIApFeHBlY3RlZD1kYXRhNzYkcG9wKnN1bShkYXRhNzYkbi5iaXJ0aCkvc3VtKGRhdGE3NiRwb3ApLCAKeD1kYXRhNzYkRWFzdGluZywgeT1kYXRhNzYkTm9ydGhpbmcpCmRpc3QgPC0gKGRhdGE3Nl9PRSR4LWRhdGE3Nl9PRSR4WzFdKV4yKyhkYXRhNzZfT0UkeS1kYXRhNzZfT0UkeVsxXSleMgppbmRleDwtb3JkZXIoZGlzdCkKa3VsbG5hZ2FyLnN0YXQoZGF0YTc2X09FW2luZGV4LF0sIGZyYWN0cG9wPS41KQpgYGAK