第6章で使うための、整理整頓済みデータの読み込み

###For chapter 06
phyto_metadata <- readRDS("phyto_metadata.obj")
species_ryuko_data <- readRDS("phyto_ryuko_data.obj")
metadata_ecoplate <- readRDS("metadata_ecopl.obj")
summary_ecoplate <- readRDS("summary_ecopl.obj")
#from basic_graphics.R 種数について再度計算
species_richness <- apply(species_ryuko_data > 0, 1, sum)

6.3.1 subset関数

一番シンプルな使い方

#subset関数を使うと条件を満たす要素を抜き出せる
subset(species_richness, phyto_metadata$year == "2018")
20180316_1_ryuko.csv 20180316_2_ryuko.csv 20181004_1_ryuko.csv 
                  16                   17                   43 
20181004_2_ryuko.csv 20181004_3_ryuko.csv 20181025_1_ryuko.csv 
                  32                   36                   23 
20181025_2_ryuko.csv 
                  32 
subset(species_ryuko_data, phyto_metadata$year == "2018")

subset関数と代入演算子(<-)を組み合わせる

#subset関数で抜き出した要素を、左辺のオブジェクトに格納(代入)する。
species_richness2018 <- subset(species_richness, phyto_metadata$year == "2018")
species_richness2019 <- subset(species_richness, phyto_metadata$year == "2019")

6.3.2基本統計量とtapply関数

抜き出したデータがどんな感じかをsummary関数で確認

#抜き出したデータの要約統計量
summary(species_richness2018)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  16.00   20.00   32.00   28.43   34.00   43.00 
summary(species_richness2019)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  19.00   24.25   25.50   26.50   27.50   37.00 

tapply関数を使ってsummary(要約統計量), mean(平均), var(分散)を計算する

#要約統計量
tapply(species_richness, phyto_metadata$year, summary)
$`2018`
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  16.00   20.00   32.00   28.43   34.00   43.00 

$`2019`
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  19.00   24.25   25.50   26.50   27.50   37.00 
#平均
tapply(species_richness, phyto_metadata$year, mean)
    2018     2019 
28.42857 26.50000 
#分散
tapply(species_richness, phyto_metadata$year, var)
     2018      2019 
101.61905  31.71429 

6.3.3 t検定

植物プランクトンの種数をyear間(2018 vs 2019)で比較する

#Welch(ウェルチ)の2標本t検定を使うのが最近のデフォルト
#公式(Y~X)の形で書く
t.test(species_richness ~ phyto_metadata$year, var.equal = F)

    Welch Two Sample t-test

data:  species_richness by phyto_metadata$year
t = 0.44861, df = 9.1401, p-value = 0.6642
alternative hypothesis: true difference in means between group 2018 and group 2019 is not equal to 0
95 percent confidence interval:
 -7.77373 11.63087
sample estimates:
mean in group 2018 mean in group 2019 
          28.42857           26.50000 

全個体数の比較

種組成のデータ=各種の個体数のデータを各行(1)に対して、全種について足し合わせて(sum),全個体数を計算する

total_abundance <- apply(species_ryuko_data,1,sum)
全個体数の2群比較
可視化(図6.6)
boxplot( #箱ひげ図
  total_abundance ~ phyto_metadata$year, #公式スタイル
  outline = TRUE, #外れ値の表示
  col = "white" #箱の色指定
)
stripchart( #一次元散布図
  total_abundance ~ phyto_metadata$year, #公式スタイル
  method = "stack", #重複する点は規則的に並べる
  pch = c(1,2), #点のマーク(記号)の指定
  cex = 3, #マークのサイズ
  vertical = TRUE, #垂直(vertical)方向に散布図を延ばす
  add = TRUE #上の箱ひげ図に重ねて描画
)

t検定
#年ごとに総個体数(total_abundance)の平均(mean)を計算
tapply(total_abundance, phyto_metadata$year, mean)
    2018     2019 
462.1429 205.5000 
#Welchのt検定
t.test(total_abundance ~ phyto_metadata$year, var.equal = F)

    Welch Two Sample t-test

data:  total_abundance by phyto_metadata$year
t = 2.392, df = 6.7469, p-value = 0.04933
alternative hypothesis: true difference in means between group 2018 and group 2019 is not equal to 0
95 percent confidence interval:
   0.9986613 512.2870530
sample estimates:
mean in group 2018 mean in group 2019 
          462.1429           205.5000 

6.4 分散分析

6.4.2 植物プランクトン種数の月間比較

分散分析用の可視化(まずは可視化! 図6.9A)
#箱ひげ図と一次元散布図の重ね合わせ
#因子(要因)phyto_matadata$monthは、as.factor関数を使って明示的に「因子」にする
boxplot(species_richness ~ as.factor(phyto_metadata$month), 
     outline = FALSE, #外れ値は明示しない
     col = "white",
     xlab = "month",
     ylab = "species richness",
     ylim = c(0,40) #Y軸の表示範囲(最小値,最大値)を指定
)
stripchart(
  species_richness ~ as.factor(phyto_metadata$month),
  method = "stack",
  cex = 2,
  vertical = TRUE,
  add = TRUE
)

分散分析してみる
#anova(lm(応答変数 ~ 説明変数(説明因子))の形式で書く
anova(lm(species_richness ~ as.factor(phyto_metadata$month)))
Analysis of Variance Table

Response: species_richness
                                Df Sum Sq Mean Sq F value  Pr(>F)  
as.factor(phyto_metadata$month)  3 418.83 139.611  3.5985 0.04961 *
Residuals                       11 426.77  38.797                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

6.4.3 害虫数の殺虫剤間比較

