diff --git a/DESCRIPTION b/DESCRIPTION index 368900a..3173734 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: BoolTraineR Type: Package Title: Tools For Training and Analysing Asynchronous Boolean Models -Version: 1.1.1 +Version: 1.1.2 Date: 2015-10-22 Author: Chee Yee Lim Maintainer: Chee Yee Lim @@ -22,6 +22,7 @@ LinkingTo: Rcpp License: GPL-3 LazyData: true Suggests: + bnlearn (>= 3.8.1), knitr, rmarkdown VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index e2ec62b..6495ba8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,8 +9,6 @@ export(calc_roc) export(compress_bmodel) export(decompress_bmodel) export(df_to_bm) -export(gen_randata) -export(gen_randata_bn) export(gen_two_rmodel) export(gen_two_rmodel_dag) export(get_encodings) diff --git a/R/data_desc.R b/R/data_desc.R index 2fbbb5c..397251b 100644 --- a/R/data_desc.R +++ b/R/data_desc.R @@ -96,15 +96,41 @@ NULL #' @usage data(wilson_raw_rnaseq) NULL -#' @title Example Boolean Models used in the vignette +#' @title Example Boolean Model used in the vignette #' #' @description -#' 3 Boolean models used in the examples of the vignette. +#' A Boolean model used in the examples of the vignette. #' #' @format #' Each Boolean model is a BoolModel object. #' #' @docType data -#' @name example_models +#' @name emodel1 #' @usage data(example_models) -NULL \ No newline at end of file +NULL + +#' @title Example Boolean Model used in the vignette +#' +#' @description +#' A Boolean model used in the examples of the vignette. +#' +#' @format +#' Each Boolean model is a BoolModel object. +#' +#' @docType data +#' @name emodel2 +#' @usage data(example_models) +NULL + +#' @title Example Boolean Model used in the vignette +#' +#' @description +#' A Boolean model used in the examples of the vignette. +#' +#' @format +#' Each Boolean model is a BoolModel object. +#' +#' @docType data +#' @name emodel3 +#' @usage data(example_models) +NULL diff --git a/R/initialisation.R b/R/initialisation.R index 56ac7e5..e3704af 100644 --- a/R/initialisation.R +++ b/R/initialisation.R @@ -12,8 +12,6 @@ #' @export initialise_raw_data = function(x, data_type='qpcr', uni_thre=0.2, scale=T) { - require(diptest) - #(1) Convert negative to positive values. if(min(x)<0) { @@ -53,7 +51,7 @@ initialise_raw_data = function(x, data_type='qpcr', uni_thre=0.2, scale=T) for(i in 1:ncol(x)) { #Perform unimodality test for each gene. - uni_test = dip.test(x[,i])$p.value + uni_test = diptest::dip.test(x[,i])$p.value if(uni_test > uni_thre) { diff --git a/R/methods.R b/R/methods.R index 5a132a1..ffef26e 100644 --- a/R/methods.R +++ b/R/methods.R @@ -66,6 +66,7 @@ writeBM = function(bmodel, file, gene.names=F, rownames=F) #' #' @description #' This method plots the network underlying Boolean models by using igraph for quick visualisation. +#' Require igraph. #' #' @param bmodel S4 BoolModel object. #' @param makePlot logical. Whether to make plot or just return the object. Default to T. @@ -74,29 +75,27 @@ writeBM = function(bmodel, file, gene.names=F, rownames=F) #' @export plotBM = function(bmodel, makePlot=T, ...) { - require(igraph) - #Convert to amat. am = bm_to_amat(bmodel) #Convert into a graph. - g = graph.adjacency(am, mode='directed', weighted=T) + g = igraph::graph.adjacency(am, mode='directed', weighted=T) #Setup edge colour for plotting. #Activation = black, inhibition = red - E(g)$color = sapply(E(g)$weight, function(x) ifelse(x==1, 'black', 'red')) + igraph::E(g)$color = sapply(igraph::E(g)$weight, function(x) ifelse(x==1, 'black', 'red')) #Setup other colours. - V(g)$frame.color = "white" - V(g)$color = rgb(255, 165, 0, 200, maxColorValue = 255) + igraph::V(g)$frame.color = "white" + igraph::V(g)$color = rgb(255, 165, 0, 200, maxColorValue = 255) #Setup vertex font size. - V(g)$label.cex = 1.5 + igraph::V(g)$label.cex = 1.5 if(makePlot) { #Make the plot. - plot(g, layout=layout_in_circle, ...) + igraph::plot.igraph(g, layout=igraph::layout_in_circle, ...) } invisible(g) @@ -265,7 +264,7 @@ bm_to_df = function(bmodel) #' This method converts a data frame into a BoolModel object. #' Note that the model should only has 1 NOT operator. More than 1 is STRICTLY NOT allowed. #' -#' @param df data frame with 2 columns, targets and factors +#' @param in_df data frame with 2 columns, targets and factors #' #' @export df_to_bm = function(in_df) diff --git a/R/rand_model.R b/R/rand_model.R index db07224..dd2ac8c 100644 --- a/R/rand_model.R +++ b/R/rand_model.R @@ -152,8 +152,6 @@ gen_singlerule = function(x, np, tar_ind, and_bool, self_loop=F) #' The number of terms in a function for a gene is modelled by power-law distribution. gen_one_rmodel = function(var, mvar=length(var), and_bool, self_loop=F) { - require(poweRlaw) - if(mvar > length(var)) { mvar=length(var) @@ -172,140 +170,6 @@ gen_one_rmodel = function(var, mvar=length(var), and_bool, self_loop=F) return(bmodel) } -#' @title Generate sets of random data -#' -#' @description -#' This function generates specified sets of random data, which include initial states, two Boolean models (starting and destination), and continuous+discrete data of the destination model. -#' -#' @param n integer. Number of sets of random data required. -#' @param steps integer. Specify the number of steps between the two Boolean models. If steps=0, give completely random starting model. -#' @param num_genes integer. Number of genes in the Boolean models. -#' @param max_varperrule integer. Maximum number of terms per rule (combining both act and inh rule). Note that this number must not be smaller than number of variables. Default to 6. -#' @param and_bool logical. Indicate whether to consider AND terms. -#' -#' @export -gen_randata = function(n, steps, num_genes, max_varperrule, and_bool) -{ - var = paste('v', seq(1, num_genes), 's', sep='') - - output = list() - for(i in 1:n) - { - istate = rbinom(length(var), 1, 0.5) - #Getting a random initial state. - while(mean(istate) > 0.9 | mean(istate) < 0.1) #do not want initial state that is too homogenous. - { - istate = rbinom(length(var), 1, 0.5) - } - istate = data.frame(matrix(istate, nrow=1)) - colnames(istate) = var - istate = initialise_data(istate) - - #Setting the starting and ending models. - bmodel_pair = gen_two_rmodel(var, steps, max_varperrule, and_bool) - bmodel_start = bmodel_pair[[1]] - bmodel_end = bmodel_pair[[2]] - - #Getting the simulated data of bmodel_end. - ddata = simulate_model(bmodel_end, istate) - - #Getting parameters from real data. - #real_param = param_bimodal(wilson_raw_data, data_type='qpcr') #only need to run once. - data(real_param) - - #Converting binary values to continuous values. - cdata = bin_to_real(ddata, real_param) - - stopifnot(dim(ddata)==dim(cdata)) - rownames(cdata) = rownames(ddata) - colnames(cdata) = colnames(ddata) - - out_entry = list(istate=istate, bmodel_start=bmodel_start, bmodel_end=bmodel_end, ddata=ddata, cdata=cdata) - - output = c(output, list(out_entry)) - } - - return(output) -} - -#' @title Generate sets of random data -#' -#' @description -#' (Requires bnlearn) This function generates specified sets of random data, which include initial states, two Boolean models (starting and destination), and continuous+discrete data of the destination model. -#' -#' @param n integer. Number of sets of random data required. -#' @param steps integer. Specify the number of steps between the two Boolean models. If steps=0, give completely random starting model. -#' @param num_genes integer. Number of genes in the Boolean models. -#' @param max_varperrule integer. Maximum number of terms per rule (combining both act and inh rule). Note that this number must not be smaller than number of variables. Default to 6. -#' -#' @export -gen_randata_bn = function(n, steps, num_genes, max_varperrule) -{ - if (!requireNamespace("bnlearn", quietly = TRUE)) { - stop("Package bnlearn needed for this function to work. Please install it.", - call. = FALSE) - } - require('bnlearn') - - var = paste('v', seq(1, num_genes), 's', sep='') - - output = list() - for(i in 1:n) - { - istate = rbinom(length(var), 1, 0.5) - #Getting a random initial state. - while(mean(istate) > 0.9 | mean(istate) < 0.1) #do not want initial state that is too homogenous. - { - istate = rbinom(length(var), 1, 0.5) - } - istate = data.frame(matrix(istate, nrow=1)) - colnames(istate) = var - istate = initialise_data(istate) - - # #Generate random binary values. - # bn_data = matrix(replicate(num_genes * 100, round(runif(1))), ncol=num_genes) - # - # #Getting parameters from real data. - # #real_param = param_bimodal(wilson_raw_data, data_type='qpcr') #only need to run once. - # data(real_param) - # - # #Converting binary values to continuous values. - # bn_data = data.frame(bin_to_real(bn_data, real_param)) - # colnames(bn_data) = var - - #Setting the starting and ending models. - bn_model_pair = gen_two_rmodel_dag(var, steps, max_varperrule) - bn_model_start = bn_model_pair[[1]] - bn_model_end = bn_model_pair[[2]] - - #Converting the starting and ending models from bn objects to BoolModel objects. - bmodel_start = amat_to_bm(amat(bn_model_start)) - bmodel_end = amat_to_bm(amat(bn_model_end)) - - #Getting the simulated data of bmodel_end. - ddata = simulate_model(bmodel_end, istate) - - #Getting parameters from real data. - #real_param = param_bimodal(wilson_raw_data, data_type='qpcr') #only need to run once. - data(real_param) - - #Converting binary values to continuous values. - cdata = bin_to_real(ddata, real_param) - - stopifnot(dim(ddata)==dim(cdata)) - rownames(cdata) = rownames(ddata) - colnames(cdata) = colnames(ddata) - - out_entry = list(istate=istate, bmodel_start=bmodel_start, bmodel_end=bmodel_end, - ddata=ddata, cdata=cdata, - bn_model_start=bn_model_start, bn_model_end=bn_model_end) - - output = c(output, list(out_entry)) - } - - return(output) -} - #' @title Generate two random DAG Boolean models with a specified number of steps apart #' #' @description @@ -321,107 +185,110 @@ gen_randata_bn = function(n, steps, num_genes, max_varperrule) #' @export gen_two_rmodel_dag = function(var, steps, mvar=length(var), in_amat=NULL, acyclic=T) { - require(bnlearn) - - if(steps==0) - { - start_model = random.graph(var, method = "melancon", max.degree=mvar) - end_model = random.graph(var, method = "melancon", max.degree=mvar) + if(!requireNamespace('bnlearn', quietly = TRUE)) { + stop('Requires bnlearn package to run this function.') } else { - if(is.null(in_amat)) + if(steps==0) { - #(3) Get first model. - start_model = random.graph(var, method = "melancon", max.degree=mvar) + start_model = bnlearn::random.graph(var, method = "melancon", max.degree=mvar) + end_model = bnlearn::random.graph(var, method = "melancon", max.degree=mvar) } else { - start_model = empty.graph(var) - if(acyclic) + if(is.null(in_amat)) { - amat(start_model) = in_amat + #(3) Get first model. + start_model = bnlearn::random.graph(var, method = "melancon", max.degree=mvar) } else { - amat(start_model, ignore.cycles=T) = in_amat + start_model = bnlearn::empty.graph(var) + if(acyclic) + { + bnlearn::amat(start_model) = in_amat + } else + { + bnlearn::amat(start_model, ignore.cycles=T) = in_amat + } } - } - - cur_ite = 1 - max_ite = 100 - out_break = F - while(cur_ite < max_ite & !out_break) - { - #(4) Get second model of a specified number of steps away. - end_model = start_model - memory_ind = c() - #memory_ind = apply(which(t(amat(end_model))==1, arr.ind = T), 1, function(x) paste(x, collapse=',')) #no undirected arcs. - #memory_ind = c(memory_ind, paste(1:nrow(tmp), 1:ncol(tmp), sep=',')) #no self_loops. - #start_time = proc.time() - while(TRUE) + + cur_ite = 1 + max_ite = 100 + out_break = F + while(cur_ite < max_ite & !out_break) { - tryCatch({ - #used_time = proc.time() - start_time - #used_time = as.numeric(used_time)[3] - - tmp_graph = empty.graph(var) - tmp = amat(end_model) - - x_ind = sample(1:nrow(tmp),1) - y_ind = sample(1:ncol(tmp),1) - - while(paste(x_ind, y_ind, collapse=',') %in% memory_ind) - { + #(4) Get second model of a specified number of steps away. + end_model = start_model + memory_ind = c() + #memory_ind = apply(which(t(amat(end_model))==1, arr.ind = T), 1, function(x) paste(x, collapse=',')) #no undirected arcs. + #memory_ind = c(memory_ind, paste(1:nrow(tmp), 1:ncol(tmp), sep=',')) #no self_loops. + #start_time = proc.time() + while(TRUE) + { + tryCatch({ + #used_time = proc.time() - start_time + #used_time = as.numeric(used_time)[3] + + tmp_graph = bnlearn::empty.graph(var) + tmp = bnlearn::amat(end_model) + x_ind = sample(1:nrow(tmp),1) y_ind = sample(1:ncol(tmp),1) - } - - memory_ind = c(memory_ind, paste(x_ind, y_ind, collapse=',')) - if(length(memory_ind) == nrow(tmp)*ncol(tmp)) #break loop, get a new starting model and try again. - { - #cat(sprintf('For step %s, no other possible model exists.', steps)) - break - } - - #Change one step at a time. - if(tmp[x_ind,y_ind]==0) - { - tmp[x_ind,y_ind] = 1 - } else - { - tmp[x_ind,y_ind] = 0 - } - - if(acyclic) - { - amat(tmp_graph) = tmp - } else - { - amat(tmp_graph, ignore.cycles=T) = tmp - } - - end_model = tmp_graph - - if(sum(abs(amat(start_model)-amat(tmp_graph))) == steps) - { - if(nrow(undirected.arcs(tmp_graph))==0) #cannot have undirected arcs in the models. + + while(paste(x_ind, y_ind, collapse=',') %in% memory_ind) + { + x_ind = sample(1:nrow(tmp),1) + y_ind = sample(1:ncol(tmp),1) + } + + memory_ind = c(memory_ind, paste(x_ind, y_ind, collapse=',')) + if(length(memory_ind) == nrow(tmp)*ncol(tmp)) #break loop, get a new starting model and try again. { - out_break = T + #cat(sprintf('For step %s, no other possible model exists.', steps)) break } - } - }, error=function(e){}, - finally={}) + + #Change one step at a time. + if(tmp[x_ind,y_ind]==0) + { + tmp[x_ind,y_ind] = 1 + } else + { + tmp[x_ind,y_ind] = 0 + } + + if(acyclic) + { + bnlearn::amat(tmp_graph) = tmp + } else + { + bnlearn::amat(tmp_graph, ignore.cycles=T) = tmp + } + + end_model = tmp_graph + + if(sum(abs(bnlearn::amat(start_model)-bnlearn::amat(tmp_graph))) == steps) + { + if(nrow(bnlearn::undirected.arcs(tmp_graph))==0) #cannot have undirected arcs in the models. + { + out_break = T + break + } + } + }, error=function(e){}, + finally={}) + } + + cur_ite = cur_ite + 1 } - cur_ite = cur_ite + 1 + if(cur_ite == max_ite) + { + stop(sprintf('For step %s, no other possible model exists.', steps)) + } } - if(cur_ite == max_ite) - { - stop(sprintf('For step %s, no other possible model exists.', steps)) - } + return(list(start_model, end_model)) } - - return(list(start_model, end_model)) } #' @title Generate two random Boolean models with a specified number of steps apart diff --git a/R/score_calculation.R b/R/score_calculation.R index 5501305..41689c2 100644 --- a/R/score_calculation.R +++ b/R/score_calculation.R @@ -62,7 +62,7 @@ m_score = function(x, bmodel, max_varperrule, detail=F) #' #' @param bmodel S4 BoolModel object. Model to be evaluated. #' @param istate data frame. Must have only 1 row, which represents 1 initial state. -#' @param data matrix. Represents the expression data df. +#' @param fcdata matrix. Represents the expression data df. #' @param overlap_gene character vector. Specify which genes are present in both model and data inputs. #' @param max_varperrule integer. Maximum number of terms per rule (combining both act and inh rule). Note that this number must not be smaller than number of variables. Default to 6. #' @param detail logical. Whether to give more details in score calculation. Default to FALSE. diff --git a/R/search.R b/R/search.R index 4812212..cde2ccf 100644 --- a/R/search.R +++ b/R/search.R @@ -250,7 +250,10 @@ model_train = function(edata, bmodel=NULL, istate=NULL, max_varperrule=6, and_bo } vcat('Stage 1: Exploring neighbouring models.\n', verbose) - mod_model = sample(unlist(minmod_model(mod_model[[i]], overlap_gene=overlap_gene)), 1) + mod_model = foreach(i=1:length(mod_model)) %dopar% { + c(mod_model[[i]], unlist(minmod_model(mod_model[[i]], overlap_gene=overlap_gene))) + } + mod_model = unlist(mod_model) vcat(sprintf('Total neighbouring models: %s.\n', length(mod_model)), verbose) if(length(mod_model)>1000000) diff --git a/booltrainer.Rproj b/booltrainer.Rproj deleted file mode 100644 index 8ecf4c0..0000000 --- a/booltrainer.Rproj +++ /dev/null @@ -1,18 +0,0 @@ -Version: 1.0 - -RestoreWorkspace: Default -SaveWorkspace: Default -AlwaysSaveHistory: Default - -EnableCodeIndexing: Yes -UseSpacesForTab: Yes -NumSpacesForTab: 2 -Encoding: UTF-8 - -RnwWeave: knitr -LaTeX: pdfLaTeX - -BuildType: Package -PackageUseDevtools: Yes -PackageInstallArgs: --no-multiarch --with-keep.source -PackageRoxygenize: rd,namespace diff --git a/man/calc_mscore.Rd b/man/calc_mscore.Rd index e9ddb87..a1224c5 100644 --- a/man/calc_mscore.Rd +++ b/man/calc_mscore.Rd @@ -11,13 +11,13 @@ calc_mscore(bmodel, istate, fcdata, overlap_gene, max_varperrule, detail = F) \item{istate}{data frame. Must have only 1 row, which represents 1 initial state.} +\item{fcdata}{matrix. Represents the expression data df.} + \item{overlap_gene}{character vector. Specify which genes are present in both model and data inputs.} \item{max_varperrule}{integer. Maximum number of terms per rule (combining both act and inh rule). Note that this number must not be smaller than number of variables. Default to 6.} \item{detail}{logical. Whether to give more details in score calculation. Default to FALSE.} - -\item{data}{matrix. Represents the expression data df.} } \description{ This function calculates a score for a Boolean model wrt to a dataset. diff --git a/man/df_to_bm.Rd b/man/df_to_bm.Rd index 14944bc..04923a2 100644 --- a/man/df_to_bm.Rd +++ b/man/df_to_bm.Rd @@ -7,7 +7,7 @@ df_to_bm(in_df) } \arguments{ -\item{df}{data frame with 2 columns, targets and factors} +\item{in_df}{data frame with 2 columns, targets and factors} } \description{ This method converts a data frame into a BoolModel object. diff --git a/man/example_models.Rd b/man/emodel1.Rd similarity index 58% rename from man/example_models.Rd rename to man/emodel1.Rd index 7355b88..b51d416 100644 --- a/man/example_models.Rd +++ b/man/emodel1.Rd @@ -1,14 +1,14 @@ % Generated by roxygen2 (4.1.1): do not edit by hand % Please edit documentation in R/data_desc.R \docType{data} -\name{example_models} -\alias{example_models} -\title{Example Boolean Models used in the vignette} +\name{emodel1} +\alias{emodel1} +\title{Example Boolean Model used in the vignette} \format{Each Boolean model is a BoolModel object.} \usage{ data(example_models) } \description{ -3 Boolean models used in the examples of the vignette. +A Boolean model used in the examples of the vignette. } diff --git a/man/emodel2.Rd b/man/emodel2.Rd new file mode 100644 index 0000000..7c26d86 --- /dev/null +++ b/man/emodel2.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2 (4.1.1): do not edit by hand +% Please edit documentation in R/data_desc.R +\docType{data} +\name{emodel2} +\alias{emodel2} +\title{Example Boolean Model used in the vignette} +\format{Each Boolean model is a BoolModel object.} +\usage{ +data(example_models) +} +\description{ +A Boolean model used in the examples of the vignette. +} + diff --git a/man/emodel3.Rd b/man/emodel3.Rd new file mode 100644 index 0000000..a68d0ff --- /dev/null +++ b/man/emodel3.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2 (4.1.1): do not edit by hand +% Please edit documentation in R/data_desc.R +\docType{data} +\name{emodel3} +\alias{emodel3} +\title{Example Boolean Model used in the vignette} +\format{Each Boolean model is a BoolModel object.} +\usage{ +data(example_models) +} +\description{ +A Boolean model used in the examples of the vignette. +} + diff --git a/man/gen_randata.Rd b/man/gen_randata.Rd deleted file mode 100644 index cdc0960..0000000 --- a/man/gen_randata.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2 (4.1.1): do not edit by hand -% Please edit documentation in R/rand_model.R -\name{gen_randata} -\alias{gen_randata} -\title{Generate sets of random data} -\usage{ -gen_randata(n, steps, num_genes, max_varperrule, and_bool) -} -\arguments{ -\item{n}{integer. Number of sets of random data required.} - -\item{steps}{integer. Specify the number of steps between the two Boolean models. If steps=0, give completely random starting model.} - -\item{num_genes}{integer. Number of genes in the Boolean models.} - -\item{max_varperrule}{integer. Maximum number of terms per rule (combining both act and inh rule). Note that this number must not be smaller than number of variables. Default to 6.} - -\item{and_bool}{logical. Indicate whether to consider AND terms.} -} -\description{ -This function generates specified sets of random data, which include initial states, two Boolean models (starting and destination), and continuous+discrete data of the destination model. -} - diff --git a/man/gen_randata_bn.Rd b/man/gen_randata_bn.Rd deleted file mode 100644 index d673660..0000000 --- a/man/gen_randata_bn.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2 (4.1.1): do not edit by hand -% Please edit documentation in R/rand_model.R -\name{gen_randata_bn} -\alias{gen_randata_bn} -\title{Generate sets of random data} -\usage{ -gen_randata_bn(n, steps, num_genes, max_varperrule) -} -\arguments{ -\item{n}{integer. Number of sets of random data required.} - -\item{steps}{integer. Specify the number of steps between the two Boolean models. If steps=0, give completely random starting model.} - -\item{num_genes}{integer. Number of genes in the Boolean models.} - -\item{max_varperrule}{integer. Maximum number of terms per rule (combining both act and inh rule). Note that this number must not be smaller than number of variables. Default to 6.} -} -\description{ -(Requires bnlearn) This function generates specified sets of random data, which include initial states, two Boolean models (starting and destination), and continuous+discrete data of the destination model. -} - diff --git a/man/plotBM.Rd b/man/plotBM.Rd index 5028161..8e7d538 100644 --- a/man/plotBM.Rd +++ b/man/plotBM.Rd @@ -15,5 +15,6 @@ plotBM(bmodel, makePlot = T, ...) } \description{ This method plots the network underlying Boolean models by using igraph for quick visualisation. +Require igraph. } diff --git a/vignettes/booltrainer.Rmd b/vignettes/booltrainer.Rmd index 8dfaa71..30bbe4f 100644 --- a/vignettes/booltrainer.Rmd +++ b/vignettes/booltrainer.Rmd @@ -6,17 +6,20 @@ output: rmarkdown::html_vignette: toc: true number_sections: true +vignette: > + %\VignetteIndexEntry{Using BoolTraineR to reconstruct asynchronous Boolean models} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + + ```{r, echo=FALSE} library('BoolTraineR')