Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scale palettes from theme #5946

Merged
merged 25 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e1ea0fe
add palette theme elements
teunbrand Jun 18, 2024
aec8cb1
set palettes
teunbrand Jun 18, 2024
e2d0237
expand options for numeric palettes
teunbrand Jun 19, 2024
e0a9449
backward compatibility for `options()` default scales
teunbrand Jun 19, 2024
d57a2cf
use explicit scales in tests
teunbrand Jun 19, 2024
52d7fe6
standard colour scales have `palette = NULL`
teunbrand Jun 19, 2024
78775db
document
teunbrand Jun 19, 2024
9a202c7
properly document this time
teunbrand Jun 19, 2024
aa42bc9
misc fixes
teunbrand Jun 19, 2024
47adf69
more palettes in theme
teunbrand Jun 21, 2024
e2b5521
use binned versions of discrete palettes for continuous linetype/shape
teunbrand Jun 21, 2024
ddef5d3
Set default palettes to `NULL`
teunbrand Jun 21, 2024
71d3122
tweak test to populate palettes
teunbrand Jun 21, 2024
489d505
try registered theme palettes
teunbrand Jun 21, 2024
94a1750
document
teunbrand Jun 21, 2024
03b8204
resolve merge conflict
teunbrand Oct 3, 2024
00dd12c
remove redundant call to `plot_theme()`
teunbrand Oct 3, 2024
7251f11
simplify `fallback_palette()` args
teunbrand Oct 3, 2024
0901257
Put in shims for scales/#427
teunbrand Oct 3, 2024
c0b5734
Streamline `ScalesList$set_palettes()` method
teunbrand Oct 3, 2024
d731ace
resolve merge conflict
teunbrand Oct 31, 2024
d9c9147
try to match first non-null aesthetic
teunbrand Nov 11, 2024
36681dc
Merge branch 'main' into scale_palettes
teunbrand Nov 11, 2024
4414069
Merge branch 'main' into scale_palettes
teunbrand Dec 2, 2024
75e26a8
add news bullet
teunbrand Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@
* Added `keep.zeroes` argument to `stat_bin()` (@teunbrand, #3449)
* `coord_sf()` no longer errors when dealing with empty graticules (@teunbrand, #6052)
* Added `theme_transparent()` with transparent backgrounds (@topepo).
* New theme elements `palette.{aes}.discrete` and `palette.{aes}.continuous`.
Theme palettes replace palettes in scales where `palette = NULL`, which is
the new default in many scales (@teunbrand, #4696).

# ggplot2 3.5.1

Expand Down
2 changes: 1 addition & 1 deletion R/geom-text.R
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
#' # Add aesthetic mappings
#' p + geom_text(aes(colour = factor(cyl)))
#' p + geom_text(aes(colour = factor(cyl))) +
#' scale_colour_discrete(l = 40)
#' scale_colour_hue(l = 40)
#' p + geom_label(aes(fill = factor(cyl)), colour = "white", fontface = "bold")
#'
#' # Scale size of text, and change legend key glyph from a to point
Expand Down
1 change: 1 addition & 0 deletions R/plot-build.R
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ ggplot_build.ggplot <- function(plot) {
# Train and map non-position scales and guides
npscales <- scales$non_position_scales()
if (npscales$n() > 0) {
npscales$set_palettes(plot$theme)
lapply(data, npscales$train_df)
plot$guides <- plot$guides$build(npscales, plot$layers, plot$labels, data, plot$theme)
data <- lapply(data, npscales$map_df)
Expand Down
1 change: 1 addition & 0 deletions R/scale-.R
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ Scale <- ggproto("Scale", NULL,
if (empty(df)) {
return()
}
self$palette <- self$palette %||% fallback_palette(self)

aesthetics <- intersect(self$aesthetics, names(df))
names(aesthetics) <- aesthetics
Expand Down
35 changes: 19 additions & 16 deletions R/scale-alpha.R
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@
#'
#' # Changing the title
#' p + scale_alpha("cylinders")
scale_alpha <- function(name = waiver(), ..., range = c(0.1, 1)) {
continuous_scale("alpha", name = name, palette = pal_rescale(range), ...)
scale_alpha <- function(name = waiver(), ..., range = NULL) {
palette <- if (!is.null(range)) pal_rescale(range) else NULL
continuous_scale("alpha", name = name, palette = palette, ...)
}

#' @rdname scale_alpha
Expand All @@ -41,8 +42,9 @@

#' @rdname scale_alpha
#' @export
scale_alpha_binned <- function(name = waiver(), ..., range = c(0.1, 1)) {
binned_scale("alpha", name = name, palette = pal_rescale(range), ...)
scale_alpha_binned <- function(name = waiver(), ..., range = NULL) {
palette <- if (!is.null(range)) pal_rescale(range) else NULL
binned_scale("alpha", name = name, palette = palette, ...)
}

#' @rdname scale_alpha
Expand All @@ -56,32 +58,33 @@

#' @rdname scale_alpha
#' @export
scale_alpha_ordinal <- function(name = waiver(), ..., range = c(0.1, 1)) {
discrete_scale(
"alpha", name = name,
palette = function(n) seq(range[1], range[2], length.out = n),
...
)
scale_alpha_ordinal <- function(name = waiver(), ..., range = NULL) {
palette <- if (!is.null(range)) {
function(n) seq(range[1], range[2], length.out = n)

Check warning on line 63 in R/scale-alpha.R

View check run for this annotation

Codecov / codecov/patch

R/scale-alpha.R#L63

Added line #L63 was not covered by tests
} else {
NULL
}
discrete_scale("alpha", name = name, palette = palette, ...)
}

#' @rdname scale_alpha
#' @export
#' @usage NULL
scale_alpha_datetime <- function(name = waiver(), ..., range = c(0.1, 1)) {
scale_alpha_datetime <- function(name = waiver(), ..., range = NULL) {
palette <- if (!is.null(range)) pal_rescale(range) else NULL
datetime_scale(
aesthetics = "alpha", transform = "time", name = name,
palette = pal_rescale(range),
...
palette = palette, ...
)
}

#' @rdname scale_alpha
#' @export
#' @usage NULL
scale_alpha_date <- function(name = waiver(), ..., range = c(0.1, 1)){
scale_alpha_date <- function(name = waiver(), ..., range = NULL){
palette <- if (!is.null(range)) pal_rescale(range) else NULL
datetime_scale(
aesthetics = "alpha", transform = "date", name = name,
palette = pal_rescale(range),
...
palette = palette, ...
)
}
216 changes: 123 additions & 93 deletions R/scale-colour.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#' you want to manually set the colors of a scale, consider using
#' [scale_colour_gradient()] or [scale_colour_steps()].
#'
#' @inheritParams continuous_scale
#' @param ... Additional parameters passed on to the scale type
#' @param type One of the following:
#' * "gradient" (the default)
Expand Down Expand Up @@ -77,122 +78,81 @@
#' v
#' options(ggplot2.continuous.fill = tmp) # restore previous setting
#' @export
scale_colour_continuous <- function(...,
scale_colour_continuous <- function(..., aesthetics = "colour",
guide = "colourbar", na.value = "grey50",
type = getOption("ggplot2.continuous.colour")) {
type <- type %||% "gradient"
args <- list2(...)
args$call <- args$call %||% current_call()

if (is.function(type)) {
if (!any(c("...", "call") %in% fn_fmls_names(type))) {
args$call <- NULL
}
check_scale_type(exec(type, !!!args), "scale_colour_continuous", "colour")
} else if (identical(type, "gradient")) {
exec(scale_colour_gradient, !!!args)
} else if (identical(type, "viridis")) {
exec(scale_colour_viridis_c, !!!args)
} else {
cli::cli_abort(c(
"Unknown scale type: {.val {type}}",
"i" = "Use either {.val gradient} or {.val viridis}."
))
if (!is.null(type)) {
scale <- scale_backward_compatibility(
..., guide = guide, na.value = na.value, scale = type,
aesthetic = "colour", type = "continuous"
)
return(scale)

Check warning on line 90 in R/scale-colour.R

View check run for this annotation

Codecov / codecov/patch

R/scale-colour.R#L90

Added line #L90 was not covered by tests
}

continuous_scale(
aesthetics, palette = NULL, guide = guide, na.value = na.value,
...
)
}

#' @rdname scale_colour_continuous
#' @export
scale_fill_continuous <- function(...,
scale_fill_continuous <- function(..., aesthetics = "fill", guide = "colourbar",
na.value = "grey50",
type = getOption("ggplot2.continuous.fill")) {
type <- type %||% "gradient"
args <- list2(...)
args$call <- args$call %||% current_call()

if (is.function(type)) {
if (!any(c("...", "call") %in% fn_fmls_names(type))) {
args$call <- NULL
}
check_scale_type(exec(type, !!!args), "scale_fill_continuous", "fill")
} else if (identical(type, "gradient")) {
exec(scale_fill_gradient, !!!args)
} else if (identical(type, "viridis")) {
exec(scale_fill_viridis_c, !!!args)
} else {
cli::cli_abort(c(
"Unknown scale type: {.val {type}}",
"i" = "Use either {.val gradient} or {.val viridis}."
))
if (!is.null(type)) {
scale <- scale_backward_compatibility(
..., guide = guide, na.value = na.value, scale = type,
aesthetic = "fill", type = "continuous"
)
return(scale)

Check warning on line 110 in R/scale-colour.R

View check run for this annotation

Codecov / codecov/patch

R/scale-colour.R#L110

Added line #L110 was not covered by tests
}

continuous_scale(
aesthetics, palette = NULL, guide = guide, na.value = na.value,
...
)
}

#' @export
#' @rdname scale_colour_continuous
scale_colour_binned <- function(...,
scale_colour_binned <- function(..., aesthetics = "colour", guide = "coloursteps",
na.value = "grey50",
type = getOption("ggplot2.binned.colour")) {
args <- list2(...)
args$call <- args$call %||% current_call()
if (is.function(type)) {
if (!any(c("...", "call") %in% fn_fmls_names(type))) {
args$call <- NULL
}
check_scale_type(exec(type, !!!args), "scale_colour_binned", "colour")
} else {
type_fallback <- getOption("ggplot2.continuous.colour", default = "gradient")
# don't use fallback from scale_colour_continuous() if it is
# a function, since that would change the type of the color
# scale from binned to continuous
if (is.function(type_fallback)) {
type_fallback <- "gradient"
}
type <- type %||% type_fallback

if (identical(type, "gradient")) {
exec(scale_colour_steps, !!!args)
} else if (identical(type, "viridis")) {
exec(scale_colour_viridis_b, !!!args)
} else {
cli::cli_abort(c(
"Unknown scale type: {.val {type}}",
"i" = "Use either {.val gradient} or {.val viridis}."
))
}
if (!is.null(type)) {
scale <- scale_backward_compatibility(
..., guide = guide, na.value = na.value, scale = type,
aesthetic = "colour", type = "binned"
)
return(scale)

Check warning on line 129 in R/scale-colour.R

View check run for this annotation

Codecov / codecov/patch

R/scale-colour.R#L129

Added line #L129 was not covered by tests
}

binned_scale(
aesthetics, palette = NULL, guide = guide, na.value = na.value,
...
)
}

#' @export
#' @rdname scale_colour_continuous
scale_fill_binned <- function(...,
scale_fill_binned <- function(..., aesthetics = "fill", guide = "coloursteps",
na.value = "grey50",
type = getOption("ggplot2.binned.fill")) {
args <- list2(...)
args$call <- args$call %||% current_call()
if (is.function(type)) {
if (!any(c("...", "call") %in% fn_fmls_names(type))) {
args$call <- NULL
}
check_scale_type(exec(type, !!!args), "scale_fill_binned", "fill")
} else {
type_fallback <- getOption("ggplot2.continuous.fill", default = "gradient")
# don't use fallback from scale_colour_continuous() if it is
# a function, since that would change the type of the color
# scale from binned to continuous
if (is.function(type_fallback)) {
type_fallback <- "gradient"
}
type <- type %||% type_fallback

if (identical(type, "gradient")) {
exec(scale_fill_steps, !!!args)
} else if (identical(type, "viridis")) {
exec(scale_fill_viridis_b, !!!args)
} else {
cli::cli_abort(c(
"Unknown scale type: {.val {type}}",
"i" = "Use either {.val gradient} or {.val viridis}."
))
}
if (!is.null(type)) {
scale <- scale_backward_compatibility(
..., guide = guide, na.value = na.value, scale = type,
aesthetic = "fill", type = "binned"
)
return(scale)

Check warning on line 148 in R/scale-colour.R

View check run for this annotation

Codecov / codecov/patch

R/scale-colour.R#L148

Added line #L148 was not covered by tests
}
}

binned_scale(
aesthetics, palette = NULL, guide = guide, na.value = na.value,
...
)
}

# helper function to make sure that the provided scale is of the correct
# type (i.e., is continuous and works with the provided aesthetic)
Expand Down Expand Up @@ -222,3 +182,73 @@

scale
}

# helper function for backwards compatibility through setting defaults
# scales through `options()` instead of `theme()`.
scale_backward_compatibility <- function(..., scale, aesthetic, type) {
aesthetic <- standardise_aes_names(aesthetic[1])

args <- list2(...)
args$call <- args$call %||% caller_call() %||% current_call()

if (type == "binned") {
fallback <- getOption(
paste("ggplot2", type, aesthetic, sep = "."),
default = "gradient"
)
if (is.function(fallback)) {
fallback <- "gradient"

Check warning on line 200 in R/scale-colour.R

View check run for this annotation

Codecov / codecov/patch

R/scale-colour.R#L200

Added line #L200 was not covered by tests
}
scale <- scale %||% fallback
}

if (is_bare_string(scale)) {
if (scale == "continuous") {
scale <- "gradient"

Check warning on line 207 in R/scale-colour.R

View check run for this annotation

Codecov / codecov/patch

R/scale-colour.R#L207

Added line #L207 was not covered by tests
}
if (scale == "discrete") {
scale <- "hue"

Check warning on line 210 in R/scale-colour.R

View check run for this annotation

Codecov / codecov/patch

R/scale-colour.R#L210

Added line #L210 was not covered by tests
}
if (scale == "viridis") {
scale <- switch(
type, discrete = "viridis_d", binned = "viridis_b", "viridis_c"
)

Check warning on line 215 in R/scale-colour.R

View check run for this annotation

Codecov / codecov/patch

R/scale-colour.R#L213-L215

Added lines #L213 - L215 were not covered by tests
}

candidates <- paste("scale", aesthetic, scale, sep = "_")
for (candi in candidates) {
f <- find_global(candi, env = caller_env(), mode = "function")
if (!is.null(f)) {
scale <- f
break

Check warning on line 223 in R/scale-colour.R

View check run for this annotation

Codecov / codecov/patch

R/scale-colour.R#L222-L223

Added lines #L222 - L223 were not covered by tests
}
}
}

if (!is.function(scale) && type == "discrete") {
args$type <- scale
scale <- switch(
aesthetic,
colour = scale_colour_qualitative,
fill = scale_fill_qualitative
)
}

if (is.function(scale)) {
if (!any(c("...", "call") %in% fn_fmls_names(scale))) {
args$call <- NULL
}
if (!"..." %in% fn_fmls_names(scale)) {
args <- args[intersect(names(args), fn_fmls_names(scale))]
}
scale <- check_scale_type(
exec(scale, !!!args),
paste("scale", aesthetic, type, sep = "_"),
aesthetic,
scale_is_discrete = type == "discrete"
)
return(scale)
}

cli::cli_abort("Unknown scale type: {.val {scale}}")
}
Loading
Loading