#組み込みデータInsectSpraysの読み込み
data("InsectSprays")
#データの中身を表示
View(InsectSprays)
箱ひげ図と一次元散布図でまずは可視化(図6.9B)
boxplot(count ~ spray, data = InsectSprays, #いままでと違う書き方
        outline = FALSE,
        col = "white",
        xlab = "spray type",
        ylab = "insect count"
)
stripchart(
  count ~ as.factor(spray), data = InsectSprays, #いままでと違う書き方
  method = "stack",
  cex = 2,
  vertical = TRUE,
  add = TRUE
)

分散分析
anova(lm(count ~ spray, data = InsectSprays))
Analysis of Variance Table

Response: count
          Df Sum Sq Mean Sq F value    Pr(>F)    
spray      5 2668.8  533.77  34.702 < 2.2e-16 ***
Residuals 66 1015.2   15.38                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

6.5.1 相関係数

可視化おさらい(図6.5A, 植物プランクトンの種数vs温度)

plot(
  species_richness ~ phyto_metadata$temp, 
  type="p", 
  cex = 3,
  xlab = "temperature",
  ylab = "species richness"
)

相関係数

余計な引数を付けない単純なコードを使う場合
#植物プランクトンの種数(species_richness)と水温(temp)の相関
cor(species_richness, phyto_metadata$temp)
[1] 0.701338
#微生物の異なる炭素基質活性間の相関
#3列以上のデータフレームを引数にすると総当たりのペアでの相関が計算される
cor(summary_ecoplate[,1:5])
           s01         s02       s03         s04        s05
s01  1.0000000 -0.04709880 0.1032132 -0.48970438 -0.2143492
s02 -0.0470988  1.00000000 0.3721024 -0.05531352  0.3005611
s03  0.1032132  0.37210238 1.0000000  0.14759165  0.2211696
s04 -0.4897044 -0.05531352 0.1475916  1.00000000  0.4894126
s05 -0.2143492  0.30056114 0.2211696  0.48941263  1.0000000
method引数を指定すると、相関のタイプを指定できる
#スペルマン(spearman)の順位相関係数
cor(species_richness, phyto_metadata$temp, method = "spearman")
[1] 0.6957425
相関係数が有意に0からずれているかも検定できる
cor.test(species_richness, phyto_metadata$temp)

    Pearson's product-moment correlation

data:  species_richness and phyto_metadata$temp
t = 3.5474, df = 13, p-value = 0.003574
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.2950930 0.8928332
sample estimates:
     cor 
0.701338 

6.5.2 回帰分析(線形回帰)

簡単な回帰分析

#Y~Xという公式で「YをXで回帰する」という設定になる
#lm関数の出力をmodel01というオブジェクトに格納(代入 <- )
model01 <- lm(species_richness ~ phyto_metadata$temp)
#lm関数の出力を格納したmodel01の結果のまとめ
summary(model01)

Call:
lm(formula = species_richness ~ phyto_metadata$temp)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.1291 -4.5127 -0.4173  1.8918 13.3918 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)   
(Intercept)           6.9212     5.9606   1.161  0.26646   
phyto_metadata$temp   1.1751     0.3313   3.547  0.00357 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 5.749 on 13 degrees of freedom
Multiple R-squared:  0.4919,    Adjusted R-squared:  0.4528 
F-statistic: 12.58 on 1 and 13 DF,  p-value: 0.003574

6.5.3 回帰直線の可視化

plot( #plot関数の引数を従来通り設定して散布図を描く
  species_richness ~ phyto_metadata$temp, 
  type = "p", 
  cex = 3,
  xlab = "temperature",
  ylab = "species richness"
)
#回帰直線をabline(モデルの結果を格納したオブジェクト, 線の色)の形で重ねて描画する
abline(model01,col = 4)

6.5.4 相関と回帰の違い

スケール依存性

#回帰係数は元データの値を2倍や10倍にしても変わらない
cor(phyto_metadata$temp, species_richness)
[1] 0.701338
#片方を2倍にしても・・・
cor(phyto_metadata$temp*2, species_richness)
[1] 0.701338
#他方を10倍にしても・・・
cor(phyto_metadata$temp, species_richness*10)
[1] 0.701338
temp2 <- 2*phyto_metadata$temp #水温データを2倍にする
species_richness10 <- 10*species_richness #種数データを10倍にする
#元の回帰
lm(species_richness ~ phyto_metadata$temp)

Call:
lm(formula = species_richness ~ phyto_metadata$temp)

Coefficients:
        (Intercept)  phyto_metadata$temp  
              6.921                1.175  
#水温を2倍にした場合
lm(species_richness ~ temp2)

Call:
lm(formula = species_richness ~ temp2)

Coefficients:
(Intercept)        temp2  
     6.9212       0.5876  
#種数を10倍にした場合
lm(species_richness10 ~ phyto_metadata$temp)

Call:
lm(formula = species_richness10 ~ phyto_metadata$temp)

Coefficients:
        (Intercept)  phyto_metadata$temp  
              69.21                11.75  

誤差の考えかたの違い

#相関の場合XとYを入れ替えても相関係数は変わらない
cor(phyto_metadata$temp, species_richness)
[1] 0.701338
cor(species_richness, phyto_metadata$temp)
[1] 0.701338
#回帰についてXとYを入れ替えてみた場合
model02 <- lm(phyto_metadata$temp ~ species_richness)
#回帰モデルの結果のうち、推定された係数(coefficients)のみを抜き出す
model02$coefficients
     (Intercept) species_richness 
       5.9579391        0.4185667 
図6.12
#tempによるspecies_richnessの回帰直線とspecies_richnessによるtempの回帰直線を重ねて描画してみる
# phyto_metadata$temp = 5.9579 + 0.4186*species_richness
#この式を変形して・・・
# species_richness = -0.9579/0.4186 + (1.0/0.4186)*phyto_metadata$temp
plot(
  species_richness ~ phyto_metadata$temp, 
  type="p", 
  cex = 3,
  xlab = "temperature",
  ylab = "species richness"
)
#tempによるspecies_richnessの回帰直線(水色実践)
abline(model01,col = 4)
#species_richnessによるtempの回帰直線(黒色破線)
abline(c(-model02$coefficients[1]/model02$coefficients[2], 1.0/model02$coefficients[2]),lty=2)

