Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mixture cure models (Weibull and log-normal) #1453

Draft
wants to merge 69 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
f3337e3
added stan functions for mixcure models
yananlong Feb 1, 2023
77753bf
added mixcure PDFs and CDFs
yananlong Feb 1, 2023
78e8ed7
added mixcure log-likelihood functions
yananlong Feb 1, 2023
174fda4
minor changes
yananlong Feb 1, 2023
82eb565
minor changes
yananlong Feb 1, 2023
981ccc5
added mixcure families
yananlong Feb 1, 2023
122ddd7
added default priors for the incidence parameter in mixcure models
yananlong Feb 1, 2023
e8c4a99
updated manuals
yananlong Feb 2, 2023
f903828
added functions for mixcure models
yananlong Feb 2, 2023
5fec70e
fixed typos in stan functions for cure models
yananlong Feb 2, 2023
aa1701c
Merge pull request #1 from paul-buerkner/master
yananlong Feb 6, 2023
25dce93
minor changes
yananlong Feb 6, 2023
9143e88
Merge branch 'master' of https://github.com/yananlong/brms
yananlong Feb 6, 2023
110beef
fixed typos
yananlong Feb 6, 2023
ba43f65
added tests for mixcure likelihood functions
yananlong Feb 6, 2023
ffa6807
added tests for mixcure models
yananlong Feb 7, 2023
1803a24
minor changes
yananlong Feb 7, 2023
b8bcaa0
minor changes
yananlong Feb 7, 2023
977d30d
corrected typo in stan function
yananlong Feb 7, 2023
9f9870c
fixed typos in family
yananlong Feb 7, 2023
6c45b0f
added loo model comparison in local test
yananlong Feb 7, 2023
e84df01
minor changes
yananlong Feb 8, 2023
068263a
minor changes
yananlong Feb 14, 2023
986d5d0
fixed indentations
yananlong Feb 16, 2023
4bd37c2
added the complementary log-log link for inc
yananlong Feb 16, 2023
9dfa184
minor changes
yananlong Feb 16, 2023
3eedf4e
fixed link function for mixcure models
yananlong Feb 16, 2023
cf8ceef
improved doc strings for stan code chunks for mixcure models
yananlong Feb 16, 2023
a749f4a
improved doc strings for stan code chunks for mixcure models
yananlong Feb 16, 2023
0907128
updated stan code generation for mixcure models
yananlong Feb 21, 2023
f992dc6
added documentation for mixcure models
yananlong Feb 21, 2023
9bfb9ce
removed library import
yananlong Feb 21, 2023
008d921
added tests for make_stancode
yananlong Feb 21, 2023
f29c11f
updated stop message for mixcure models
yananlong Feb 24, 2023
7b8d234
corrected documentation for parameters
yananlong Feb 25, 2023
32aa4b4
Merge branch 'paul-buerkner:master' into master
yananlong Feb 25, 2023
309392a
added log-logistic family
yananlong Feb 25, 2023
bbe730b
added PPD for mixcure models
yananlong Feb 25, 2023
0a09dc8
Merge branch 'paul-buerkner:master' into master
yananlong Mar 7, 2023
5f54717
Merge branch 'paul-buerkner:master' into master
yananlong Mar 10, 2023
cb37642
added log-logistic models
yananlong Mar 10, 2023
93905fa
added log-logistic models
yananlong Mar 10, 2023
36ce202
updated PPD functions for mixcure family models
yananlong Mar 10, 2023
c7e128f
updated PPD functions for mixcure family models
yananlong Mar 10, 2023
de8bcba
added functions for log-logistic family models
yananlong Mar 10, 2023
d744e02
Merge branch 'paul-buerkner:master' into master
yananlong Mar 15, 2023
cd317a1
Merge branch 'paul-buerkner:master' into master
yananlong Apr 7, 2023
5196e48
minor changes
yananlong Apr 7, 2023
423edd8
Merge branch 'master' of https://github.com/yananlong/brms
yananlong Apr 7, 2023
7286a86
Merge branch 'paul-buerkner:master' into master
yananlong Apr 11, 2023
eabb8a9
Merge branch 'paul-buerkner:master' into master
yananlong May 3, 2023
0be151c
Merge branch 'paul-buerkner:master' into master
yananlong May 10, 2023
4a8e5bc
Merge branch 'paul-buerkner:master' into master
yananlong May 20, 2023
8dbaa32
Merge branch 'paul-buerkner:master' into master
yananlong Jun 2, 2023
ecbc9de
Merge branch 'paul-buerkner:master' into master
yananlong Jun 14, 2023
a6fa42c
updated vignettes
yananlong Jun 21, 2023
9e692c4
Merge branch 'paul-buerkner:master' into master
yananlong Jul 7, 2023
3e0123f
minor changes
yananlong Oct 8, 2023
7ab3f68
minor changes
yananlong Oct 8, 2023
5541e7e
Merge branch 'master' of https://github.com/paul-buerkner/brms
yananlong Oct 8, 2023
3f54932
Merge branch 'paul-buerkner:master' into master
yananlong Oct 11, 2023
9c8e44b
Merge branch 'paul-buerkner:master' into master
yananlong Oct 16, 2023
8e83ec4
Merge branch 'paul-buerkner:master' into master
yananlong Dec 24, 2023
e62c387
Merge branch 'paul-buerkner:master' into master
yananlong Jan 13, 2024
ca9673b
Merge branch 'paul-buerkner:master' into master
yananlong Jan 21, 2024
d4e50eb
Merge branch 'paul-buerkner:master' into master
yananlong Jan 24, 2024
67b4aaa
Merge branch 'paul-buerkner:master' into master
yananlong Jan 27, 2024
9073341
Merge branch 'paul-buerkner:master' into master
yananlong Feb 1, 2024
bf1b448
Merge branch 'paul-buerkner:master' into master
yananlong Feb 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ tests/local/models_0.8.0.Rda
tests/local/models_0.10.0.Rda
tests/local/models_1.2.0.Rda
tests/local/Rplots.pdf
.ipynb*
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like an unusal gitignore for an R package. Do we really need it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that, I use jupyter lab for editing so I added that line to avoid adding the checkpoints files. Will fix this.

