Skip to content

Commit

Permalink
Merge branch 'develop' into feature/108-implement-sdt-models
Browse files Browse the repository at this point in the history
  • Loading branch information
venpopov authored Feb 28, 2024
2 parents 9bf4fe9 + bcb9d7e commit 82cbf34
Show file tree
Hide file tree
Showing 43 changed files with 1,580 additions and 914 deletions.
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
^tests/internal-.*$
^tests/internal$
^.dev$
^.Rprofile$
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.Rproj.user
.Rhistory
.Rdata
.Rprofile
.httr-oauth
.DS_Store
local/
Expand Down
30 changes: 19 additions & 11 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
Package: bmm
Title: Easy and Accesible Bayesian Measurement Models using 'brms'
Version: 0.3.4.9000
Version: 0.4.0.9000
Authors@R: c(
person("Vencislav", "Popov", , "[email protected]", role = c("aut", "cre", "cph")),
person("Gidon", "Frischkorn", , "[email protected]", role = c("aut", "cph")))
Description: Wrapper functions and custom distributions that make it easier to estimate common
measurement models for using the 'brms' package. Currently implemented
are the two-parameter mixture model by Zhang and Luck (2008),the three-
parameter mixture model by Bays et al (2009), and the Interference Measurement Model
(Oberauer et al., 2017).
License: GPL (>= 3)
person("Gidon", "Frischkorn", , "[email protected]", role = c("aut", "cph")),
person("Paul", "Bürkner", , "[email protected]", role = c("cph"),
comment = "Creator of brms, a package for Bayesian regression model that this package builds upon."))
Description: Implementations of computational measurement models using the 'brms' package.
Currently implemented models can be listed using supported_models(). The package also
provides functions to extract model informations such as priors, or the generated
STAN code. For all implemented models there are also density and random generation
functions to easily explore model predictions and evaluate parameter recovery.
Finally, helper functions aid in pre- and post-processing data for efficient communication
of results.
License: GPL-2
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.1
Expand All @@ -26,10 +30,10 @@ Suggests:
ggthemes,
cowplot,
stringr,
remotes
remotes,
waldo
Config/testthat/edition: 3
Imports:
brms,
magrittr,
parallel,
dplyr,
Expand All @@ -42,7 +46,11 @@ Imports:
evd
URL: https://github.com/venpopov/bmm, https://venpopov.github.io/bmm/
BugReports: https://github.com/venpopov/bmm/issues
Additional_repositories:
https://mc-stan.org/r-packages/
https://paul-buerkner.github.io/brms/
VignetteBuilder: knitr
Depends:
R (>= 2.10)
R (>= 2.10),
brms
LazyData: true
884 changes: 314 additions & 570 deletions LICENSE.md

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ S3method(check_data,vwm)
S3method(check_formula,bmmmodel)
S3method(check_formula,default)
S3method(check_formula,nontargets)
S3method(check_model,bmmmodel)
S3method(check_model,default)
S3method(configure_model,IMMabc)
S3method(configure_model,IMMbsc)
S3method(configure_model,IMMfull)
Expand All @@ -25,12 +27,18 @@ S3method(configure_model,mixture3p)
S3method(configure_model,sdmSimple)
S3method(fit_info,brmsfit)
S3method(fit_info,brmsfit_list)
S3method(identical,bmmformula)
S3method(identical,brmsformula)
S3method(identical,default)
S3method(identical,formula)
S3method(model_info,bmmmodel)
S3method(postprocess_brm,SDT)
S3method(postprocess_brm,bmmmodel)
S3method(postprocess_brm,default)
S3method(postprocess_brm,sdmSimple)
S3method(postprocess_brm,vwm)
S3method(print,message)
S3method(revert_postprocess_brm,default)
S3method(revert_postprocess_brm,sdmSimple)
S3method(rhs_vars,bmmformula)
S3method(rhs_vars,formula)
S3method(update,bmmfit)
Expand All @@ -42,6 +50,7 @@ export(SDT)
export(aggregate_data)
export(bmf)
export(bmf2bf)
export(bmm_options)
export(bmmformula)
export(c_bessel2sqrtexp)
export(c_sqrtexp2bessel)
Expand Down Expand Up @@ -78,10 +87,10 @@ export(qsdm)
export(rIMM)
export(rSDT)
export(rad2deg)
export(revert_postprocess_brm)
export(rmixture2p)
export(rmixture3p)
export(rsdm)
export(save_pars)
export(sdmSimple)
export(set_default_prior)
export(softmax)
Expand Down
14 changes: 12 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# bmm 0.3.0+
# bmm 0.4.0+

# bmm 0.4.0

### New features

