.are.colors <- function(cols) {
#TODO use this to deduplicate code in internals
## check cols, if all valid colors, return cols, else, throw error
all.cols <- sapply(cols, function(X) {
tryCatch(is.matrix(col2rgb(X)),
error = function(e) FALSE)
})
if (any(!all.cols))
{
stop('invalid colour character/vector.\n', call. = FALSE)
}
cols
}
.get.colors <- function(col, n_col=0) {
#TODO use this to deduplicate code in internals
## ensure 'col' is valid color(s) and of length 'col.length', repeat it if
## necessary
## return a vector of lenfth col.length, or throw condition
if (is.null(col))
{
col <- 'black'
}
col <- .are.colors(col)
if (length(col) == 1)
{
col <- rep(col, n_col)
}
else if (length(col == n_col))
{
col <- col
}
else
{
stop("'col' must be character of length 1 or ", paste0(n_col))
}
col
}
.get.character.vector <- function(arg, vec) {
#TODO use this to deduplicate code in internals
## if 'arg' is TRUE, return vec, if FALSE, return NULL, if character, ensure
## it's of the same length as vec
## return a character of the same length as vec
stopifnot(is.character(vec))
fail.msg <- paste0(sQuote(deparse(substitute(arg))),
" must be either logical or a character vector of length ", length(vec))
if (isTRUE(arg))
{
res <- vec
}
else if (isFALSE(arg))
{
res <- NULL
}
else if (is.character(arg))
{
if (length(arg) != length(vec))
{
stop(fail.msg, call. = FALSE)
}
else
{
res <- arg
}
} else
{
res <- tryCatch(as.character(arg))
if (length(res) != length(vec))
{
stop(fail.msg, call. = FALSE)
}
}
res
}
#' @noRd
#' @examples
#' .get.group(group = NULL, object = NULL, n_ind = 10)
#' .get.group(group = letters[1:10], object = NULL, n_ind = 10)
#' .get.group(group = NULL, object = structure(list(Y = 10:19), class='DA'), n_ind = 10)
#' \dontrun{
#' .get.group(group = letters[1:11], object = NULL, n_ind = 10)
#' .get.group(group = NULL, object = structure(list(Y = 10:19), class='DA'), n_ind = 10)
#' }
.get.group <- function(group, object=NULL, n_ind=0) {
#TODO use this to deduplicate code in internals
## check group, if and if it's not NULL return a factor
## if object is of class 'DA', return object$Y which should be factor
out <- group
## if no group given
if (is.null(out))
{
if (is (object, 'DA'))
{
out <- object$Y
if (n_ind != length(out))
{
stop("Unexpected error. Please submit an issue with reproducible example to\n",
"https://github.com/mixOmicsTeam/mixOmics/issues")
}
}
else
{
## for consistency of plot so group is always an aes
out <- factor(rep(1, n_ind))
}
}
## group is factor and does not drop NAs
if (!is.factor(out))
{
out[is.na(out)] <- "missing group (NA)"
out <- as.factor(out)
}
## group length is valid
if (length(out) != n_ind)
{
stop("'group' must be a factor of length ", n_ind)
}
return(out)
}
#'@noRd
#'@examples
#' .get.cols.and.group(n_ind = 3)
#' .get.cols.and.group(col = 'blue', n_ind = 3)
#' .get.cols.and.group(group = c(2,2,1))
#' .get.cols.and.group(col.per.group = c('1'='red', '2'='blue'), group = c(2,2,1))
.get.cols.and.group <- function(
col.per.group=NULL,
group=NULL,
col=NULL,
object=NULL,
n_ind=ifelse(is.null(group), 0, length(group))
) {
#TODO use this to deduplicate code in internals
## check group, if and if it's not NULL return a factor
## if object is of class 'DA', return object$Y which should be factor
## group factor
group <- .get.group(group, object, n_ind)
## create col.per.group
if (is.null(col.per.group))
{
if (nlevels(group) == 1)
{
col.per.group <- ifelse(is.null(col), color.mixo(1), .are.colors(col))
} else if (nlevels(group) < 10)
{
col.per.group <- color.mixo(seq_len(nlevels(group)))
} else if (nlevels(group) >= 10)
{
col.per.group <- color.jet(nlevels(group))
}
names(col.per.group) <- levels(group)
}
## valid col.per.group
if (!all(names(col.per.group) %in% levels(group)))
{
stop("'col.per.group' should be a named vector whose names match group (",
levels(group), ")")
}
## return group and col.per.group
return(list(
group = group,
col.per.group = col.per.group
))
}
.get.ind.colors <- function(group=NULL, col=NULL, col.per.group=NULL, n_ind=0) {
#TODO use this to deduplicate code in internals
## consider all valid combinations and return a vector of colors
## if group != NULL, return a vector whose names are colors and values the
## group levels for ggplot
## ------------- group == NULL
if (is.null(group))
{
col <- .get.colors(col = col, n_col = n_ind)
}
else
{
col.per.group <-
.change_if_null(col.per.group,
color.mixo(seq_len(1+nlevels(group))[-3] ## bc 3rd one is grey
)
)
names(col.per.group) <- levels(group)
if (!all(names(col.per.group) %in% levels(group)))
{
stop("'col.per.group' should be a named vector whose names match group (",
levels(group), ")")
}
col <- group
names(col) <- col.per.group[group]
}
return(col)
}
#' @noRd
#' @examples
#' .get.pch(pch = NULL, pch.levels = NULL)
#' .get.pch(pch = 6, pch.levels = NULL)
#' .get.pch(pch = mtcars$cyl, pch.levels = NULL)
.get.pch <- function(pch = NULL,
pch.levels = NULL,
pch.legend = TRUE,
n_ind = length(pch))
{
## NULL -> 16
if (is.null(pch))
{
pch <- 16
}
if (length(pch) == 1)
{
names(pch.levels) <- pch.levels <- pch
pch <- rep(pch, n_ind)
}
pch <- factor(pch)
if (is.null(pch.levels))
{
all.pch.levels <- 0:24
main.pch.levels <- c(16, 15, 17, 3, 4)
ref.pch.levels <- c(main.pch.levels, all.pch.levels[-which(all.pch.levels %in% main.pch.levels)])
pch.levels <- ref.pch.levels[seq_len(nlevels(pch))]
names(pch.levels) <- levels(pch)
}
else
{
if ( length(setdiff(names(pch.levels), levels(pch)) ) > 0 |
length(setdiff(levels(pch), names(pch.levels)) ) > 0 )
{
stop("'pch.levels' must be a vector of pch values with names: ",
levels(pch), call. = FALSE)
}
}
pch.legend <- pch.legend & ifelse(length(pch.levels) == 1, FALSE, TRUE)
return(list(pch = pch,
pch.levels = pch.levels,
pch.legend = pch.legend))
}
.check.cutoff <- function(cutoff = 0,
style = 'ggplot2') {
ncomp.vis <- ifelse(style != '3d', yes = 2, no = 3)
cutoff <- .change_if_null(cutoff, 0)
## check that cutoff value is valid
## it could be of length 2 when different cutoff for different components
## are needed (useful when most of selected variables tend to contribute
## to one component only so we can tailor the cutoff)
err <- FALSE
if (length(cutoff) == 1)
{
if (! (is.numeric(cutoff) | (cutoff > 1) | (cutoff < 0)) )
{
err <- TRUE
} else
{
cutoff <- rep(cutoff, ncomp.vis)
}
}
else if (length(cutoff) == ncomp.vis)
{
if (! (all(is.numeric(cutoff) | (cutoff > 1) | (cutoff < 0)) ))
err <- TRUE
}
else
{
err <- TRUE
}
if (isTRUE(err))
{
stop("cutoff must be a numeric of length 1 (or 'ncomp') between 0 and 1", call. = FALSE)
}
return(cutoff)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.