6.5.5 なぜ可視化を統計分析よりも先にするべきなのか?

統計量・検定結果に騙されてはいけない

data(anscombe) #Rに組み込まれているデータの読み込み
#4つの異なる組合せで回帰分析
model_a01 <- lm(y1~x1, data = anscombe) 
model_a02 <- lm(y2~x2, data = anscombe)
model_a03 <- lm(y3~x3, data = anscombe)
model_a04 <- lm(y4~x4, data = anscombe)
#推定された回帰係数等の結果が同じになることを確認してみよう
summary(model_a01)

Call:
lm(formula = y1 ~ x1, data = anscombe)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.92127 -0.45577 -0.04136  0.70941  1.83882 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)   3.0001     1.1247   2.667  0.02573 * 
x1            0.5001     0.1179   4.241  0.00217 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.237 on 9 degrees of freedom
Multiple R-squared:  0.6665,    Adjusted R-squared:  0.6295 
F-statistic: 17.99 on 1 and 9 DF,  p-value: 0.00217
summary(model_a02)

Call:
lm(formula = y2 ~ x2, data = anscombe)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.9009 -0.7609  0.1291  0.9491  1.2691 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)    3.001      1.125   2.667  0.02576 * 
x2             0.500      0.118   4.239  0.00218 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.237 on 9 degrees of freedom
Multiple R-squared:  0.6662,    Adjusted R-squared:  0.6292 
F-statistic: 17.97 on 1 and 9 DF,  p-value: 0.002179
summary(model_a03)

Call:
lm(formula = y3 ~ x3, data = anscombe)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.1586 -0.6146 -0.2303  0.1540  3.2411 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)   3.0025     1.1245   2.670  0.02562 * 
x3            0.4997     0.1179   4.239  0.00218 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.236 on 9 degrees of freedom
Multiple R-squared:  0.6663,    Adjusted R-squared:  0.6292 
F-statistic: 17.97 on 1 and 9 DF,  p-value: 0.002176
summary(model_a04)

Call:
lm(formula = y4 ~ x4, data = anscombe)

Residuals:
   Min     1Q Median     3Q    Max 
-1.751 -0.831  0.000  0.809  1.839 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)   3.0017     1.1239   2.671  0.02559 * 
x4            0.4999     0.1178   4.243  0.00216 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.236 on 9 degrees of freedom
Multiple R-squared:  0.6667,    Adjusted R-squared:  0.6297 
F-statistic:    18 on 1 and 9 DF,  p-value: 0.002165
図6.13
#可視化したら全然違うパターンになっている
plot(
  y1~x1, data = anscombe, 
  type = "p", 
  cex = 3,
  xlim = c(0, 20),
  ylim = c(0, 15),
  xlab = "",
  ylab = ""
)
abline(model_a01)

plot(
  y2~x2, data = anscombe, 
  type = "p", 
  cex = 3,
  xlim = c(0, 20),
  ylim = c(0, 15),
  xlab = "",
  ylab = ""
)
abline(model_a02)

plot(
  y3~x3, data = anscombe, 
  type = "p", 
  cex = 3,
  xlim = c(0, 20),
  ylim = c(0, 15),
  xlab = "",
  ylab = ""
)
abline(model_a03)

plot(
  y4~x4, data = anscombe, 
  type = "p", 
  cex = 3,
  xlim = c(0, 20),
  ylim = c(0, 15),
  xlab = "",
  ylab = ""
)
abline(model_a04)

もっと極端な例:データザウルス

#CSVファイルからデータ読み込み
data_s <- read.csv("DatasaurusDozen.csv", header=T) 
#異なる二つのデータペアを抜き出す
data_s01 <- subset(data_s, dataset == "circle")[2:3]
data_s02 <- subset(data_s, dataset == "dino")[2:3]
#相関係数に違いがないことを確かめよう
cor(data_s01)
            x           y
x  1.00000000 -0.06834336
y -0.06834336  1.00000000
cor(data_s02)
            x           y
x  1.00000000 -0.06447185
y -0.06447185  1.00000000
データの分布は全然違う!
plot(data_s01)

plot(data_s02)