3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ Authors@R:
person("Mattan S.", "Ben-Shachar", role = c("ctb")),
person("Hayden", "Rabel", role = c("ctb")),
person("Simon C.", "Mills", role = c("ctb")),
person("Stephen", "Wild", role = c("ctb")))
person("Stephen", "Wild", role = c("ctb")),
person("Yanan", "Long", role = c("ctb")))
Depends:
R (>= 3.5.0),
Rcpp (>= 0.12.0),
Expand Down
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ export(dhurdle_poisson)
export(dinv_gaussian)
export(dirichlet)
export(dlogistic_normal)
export(dmixcure_lognormal)
export(dmixcure_weibull)
export(dmulti_normal)
export(dmulti_student_t)
export(do_call)
Expand Down Expand Up @@ -461,6 +463,8 @@ export(marginal_smooths)
export(mcmc_plot)
export(me)
export(mi)
export(mixcure_lognormal)
export(mixcure_weibull)
export(mixture)
export(mm)
export(mmc)
Expand Down Expand Up @@ -493,6 +497,8 @@ export(phurdle_lognormal)
export(phurdle_negbinomial)
export(phurdle_poisson)
export(pinv_gaussian)
export(pmixcure_lognormal)
export(pmixcure_weibull)
export(post_prob)
export(posterior_average)
export(posterior_epred)
Expand Down
101 changes: 101 additions & 0 deletions R/distributions.R
Original file line number Diff line number Diff line change
Expand Up @@ -2052,6 +2052,107 @@ phurdle_lognormal <- function(q, mu, sigma, hu, lower.tail = TRUE,
out
}

#' @rdname Mixcure
#' @export
dmixcure_lognormal <- function(x, mu, sigma, inc, log = FALSE) {
pars <- list(meanlog = mu, sdlog = sigma)
.dmixcure(x, "lnorm", inc, pars, log)
}

