-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlinexp_gastro_2b.stan
98 lines (89 loc) · 2.48 KB
/
linexp_gastro_2b.stan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Fit linexp gastric emptying curves with Stan
// This is the recommend model currently; it includes the
// simpler models as special cases for lkj and student_t
// Covariance between kappa and tempt is estimated using LKJ prior.
// Initial volume is locally normalized to 1, and denormalized
// in generated quantities for v0.
// Student-t with degrees of freedom that can be set.
// Lower LKJ: lower variance of kappa
// Lower values of df: lower variance of kappa. Other mainly unaffected
data{
real lkj; // lkj parameter, see below
int student_df; // 3 to 9
int<lower=0> n; // Number of data
int<lower=0> n_record; // Number of records, used for v0
array[n] int record;
vector[n] minute;
vector[n] volume;
}
transformed data{
vector[2] zeros;
vector[n] volume_1;
real norm_vol;
int n_norm;
zeros[1] = 0;
zeros[2] = 0;
n_norm = 0;
norm_vol = 0;
// Use mean of initial volume to normalize
for (i in 1:n){
if (minute[i] < 5) {
norm_vol += volume[i];
n_norm += 1;
}
}
norm_vol /= n_norm;
volume_1 = volume/norm_vol;
}
parameters{
vector <lower=0>[n_record] v0_1;
vector<lower=0>[2] sigma_record;
real <lower=0> mu_kappa;
real <lower=0> mu_tempt;
corr_matrix[2] rho;
real<lower=0> sigma;
array[n_record] vector[2] cf;
}
transformed parameters{
matrix[2,2] sigma_cf;
sigma_cf = quad_form_diag(rho, sigma_record);
}
model{
int rec;
real v0r;
real kappar;
real temptr;
vector[n] mu;
// http://www.psychstatistics.com/2014/12/27/d-lkj-priors/
// Large values, e.g. 70, give priors that prefer low correlations
// near 0. At 1 flat -1 to 1; lower 1 produces a trough at 0
rho ~ lkj_corr(lkj);
v0_1 ~ normal(1, 0.3);
cf ~ multi_normal( zeros , sigma_cf );
mu_kappa ~ normal(0.8, 0.3);
mu_tempt ~ normal(40, 20);
sigma_record[1] ~ cauchy(0,20);
sigma_record[2] ~ cauchy(0,0.4);
sigma ~ cauchy(0., 0.1);
for (i in 1:n){
rec = record[i];
v0r = v0_1[rec];
temptr = mu_tempt + cf[rec, 1];
kappar = mu_kappa + cf[rec, 2];
mu[i] = v0r*(1+kappar*minute[i]/temptr)*exp(-minute[i]/temptr);
}
// Using fixed student_t degrees of freedom. Values from 3 (many outliers)
// to 9 are useful
volume_1 ~ student_t(student_df, mu, sigma);
}
generated quantities{
vector[n_record] v0;
vector[n_record] tempt;
vector[n_record] kappa;
// Denormalized v0
v0 = v0_1 * norm_vol;
for (i in 1:n_record){
tempt[i] = mu_tempt + cf[i,1];
kappa[i] = mu_kappa + cf[i,2];
}
}