Skip to content

Commit

Permalink
version 1.5.1
Browse files Browse the repository at this point in the history
  • Loading branch information
f-rousset authored and cran-robot committed Feb 20, 2021
1 parent 5443608 commit 073041c
Show file tree
Hide file tree
Showing 49 changed files with 1,343 additions and 517 deletions.
14 changes: 7 additions & 7 deletions DESCRIPTION
Expand Up @@ -3,11 +3,11 @@ Type: Package
Title: Inference Using Simulation
Description: Implements functions for simulation-based inference. In particular, implements functions to perform likelihood inference from data summaries whose distributions are simulated (Rousset et al. 2017 <doi:10.1111/1755-0998.12627>).
Encoding: UTF-8
Version: 1.4.1
Date: 2019-08-19
Imports: spaMM (>= 2.4.35), proxy, blackbox (>= 1.0.14), mvtnorm,
Version: 1.5.1
Date: 2021-02-20
Imports: spaMM (>= 3.6.0), proxy, blackbox (>= 1.0.14), mvtnorm,
methods, numDeriv, viridis, pbapply, foreach
Suggests: testthat, ranger
Suggests: testthat, ranger, Rmixmod, crayon
Depends: R (>= 3.3.0)
Authors@R: c(person("François", "Rousset", role = c("aut", "cre", "cph"),
email = "francois.rousset@umontpellier.fr",
Expand All @@ -16,10 +16,10 @@ Maintainer: François Rousset <francois.rousset@umontpellier.fr>
License: CeCILL-2
ByteCompile: true
URL: https://www.R-project.org,
http://kimura.univ-montp2.fr/~rousset/Infusion.htm
https://kimura.univ-montp2.fr/~rousset/Infusion.htm
NeedsCompilation: no
Packaged: 2019-08-19 12:44:56 UTC; Francois.rousset
Packaged: 2021-02-20 14:54:06 UTC; francois.rousset
Author: François Rousset [aut, cre, cph]
(<https://orcid.org/0000-0003-4670-0371>)
Repository: CRAN
Date/Publication: 2019-08-19 13:20:02 UTC
Date/Publication: 2021-02-20 15:20:02 UTC
88 changes: 48 additions & 40 deletions MD5
@@ -1,58 +1,66 @@
db4ee460c3a2f22b952db2c4acdfbcc3 *DESCRIPTION
971b0cac3011722d6f674863349e8bbb *NAMESPACE
f7f10efe45cb4d6409e7351c3f3e8752 *DESCRIPTION
b702190cc1e266caec2325ae5baf943b *NAMESPACE
4e481e4e0a846065f17d6f628feae386 *R/Infusion_internals.R
94586f4bea762be8174df9e323a7fc4b *R/MSL.R
b577bcf81bf1ae1ffdb2921dcae310e3 *R/Rmixmod.R
b4ca1f6ec27c4c0d62381faf6130f57d *R/SLik.R
8cbafca3e57c32c63f8441cd5745bd35 *R/SLikSQuant.R
c266f27e97083770e757df949d2a7ff9 *R/add_simulation.R
00759c383aad4086d108fef57d48624a *R/calc_all_slices.R
f1ea3182bf037f19af378be9018301a5 *R/MSL.R
e91c8c331a9c5fca5c93479b28c3fe6d *R/Rmixmod.R
d52144748bd7ffd6cf2eb0fa1ba524f3 *R/SLik.R
296a79a5db0c96f1f4d30f411adb696c *R/SLikSQuant.R
7dce6358161b6ef89f65e0b1d401f345 *R/add_simulation.R
47db93e402daa056712fe4475fe8ee9b *R/calc_all_slices.R
2852ced0beb27ba924909bfc60d1bcdd *R/check_logLs_input.R
9be59f46ea85ab1e79ba52a72dd2e6d8 *R/confintLR.SLik.R
ab25fd3ca976c927d0d66d1ece1e478d *R/coresWrapper.R
9503a722442df6e033d186cb905a7eea *R/confintLR.SLik.R
52fe74950f83a03975dbb30b2dabd7f1 *R/coresWrapper.R
ad5a270498e6755bf56ab113651783aa *R/extractors.R
ae5893cbe4570a7cad1759cc7789c0ad *R/generate_data.R
1b4601da02a1fda17282220491ef384e *R/infer_logLs.R
93ba578718b7e4bad0d7c2d19ed89913 *R/goodness.R
81296f482cfe6ad0aac2d6b9158521f3 *R/infer_logLs.R
3aa6c2744f7f7d2729afebd1bf29d2c8 *R/infer_surface.R
20712244dde5904874f8f9f645c7ae45 *R/jointDens.R
5c3c312e9b002e71733ceea74cdd2c8c *R/jointDens.R
44c4c5ea1d0f7bf5a3d3ce85a06b9abf *R/keras.R
6809f3b471e27dcfe0a3223fa47b28dc *R/mclust.R
c0d1e8dea83ba662ca71b6ba00f9c52c *R/mclust.R
9643a88e4d07d9057edbcf9661eebdb1 *R/minImIze.R
1500b206fbb1dcb877b7e385b49f552e *R/newParameters.R
43c726cc31e626952e3c8c5589687617 *R/plot.SLik.R
35600e1883f57c2b1c14246386c1bd2b *R/plot.SLik_j.R
1696f734f7cb37f8e35b1930efde751e *R/plotProfiles.R
b38492f54ac1119a9b3ac795dd1203d0 *R/profile.R
7a8955ec1b2a4dc6fdc88c91b6b2659b *R/project.R
07e5be4727ee6b373d3d7e21b4f5d7b7 *R/quantiles.R
a6dc7947965db047f2b06bbb28100b02 *R/undocumentedFns.R
782796dd199cef011d5ae9bdf203b91c *R/newParameters.R
fdfc545b76459207f9bfb641a1cc9e68 *R/plot.SLik.R
a393cc6b5c0cc872100ef05e2c0ebcf6 *R/plot.SLik_j.R
d5b5fdc6b98ab9f39b28b6ec0a963f6e *R/plotProfiles.R
736551e587421c1d03bb70a70520d971 *R/profile.R
28454fd3b1f1b8bdeaee46ae838bfab4 *R/project.R
533b5e557aaaf6e9b9dce6b3a99e54fd *R/quantiles.R
41f581b82fa7247a6c0474ca7c6ba920 *R/safe_constrOptim.R
118f8922d8a7d4a5c2551a2b067e6fa7 *R/undocumentedFns.R
34fddea1d6c7f921532196783a931a65 *data/densb.RData
88964b1928e06bc43a9981502af91c50 *data/densv.RData
fdb5abb3d4e2119b1cd8f06e16eafd1e *data/myrnorm.RData
e1ffc821b36641fb7b17c6bb65a4c643 *inst/CITATION
8ceea7cdb6f9c33e228f86734df55fa2 *inst/NEWS.Rd
e0041773c0c2d38315603ee620136a60 *man/Infusion-internal.Rd
6b7452614030606b1f9f3923d0048812 *inst/NEWS.Rd
fed9e6c7bf207b81adbb59b50282b783 *man/Infusion-internal.Rd
0c7577558ea55f5de6ed55cf266e1425 *man/Infusion.Rd
cd1a1274c5f20b4c8f9147a8b87ba2ac *man/MSL.Rd
439a55d5072c8e422502934747257025 *man/add.simulation.Rd
eb56d06e84da7e679114e34b694ce272 *man/MSL.Rd
3d4ee7bc97e254fcdb24bcbb3992e544 *man/add.simulation.Rd
28df4c638f4caf9bc6f9a0bf175c7c81 *man/confint.SLik.Rd
4eb05cf905ed92f08bd062801513b421 *man/dMixmod.Rd
055cdf883a274b3ef9ef07e90e32a107 *man/dMixmod.Rd
8c3d919177eb0f3983ac3eabe7856464 *man/densv.Rd
a3413ad8c24f7d6bf413a27d2393fbd0 *man/example_raw.Rd
b0b17350b7cb335fba789fd55c131d42 *man/example_reftable.Rd
6b0ece191ff20e51eb96c7f673265c49 *man/example_raw.Rd
3c9dd234364b0ae3432d134f1268d6d5 *man/example_reftable.Rd
18c31f96efa117b8e2cf7ddddf2801e4 *man/extractors.Rd
8fffb74ed9dde9605559f459c641ea3b *man/get_from.Rd
8b282d61f411f1ee801c7f9d0d72a684 *man/goftest.Rd
4dfc80a6b2cfb254dbd14aad0698e14a *man/handling_NAs.Rd
87044eb367194aabd0a6f5c4e5bd704e *man/infer_jointDens.Rd
ceb4ab68b415b7a1d43c11c9ca2ca9e7 *man/infer_logLs.Rd
343c8a5b05b118b985ae4c06e7874f38 *man/infer_jointDens.Rd
f4bc71913b26919b85bfe1bc8878cd47 *man/infer_logLs.Rd
f94d16ce86a5a3978a74b487e65ecefa *man/infer_surface.Rd
ca5af1babe4982be52f8cfa29d72a153 *man/init_grid.Rd
7e196bf5012b1fd547ca8ec71b44da90 *man/magic.binning.Rd
a4e27a2c816e8f90ab2ce9a331671dc4 *man/options.Rd
e068210c20cd3f2efa6d8e76555de6bf *man/plot.SLik.Rd
9a28ededdfe79e826916cd22b51c6ebd *man/plot1Dprof.Rd
d164cc8ff6a078b7558f5af07c5ffb5d *man/profile.SLik.Rd
64b27eab6e55a02277959abab234bdd0 *man/project.Rd
d0bffe2ffffbb264e852e60890ac6919 *man/refine.SLik.Rd
92cc9a9b5e5fbfdc0ded4392028afd8e *man/options.Rd
b3ae0d999b8e683e86e0ff2fa84d4fe0 *man/plot.SLik.Rd
fb60f7192ebc309f4fc9bca2036ab5b3 *man/plot1Dprof.Rd
b48374fbeeae9215f69344612ea267a6 *man/profile.SLik.Rd
756e0bce59cffe143a0b80404b746f52 *man/project.Rd
10e5d78c0b7dcabbb492c695dc63e827 *man/refine.SLik.Rd
b69d077e06bde675d1202e327ef9b8f6 *man/sample_volume.Rd
d6cebc9855a45ca2bb1e2a2fa5239cfb *tests/test-all.R
428869ad1374d693382df2088bf2b9db *tests/testthat/test-3par.R
d19035ada3a28cdc5372fbeb2e452a3a *tests/testthat/test-Infusion.R
aa4cd6f58873fca8eb4dbe7dd7cf770a *tests/testthat/test-reftable.R
8b714ec3e3de11c12ba673bbbe0a5cbe *tests/test-all.R
d13c12a1189e8feb74551b6f35bd9166 *tests/testthat/test-3par.R
820d6f9848aafd9b72abcb984f4b96b1 *tests/testthat/test-Infusion.R
731ba44c2e9c51d59e8bcaab456af507 *tests/testthat/test-MSL_updating.R
2df4144b0bf3ea84f9a7f62693c23430 *tests/testthat/test-localmax.R
093a9eccd763fc4378aef0dc718795b4 *tests/testthat/test-reftable.R
13 changes: 10 additions & 3 deletions NAMESPACE
Expand Up @@ -12,9 +12,9 @@ importFrom("proxy", "dist")
#importFrom("Rmixmod", "mixmodCluster", "mixmodStrategy", "mixmodGaussianModel", "plotCluster")
importFrom("spaMM", "corrHLfit", "MaternCorr", "mapMM", "fitme", "spaMM.colors", "fixef", "filled.mapMM",
"spaMM.filled.contour", "HLCor", "HLfit", "spaMMplot2D", "get_residVar") ## doc'ed fns
importFrom("spaMM", "get_ranPars")
importFrom("spaMM", "makeTicks") ## undoc fns
importFrom("stats", "deviance", "glm", "var", "as.formula", "cov", "dnorm", "fitted", "optim", "pchisq", "pnorm",
importFrom("spaMM", "get_ranPars", "spaMM.getOption")
importFrom("spaMM", "makeTicks", ".safe_opt") ## undoc fns
importFrom("stats", "deviance", "glm", "var", "as.formula", "cov", "dnorm", "fitted", "optim", "pchisq", "pnorm", "quantile",
"predict", "qchisq", "runif", "uniroot", "binomial", "poisson", "constrOptim", "dchisq", "profile", "confint", "rnorm")
importFrom("utils", "packageVersion", "setTxtProgressBar", "txtProgressBar", "packageDescription", "getS3method")
importFrom("viridis", "viridis")
Expand All @@ -35,8 +35,11 @@ S3method(summary, logLs)
S3method(plot, SLikp)
S3method(plot, SLik_j)
S3method(plot,MixmodResults)
S3method(plot, dMixmod)
S3method(print, SLikp)
S3method(summary, SLikp)
S3method(logLik,SLik)
S3method(logLik,SLik_j)
S3method(confint,SLik)
S3method(confint,SLik_j)
S3method(confint,SLikp)
Expand All @@ -57,3 +60,7 @@ S3method(infer_surface,tailp)
S3method(calc.lrthreshold,SLik)
S3method(calc.lrthreshold,SLikp)
S3method(calc.lrthreshold,default)
S3method(get_from, SLik)
S3method(get_from, SLik_j)
S3method(get_from, default)
S3method("[", reftable)
154 changes: 66 additions & 88 deletions R/MSL.R
Expand Up @@ -42,9 +42,9 @@

# creates <slik>$par_RMSEs
.par_RMSEwrapper <- function(object,verbose=interactive()) {
RMSEs <- object$RMSEs
if( (lenRMSEs <- length(RMSEs))>1L) {
CIs <- object$CIobject$CIs
RMSEs <- object$RMSEs$RMSEs
CIs <- object$CIobject$CIs
if (( ! is.null(CIs)) && (lenRMSEs <- length(RMSEs))>1L) {
pars <- names(CIs)
par_RMSEs <- rep(NA,lenRMSEs-1L) ## (over)size as the MSEs have no NAs
par_ests <- rep(NA,lenRMSEs-1L) ## (over)size as the MSEs have no NAs
Expand Down Expand Up @@ -75,63 +75,12 @@
} else return(NULL)
}

.par_wrapper <- function(object,verbose=interactive()) {
CIs <- object$CIobject$CIs
lenCIs <- length(CIs)
pars <- names(CIs)
resu <- rep(NA_real_,NROW(object$CIobject$bounds)) ## (over)size as the MSEs have no NAs
names(resu) <- rownames(object$CIobject$bounds)
map <- c(low=1L,up=2L)
for (nam in rownames(object$CIobject$bounds)) {
stterms <- regmatches(nam, regexpr("\\.", nam), invert = TRUE)[[1]] ## regmatches(<...>) splits at the first '.'
parm <- stterms[2L]
interval <- CIs[[parm]]$interval
th <- interval[map[stterms[1L]]]
resu[nam] <- th
}
if (verbose && length(resu)>0L) {
par_headline <- "*** Interval estimates ***\n"
cat(par_headline)
print(resu)
return(invisible(resu))
} else return(resu)
}

## summary likelihood ratio (with uncertainty measures) extractor. Unfinished, in particular, need to separate residVar an to handle prior.weights
.SLR <- function(object,newdata=NULL,variance="predVar",df=NULL) {
fittedPars <- object$colTypes$fittedPars
if (is.null(newdata)) newdata <- unique(object$logLs[,fittedPars])
locdata <- rbind(MSLE=object$MSL$MSLE, ## name needed for spaMM::calcNewCorrs -> newuniqueGeo
newdata)
if (variance=="respVar") {
logls <- predict(object$fit,newdata=locdata,variances=list(respVar=TRUE,cov=TRUE))
covmat <- attr(logls,"respVar")
# but problem with prior weights
} else {
logls <- predict(object$fit,newdata=locdata,variances=list(linPred=TRUE,dispVar=TRUE,cov=TRUE))
covmat <- attr(logls,"predVar")
}
slr <- object$MSL$maxlogL -logls[]
MSEs <- c(diag(covmat[-1,-1,drop=FALSE])+covmat[1,1]-2*covmat[1,-1])
if ( any(MSEs<0) ) {
message("Inaccurate MSE computation, presumably from nearly-singular covariance matrices.")
MSEs[MSEs<0] <- NA ## quick patch
}
RMSEs <- sqrt(MSEs)
resu <- rbind(LRstat=2*slr[-1],RMSE=RMSEs)
if (!is.null(df)) {
resu <- rbind(resu,p_RMSE=RMSEs*dchisq(resu["LRstat",],df=df))
}
return(resu)
}

#.SLR(slik)

# both SLik and SLikp, with different methods used in -> allCIs -> confint
MSL <- function (object,CIs=TRUE,level=0.95, verbose=interactive(),
eval_RMSEs=TRUE, #inherits(object,"SLik"),
cluster_args=list(),
...) { ##
# Maximization ## revised 13/07/2016
fittedPars <- object$colTypes$fittedPars
if (inherits(object,"SLik")) {
vertices <- object$fit$data[,fittedPars,drop=FALSE]
Expand All @@ -143,33 +92,59 @@ MSL <- function (object,CIs=TRUE,level=0.95, verbose=interactive(),
lower <- object$lower
upper <- object$upper
}
# (a constrOptim woul be even better)
stat.obs <- object$stat.obs
# coeffs <- object$coeffs
# (a constrOptim would be even better)
parscale <- (upper-lower)
if ( is.null(init <- object$optrEDF$par)) { ## ...if inherits(object,"SLik_j")
# SLik object:
if (inherits(object,"SLik_j")) {
pred_data <- object$logLs[,fittedPars, drop=FALSE]
if (is.null(object$thr_dpar)) {
pardensv <- predict(object,newdata = pred_data, which="parvaldens")
object$thr_dpar <- min(max(pardensv)- qchisq(1-(1-level)/2,df=1)/2 , ## __F I X M E__ rethink
quantile(pardensv,probs=1/sqrt(length(pardensv)))
)
#print(object$thr_dpar)
}
predsafe <- predict(object,newdata=pred_data, which="safe")
init <- unlist(pred_data[which.max(predsafe), ])
} else {
init <- unlist(object$obspred[which.max(object$obspred[,attr(object$obspred,"fittedName")]),fittedPars])
init <- init*0.999+ colMeans(vertices)*0.001
}
method <- "L-BFGS-B" ## works also in 1Dand does not ignore the init value (while Brent would)
prev_init <- object$MSL$init_from_prof ## provided by plot1Dprof() -> profil().
## prev_init is not NULL if MSL called by .MSL_update() or by [refine() after a plot], but then object$MSL$MSLE should not be used ;
## in other calls by refine(), the object is being reconstructed from scratch, and then object$MSL$MSLE is NULL too ;
## in neither case the next line is useful
# if (is.null(prev_init)) prev_init <- object$MSL$MSLE
## which="safe" is effective only for SLik_j objects. Otherwise, it is ignored.
if ( (! is.null(prev_init)) &&
predict(object,newdata=prev_init, which="safe") > predict(object,newdata=init, which="safe")) {init <- prev_init}
time1 <- Sys.time()
msl <- optim(init, function(v) {as.numeric(predict(object,newdata=v))},
## as numeric because otherwise in 1D, optim -> minimize -> returns a max
## of same type as predict(object$fit,newdata=v), i.e. matrix...
## FR->FR with spaMM>1.7.12, predict(object,newdata=v)[] should be OK
lower=lower,upper=upper,control=list(fnscale=-1,parscale=parscale),method=method)
msl <- .safe_opt(init, objfn=function(v) { - predict(object,newdata=v, which="safe")},
lower=lower,upper=upper, LowUp=list(), verbose=FALSE)
msl$value <- - msl$objective
msl$par <- msl$solution
optim_time <- round(as.numeric(difftime(Sys.time(), time1, units = "secs")), 1) ## spaMM:::.timerraw(time1)
if (inherits(object,"SLik") && length(fittedPars)>1L) {
if (inherits(object,"SLik") && length(fittedPars)>1L) { # for SLik_j objects, this should not be run
locchull <- resetCHull(vertices, formats=c("constraints"))
if( ! (isPointInCHull(msl$par, constraints=locchull[c("a", "b")]))) { ## if simple optim result not in convex hull
# this block can be tested by test-3par, with mixmodGaussianModel="Gaussian_pk_Lk_Ck"
ui <- -locchull$a
ci <- -locchull$b
objectivefn <- function(v) {as.numeric(predict(object,newdata=v))}
candttes_in_hull <- 0.99*vertices + 0.01*colMeans(vertices)
best_candidate <- unlist(candttes_in_hull[which.max(predict(object,newdata=candttes_in_hull, which="safe")),])
objectivefn <- function(v) { - as.numeric(predict(object,newdata=v, which="safe"))}
objectivefn.grad <- function(x) {grad(func=objectivefn, x=x)} ## no need to specify fixedlist here
msl <- constrOptim(theta=init,f=objectivefn,grad=objectivefn.grad, ui=ui, ci=ci ,
mu=1e-08, ## a low mu appear important
method = "BFGS",control=list(fnscale=-1,parscale=parscale))
if (TRUE || .Infusion.data$options$constrOptim) {
msl <- constrOptim(theta=best_candidate,f=objectivefn,grad=objectivefn.grad, ui=ui, ci=ci ,
mu=1e-08, ## a low mu appear important
method = "BFGS",control=list(parscale=parscale))
msl$value <- - msl$value
} else { ## more or less works, but the result is not as accurate as by constrOptim. Presumably related to the method used, with bound constraints.
msl <- .safe_constrOptim(theta=best_candidate,f=objectivefn,grad=objectivefn.grad, ui=ui, ci=ci ,
lower=lower,upper=upper,
mu=1e-08)
msl$value <- - msl$objective
msl$par <- msl$solution
}
## then we will optimize in the convex hull using constroptim(R). But we need a good starting point
}
}
Expand All @@ -185,46 +160,49 @@ MSL <- function (object,CIs=TRUE,level=0.95, verbose=interactive(),
print(c(msl$par,"tailp"=msl$value))
}
}
object$MSL$MSLE <- msl$par
if (length(lower)==1) names(object$MSL$MSLE) <- names(lower)
object$MSL$maxlogL <- msl$value
if (length(lower)==1) names(msl$par) <- names(lower)
object$MSL <- list2env(list(MSLE=msl$par, maxlogL=msl$value))
if (inherits(object$fit,"HLfit")) object$MSL$predVar <- attr(predict(object,newdata=msl$par,variances=list(linPred=TRUE,dispVar=TRUE)),"predVar")
# CIs
prevmsglength <- 0L
if(CIs) {
locverbose <- (verbose && ! inherits(object$fit,"HLfit")## for HLfit object, printing is later
&& optim_time>3) # guess when it is useful to be verbose from the time to find the maximum
if (locverbose) {
prevmsglength <- .overcat("Computing confidence intervals...\n", 0L)
} else {
prevmsglength <- 0L
}
object$CIobject <- .allCIs(object,verbose=locverbose, level=level) ## may be NULL
} else object$CIobject <- NULL
}
object$CIobject <- list2env(.allCIs(object,verbose=locverbose, level=level)) ## may be NULL
}
# MSEs computation
if (inherits(object$fit,"HLfit")) {
object$RMSEs <- .RMSEwrapper(object,verbose=FALSE)
object$RMSEs <- list2env(list(RMSEs=.RMSEwrapper(object,verbose=FALSE),
warn=NULL))
} else {
if (eval_RMSEs) {
if (verbose) .overcat("Computing RMSEs... (may be slow)\n",prevmsglength)
object$RMSEs <- .RMSEwrapper.SLik_j(object,verbose=FALSE)
} else {
object$pars <- .par_wrapper(object,verbose=FALSE) ## quick patch b/c no RMSEs
object$RMSEs <- list2env(list(RMSEs=.RMSEwrapper.SLik_j(object,cluster_args=cluster_args,verbose=FALSE),
warn=NULL))
}
}
object$par_RMSEs <- .par_RMSEwrapper(object,verbose=FALSE)
# needs $CIobject information and $RMSEs information:
object$par_RMSEs <- list2env(list(par_RMSEs=.par_RMSEwrapper(object,verbose=FALSE)))
if (verbose) {
if ( ! is.null(object$par_RMSEs)) {
if ( ! is.null(object$par_RMSEs$par_RMSEs)) {
.overcat("*** Interval estimates and RMSEs ***\n",prevmsglength)
print(object$par_RMSEs)
print(object$par_RMSEs$par_RMSEs)
} else {
.overcat("*** Interval estimates ***\n",prevmsglength)
print(object$pars)
bounds <- .extract_intervals(object,verbose=FALSE)
if (length(bounds)) {
.overcat("*** Interval estimates ***\n",prevmsglength)
print(bounds)
}
}
}
if (is.null(object$logLs$cumul_iter)) {
object$logLs$cumul_iter <- 1L ## adds a column to the data frame
attr(object$logLs,"n_first_iter") <- nrow(object$logLs)
}
object$`Infusion.version` <- packageVersion("Infusion")
invisible(object)
}

0 comments on commit 073041c

Please sign in to comment.