#' @rdname Mixcure
#' @export
pmixcure_lognormal <- function(q, mu, sigma, inc, lower.tail = TRUE, log.p = FALSE) {
pars <- list(meanlog = mu, sdlog = sigma)
.pmixcure(q, "lnorm", inc, pars, lower.tail, log.p)
}

#' @rdname Mixcure
#' @export
dmixcure_weibull <- function(x, shape, scale, inc, log = FALSE) {
pars <- list(shape = shape, scale = scale)
.dmixcure(x, "weibull", inc, pars, log)
}

#' @rdname Mixcure
#' @export
pmixcure_weibull <- function(q, shape, scale, inc, lower.tail = TRUE, log.p = FALSE) {
pars <- list(shape = shape, scale = scale)
.pmixcure(q, "weibull", inc, pars, lower.tail, log.p)
}

# density of a mixcure distribution
# @param dist name of the distribution
# @param inc bernoulli incidence parameter
# @param pars list of parameters passed to pdf
.dmixcure <- function(x, dist, inc, pars, log) {
stopifnot(is.list(pars))
dist <- as_one_character(dist)
log <- as_one_logical(log)
args <- expand(dots = c(nlist(x, inc), pars))
x <- args$x
inc <- args$inc
pars <- args[names(pars)]
pdf <- paste0("d", dist)
# incidence part (not censored): pi(z) * f(t | x)
out <- log(inc) + do_call(pdf, c(list(x), pars, log = TRUE))
if (!log) {
out <- exp(out)
}
out
}

# CDF of a mixcure distribution
# @param dist name of the distribution
# @param inc bernoulli incidence parameter
# @param pars list of parameters passed to pdf
# @param lb lower bound of the conditional distribution
# @param ub upper bound of the conditional distribution
.pmixcure <- function(q, dist, inc, pars, lower.tail, log.p, lb = 0, ub = Inf) {
stopifnot(is.list(pars))
dist <- as_one_character(dist)
lower.tail <- as_one_logical(lower.tail)
log.p <- as_one_logical(log.p)
args <- expand(dots = c(nlist(q, inc), pars))
q <- args$q
inc <- args$inc
pars <- args[names(pars)]
cdf <- paste0("p", dist)
# compute log CCDF values
# latency part (right-censored): [1 - pi(z)] + pi(z) * S(t | x)
out <- matrixStats::logSumExp(c(
1, -inc,
inc + do_call(
cdf,
c(list(q), pars, lower.tail = FALSE, log.p = TRUE)
)
))
# take the limits of the distribution into account
out <- ifelse(q < lb, 0, out)
out <- ifelse(q > ub, -Inf, out)
if (lower.tail) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some strange indentation going on here. Please fix.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention is to use 2 spaces for indentation, correct?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but what about the if statements afterwards?

out <- 1 - exp(out)
if (log.p) {
out <- log(out)
}
} else {
if (!log.p) {
out <- exp(out)
}
}
out
if (lower.tail) {
out <- 1 - exp(out)
if (log.p) {
out <- log(out)
}
} else {
if (!log.p) {
out <- exp(out)
}
}
out
}

