Skip to content

Commit 0554656

Browse files
authored
Merge pull request #25 from weberse2/issue-release-1-8-2
release 1.8-2
2 parents 4ba8689 + 825871e commit 0554656

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+4645
-1319
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ src/stan_files/.*\.hpp$
2323
^.brms-cache
2424
^.gitignore$
2525
^.gitattributes$
26+
^vignettes/.gitignore$
2627
^_pkgdown\.yml$
2728
^docs$
2829
^pkgdown$

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ src/*.so
77
src/*.o
88
src/stan_files/*.hpp
99
src/stan_files/*.o
10+
*.*~
11+
inst/sbc/sbc*html

DESCRIPTION

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ Description: Tool-set to support Bayesian evidence synthesis. This
88
for details on applying this package while Neuenschwander et al. (2010)
99
<doi:10.1177/1740774509356002> and Schmidli et al. (2014)
1010
<doi:10.1111/biom.12242> explain details on the methodology.
11-
Version: 1.8-1
12-
Date: 2025-01-20
11+
Version: 1.8-2
12+
Date: 2025-04-25
1313
Authors@R: c(person("Novartis", "Pharma AG", role = "cph")
1414
,person("Sebastian", "Weber", email="sebastian.weber@novartis.com", role=c("aut", "cre"))
1515
,person("Beat", "Neuenschwander", email="beat.neuenschwander@novartis.com", role="ctb")
@@ -39,7 +39,9 @@ Imports:
3939
utils,
4040
matrixStats,
4141
abind,
42-
rlang
42+
rlang,
43+
jsonlite,
44+
lifecycle
4345
LinkingTo:
4446
BH (>= 1.72.0),
4547
Rcpp (>= 0.12.0),
@@ -68,9 +70,11 @@ Suggests:
6870
parallel,
6971
brms,
7072
glue,
71-
ragg
73+
ragg,
74+
withr
7275
VignetteBuilder: knitr
7376
SystemRequirements: GNU make, pandoc (>= 1.12.3), pngquant, C++17
7477
Encoding: UTF-8
7578
RoxygenNote: 7.3.2
7679
Config/testthat/edition: 3
80+
Roxygen: list(markdown = TRUE)

Makefile

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ TARGET = r-source
55
OUTDIR = ./build
66

77
# includes all src dirs excluding R/
8-
SRCDIR = ./demo ./inst/stan ./inst/stan/include ./man-roxygen
8+
SRCDIR = ./demo ./inst/stan ./inst/stan/include ./man-roxygen ./vignettes
99
##DIR_OBJ = ./obj
1010

1111
OUTDIR_ABS=$(abspath $(OUTDIR))
@@ -86,7 +86,10 @@ man/package-doc: $(R_PKG_SRCS) $(BIN_OBJS)
8686
"${R_HOME}/bin/Rscript" -e 'roxygen2::roxygenize()'
8787
touch man/package-doc
8888

89-
inst/sbc/sbc_report.html : inst/sbc/calibration.rds
89+
inst/sbc/sbc_report.html : inst/sbc/sbc_report.R inst/sbc/calibration.rds
90+
cd $(@D); echo running $(RCMD) -e "rmarkdown::render('$(<F)', output_format=rmarkdown::html_vignette(self_contained=TRUE))"
91+
cd $(@D); $(RCMD) -e "rmarkdown::render('$(<F)', output_format=rmarkdown::html_vignette(self_contained=TRUE))"
92+
9093

9194
inst/sbc/calibration.rds :
9295
echo "Please run inst/sbc/make_reference_rankhist.R"
@@ -166,6 +169,12 @@ build/installed/$(RPKG)/DESCRIPTION : build/r-source-fast
166169
install -d build/installed
167170
cd build; $(RCMD) CMD INSTALL --library=./installed --no-docs --no-multiarch --no-test-load --no-clean-on-error $(RPKG)-source.tar.gz
168171

172+
docs/index.html : $(SRCS)
173+
NOT_CRAN=true $(RCMD) -e 'pkgdown::build_site()'
174+
175+
PHONY += pkgdown
176+
pkgdown: docs/index.html
177+
169178
PHONY += dev-install
170179
dev-install: build/installed/$(RPKG)/DESCRIPTION
171180

@@ -185,19 +194,19 @@ PHONY += check-winbuilder-devel
185194
check-winbuilder-devel : r-source-release
186195
cd build; $(RCMD) -e 'target <- tempdir()' \
187196
-e 'untar("$(RPKG)_$(PKG_VERSION).tar.gz", exdir=target)' \
188-
-e 'devtools::check_win_devel(pkg=file.path(target, "RBesT"))'
197+
-e 'devtools::check_win_devel(pkg=file.path(target, "$(RPKG)"))'
189198

190199
PHONY += check-winbuilder-release
191200
check-winbuilder-release : r-source-release
192201
cd build; $(RCMD) -e 'target <- tempdir()' \
193202
-e 'untar("$(RPKG)_$(PKG_VERSION).tar.gz", exdir=target)' \
194-
-e 'devtools::check_win_release(pkg=file.path(target, "RBesT"))'
203+
-e 'devtools::check_win_release(pkg=file.path(target, "$(RPKG)"))'
195204

196205
PHONY += check-winbuilder-oldrelease
197206
check-winbuilder-oldrelease : r-source-release
198207
cd build; $(RCMD) -e 'target <- tempdir()' \
199208
-e 'untar("$(RPKG)_$(PKG_VERSION).tar.gz", exdir=target)' \
200-
-e 'devtools::check_win_oldrelease(pkg=file.path(target, "RBesT"))'
209+
-e 'devtools::check_win_oldrelease(pkg=file.path(target, "$(RPKG)"))'
201210

202211
PHONY += check-winbuilder
203212
check-winbuilder : check-winbuilder-devel check-winbuilder-release check-winbuilder-oldrelease

NAMESPACE

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export(mn2gamma)
147147
export(mn2norm)
148148
export(ms2beta)
149149
export(ms2gamma)
150+
export(msr2mvnorm)
150151
export(oc1S)
151152
export(oc1Sdecision)
152153
export(oc2S)
@@ -159,10 +160,12 @@ export(postmix)
159160
export(preddist)
160161
export(qmix)
161162
export(qmixdiff)
163+
export(read_mix_json)
162164
export(rmix)
163165
export(rmixdiff)
164166
export(robustify)
165167
export(sigma)
168+
export(write_mix_json)
166169
import(Formula)
167170
import(Rcpp)
168171
import(abind)
@@ -175,6 +178,9 @@ import(rstantools)
175178
import(stats)
176179
importFrom(RcppParallel,CxxFlags)
177180
importFrom(RcppParallel,RcppParallelLibs)
181+
importFrom(jsonlite,fromJSON)
182+
importFrom(jsonlite,toJSON)
183+
importFrom(lifecycle,deprecated)
178184
importFrom(matrixStats,colLogSumExps)
179185
importFrom(matrixStats,colSums2)
180186
importFrom(matrixStats,logSumExp)

NEWS.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
# RBesT 1.8-2 - April 25th, 2025
2+
3+
## Enhancements
4+
5+
* Add experimental `write_mix_json` and `read_mix_json` functions
6+
which write and read mixture objects as JSON to/from files.
7+
* Add `"msr"` parametrization to `mixmvnorm` which allows to consturct
8+
multi-variate normal mixtures in a parametrization using the mean
9+
vector, standard deviations and the correlations. This functionality
10+
is based on the new `msr2mvnorm` utility function.
11+
* Allow standard deviations of 0 for components of a multi-variate
12+
normal mixture.
13+
114
# RBesT 1.8-1 - January 20th, 2025
215

316
## Bugfixes

R/AS.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#' \item{n}{study size}
1313
#' \item{r}{number of events}
1414
#' }
15-
#' @references Baeten D. et. al, \emph{The Lancet}, 2013, (382), 9906, p 1705
15+
#' @references Baeten D. et. al, *The Lancet*, 2013, (382), 9906, p 1705
1616
#'
1717
#' @template example-start
1818
#' @examples

R/BinaryExactCI.R

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#' @param r Number of success or responder
77
#' @param n Sample size
88
#' @param alpha confidence level
9-
#' @param drop Determines if \code{\link{drop}} will be called on the result
9+
#' @param drop Determines if [drop()] will be called on the result
1010
#'
1111
#' @details
1212
#' Confidence intervals are obtained by a procedure first given in
@@ -33,7 +33,10 @@ BinaryExactCI <- function(r, n, alpha = 0.05, drop = TRUE) {
3333
pLow <- qbeta(Low, r, n - r + 1)
3434
pHigh <- qbeta(High, r + 1, n - r)
3535

36-
nms <- c(paste(round(100 * Low, 1), "%", sep = ""), paste(round(100 * High, 1), "%", sep = ""))
36+
nms <- c(
37+
paste(round(100 * Low, 1), "%", sep = ""),
38+
paste(round(100 * High, 1), "%", sep = "")
39+
)
3740

3841
CI <- cbind(pLow, pHigh)
3942
colnames(CI) <- nms

R/EM_bmm_ab.R

Lines changed: 87 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
## EM for Beta Mixture Models (BMM) with Nc components
22

3-
EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max = 500, tol, Neps, eps = c(w = 0.005, a = 0.005, b = 0.005), constrain_gt1 = TRUE) {
3+
EM_bmm_ab <- function(
4+
x,
5+
Nc,
6+
mix_init,
7+
Ninit = 50,
8+
verbose = FALSE,
9+
Niter.max = 500,
10+
tol,
11+
Neps,
12+
eps = c(w = 0.005, a = 0.005, b = 0.005),
13+
constrain_gt1 = TRUE
14+
) {
415
N <- length(x)
516
assert_that(N + Nc >= Ninit)
617

@@ -11,12 +22,20 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
1122
## ensures proper handling during fit.
1223
x0 <- x == 0
1324
if (any(x0)) {
14-
message("Detected ", sum(x0), " value(s) which are exactly 0.\nTo avoid numerical issues during EM such values are moved to smallest eps on machine.")
25+
message(
26+
"Detected ",
27+
sum(x0),
28+
" value(s) which are exactly 0.\nTo avoid numerical issues during EM such values are moved to smallest eps on machine."
29+
)
1530
x[x0] <- .Machine$double.eps
1631
}
1732
x1 <- x == 1
1833
if (any(x1)) {
19-
message("Detected ", sum(x1), " value(s) which are exactly 1.\nTo avoid numerical issues during EM such values are moved to one minus smallest eps on machine.")
34+
message(
35+
"Detected ",
36+
sum(x1),
37+
" value(s) which are exactly 1.\nTo avoid numerical issues during EM such values are moved to one minus smallest eps on machine."
38+
)
2039
x[x1] <- 1 - .Machine$double.eps
2140
}
2241

@@ -32,7 +51,10 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
3251
## abmEst[,1] <- 1/Nc
3352
## assume that the sample is ordered randomly
3453
ind <- seq(1, N - Nc, length = Ninit)
35-
knnInit <- list(mu = matrix(0, nrow = Nc, ncol = 1), p = rep(1 / Nc, times = Nc))
54+
knnInit <- list(
55+
mu = matrix(0, nrow = Nc, ncol = 1),
56+
p = rep(1 / Nc, times = Nc)
57+
)
3658
for (k in seq(Nc)) {
3759
knnInit$mu[k, 1] <- mean(x[ind + k - 1])
3860
}
@@ -52,7 +74,11 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
5274
cmin <- which.min(KNN$p)
5375
muInit[cmin] <- sum(KNN$p * KNN$center)
5476
## muInit[cmin] <- mean(x) ## could be considered here
55-
nInit[cmin] <- pmax(muInit[cmin] * (1 - muInit[cmin]) / var(x) - 1, 1, na.rm = TRUE)
77+
nInit[cmin] <- pmax(
78+
muInit[cmin] * (1 - muInit[cmin]) / var(x) - 1,
79+
1,
80+
na.rm = TRUE
81+
)
5682
## Nmax <- max(2, max(nInit))
5783
## ensure n is positive for each cluster; if this is not the
5884
## case, sample uniformly from the range of n we have
@@ -126,7 +152,11 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
126152
traceMix <- list()
127153
traceLli <- c()
128154
Dlli <- Inf
129-
runMixPar <- array(-Inf, dim = c(Neps, 3, Nc), dimnames = list(NULL, rownames(mixEstPar), NULL))
155+
runMixPar <- array(
156+
-Inf,
157+
dim = c(Neps, 3, Nc),
158+
dimnames = list(NULL, rownames(mixEstPar), NULL)
159+
)
130160
runOrder <- 0:(Neps - 1)
131161
Npar <- Nc + 2 * Nc
132162
if (Nc == 1) Npar <- Npar - 1
@@ -160,10 +190,14 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
160190

161191
trig_n <- trigamma(n)
162192

163-
grad1 <- 2 * sqTerm1 * (trigamma(ab[1]) * ab[1] - trig_n * ab[1]) -
193+
grad1 <- 2 *
194+
sqTerm1 *
195+
(trigamma(ab[1]) * ab[1] - trig_n * ab[1]) -
164196
2 * sqTerm2 * (trig_n * ab[1])
165197

166-
grad2 <- -2 * sqTerm1 * (trig_n * ab[2]) +
198+
grad2 <- -2 *
199+
sqTerm1 *
200+
(trig_n * ab[2]) +
167201
2 * sqTerm2 * (trigamma(ab[2]) * ab[2] - trig_n * ab[2])
168202

169203
c(grad1, grad2)
@@ -182,7 +216,14 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
182216
a <- mixEst[2, ]
183217
b <- mixEst[3, ]
184218
## lli <- sweep( sweep(Lx, 2, a - 1, "*", check.margin=FALSE) + sweep(LxC, 2, b - 1, "*", check.margin=FALSE), 2, log(w) + lgamma(a + b) - lgamma(a) - lgamma(b), "+", check.margin=FALSE)
185-
lli <- sweep(sweep(Lx, 2, a - 1, "*", check.margin = FALSE) + sweep(LxC, 2, b - 1, "*", check.margin = FALSE), 2, log(w) - lbeta(a, b), "+", check.margin = FALSE)
219+
lli <- sweep(
220+
sweep(Lx, 2, a - 1, "*", check.margin = FALSE) +
221+
sweep(LxC, 2, b - 1, "*", check.margin = FALSE),
222+
2,
223+
log(w) - lbeta(a, b),
224+
"+",
225+
check.margin = FALSE
226+
)
186227
## lli <- t(matrix(log(mixEst[1,]) + dbeta(xRep, mixEst[2,], mixEst[3,], log=TRUE), nrow=Nc))
187228

188229
## ensure that the log-likelihood does not go out of numerical
@@ -202,15 +243,36 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
202243
Dlli <- (traceLli[iter + 1] - traceLli[iter - 1]) / 2
203244
}
204245
if (Nc > 1) {
205-
smean <- apply(runMixPar[order(runOrder), , , drop = FALSE], c(2, 3), function(x) mean(abs(diff(x))))
246+
smean <- apply(
247+
runMixPar[order(runOrder), , , drop = FALSE],
248+
c(2, 3),
249+
function(x) mean(abs(diff(x)))
250+
)
206251
eps.converged <- sum(sweep(smean, 1, eps, "-") < 0)
207252
} else {
208-
smean <- apply(runMixPar[order(runOrder), -1, , drop = FALSE], c(2, 3), function(x) mean(abs(diff(x))))
253+
smean <- apply(
254+
runMixPar[order(runOrder), -1, , drop = FALSE],
255+
c(2, 3),
256+
function(x) mean(abs(diff(x)))
257+
)
209258
eps.converged <- sum(sweep(smean, 1, eps[-1], "-") < 0)
210259
}
211260
if (is.na(eps.converged)) eps.converged <- 0
212261
if (verbose) {
213-
message("Iteration ", iter, ": log-likelihood = ", lliCur, "; Dlli = ", Dlli, "; converged = ", eps.converged, " / ", Npar, "\n", sep = "")
262+
message(
263+
"Iteration ",
264+
iter,
265+
": log-likelihood = ",
266+
lliCur,
267+
"; Dlli = ",
268+
Dlli,
269+
"; converged = ",
270+
eps.converged,
271+
" / ",
272+
Npar,
273+
"\n",
274+
sep = ""
275+
)
214276
}
215277
if (checkTol & Dlli < tol) {
216278
break
@@ -250,7 +312,13 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
250312
## Default would be Nelder-Mead
251313
Lest <- optim(theta, bmm_ml(c1[i], c2[i]))
252314
if (Lest$convergence != 0 & Lest$value > 1E-4) {
253-
warning("Warning: Component", i, "in iteration", iter, "had convergence problems!")
315+
warning(
316+
"Warning: Component",
317+
i,
318+
"in iteration",
319+
iter,
320+
"had convergence problems!"
321+
)
254322
}
255323
if (constrain_gt1) {
256324
mixEst[2:3, i] <- 1 + pmax(exp(Lest$par), c(1E-8, 1E-8))
@@ -297,6 +365,11 @@ EM_bmm_ab <- function(x, Nc, mix_init, Ninit = 50, verbose = FALSE, Niter.max =
297365

298366
#' @export
299367
print.EMbmm <- function(x, ...) {
300-
cat("EM for Beta Mixture Model\nLog-Likelihood = ", logLik(x), "\n\n", sep = "")
368+
cat(
369+
"EM for Beta Mixture Model\nLog-Likelihood = ",
370+
logLik(x),
371+
"\n\n",
372+
sep = ""
373+
)
301374
NextMethod()
302375
}

0 commit comments

Comments
 (0)