Expand All @@ -7,9 +9,17 @@
* add postprocessing methods for sdmSimple to allow for pp_check(), conditional_effects and bridgesampling usage with the model (#30)
* add informed default priors for all models. You can always use the `get_model_prior()` function to see the default priors for a model
* add a new function `set_default_prior` for developers, which allows them to more easily set default priors on new models regardless of the user-specified formula
* you can now specify variables for models via regular expressions rather than character vectors (#102)
* you can now view and set all bmm global options via `bmm_options()`. See `?bmm_options` for more information
* add a startup message upon loading the package

### Bug fixes
* fix a bug in the mixture3p and IMM models which caused an error when intercept was not supressed and set size was used as predictor
* update() now works properly with bmmfit objects (#95)
* fix a bug in the sort_data check which caused an error when using grouped covariance structure in random effects across different parameters

### Other changes
* `brms` is now loaded automatically when loading `bmm` with `library(bmm)`



Expand All @@ -25,7 +35,7 @@
* there is now an option `bmm.silent` that allows to suppress messages
* the baseline activation `b` was removed from the `IMM` models, as this is internally fixed
to zero for scaling and as of now cannot be predicted by independent variables because the model would be unidentifiable.
* the arguments used to fit the bmm model are now accessible in the `bmmfit` object via the `fit$bmm_fit_args` list.
* the arguments used to fit the bmm model are now accessible in the `bmmfit` object via the `fit$bmm$fit_args` list.
* add class('bmmfit') to the object returned from fit_model() allowing for more flexible postprocessing of the underlying `brmsfit` object. The object is now of class('bmmfit', 'brmsfit')
* changes to column names of datasets `ZhangLuck_2008` and `OberauerLin_2017` to make them more consistent

Expand Down
112 changes: 93 additions & 19 deletions R/bmm_model_IMM.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
# MODELS ####
#############################################################################!

.model_IMMabc <- function(resp_err, nt_features, setsize, ...) {
.model_IMMabc <- function(resp_err = NULL, nt_features = NULL, setsize = NULL,
regex = FALSE, ...) {
out <- list(
resp_vars = nlist(resp_err),
other_vars = nlist(nt_features, setsize),
Expand All @@ -29,11 +30,14 @@
)),
void_mu = FALSE
)
attr(out, "regex") <- regex
attr(out, "regex_vars") <- c('nt_features') # variables that can be specified via regular expression
class(out) <- c("bmmmodel", "vwm","nontargets","IMMabc")
out
}

.model_IMMbsc <- function(resp_err, nt_features, nt_distances, setsize, ...) {
.model_IMMbsc <- function(resp_err = NULL, nt_features = NULL, nt_distances = NULL,
setsize = NULL, regex = FALSE, ...) {
out <- list(
resp_vars = nlist(resp_err),
other_vars = nlist(nt_features, nt_distances, setsize),
Expand All @@ -60,11 +64,15 @@
)),
void_mu = FALSE
)
attr(out, "regex") <- regex
# variables that can be specified via regular expression
attr(out, "regex_vars") <- c('nt_features', 'nt_distances')
class(out) <- c("bmmmodel","vwm","nontargets","IMMspatial","IMMbsc")
out
}

.model_IMMfull <- function(resp_err, nt_features, nt_distances, setsize, ...) {
.model_IMMfull <- function(resp_err = NULL, nt_features = NULL, nt_distances = NULL,
setsize = NULL, regex = FALSE, ...) {
out <- list(
resp_vars = nlist(resp_err),
other_vars = nlist(nt_features, nt_distances, setsize),
Expand Down Expand Up @@ -92,54 +100,120 @@
)),
void_mu = FALSE
)
attr(out, "regex") <- regex
# variables that can be specified via regular expression
attr(out, "regex_vars") <- c('nt_features', 'nt_distances')
class(out) <- c("bmmmodel","vwm","nontargets","IMMspatial","IMMfull")
out
}

# user facing alias