LS0tDQp0aXRsZTogImJhc2ljX3Rlc3QuUuOBq+WvvuW/nOOBl+OBn1IgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyMjIOesrDbnq6Djgafkvb/jgYbjgZ/jgoHjga7jgIHmlbTnkIbmlbTpoJPmuIjjgb/jg4fjg7zjgr/jga7oqq3jgb/ovrzjgb8NCmBgYHtyfQ0KIyMjRm9yIGNoYXB0ZXIgMDYNCnBoeXRvX21ldGFkYXRhIDwtIHJlYWRSRFMoInBoeXRvX21ldGFkYXRhLm9iaiIpDQpzcGVjaWVzX3J5dWtvX2RhdGEgPC0gcmVhZFJEUygicGh5dG9fcnl1a29fZGF0YS5vYmoiKQ0KbWV0YWRhdGFfZWNvcGxhdGUgPC0gcmVhZFJEUygibWV0YWRhdGFfZWNvcGwub2JqIikNCnN1bW1hcnlfZWNvcGxhdGUgPC0gcmVhZFJEUygic3VtbWFyeV9lY29wbC5vYmoiKQ0KI2Zyb20gYmFzaWNfZ3JhcGhpY3MuUiDnqK7mlbDjgavjgaTjgYTjgablho3luqboqIjnrpcNCnNwZWNpZXNfcmljaG5lc3MgPC0gYXBwbHkoc3BlY2llc19yeXVrb19kYXRhID4gMCwgMSwgc3VtKQ0KYGBgDQojIyMgNi4zLjEgc3Vic2V06Zai5pWwDQojIyMjIOS4gOeVquOCt+ODs+ODl+ODq+OBquS9v+OBhOaWuQ0KYGBge3J9DQojc3Vic2V06Zai5pWw44KS5L2/44GG44Go5p2h5Lu244KS5rqA44Gf44GZ6KaB57Sg44KS5oqc44GN5Ye644Gb44KLDQpzdWJzZXQoc3BlY2llc19yaWNobmVzcywgcGh5dG9fbWV0YWRhdGEkeWVhciA9PSAiMjAxOCIpDQpzdWJzZXQoc3BlY2llc19yeXVrb19kYXRhLCBwaHl0b19tZXRhZGF0YSR5ZWFyID09ICIyMDE4IikNCmBgYA0KIyMjIyBzdWJzZXTplqLmlbDjgajku6PlhaXmvJTnrpflrZAoPC0p44KS57WE44G/5ZCI44KP44Gb44KLDQpgYGB7cn0NCiNzdWJzZXTplqLmlbDjgafmipzjgY3lh7rjgZfjgZ/opoHntKDjgpLjgIHlt6bovrrjga7jgqrjg5bjgrjjgqfjgq/jg4jjgavmoLzntI0o5Luj5YWlKeOBmeOCi+OAgg0Kc3BlY2llc19yaWNobmVzczIwMTggPC0gc3Vic2V0KHNwZWNpZXNfcmljaG5lc3MsIHBoeXRvX21ldGFkYXRhJHllYXIgPT0gIjIwMTgiKQ0Kc3BlY2llc19yaWNobmVzczIwMTkgPC0gc3Vic2V0KHNwZWNpZXNfcmljaG5lc3MsIHBoeXRvX21ldGFkYXRhJHllYXIgPT0gIjIwMTkiKQ0KYGBgDQoNCiMjIyA2LjMuMuWfuuacrOe1seioiOmHj+OBqHRhcHBseemWouaVsA0KIyMjIyDmipzjgY3lh7rjgZfjgZ/jg4fjg7zjgr/jgYzjganjgpPjgarmhJ/jgZjjgYvjgpJzdW1tYXJ56Zai5pWw44Gn56K66KqNDQpgYGB7cn0NCiPmipzjgY3lh7rjgZfjgZ/jg4fjg7zjgr/jga7opoHntITntbHoqIjph48NCnN1bW1hcnkoc3BlY2llc19yaWNobmVzczIwMTgpDQpzdW1tYXJ5KHNwZWNpZXNfcmljaG5lc3MyMDE5KQ0KYGBgDQojIyMjIHRhcHBseemWouaVsOOCkuS9v+OBo+OBpnN1bW1hcnko6KaB57SE57Wx6KiI6YePKSwgbWVhbijlubPlnYcpLCB2YXIo5YiG5pWjKeOCkuioiOeul+OBmeOCiyAgDQpgYGB7cn0NCiPopoHntITntbHoqIjph48NCnRhcHBseShzcGVjaWVzX3JpY2huZXNzLCBwaHl0b19tZXRhZGF0YSR5ZWFyLCBzdW1tYXJ5KQ0KI+W5s+Wdhw0KdGFwcGx5KHNwZWNpZXNfcmljaG5lc3MsIHBoeXRvX21ldGFkYXRhJHllYXIsIG1lYW4pDQoj5YiG5pWjDQp0YXBwbHkoc3BlY2llc19yaWNobmVzcywgcGh5dG9fbWV0YWRhdGEkeWVhciwgdmFyKQ0KYGBgDQojIyMgNi4zLjMgdOaknOWumg0KIyMjIyDmpI3nianjg5fjg6njg7Pjgq/jg4jjg7Pjga7nqK7mlbDjgpJ5ZWFy6ZaTKDIwMTggdnMgMjAxOSnjgafmr5TovIPjgZnjgosNCmBgYHtyfQ0KI1dlbGNoKOOCpuOCp+ODq+ODgSnjga4y5qiZ5pysdOaknOWumuOCkuS9v+OBhuOBruOBjOacgOi/keOBruODh+ODleOCqeODq+ODiA0KI+WFrOW8jyhZflgp44Gu5b2i44Gn5pu444GPDQp0LnRlc3Qoc3BlY2llc19yaWNobmVzcyB+IHBoeXRvX21ldGFkYXRhJHllYXIsIHZhci5lcXVhbCA9IEYpDQpgYGANCiMjIyMg5YWo5YCL5L2T5pWw44Gu5q+U6LyDDQrnqK7ntYTmiJDjga7jg4fjg7zjgr/vvJ3lkITnqK7jga7lgIvkvZPmlbDjga7jg4fjg7zjgr/jgpLlkITooYwoMSnjgavlr77jgZfjgabjgIHlhajnqK7jgavjgaTjgYTjgabotrPjgZflkIjjgo/jgZvjgaYoc3VtKSzlhajlgIvkvZPmlbDjgpLoqIjnrpfjgZnjgosNCmBgYHtyfQ0KdG90YWxfYWJ1bmRhbmNlIDwtIGFwcGx5KHNwZWNpZXNfcnl1a29fZGF0YSwxLHN1bSkNCmBgYA0KIyMjIyMg5YWo5YCL5L2T5pWw44GuMue+pOavlOi8gw0KIyMjIyMjIOWPr+imluWMlijlm7M2LjYpDQpgYGB7cn0NCmJveHBsb3Qo44CAI+euseOBsuOBkuWbsw0KICB0b3RhbF9hYnVuZGFuY2UgfiBwaHl0b19tZXRhZGF0YSR5ZWFyLOOAgCPlhazlvI/jgrnjgr/jgqTjg6sNCiAgb3V0bGluZSA9IFRSVUUsICPlpJbjgozlgKTjga7ooajnpLoNCiAgY29sID0gIndoaXRlIuOAgCPnrrHjga7oibLmjIflrpoNCikNCnN0cmlwY2hhcnQo44CAI+S4gOasoeWFg+aVo+W4g+Wbsw0KICB0b3RhbF9hYnVuZGFuY2UgfiBwaHl0b19tZXRhZGF0YSR5ZWFyLCAj5YWs5byP44K544K/44Kk44OrDQogIG1ldGhvZCA9ICJzdGFjayIsICPph43opIfjgZnjgovngrnjga/opo/liYfnmoTjgavkuKbjgbnjgosNCiAgcGNoID0gYygxLDIpLCAj54K544Gu44Oe44O844KvKOiomOWPtynjga7mjIflrpoNCiAgY2V4ID0gMywgI+ODnuODvOOCr+OBruOCteOCpOOCug0KICB2ZXJ0aWNhbCA9IFRSVUUs44CAI+WeguebtCh2ZXJ0aWNhbCnmlrnlkJHjgavmlaPluIPlm7PjgpLlu7bjgbDjgZkNCiAgYWRkID0gVFJVReOAgCPkuIrjga7nrrHjgbLjgZLlm7Pjgavph43jga3jgabmj4/nlLsNCikNCmBgYA0KIyMjIyMjIHTmpJzlrpoNCmBgYHtyfQ0KI+W5tOOBlOOBqOOBq+e3j+WAi+S9k+aVsCh0b3RhbF9hYnVuZGFuY2Up44Gu5bmz5Z2HKG1lYW4p44KS6KiI566XDQp0YXBwbHkodG90YWxfYWJ1bmRhbmNlLCBwaHl0b19tZXRhZGF0YSR5ZWFyLCBtZWFuKQ0KI1dlbGNo44GudOaknOWumg0KdC50ZXN0KHRvdGFsX2FidW5kYW5jZSB+IHBoeXRvX21ldGFkYXRhJHllYXIsIHZhci5lcXVhbCA9IEYpDQpgYGANCiMjIyA2LjQg5YiG5pWj5YiG5p6QDQojIyMgNi40LjIg5qSN54mp44OX44Op44Oz44Kv44OI44Oz56iu5pWw44Gu5pyI6ZaT5q+U6LyDDQojIyMjIyDliIbmlaPliIbmnpDnlKjjga7lj6/oppbljJYo44G+44Ga44Gv5Y+v6KaW5YyW77yBIOWbszYuOUEpDQpgYGB7cn0gDQoj566x44Gy44GS5Zuz44Go5LiA5qyh5YWD5pWj5biD5Zuz44Gu6YeN44Gt5ZCI44KP44GbDQoj5Zug5a2QKOimgeWboClwaHl0b19tYXRhZGF0YSRtb250aOOBr+OAgWFzLmZhY3RvcumWouaVsOOCkuS9v+OBo+OBpuaYjuekuueahOOBq+OAjOWboOWtkOOAjeOBq+OBmeOCiw0KYm94cGxvdChzcGVjaWVzX3JpY2huZXNzIH4gYXMuZmFjdG9yKHBoeXRvX21ldGFkYXRhJG1vbnRoKSwgDQogICAgIG91dGxpbmUgPSBGQUxTRSzjgIAj5aSW44KM5YCk44Gv5piO56S644GX44Gq44GEDQogICAgIGNvbCA9ICJ3aGl0ZSIsDQogICAgIHhsYWIgPSAibW9udGgiLA0KICAgICB5bGFiID0gInNwZWNpZXMgcmljaG5lc3MiLA0KICAgICB5bGltID0gYygwLDQwKeOAgCNZ6Lu444Gu6KGo56S656+E5ZuyKOacgOWwj+WApO+8jOacgOWkp+WApCnjgpLmjIflrpoNCikNCnN0cmlwY2hhcnQoDQogIHNwZWNpZXNfcmljaG5lc3MgfiBhcy5mYWN0b3IocGh5dG9fbWV0YWRhdGEkbW9udGgpLA0KICBtZXRob2QgPSAic3RhY2siLA0KICBjZXggPSAyLA0KICB2ZXJ0aWNhbCA9IFRSVUUsDQogIGFkZCA9IFRSVUUNCikNCg0KYGBgDQojIyMjIyDliIbmlaPliIbmnpDjgZfjgabjgb/jgosNCmBgYHtyfQ0KI2Fub3ZhKGxtKOW/nOetlOWkieaVsCB+IOiqrOaYjuWkieaVsO+8iOiqrOaYjuWboOWtkO+8iSnjga7lvaLlvI/jgafmm7jjgY8NCmFub3ZhKGxtKHNwZWNpZXNfcmljaG5lc3MgfiBhcy5mYWN0b3IocGh5dG9fbWV0YWRhdGEkbW9udGgpKSkNCmBgYA0KIyMjIyA2LjQuMyDlrrPomavmlbDjga7mrrromavliaTplpPmr5TovIMNCmBgYHtyfQ0KI+e1hOOBv+i+vOOBv+ODh+ODvOOCv0luc2VjdFNwcmF5c+OBruiqreOBv+i+vOOBvw0KZGF0YSgiSW5zZWN0U3ByYXlzIikNCiPjg4fjg7zjgr/jga7kuK3ouqvjgpLooajnpLoNClZpZXcoSW5zZWN0U3ByYXlzKQ0KYGBgDQojIyMjIyDnrrHjgbLjgZLlm7PjgajkuIDmrKHlhYPmlaPluIPlm7Pjgafjgb7jgZrjga/lj6/oppbljJYo5ZuzNi45QikNCmBgYHtyfQ0KYm94cGxvdChjb3VudCB+IHNwcmF5LCBkYXRhID0gSW5zZWN0U3ByYXlzLCAj44GE44G+44G+44Gn44Go6YGV44GG5pu444GN5pa5DQogICAgICAgIG91dGxpbmUgPSBGQUxTRSwNCiAgICAgICAgY29sID0gIndoaXRlIiwNCiAgICAgICAgeGxhYiA9ICJzcHJheSB0eXBlIiwNCiAgICAgICAgeWxhYiA9ICJpbnNlY3QgY291bnQiDQopDQpzdHJpcGNoYXJ0KA0KICBjb3VudCB+IGFzLmZhY3RvcihzcHJheSksIGRhdGEgPSBJbnNlY3RTcHJheXMs44CAI+OBhOOBvuOBvuOBp+OBqOmBleOBhuabuOOBjeaWuQ0KICBtZXRob2QgPSAic3RhY2siLA0KICBjZXggPSAyLA0KICB2ZXJ0aWNhbCA9IFRSVUUsDQogIGFkZCA9IFRSVUUNCikNCmBgYA0KIyMjIyMg5YiG5pWj5YiG5p6QDQpgYGB7cn0NCmFub3ZhKGxtKGNvdW50IH4gc3ByYXksIGRhdGEgPSBJbnNlY3RTcHJheXMpKQ0KYGBgDQoNCiMjIyA2LjUuMSDnm7jplqLkv4LmlbANCiMjIyMg5Y+v6KaW5YyW44GK44GV44KJ44GEKOWbszYuNUEsIOakjeeJqeODl+ODqeODs+OCr+ODiOODs+OBrueoruaVsHZz5rip5bqmKQ0KYGBge3J9DQpwbG90KA0KICBzcGVjaWVzX3JpY2huZXNzIH4gcGh5dG9fbWV0YWRhdGEkdGVtcCwgDQogIHR5cGU9InAiLCANCiAgY2V4ID0gMywNCiAgeGxhYiA9ICJ0ZW1wZXJhdHVyZSIsDQogIHlsYWIgPSAic3BlY2llcyByaWNobmVzcyINCikNCmBgYA0KIyMjIyDnm7jplqLkv4LmlbANCiMjIyMjIOS9meioiOOBquW8leaVsOOCkuS7mOOBkeOBquOBhOWNmOe0lOOBquOCs+ODvOODieOCkuS9v+OBhuWgtOWQiA0KYGBge3J9DQoj5qSN54mp44OX44Op44Oz44Kv44OI44Oz44Gu56iu5pWwKHNwZWNpZXNfcmljaG5lc3Mp44Go5rC05ripKHRlbXAp44Gu55u46ZaiDQpjb3Ioc3BlY2llc19yaWNobmVzcywgcGh5dG9fbWV0YWRhdGEkdGVtcCkNCiPlvq7nlJ/nianjga7nlbDjgarjgovngq3ntKDln7ros6rmtLvmgKfplpPjga7nm7jplqINCiMz5YiX5Lul5LiK44Gu44OH44O844K/44OV44Os44O844Og44KS5byV5pWw44Gr44GZ44KL44Go57eP5b2T44Gf44KK44Gu44Oa44Ki44Gn44Gu55u46Zai44GM6KiI566X44GV44KM44KLDQpjb3Ioc3VtbWFyeV9lY29wbGF0ZVssMTo1XSkNCmBgYA0KIyMjIyMgbWV0aG9k5byV5pWw44KS5oyH5a6a44GZ44KL44Go44CB55u46Zai44Gu44K/44Kk44OX44KS5oyH5a6a44Gn44GN44KLDQpgYGB7cn0NCiPjgrnjg5rjg6vjg57jg7Moc3BlYXJtYW4p44Gu6aCG5L2N55u46Zai5L+C5pWwDQpjb3Ioc3BlY2llc19yaWNobmVzcywgcGh5dG9fbWV0YWRhdGEkdGVtcCwgbWV0aG9kID0gInNwZWFybWFuIikNCmBgYA0KIyMjIyMg55u46Zai5L+C5pWw44GM5pyJ5oSP44GrMOOBi+OCieOBmuOCjOOBpuOBhOOCi+OBi+OCguaknOWumuOBp+OBjeOCiw0KYGBge3J9DQpjb3IudGVzdChzcGVjaWVzX3JpY2huZXNzLCBwaHl0b19tZXRhZGF0YSR0ZW1wKQ0KYGBgDQojIyMgNi41LjIg5Zue5biw5YiG5p6QKOe3muW9ouWbnuW4sCkNCiMjIyMg57Ch5Y2Y44Gq5Zue5biw5YiG5p6QDQpgYGB7cn0NCiNZfljjgajjgYTjgYblhazlvI/jgafjgIxZ44KSWOOBp+WbnuW4sOOBmeOCi+OAjeOBqOOBhOOBhuioreWumuOBq+OBquOCiw0KI2xt6Zai5pWw44Gu5Ye65Yqb44KSbW9kZWwwMeOBqOOBhOOBhuOCquODluOCuOOCp+OCr+ODiOOBq+agvOe0jSjku6PlhaUgPC0gKQ0KbW9kZWwwMSA8LSBsbShzcGVjaWVzX3JpY2huZXNzIH4gcGh5dG9fbWV0YWRhdGEkdGVtcCkNCiNsbemWouaVsOOBruWHuuWKm+OCkuagvOe0jeOBl+OBn21vZGVsMDHjga7ntZDmnpzjga7jgb7jgajjgoENCnN1bW1hcnkobW9kZWwwMSkNCg0KYGBgDQojIyMgNi41LjMg5Zue5biw55u057ea44Gu5Y+v6KaW5YyWDQpgYGB7cn0NCnBsb3QoICNwbG906Zai5pWw44Gu5byV5pWw44KS5b6T5p2l6YCa44KK6Kit5a6a44GX44Gm5pWj5biD5Zuz44KS5o+P44GPDQogIHNwZWNpZXNfcmljaG5lc3MgfiBwaHl0b19tZXRhZGF0YSR0ZW1wLCANCiAgdHlwZSA9ICJwIiwgDQogIGNleCA9IDMsDQogIHhsYWIgPSAidGVtcGVyYXR1cmUiLA0KICB5bGFiID0gInNwZWNpZXMgcmljaG5lc3MiDQopDQoj5Zue5biw55u057ea44KSYWJsaW5lKOODouODh+ODq+OBrue1kOaenOOCkuagvOe0jeOBl+OBn+OCquODluOCuOOCp+OCr+ODiCwg57ea44Gu6ImyKeOBruW9ouOBp+mHjeOBreOBpuaPj+eUu+OBmeOCiw0KYWJsaW5lKG1vZGVsMDEsY29sID0gNCkNCmBgYA0KIyMjIDYuNS40IOebuOmWouOBqOWbnuW4sOOBrumBleOBhA0KIyMjIyDjgrnjgrHjg7zjg6vkvp3lrZjmgKcNCmBgYHtyfQ0KI+WbnuW4sOS/guaVsOOBr+WFg+ODh+ODvOOCv+OBruWApOOCkjLlgI3jgoQxMOWAjeOBq+OBl+OBpuOCguWkieOCj+OCieOBquOBhA0KY29yKHBoeXRvX21ldGFkYXRhJHRlbXAsIHNwZWNpZXNfcmljaG5lc3MpDQoj54mH5pa544KSMuWAjeOBq+OBl+OBpuOCguODu+ODu+ODuw0KY29yKHBoeXRvX21ldGFkYXRhJHRlbXAqMiwgc3BlY2llc19yaWNobmVzcykNCiPku5bmlrnjgpIxMOWAjeOBq+OBl+OBpuOCguODu+ODu+ODuw0KY29yKHBoeXRvX21ldGFkYXRhJHRlbXAsIHNwZWNpZXNfcmljaG5lc3MqMTApDQpgYGANCmBgYHtyfQ0KdGVtcDIgPC0gMipwaHl0b19tZXRhZGF0YSR0ZW1w44CAI+awtOa4qeODh+ODvOOCv+OCkjLlgI3jgavjgZnjgosNCnNwZWNpZXNfcmljaG5lc3MxMCA8LSAxMCpzcGVjaWVzX3JpY2huZXNz44CAI+eoruaVsOODh+ODvOOCv+OCkjEw5YCN44Gr44GZ44KLDQoj5YWD44Gu5Zue5biwDQpsbShzcGVjaWVzX3JpY2huZXNzIH4gcGh5dG9fbWV0YWRhdGEkdGVtcCkNCiPmsLTmuKnjgpIy5YCN44Gr44GX44Gf5aC05ZCIDQpsbShzcGVjaWVzX3JpY2huZXNzIH4gdGVtcDIpDQoj56iu5pWw44KSMTDlgI3jgavjgZfjgZ/loLTlkIgNCmxtKHNwZWNpZXNfcmljaG5lc3MxMCB+IHBoeXRvX21ldGFkYXRhJHRlbXApDQoNCmBgYA0KIyMjIyDoqqTlt67jga7ogIPjgYjjgYvjgZ/jga7pgZXjgYQNCmBgYHtyfQ0KI+ebuOmWouOBruWgtOWQiFjjgahZ44KS5YWl44KM5pu/44GI44Gm44KC55u46Zai5L+C5pWw44Gv5aSJ44KP44KJ44Gq44GEDQpjb3IocGh5dG9fbWV0YWRhdGEkdGVtcCwgc3BlY2llc19yaWNobmVzcykNCmNvcihzcGVjaWVzX3JpY2huZXNzLCBwaHl0b19tZXRhZGF0YSR0ZW1wKQ0KYGBgDQpgYGB7cn0NCiPlm57luLDjgavjgaTjgYTjgabvvLjjgajvvLnjgpLlhaXjgozmm7/jgYjjgabjgb/jgZ/loLTlkIgNCm1vZGVsMDIgPC0gbG0ocGh5dG9fbWV0YWRhdGEkdGVtcCB+IHNwZWNpZXNfcmljaG5lc3MpDQoj5Zue5biw44Oi44OH44Or44Gu57WQ5p6c44Gu44GG44Gh44CB5o6o5a6a44GV44KM44Gf5L+C5pWwKGNvZWZmaWNpZW50cynjga7jgb/jgpLmipzjgY3lh7rjgZkNCm1vZGVsMDIkY29lZmZpY2llbnRzDQpgYGANCiMjIyMjIOWbszYuMTINCmBgYHtyfQ0KI3RlbXDjgavjgojjgotzcGVjaWVzX3JpY2huZXNz44Gu5Zue5biw55u057ea44Goc3BlY2llc19yaWNobmVzc+OBq+OCiOOCi3RlbXDjga7lm57luLDnm7Tnt5rjgpLph43jga3jgabmj4/nlLvjgZfjgabjgb/jgosNCiMgcGh5dG9fbWV0YWRhdGEkdGVtcCA9IDUuOTU3OSArIDAuNDE4NipzcGVjaWVzX3JpY2huZXNzDQoj44GT44Gu5byP44KS5aSJ5b2i44GX44Gm44O744O744O7DQojIHNwZWNpZXNfcmljaG5lc3MgPSAtMC45NTc5LzAuNDE4NiArICgxLjAvMC40MTg2KSpwaHl0b19tZXRhZGF0YSR0ZW1wDQpwbG90KA0KICBzcGVjaWVzX3JpY2huZXNzIH4gcGh5dG9fbWV0YWRhdGEkdGVtcCwgDQogIHR5cGU9InAiLCANCiAgY2V4ID0gMywNCiAgeGxhYiA9ICJ0ZW1wZXJhdHVyZSIsDQogIHlsYWIgPSAic3BlY2llcyByaWNobmVzcyINCikNCiN0ZW1w44Gr44KI44KLc3BlY2llc19yaWNobmVzc+OBruWbnuW4sOebtOe3mijmsLToibLlrp/ot7UpDQphYmxpbmUobW9kZWwwMSxjb2wgPSA0KQ0KI3NwZWNpZXNfcmljaG5lc3Pjgavjgojjgot0ZW1w44Gu5Zue5biw55u057eaKOm7kuiJsuegtOe3mikNCmFibGluZShjKC1tb2RlbDAyJGNvZWZmaWNpZW50c1sxXS9tb2RlbDAyJGNvZWZmaWNpZW50c1syXSwgMS4wL21vZGVsMDIkY29lZmZpY2llbnRzWzJdKSxsdHk9MikNCmBgYA0KIyMjIDYuNS41IOOBquOBnOWPr+imluWMluOCkue1seioiOWIhuaekOOCiOOCiuOCguWFiOOBq+OBmeOCi+OBueOBjeOBquOBruOBi++8nw0KIyMjIyDntbHoqIjph4/jg7vmpJzlrprntZDmnpzjgavpqJnjgZXjgozjgabjga/jgYTjgZHjgarjgYQNCmBgYHtyfQ0KZGF0YShhbnNjb21iZSnjgIAjUuOBq+e1hOOBv+i+vOOBvuOCjOOBpuOBhOOCi+ODh+ODvOOCv+OBruiqreOBv+i+vOOBvw0KIzTjgaTjga7nlbDjgarjgovntYTlkIjjgZvjgaflm57luLDliIbmnpANCm1vZGVsX2EwMSA8LSBsbSh5MX54MSwgZGF0YSA9IGFuc2NvbWJlKeOAgA0KbW9kZWxfYTAyIDwtIGxtKHkyfngyLCBkYXRhID0gYW5zY29tYmUpDQptb2RlbF9hMDMgPC0gbG0oeTN+eDMsIGRhdGEgPSBhbnNjb21iZSkNCm1vZGVsX2EwNCA8LSBsbSh5NH54NCwgZGF0YSA9IGFuc2NvbWJlKQ0KI+aOqOWumuOBleOCjOOBn+WbnuW4sOS/guaVsOetieOBrue1kOaenOOBjOWQjOOBmOOBq+OBquOCi+OBk+OBqOOCkueiuuiqjeOBl+OBpuOBv+OCiOOBhg0Kc3VtbWFyeShtb2RlbF9hMDEpDQpzdW1tYXJ5KG1vZGVsX2EwMikNCnN1bW1hcnkobW9kZWxfYTAzKQ0Kc3VtbWFyeShtb2RlbF9hMDQpDQpgYGANCiMjIyMjIOWbszYuMTMNCmBgYHtyfQ0KI+WPr+imluWMluOBl+OBn+OCieWFqOeEtumBleOBhuODkeOCv+ODvOODs+OBq+OBquOBo+OBpuOBhOOCiw0KcGxvdCgNCiAgeTF+eDEsIGRhdGEgPSBhbnNjb21iZSwgDQogIHR5cGUgPSAicCIsIA0KICBjZXggPSAzLA0KICB4bGltID0gYygwLCAyMCksDQogIHlsaW0gPSBjKDAsIDE1KSwNCiAgeGxhYiA9ICIiLA0KICB5bGFiID0gIiINCikNCmFibGluZShtb2RlbF9hMDEpDQpwbG90KA0KICB5Mn54MiwgZGF0YSA9IGFuc2NvbWJlLCANCiAgdHlwZSA9ICJwIiwgDQogIGNleCA9IDMsDQogIHhsaW0gPSBjKDAsIDIwKSwNCiAgeWxpbSA9IGMoMCwgMTUpLA0KICB4bGFiID0gIiIsDQogIHlsYWIgPSAiIg0KKQ0KYWJsaW5lKG1vZGVsX2EwMikNCnBsb3QoDQogIHkzfngzLCBkYXRhID0gYW5zY29tYmUsIA0KICB0eXBlID0gInAiLCANCiAgY2V4ID0gMywNCiAgeGxpbSA9IGMoMCwgMjApLA0KICB5bGltID0gYygwLCAxNSksDQogIHhsYWIgPSAiIiwNCiAgeWxhYiA9ICIiDQopDQphYmxpbmUobW9kZWxfYTAzKQ0KcGxvdCgNCiAgeTR+eDQsIGRhdGEgPSBhbnNjb21iZSwgDQogIHR5cGUgPSAicCIsIA0KICBjZXggPSAzLA0KICB4bGltID0gYygwLCAyMCksDQogIHlsaW0gPSBjKDAsIDE1KSwNCiAgeGxhYiA9ICIiLA0KICB5bGFiID0gIiINCikNCmFibGluZShtb2RlbF9hMDQpDQpgYGANCiMjIyMg44KC44Gj44Go5qW156uv44Gq5L6L77ya44OH44O844K/44K244Km44Or44K5DQpgYGB7cn0NCiNDU1bjg5XjgqHjgqTjg6vjgYvjgonjg4fjg7zjgr/oqq3jgb/ovrzjgb8NCmRhdGFfcyA8LSByZWFkLmNzdigiRGF0YXNhdXJ1c0RvemVuLmNzdiIsIGhlYWRlcj1UKSANCiPnlbDjgarjgovkuozjgaTjga7jg4fjg7zjgr/jg5rjgqLjgpLmipzjgY3lh7rjgZkNCmRhdGFfczAxIDwtIHN1YnNldChkYXRhX3MsIGRhdGFzZXQgPT0gImNpcmNsZSIpWzI6M10NCmRhdGFfczAyIDwtIHN1YnNldChkYXRhX3MsIGRhdGFzZXQgPT0gImRpbm8iKVsyOjNdDQoj55u46Zai5L+C5pWw44Gr6YGV44GE44GM44Gq44GE44GT44Go44KS56K644GL44KB44KI44GGDQpjb3IoZGF0YV9zMDEpDQpjb3IoZGF0YV9zMDIpDQpgYGANCiMjIyMjIOODh+ODvOOCv+OBruWIhuW4g+OBr+WFqOeEtumBleOBhiENCmBgYHtyfQ0KcGxvdChkYXRhX3MwMSkNCnBsb3QoZGF0YV9zMDIpDQpgYGANCg0KDQoNCg==