# density of the categorical distribution with the softmax transform
# @param x positive integers not greater than ncat
# @param eta the linear predictor (of length or ncol ncat)
Expand Down
29 changes: 25 additions & 4 deletions R/families.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#' @param link_beta Link of auxiliary parameter \code{beta} if being predicted.
#' @param link_zi Link of auxiliary parameter \code{zi} if being predicted.
#' @param link_hu Link of auxiliary parameter \code{hu} if being predicted.
#' @param link_inc Link of auxiliary parameter \code{inc} if being predicted.
#' @param link_zoi Link of auxiliary parameter \code{zoi} if being predicted.
#' @param link_coi Link of auxiliary parameter \code{coi} if being predicted.
#' @param link_disc Link of auxiliary parameter \code{disc} if being predicted.
Expand Down Expand Up @@ -192,7 +193,8 @@ brmsfamily <- function(family, link = NULL, link_sigma = "log",
link_shape = "log", link_nu = "logm1",
link_phi = "log", link_kappa = "log",
link_beta = "log", link_zi = "logit",
link_hu = "logit", link_zoi = "logit",
link_hu = "logit", link_inc = "logit",
link_zoi = "logit",
link_coi = "logit", link_disc = "log",
link_bs = "log", link_ndt = "log",
link_bias = "logit", link_xi = "log1p",
Expand All @@ -206,7 +208,7 @@ brmsfamily <- function(family, link = NULL, link_sigma = "log",
link_sigma = link_sigma, link_shape = link_shape,
link_nu = link_nu, link_phi = link_phi,
link_kappa = link_kappa, link_beta = link_beta,
link_zi = link_zi, link_hu = link_hu,
link_zi = link_zi, link_hu = link_hu, link_inc = link_inc,
link_zoi = link_zoi, link_coi = link_coi,
link_disc = link_disc, link_bs = link_bs,
link_ndt = link_ndt, link_bias = link_bias,
Expand Down Expand Up @@ -735,6 +737,24 @@ hurdle_cumulative <- function(link = "logit", link_hu = "logit",
threshold = threshold)
}

#' @rdname brmsfamily
#' @export
mixcure_lognormal <- function(link = "identity", link_sigma = "log",
link_inc = "logit") {
slink <- substitute(link)
.brmsfamily("mixcure_lognormal", link = link, slink = slink,
link_sigma = link_sigma, link_inc = link_inc)
}

#' @rdname brmsfamily
#' @export
mixcure_weibull <- function(link = "log", link_shape = "log",
link_inc = "logit") {
slink <- substitute(link)
.brmsfamily("mixcure_weibull", link = link, slink = slink,
link_shape = link_shape, link_inc = link_inc)
}

#' @rdname brmsfamily
#' @export
zero_inflated_beta <- function(link = "logit", link_phi = "log",
Expand Down Expand Up @@ -1333,6 +1353,7 @@ links_dpars <- function(dpar) {
beta = c("log", "identity", "softplus", "squareplus"),
zi = c("logit", "identity"),
hu = c("logit", "identity"),
inc = c("logit", "identity"),
zoi = c("logit", "identity"),
coi = c("logit", "identity"),
disc = c("log", "identity", "softplus", "squareplus"),
Expand Down Expand Up @@ -1867,8 +1888,8 @@ family_bounds.brmsterms <- function(x, ...) {
"gamma", "weibull", "exponential", "lognormal",
"frechet", "inverse.gaussian",
"hurdle_poisson", "hurdle_negbinomial", "hurdle_gamma",
"hurdle_lognormal", "zero_inflated_poisson",
"zero_inflated_negbinomial"
"hurdle_lognormal", "mixcure_lognormal", "mixcure_weibull",
"zero_inflated_poisson", "zero_inflated_negbinomial"
)
beta_families <- c("beta", "zero_inflated_beta", "zero_one_inflated_beta")
ordinal_families <- c("cumulative", "cratio", "sratio", "acat")
Expand Down
24 changes: 24 additions & 0 deletions R/family-lists.R
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,30 @@
)
}

.family_mixcure_lognormal <- function() {
list(
links = c("identity", "inverse"),
dpars = c("mu", "sigma", "inc"), type = "real",
ybounds = c(0, Inf), closed = c(TRUE, NA),
ad = c("weights", "subset", "cens", "trunc", "index"),
include = "fun_mixcure_lognormal.stan",
specials = c("logscale", "sbi_inc_logit"),
normalized = ""
)
}

.family_mixcure_weibull <- function() {
list(
links = c("log", "identity", "inverse", "softplus", "squareplus"),
dpars = c("mu", "shape", "inc"), type = "real",
ybounds = c(0, Inf), closed = c(TRUE, NA),
ad = c("weights", "subset", "cens", "trunc", "index"),
include = "fun_mixcure_weibull.stan",
specials = c("logscale", "sbi_inc_logit"),
normalized = ""
)
}

.family_zero_inflated_poisson <- function() {
list(
links = c("log", "identity", "sqrt", "softplus", "squareplus"),
Expand Down
24 changes: 24 additions & 0 deletions R/log_lik.R
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,30 @@ log_lik_hurdle_cumulative <- function(i, prep) {
log_lik_weight(out, i = i, prep = prep)
}

log_lik_mixcure_lognormal <- function(i, prep) {
mu <- get_dpar(prep, "mu", i)
sigma <- get_dpar(prep, "sigma", i = i)
inc <- get_dpar(prep, "inc", i)
args <- nlist(mu = mu, sigma = sigma, inc = inc)
out <- log_lik_censor("mixcure_lognormal", args, i, prep)
out <- log_lik_truncate(out, pmixcure_lognormal, args, i, prep)
log_lik_weight(out, i = i, prep = prep)
}

log_lik_mixcure_weibull <- function(i, prep) {
shape <- get_dpar(prep, "shape", i = i)
scale <- get_dpar(prep, "mu", i = i) / gamma(1 + 1 / shape)
inc <- get_dpar(prep, "inc", i)
args <- list(shape = shape, scale = scale, inc = inc)
out <- log_lik_censor(
dist = "mixcure_weibull", args = args, i = i, prep = prep
)
out <- log_lik_truncate(
out, cdf = pmixcure_weibull, args = args, i = i, prep = prep
)
log_lik_weight(out, i = i, prep = prep)
}

log_lik_zero_inflated_poisson <- function(i, prep) {
zi <- get_dpar(prep, "zi", i)
lambda <- get_dpar(prep, "mu", i)
Expand Down
10 changes: 10 additions & 0 deletions R/posterior_epred.R
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,16 @@ posterior_epred_hurdle_lognormal <- function(prep) {
with(prep$dpars, exp(mu + sigma^2 / 2) * (1 - hu))
}

posterior_epred_mixcure_lognormal <- function(prep) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it not possible to compute the expected value for these families?

stop2("Cannot compute expected values of the posterior predictive ",
"distribution for family 'micure_lognormal'.")
}

posterior_epred_mixcure_weibull <- function(prep) {
stop2("Cannot compute expected values of the posterior predictive ",
"distribution for family 'micure_weibull'.")
}

posterior_epred_hurdle_cumulative <- function(prep) {
adjust <- ifelse(prep$family$link == "identity", 0, 1)
ncat_max <- max(prep$data$nthres) + adjust
Expand Down
3 changes: 3 additions & 0 deletions R/priors.R
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,7 @@ def_dprior <- function(x, dpar, data = NULL) {
beta = "gamma(1, 0.1)",
zi = "beta(1, 1)",
hu = "beta(1, 1)",
inc = "beta(1, 1)",
zoi = "beta(1, 1)",
coi = "beta(1, 1)",
bs = "gamma(1, 1)",
Expand All @@ -1085,6 +1086,7 @@ def_dprior <- function(x, dpar, data = NULL) {
beta = "normal(1.7, 1.3)",
zi = "logistic(0, 1)",
hu = "logistic(0, 1)",
inc = "logistic(0, 1)",
zoi = "logistic(0, 1)",
coi = "logistic(0, 1)",
bs = "normal(-0.6, 1.3)",
Expand Down Expand Up @@ -1679,6 +1681,7 @@ dpar_bounds <- function(dpar, suffix = "", family = NULL) {
beta = list(lb = "0", ub = ""),
zi = list(lb = "0", ub = "1"),
hu = list(lb = "0", ub = "1"),
inc = list(lb = "0", ub = "1"),
zoi = list(lb = "0", ub = "1"),
coi = list(lb = "0", ub = "1"),
bs = list(lb = "0", ub = ""),
Expand Down
23 changes: 21 additions & 2 deletions R/stan-likelihood.R
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,9 @@ stan_log_lik_simple_lpdf <- function(lpdf, link, bterms, sep = "_") {
}

# prepare _logit suffix for distributional parameters
# used in zero-inflated and hurdle models
# used in zero-inflated, hurdle and mixcure models
stan_log_lik_dpar_usc_logit <- function(dpar, bterms) {
stopifnot(dpar %in% c("zi", "hu"))
stopifnot(dpar %in% c("zi", "hu", "inc"))
stopifnot(is.brmsterms(bterms))
cens_or_trunc <- stan_log_lik_adj(bterms, c("cens", "trunc"))
usc_logit <- isTRUE(bterms$dpars[[dpar]]$family$link == "logit")
Expand Down Expand Up @@ -889,6 +889,25 @@ stan_log_lik_hurdle_cumulative <- function(bterms, resp = "", mix = "",
sdist(lpdf, p$mu, p$hu, p$disc, p$thres, p$Jthres)
}

stan_log_lik_mixcure_lognormal <- function(bterms, resp = "", mix = "", ...) {
p <- stan_log_lik_dpars(bterms, TRUE, resp, mix)
usc_logit <- stan_log_lik_dpar_usc_logit("inc", bterms)
lpdf <- paste0("mixcure_lognormal", usc_logit)
sdist(lpdf, p$mu, p$sigma, p$inc)
}

stan_log_lik_mixcure_weibull <- function(bterms, resp = "", mix = "", ...) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like reqn should always be true given the stan code of this model. If true, should the code below be changed or simplified?

reqn <- stan_log_lik_adj(bterms) || nzchar(mix)
p <- stan_log_lik_dpars(bterms, TRUE, resp, mix)
usc_logit <- stan_log_lik_dpar_usc_logit("inc", bterms)
lpdf <- paste0("mixcure_weibull", usc_logit)
# Stan uses shape-scale parameterization for weibull
need_dot_div <- !reqn && paste0("shape", mix) %in% names(bterms$dpars)
div_op <- str_if(need_dot_div, " ./ ", " / ")
p$scale <- paste0(p$mu, div_op, "tgamma(1 + 1", div_op, p$shape, ")")
sdist(lpdf, p$scale, p$shape, p$inc)
}

stan_log_lik_zero_inflated_poisson <- function(bterms, resp = "", mix = "",
...) {
p <- stan_log_lik_dpars(bterms, TRUE, resp, mix)
Expand Down
30 changes: 30 additions & 0 deletions inst/chunks/fun_mixcure_lognormal.stan
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* mixcure lognormal (AFT) log-PDF of a single response
* identity parameterization of the incidence part
*/
real mixcure_lognormal_lpdf(real y, real mu, real sigma, real inc) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add some empty lines between function definitions in both stan files? And add a little more doc at the top?

return bernoulli_lpmf(1 | inc) + lognormal_lpdf(y | mu, sigma);
}
real mixcure_lognormal_lccdf(real y, real mu, real sigma, real inc) {
return log_sum_exp(
bernoulli_lpmf(0 | inc),
bernoulli_lpmf(1 | inc) + lognormal_lccdf(y | mu, sigma)
);
}
real mixcure_lognormal_lcdf(real y, real mu, real sigma, real inc) {
return log1m_exp(mixcure_lognormal_lccdf(y | mu, sigma, inc));
}
/* mixcure lognormal (AFT) log-PDF of a single response
* logit parameterization of the incidence part
*/
real mixcure_lognormal_logit_lpdf(real y, real mu, real sigma, real inc) {
return bernoulli_logit_lpmf(1 | inc) + lognormal_lpdf(y | mu, sigma);
}
real mixcure_lognormal_logit_lccdf(real y, real mu, real sigma, real inc) {
return log_sum_exp(
bernoulli_logit_lpmf(0 | inc),
bernoulli_logit_lpmf(1 | inc) + lognormal_lccdf(y | mu, sigma)
);
}
real mixcure_lognormal_logit_lcdf(real y, real mu, real sigma, real inc) {
return log1m_exp(mixcure_lognormal_logit_lccdf(y | mu, sigma, inc));
}