#' @title `r .model_IMMfull(NA, NA, NA, NA)$info$name`
#' @title `r .model_IMMfull()$info$name`
#' @name IMM
#' @details `r model_info(IMMfull(NA, NA, NA, NA), components =c('domain', 'task', 'name', 'citation'))`
#' @details `r model_info(.model_IMMfull(), components =c('domain', 'task', 'name', 'citation'))`
#' #### Version: `IMMfull`
#' `r model_info(IMMfull(NA, NA, NA, NA), components =c('requirements', 'parameters', 'fixed_parameters'))`
#' `r model_info(.model_IMMfull(), components =c('requirements', 'parameters', 'fixed_parameters'))`
#' #### Version: `IMMbsc`
#' `r model_info(IMMbsc(NA, NA, NA, NA), components =c('requirements', 'parameters', 'fixed_parameters'))`
#' `r model_info(.model_IMMbsc(), components =c('requirements', 'parameters', 'fixed_parameters'))`
#' #### Version: `IMMabc`
#' `r model_info(IMMabc(NA, NA, NA), components =c('requirements', 'parameters', 'fixed_parameters'))`
#' `r model_info(.model_IMMabc(), components =c('requirements', 'parameters', 'fixed_parameters'))`
#'
#' Additionally, all IMM models have an internal parameter that is fixed to 0 to
#' allow the model to be identifiable. This parameter is not estimated and is not
#' included in the model formula. The parameter is:
#'
#' - b = "Background activation (internally fixed to 0)"
#'
#' @param resp_err The name of the variable in the provided dataset containing the
#' response error. The response Error should code the response relative to the to-be-recalled
#' target in radians. You can transform the response error in degrees to radian using the `deg2rad` function.
#' @param nt_features A character vector with the names of the non-target variables.
#' The non_target variables should be in radians and be centered relative to the
#' target.
#' @param nt_distances A vector of names of the columns containing the distances of
#' non-target items to the target item. Only necessary for the `IMMbsc` and `IMMfull` models
#' @param resp_err The name of the variable in the provided dataset containing
#' the response error. The response Error should code the response relative to
#' the to-be-recalled target in radians. You can transform the response error
#' in degrees to radian using the `deg2rad` function.
#' @param nt_features A character vector with the names of the non-target
#' variables. The non_target variables should be in radians and be centered
#' relative to the target. Alternatively, if regex=TRUE, a regular
#' expression can be used to match the non-target feature columns in the
#' dataset.
#' @param nt_distances A vector of names of the columns containing the distances
#' of non-target items to the target item. Alternatively, if regex=TRUE, a regular
#' expression can be used to match the non-target distances columns in the
#' dataset. Only necessary for the `IMMbsc` and `IMMfull` models.
#' @param setsize Name of the column containing the set size variable (if
#' setsize varies) or a numeric value for the setsize, if the setsize is
#' fixed.
#' @param regex Logical. If TRUE, the `nt_features` and `nt_distances` arguments
#' are interpreted as a regular expression to match the non-target feature
#' columns in the dataset.
#' @param ... used internally for testing, ignore it
#' @return An object of class `bmmmodel`
#' @keywords bmmmodel
#' @examples
#' \dontrun{
#' # load data
#' data <- OberauerLin_2017
#'
#' # define formula
#' ff <- bmmformula(
#' kappa ~ 0 + set_size,
#' c ~ 0 + set_size,
#' a ~ 0 + set_size,
#' s ~ 0 + set_size
#' )
#'
#' # specify the full IMM model with explicit column names for non-target features and distances
#' model1 <- IMMfull(resp_err = "dev_rad",
#' nt_features = paste0('col_nt',1:7),
#' nt_distances = paste0('dist_nt',1:7),
#' setsize = 'set_size')
#'
#' # fit the model
#' fit <- fit_model(formula = ff,
#' data = data,
#' model = model1,
#' parallel = T,
#' iter = 500,
#' backend = 'cmdstanr')
#'
#' # alternatively specify the IMM model with a regular expression to match non-target features
#' # this is equivalent to the previous call, but more concise
#' model2 <- IMMfull(resp_err = "dev_rad",
#' nt_features = 'col_nt',
#' nt_distances = 'dist_nt',
#' setsize = 'set_size',
#' regex = TRUE)
#'
#' # fit the model
#' fit <- fit_model(formula = ff,
#' data = data,
#' model = model2,
#' parallel=T,
#' iter = 500,
#' backend='cmdstanr')
#'}
#' @export
IMMfull <- .model_IMMfull
IMMfull <- function(resp_err, nt_features, nt_distances, setsize, regex = FALSE, ...) {
stop_missing_args()
.model_IMMfull(resp_err = resp_err, nt_features = nt_features,
nt_distances = nt_distances, setsize = setsize, regex = regex, ...)
}

#' @rdname IMM
#' @keywords bmmmodel
#' @export
IMMbsc <- .model_IMMbsc
IMMbsc <- function(resp_err, nt_features, nt_distances, setsize, regex = FALSE, ...) {
stop_missing_args()
.model_IMMbsc(resp_err = resp_err, nt_features = nt_features,
nt_distances = nt_distances, setsize = setsize, regex = regex, ...)
}

#' @rdname IMM
#' @keywords bmmmodel
#' @export
IMMabc <- .model_IMMabc
IMMabc <- function(resp_err, nt_features, setsize, regex = FALSE, ...) {
stop_missing_args()
.model_IMMabc(resp_err = resp_err, nt_features = nt_features,
setsize = setsize, regex = regex,...)
}

#############################################################################!
# CHECK_DATA S3 methods ####
Expand Down
11 changes: 7 additions & 4 deletions R/bmm_model_mixture2p.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# MODELS ####
#############################################################################!

.model_mixture2p <- function(resp_err, ...) {
.model_mixture2p <- function(resp_err = NULL, ...) {
out <- list(
resp_vars = nlist(resp_err),
other_vars = nlist(),
Expand Down Expand Up @@ -31,8 +31,8 @@
}

# user facing alias
#' @title `r .model_mixture2p(NA)$info$name`
#' @details `r model_info(mixture2p(NA))`
#' @title `r .model_mixture2p()$info$name`
#' @details `r model_info(.model_mixture2p())`
#' @param resp_err The name of the variable in the provided dataset containing
#' the response error. The response Error should code the response relative to
#' the to-be-recalled target in radians. You can transform the response error
Expand Down Expand Up @@ -60,7 +60,10 @@
#' backend='cmdstanr')
#' }
#' @export
mixture2p <- .model_mixture2p
mixture2p <- function(resp_err, ...) {
stop_missing_args()
.model_mixture2p(resp_err, ...)
}

#############################################################################!
# CONFIGURE_MODEL METHODS ####
Expand Down
Loading

0 comments on commit 82cbf34

Please sign in to comment.