library(RxODE)
library(tidyverse)
library(knitr)
Model definition
# Define model ##########
ode <- "
TBP = VP*RB/CLB;
CONC = A1/VC*0.16;
CPLXP = ((KD*VP+A2+TBP)-((KD*VP+A2+TBP)^2-4*A2*TBP)^0.5)/2;
FAP = A2 - CPLXP;
RO = 100*CPLXP / (VP*RB/CLB);
d/dt(A1) = - A1*CLA/VC - Q*A1/VC + Q*FAP/VP;
d/dt(A2) = -CPLXP*CLB/VP + Q*A1/VC - Q*FAP/VP;
"
# Compile model ##########
mod1 <- RxODE(model = ode, modName = "mod1")
Sensitivity parameter setting
time.interval <- 1
test.dose <- c(50,100,250,400,500)
test.exp <- seq(0.75,0.85, 0.01)
PK parameters & simulation
data <- data.frame(time = seq(0, 21*24, time.interval),
CONC = 0)
for (i in test.dose) {
for (j in test.exp) {
DOSEmm3 = i # Dose
All_ex = j # Exponent
BW = 70 # Average bodyweight of monkey in 12 mg/kg group
CLA_est = 1.16 # Separet variable for senstivity analysis
V_est = 128 # Separet variable for senstivity analysis
VP_est = 126 # Separet variable for senstivity analysis
CLA = CLA_est*(BW/3)**All_ex # CL_ex (mL/h)
VC = V_est*(BW/3) # Central volume of distribution (mL)
Q = 8.75 * (BW/3)**All_ex # Intercompartmental clearance (mL/h)
VP = VP_est*(BW/3)
RB = 335 * (BW/3)**All_ex # RB_ex ; Target synthesis rate (pmol/h)
CLB = 2.39*(BW/3)**All_ex # Target & Complex clearance (mL/h)
KD = 4.5 # Equilibrium binding constant (nM)
TBP = VP*RB/CLB # Total binding target in peripheral
# Simulate a single dose ##########
MWlig = 150000 # Molecular weight of mAb
DOSE = DOSEmm3 * 1.73
DOSEnM = DOSE*1e-3/MWlig*1e12 #Dose as nanomole
duration = 2 # infusion duration
infrate = DOSEnM / duration # inusion rate"
sampling.day = 21 # sampling time as day
sampling.time = 24*sampling.day # sampling time as hour
params <- c(CLA = CLA, VC = VC, Q = Q, VP = VP, CLB = CLB, RB = RB, KD = KD)
inits <- c(0, 0)
# Initialize event table ##########
ev <- eventTable()
ev$add.dosing(dose = DOSEnM, nbr.doses = 1, dosing.to =1, rate = infrate)#, dosing.interval = 168)
ev$add.sampling(seq(0, sampling.time, time.interval))
#integration
data2 <- as.data.frame(mod1$run(params, ev, inits))
data2 <- data2[,c(1,5)]
colnames(data2) <- c("time", paste("dose",i,"exp",j, sep="-"))
data <- merge(data, data2, by = "time")
}}
Data management for NCA
data <- data[, -2]
data.long <-
data %>%
gather(2:ncol(data), key = "group", value = "CONC")
data3 <- separate(data.long,
group, into = c("a", "dose", "b","exp"), sep = "-")
data3 <- data3[,c(1,3,5,6)]
#colnames(test) <- c("time","dose", "exp","conc")
unique(data3[,c("dose", "exp")])
nrow(unique(data3[,c("dose", "exp")]))
[1] 55
data3$NID <- paste(data3$dose, data3$exp, sep = "-")
data3$ID <- factor(data3$NID, label=1:length(unique(data3$NID)))
# Simulated Conc-Time profile by dose
ggplot(data3, aes(time, CONC, group = ID, colour = factor(exp))) +
geom_line() +
scale_y_continuous(trans = "log10") +
facet_wrap(~dose, ncol = 2, scales="free_y")
NCA analysis using NonCompart package and data management
nca_data <- NonCompart::tabNCA(data3, "ID", "time", "CONC")
nca_data <- as.data.frame(nca_data)
nca_AUC <- nca_data %>% select(ID, AUCIFO) %>% arrange(ID)
nca_AUC %>% knitr::kable()
1 |
2880.2896 |
2 |
2791.0786 |
3 |
2704.6087 |
4 |
2620.8024 |
5 |
2539.5781 |
6 |
2460.8623 |
7 |
2384.5782 |
8 |
2310.6513 |
9 |
2239.0111 |
10 |
2169.5871 |
11 |
2102.3122 |
12 |
13672.2490 |
13 |
13249.2327 |
14 |
12842.4774 |
15 |
12446.4734 |
16 |
12062.4019 |
17 |
11689.8248 |
18 |
11328.4733 |
19 |
10978.0702 |
20 |
10638.2945 |
21 |
10308.8649 |
22 |
9989.5197 |
23 |
28778.0455 |
24 |
27784.3324 |
25 |
26844.6364 |
26 |
25954.3595 |
27 |
25111.8013 |
28 |
24312.3893 |
29 |
23548.3455 |
30 |
22814.1826 |
31 |
22105.8150 |
32 |
21420.6236 |
33 |
20757.2407 |
34 |
1059.1385 |
35 |
1026.3169 |
36 |
994.5086 |
37 |
963.6836 |
38 |
933.8118 |
39 |
904.8641 |
40 |
876.8120 |
41 |
849.6285 |
42 |
823.2866 |
43 |
797.7608 |
44 |
773.0256 |
45 |
40699.8388 |
46 |
39226.1353 |
47 |
37816.8056 |
48 |
36471.3114 |
49 |
35193.2682 |
50 |
33973.7577 |
51 |
32819.6687 |
52 |
31728.0985 |
53 |
30694.9231 |
54 |
29714.2862 |
55 |
28779.7284 |
data_sub <-
data3 %>%
select(ID, dose, exp) %>%
arrange(ID)
data_sub <- data_sub[!duplicated(data_sub$ID),]
data_sub <- merge(data_sub, nca_AUC, by="ID")
#AUC obs
AUC_obs <- read.csv(file="Cetuxmab_AUC.csv", header = T, stringsAsFactors = F, nrow = 5)
colnames(AUC_obs) <- c("dose","AUCOBS")
## merge AUCobs and AUCsim
data_all <- merge(data_sub, AUC_obs, by="dose") %>%
select(ID, dose, exp, AUCSIM=AUCIFO, AUCOBS) %>%
arrange(ID)
knitr::kable(data_all)
1 |
100 |
0.75 |
2880.2896 |
2380 |
2 |
100 |
0.76 |
2791.0786 |
2380 |
3 |
100 |
0.77 |
2704.6087 |
2380 |
4 |
100 |
0.78 |
2620.8024 |
2380 |
5 |
100 |
0.79 |
2539.5781 |
2380 |
6 |
100 |
0.8 |
2460.8623 |
2380 |
7 |
100 |
0.81 |
2384.5782 |
2380 |
8 |
100 |
0.82 |
2310.6513 |
2380 |
9 |
100 |
0.83 |
2239.0111 |
2380 |
10 |
100 |
0.84 |
2169.5871 |
2380 |
11 |
100 |
0.85 |
2102.3122 |
2380 |
12 |
250 |
0.75 |
13672.2490 |
14600 |
13 |
250 |
0.76 |
13249.2327 |
14600 |
14 |
250 |
0.77 |
12842.4774 |
14600 |
15 |
250 |
0.78 |
12446.4734 |
14600 |
16 |
250 |
0.79 |
12062.4019 |
14600 |
17 |
250 |
0.8 |
11689.8248 |
14600 |
18 |
250 |
0.81 |
11328.4733 |
14600 |
19 |
250 |
0.82 |
10978.0702 |
14600 |
20 |
250 |
0.83 |
10638.2945 |
14600 |
21 |
250 |
0.84 |
10308.8649 |
14600 |
22 |
250 |
0.85 |
9989.5197 |
14600 |
23 |
400 |
0.75 |
28778.0455 |
19000 |
24 |
400 |
0.76 |
27784.3324 |
19000 |
25 |
400 |
0.77 |
26844.6364 |
19000 |
26 |
400 |
0.78 |
25954.3595 |
19000 |
27 |
400 |
0.79 |
25111.8013 |
19000 |
28 |
400 |
0.8 |
24312.3893 |
19000 |
29 |
400 |
0.81 |
23548.3455 |
19000 |
30 |
400 |
0.82 |
22814.1826 |
19000 |
31 |
400 |
0.83 |
22105.8150 |
19000 |
32 |
400 |
0.84 |
21420.6236 |
19000 |
33 |
400 |
0.85 |
20757.2407 |
19000 |
34 |
50 |
0.75 |
1059.1385 |
795 |
35 |
50 |
0.76 |
1026.3169 |
795 |
36 |
50 |
0.77 |
994.5086 |
795 |
37 |
50 |
0.78 |
963.6836 |
795 |
38 |
50 |
0.79 |
933.8118 |
795 |
39 |
50 |
0.8 |
904.8641 |
795 |
40 |
50 |
0.81 |
876.8120 |
795 |
41 |
50 |
0.82 |
849.6285 |
795 |
42 |
50 |
0.83 |
823.2866 |
795 |
43 |
50 |
0.84 |
797.7608 |
795 |
44 |
50 |
0.85 |
773.0256 |
795 |
45 |
500 |
0.75 |
40699.8388 |
30870 |
46 |
500 |
0.76 |
39226.1353 |
30870 |
47 |
500 |
0.77 |
37816.8056 |
30870 |
48 |
500 |
0.78 |
36471.3114 |
30870 |
49 |
500 |
0.79 |
35193.2682 |
30870 |
50 |
500 |
0.8 |
33973.7577 |
30870 |
51 |
500 |
0.81 |
32819.6687 |
30870 |
52 |
500 |
0.82 |
31728.0985 |
30870 |
53 |
500 |
0.83 |
30694.9231 |
30870 |
54 |
500 |
0.84 |
29714.2862 |
30870 |
55 |
500 |
0.85 |
28779.7284 |
30870 |
Plot the result.
data_all_ex_long <-
data_all_ex %>%
gather(2:5, key = "evaluation", value = "performance")
ggplot(data_all_ex_long, aes(exp, performance)) +
geom_point() +
facet_wrap(~evaluation, scales="free_y")
LS0tDQp0aXRsZTogIkdDMTExOCBzZW5zaXRpdml0eSBhbmFseXNpcyBvZiBleHBvbmVudCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoNCmBgYHtyLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0NCmxpYnJhcnkoUnhPREUpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoa25pdHIpDQpgYGANCg0KIyMgTW9kZWwgZGVmaW5pdGlvbg0KYGBge3J9DQojIERlZmluZSBtb2RlbCAjIyMjIyMjIyMjDQpvZGUgPC0gIg0KVEJQID0gVlAqUkIvQ0xCOw0KQ09OQyA9IEExL1ZDKjAuMTY7DQpDUExYUCA9ICAoKEtEKlZQK0EyK1RCUCktKChLRCpWUCtBMitUQlApXjItNCpBMipUQlApXjAuNSkvMjsNCkZBUCA9IEEyIC0gQ1BMWFA7DQpSTyA9IDEwMCpDUExYUCAvIChWUCpSQi9DTEIpOw0KZC9kdChBMSkgPSAtIEExKkNMQS9WQyAtIFEqQTEvVkMgKyBRKkZBUC9WUDsNCmQvZHQoQTIpID0gIC1DUExYUCpDTEIvVlAgKyBRKkExL1ZDIC0gIFEqRkFQL1ZQOw0KIg0KIyBDb21waWxlIG1vZGVsICMjIyMjIyMjIyMNCm1vZDEgPC0gUnhPREUobW9kZWwgPSBvZGUsIG1vZE5hbWUgPSAibW9kMSIpDQpgYGANCg0KIyMgU2Vuc2l0aXZpdHkgcGFyYW1ldGVyIHNldHRpbmcNCmBgYHtyfQ0KdGltZS5pbnRlcnZhbCA8LSAxDQp0ZXN0LmRvc2UgPC0gYyg1MCwxMDAsMjUwLDQwMCw1MDApDQp0ZXN0LmV4cCA8LSBzZXEoMC43NSwwLjg1LCAwLjAxKQ0KYGBgDQoNCiMjIFBLIHBhcmFtZXRlcnMgJiBzaW11bGF0aW9uDQpgYGB7cn0NCmRhdGEgPC0gZGF0YS5mcmFtZSh0aW1lID0gc2VxKDAsIDIxKjI0LCB0aW1lLmludGVydmFsKSwNCiAgICAgICAgICAgICAgICAgICAgIENPTkMgPSAwKQ0KDQpmb3IgKGkgaW4gdGVzdC5kb3NlKSB7DQogIGZvciAoaiBpbiB0ZXN0LmV4cCkgew0KICAgIERPU0VtbTMgPSBpICAgIyBEb3NlIA0KICAgIEFsbF9leCA9IGogICAgIyBFeHBvbmVudA0KDQogIEJXID0gNzAgICAgICAgICAgICAgICAgICAgICAgIyBBdmVyYWdlIGJvZHl3ZWlnaHQgb2YgbW9ua2V5IGluIDEyIG1nL2tnIGdyb3VwDQogIENMQV9lc3QgPSAxLjE2ICAgICAgICAJCQkgIyBTZXBhcmV0IHZhcmlhYmxlIGZvciBzZW5zdGl2aXR5IGFuYWx5c2lzDQogIFZfZXN0ID0gMTI4ICAgICAgICAgICAgIAkgICAjIFNlcGFyZXQgdmFyaWFibGUgZm9yIHNlbnN0aXZpdHkgYW5hbHlzaXMNCiAgVlBfZXN0ID0gMTI2ICAgICAgICAgICAgIAkJICMgU2VwYXJldCB2YXJpYWJsZSBmb3Igc2Vuc3Rpdml0eSBhbmFseXNpcw0KICAgIA0KICANCiAgQ0xBID0gQ0xBX2VzdCooQlcvMykqKkFsbF9leCAgICAjIENMX2V4ICAobUwvaCkNCiAgVkMgID0gVl9lc3QqKEJXLzMpICAgIAkJCSAgICAjIENlbnRyYWwgdm9sdW1lIG9mIGRpc3RyaWJ1dGlvbiAobUwpDQogIFEgICAgPSA4Ljc1ICogKEJXLzMpKipBbGxfZXggICAgIyBJbnRlcmNvbXBhcnRtZW50YWwgY2xlYXJhbmNlIChtTC9oKQ0KICBWUCAgPSBWUF9lc3QqKEJXLzMpICAgICAgICAgICANCiAgUkIgPSAzMzUgKiAoQlcvMykqKkFsbF9leCAgICAgICAgIyBSQl9leAk7IFRhcmdldCBzeW50aGVzaXMgcmF0ZSAocG1vbC9oKQ0KICBDTEIgPSAyLjM5KihCVy8zKSoqQWxsX2V4ICAgICAgICAjIFRhcmdldCAmIENvbXBsZXggY2xlYXJhbmNlIChtTC9oKQ0KICBLRCAgPSA0LjUgICAgCQkJICAgICAgICAgICAgICAgIyBFcXVpbGlicml1bSBiaW5kaW5nIGNvbnN0YW50IChuTSkNCiAgVEJQID0gVlAqUkIvQ0xCICAgICAgICAgICAgICAgICAgIyBUb3RhbCBiaW5kaW5nIHRhcmdldCBpbiBwZXJpcGhlcmFsDQoNCiAgIyBTaW11bGF0ZSBhIHNpbmdsZSBkb3NlICMjIyMjIyMjIyMNCiAgTVdsaWcgPSAxNTAwMDAgICMgTW9sZWN1bGFyIHdlaWdodCBvZiBtQWINCiAgRE9TRSA9IERPU0VtbTMgKiAxLjczDQogIERPU0VuTSA9IERPU0UqMWUtMy9NV2xpZyoxZTEyICAjRG9zZSBhcyBuYW5vbW9sZQ0KICBkdXJhdGlvbiA9IDIgICAjIGluZnVzaW9uIGR1cmF0aW9uDQogIGluZnJhdGUgPSBET1NFbk0gLyBkdXJhdGlvbiAgIyBpbnVzaW9uIHJhdGUiDQogIHNhbXBsaW5nLmRheSA9IDIxICAjIHNhbXBsaW5nIHRpbWUgYXMgZGF5DQogIHNhbXBsaW5nLnRpbWUgPSAyNCpzYW1wbGluZy5kYXkgICAjIHNhbXBsaW5nIHRpbWUgYXMgaG91cg0KICANCnBhcmFtcyA8LSBjKENMQSA9IENMQSwgVkMgPSBWQywgUSA9IFEsIFZQID0gVlAsIENMQiA9IENMQiwgUkIgPSBSQiwgS0QgPSBLRCkNCmluaXRzIDwtIGMoMCwgMCkgICANCg0KIyBJbml0aWFsaXplIGV2ZW50IHRhYmxlICMjIyMjIyMjIyMNCmV2IDwtIGV2ZW50VGFibGUoKQ0KZXYkYWRkLmRvc2luZyhkb3NlID0gRE9TRW5NLCBuYnIuZG9zZXMgPSAxLCBkb3NpbmcudG8gPTEsIHJhdGUgPSBpbmZyYXRlKSMsIGRvc2luZy5pbnRlcnZhbCA9IDE2OCkNCmV2JGFkZC5zYW1wbGluZyhzZXEoMCwgc2FtcGxpbmcudGltZSwgdGltZS5pbnRlcnZhbCkpDQoNCiNpbnRlZ3JhdGlvbg0KZGF0YTIgPC0gYXMuZGF0YS5mcmFtZShtb2QxJHJ1bihwYXJhbXMsIGV2LCBpbml0cykpDQpkYXRhMiA8LSBkYXRhMlssYygxLDUpXQ0KDQpjb2xuYW1lcyhkYXRhMikgPC0gYygidGltZSIsIHBhc3RlKCJkb3NlIixpLCJleHAiLGosIHNlcD0iLSIpKQ0KZGF0YSAgPC0gbWVyZ2UoZGF0YSwgZGF0YTIsIGJ5ID0gInRpbWUiKQ0KICB9fQ0KYGBgDQoNCiMjIERhdGEgbWFuYWdlbWVudCBmb3IgTkNBDQpgYGB7cn0NCmRhdGEgPC0gZGF0YVssIC0yXQ0KZGF0YS5sb25nIDwtDQogIGRhdGEgJT4lDQogIGdhdGhlcigyOm5jb2woZGF0YSksIGtleSA9ICJncm91cCIsIHZhbHVlID0gIkNPTkMiKQ0KDQpkYXRhMyA8LSBzZXBhcmF0ZShkYXRhLmxvbmcsDQogICAgICAgICAgICAgICAgIGdyb3VwLCBpbnRvID0gYygiYSIsICJkb3NlIiwgImIiLCJleHAiKSwgc2VwID0gIi0iKQ0KZGF0YTMgPC0gZGF0YTNbLGMoMSwzLDUsNildDQojY29sbmFtZXModGVzdCkgPC0gYygidGltZSIsImRvc2UiLCAiZXhwIiwiY29uYyIpDQoNCnVuaXF1ZShkYXRhM1ssYygiZG9zZSIsICJleHAiKV0pDQpucm93KHVuaXF1ZShkYXRhM1ssYygiZG9zZSIsICJleHAiKV0pKQ0KDQpkYXRhMyROSUQgPC0gcGFzdGUoZGF0YTMkZG9zZSwgZGF0YTMkZXhwLCBzZXAgPSAiLSIpDQpkYXRhMyRJRCA8LSBmYWN0b3IoZGF0YTMkTklELCBsYWJlbD0xOmxlbmd0aCh1bmlxdWUoZGF0YTMkTklEKSkpDQoNCiMgU2ltdWxhdGVkIENvbmMtVGltZSBwcm9maWxlIGJ5IGRvc2UNCmdncGxvdChkYXRhMywgYWVzKHRpbWUsIENPTkMsIGdyb3VwID0gSUQsIGNvbG91ciA9IGZhY3RvcihleHApKSkgKyANCiAgZ2VvbV9saW5lKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKSArDQogIGZhY2V0X3dyYXAofmRvc2UsIG5jb2wgPSAyLCBzY2FsZXM9ImZyZWVfeSIpDQpgYGANCg0KIyMgTkNBIGFuYWx5c2lzIHVzaW5nIE5vbkNvbXBhcnQgcGFja2FnZSBhbmQgZGF0YSBtYW5hZ2VtZW50DQpgYGB7cn0NCm5jYV9kYXRhIDwtIE5vbkNvbXBhcnQ6OnRhYk5DQShkYXRhMywgIklEIiwgInRpbWUiLCAiQ09OQyIpDQpuY2FfZGF0YSA8LSBhcy5kYXRhLmZyYW1lKG5jYV9kYXRhKQ0KbmNhX0FVQyA8LSBuY2FfZGF0YSAlPiUgc2VsZWN0KElELCBBVUNJRk8pICU+JSBhcnJhbmdlKElEKQ0KbmNhX0FVQyAlPiUga25pdHI6OmthYmxlKCkNCg0KZGF0YV9zdWIgPC0gDQogIGRhdGEzICU+JSANCiAgc2VsZWN0KElELCBkb3NlLCBleHApICU+JSANCiAgYXJyYW5nZShJRCkNCmRhdGFfc3ViIDwtIGRhdGFfc3ViWyFkdXBsaWNhdGVkKGRhdGFfc3ViJElEKSxdDQpkYXRhX3N1YiA8LSBtZXJnZShkYXRhX3N1YiwgbmNhX0FVQywgYnk9IklEIikNCg0KI0FVQyBvYnMNCkFVQ19vYnMgPC0gcmVhZC5jc3YoZmlsZT0iQ2V0dXhtYWJfQVVDLmNzdiIsIGhlYWRlciA9IFQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGLCBucm93ID0gNSkNCmNvbG5hbWVzKEFVQ19vYnMpIDwtIGMoImRvc2UiLCJBVUNPQlMiKQ0KIyMgbWVyZ2UgQVVDb2JzIGFuZCBBVUNzaW0NCmRhdGFfYWxsIDwtIG1lcmdlKGRhdGFfc3ViLCBBVUNfb2JzLCBieT0iZG9zZSIpICU+JQ0KICBzZWxlY3QoSUQsIGRvc2UsIGV4cCwgIEFVQ1NJTT1BVUNJRk8sIEFVQ09CUykgJT4lDQogIGFycmFuZ2UoSUQpDQprbml0cjo6a2FibGUoZGF0YV9hbGwpDQpgYGANCg0KIyMgQ2FsY3VsYXRlIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UgKFBQRSwgUk1TRSwgQUZFLCBBQUZFKQ0KYGBge3J9DQojIEluZGl2aWR1YWwgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZQ0KZGF0YV9hbGwgPC0NCiAgZGF0YV9hbGwgJT4lDQogIG11dGF0ZShQUEVpID0gKEFVQ1NJTS1BVUNPQlMpL0FVQ09CUywNCiAgICAgICAgIFJNU0VpID0gKEFVQ1NJTS1BVUNPQlMpXjIsDQogICAgICAgICBBRkVpID0gbG9nMTAoQVVDU0lNL0FVQ09CUyksDQogICAgICAgICBBQUZFaSA9IGFicyhBRkVpKSkNCmtuaXRyOjprYWJsZShkYXRhX2FsbCkNCg0KIyBNZWFuIGJ5IGV4cG9uZW50DQpkYXRhX2FsbF9leCA8LQ0KICBkYXRhX2FsbCAlPiUNCiAgZ3JvdXBfYnkoZXhwKSAlPiUNCiAgc3VtbWFyaXNlKFBQRT1zdW0oUFBFaSkvNSoxMDAsDQogICAgICAgICAgICBSTVNFID0gc3FydChzdW0oUk1TRWkpLzUpLA0KICAgICAgICAgICAgQUZFID0gMTBeKG1lYW4oQUZFaSkpLA0KICAgICAgICAgICAgQUFGRSA9IDEwXihtZWFuKEFBRkVpKSkpDQprbml0cjo6a2FibGUoZGF0YV9hbGxfZXgpDQoNCmBgYA0KDQojIyBQbG90IHRoZSByZXN1bHQuDQpgYGB7cn0NCmRhdGFfYWxsX2V4X2xvbmcgPC0NCiAgZGF0YV9hbGxfZXggJT4lDQogIGdhdGhlcigyOjUsIGtleSA9ICJldmFsdWF0aW9uIiwgdmFsdWUgPSAicGVyZm9ybWFuY2UiKQ0KDQpnZ3Bsb3QoZGF0YV9hbGxfZXhfbG9uZywgYWVzKGV4cCwgcGVyZm9ybWFuY2UpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBmYWNldF93cmFwKH5ldmFsdWF0aW9uLCBzY2FsZXM9ImZyZWVfeSIpDQpgYGANCg==