Skip to content

Commit 2702f26

Browse files
committed
circle_layout gains a new arugment direction to control the dicretion of plot adding
1 parent c23b772 commit 2702f26

7 files changed

+88
-22
lines changed

Diff for: R/layout-chain-.R

+6-3
Original file line numberDiff line numberDiff line change
@@ -521,12 +521,15 @@ chain_layout_add.circle_switch <- function(object, layout, object_name) {
521521
i = "Did you want to add a {.fn stack_switch}?"
522522
))
523523
}
524+
if (!is.waive(radial <- .subset2(object, "radial"))) {
525+
layout@radial <- radial
526+
}
527+
if (!is.null(direction <- .subset2(object, "direction"))) {
528+
layout@direction <- direction
529+
}
524530
layout <- switch_chain_plot(
525531
layout, .subset2(object, "what"),
526532
quote(circle_switch())
527533
)
528-
if (!is.waive(radial <- .subset2(object, "radial"))) {
529-
layout@radial <- radial
530-
}
531534
layout
532535
}

Diff for: R/layout-circle-.R

+18-9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#' and applied uniformly to all plots within the layout. The parameters
1414
#' `theta` and `r.axis.inside` will always be ignored and will be set to
1515
#' `"x"` and `TRUE`, respectively, for all plots.
16+
#' @param direction A single string of `r oxford_or(c("inward", "outward"))`,
17+
#' indicating the direction in which the plot is added.
18+
#' - `outward`: The plot is added from the inner to the outer.
19+
#' - `inward`: The plot is added from the outer to the inner.
1620
#' @examples
1721
#' set.seed(123)
1822
#' small_mat <- matrix(rnorm(56), nrow = 7)
@@ -25,13 +29,14 @@
2529
#' align_dendro(aes(color = branch), k = 3L) +
2630
#' scale_color_brewer(palette = "Dark2")
2731
#' @export
28-
circle_discrete <- function(data = NULL, ..., radial = NULL, theme = NULL) {
32+
circle_discrete <- function(data = NULL, ..., radial = NULL,
33+
direction = "outward", theme = NULL) {
2934
UseMethod("circle_discrete", data)
3035
}
3136

3237
#' @export
3338
circle_discrete.default <- function(data = NULL, ..., radial = NULL,
34-
theme = NULL) {
39+
direction = "outward", theme = NULL) {
3540
# the observations are rows, we use matrix to easily
3641
# reshape it into a long formated data frame for ggplot,
3742
# and we can easily determine the number of observations
@@ -48,7 +53,7 @@ circle_discrete.default <- function(data = NULL, ..., radial = NULL,
4853
new_circle_layout(
4954
data = data,
5055
design = discrete_design(nobs = nobs),
51-
radial = radial,
56+
radial = radial, direction = direction,
5257
schemes = schemes, theme = theme
5358
)
5459
}
@@ -85,19 +90,22 @@ circle_discrete.formula <- circle_discrete.function
8590
#' theme_bw()
8691
#' @export
8792
circle_continuous <- function(data = NULL, ..., radial = NULL,
88-
limits = NULL, theme = NULL) {
93+
direction = "outward", limits = NULL,
94+
theme = NULL) {
8995
UseMethod("circle_continuous", data)
9096
}
9197

9298
#' @export
9399
circle_continuous.default <- function(data = NULL, ..., radial = NULL,
94-
limits = NULL, theme = NULL) {
100+
direction = "outward", limits = NULL,
101+
theme = NULL) {
95102
assert_limits(limits)
96103
data <- data %|w|% NULL
97104
data <- fortify_data_frame(data = data, ...)
98105
schemes <- default_schemes()
99106
new_circle_layout(
100-
data = data, design = limits, radial = radial,
107+
data = data, design = limits,
108+
radial = radial, direction = direction,
101109
schemes = schemes, theme = theme
102110
)
103111
}
@@ -115,7 +123,7 @@ circle_continuous.function <- function(data = NULL, ...) {
115123
circle_continuous.formula <- circle_continuous.function
116124

117125
#' @importFrom methods new
118-
new_circle_layout <- function(data, design, radial, schemes = NULL,
126+
new_circle_layout <- function(data, design, radial, direction, schemes = NULL,
119127
theme = NULL, name = NULL, call = caller_call()) {
120128
if (!is.null(theme)) assert_s3_class(theme, "theme", call = call)
121129
assert_s3_class(radial, "CoordRadial", allow_null = TRUE)
@@ -125,6 +133,7 @@ new_circle_layout <- function(data, design, radial, schemes = NULL,
125133
call = call
126134
)
127135
}
136+
direction <- arg_match0(direction, c("inward", "outward"))
128137
if (is.null(name)) {
129138
if (is_continuous_design(design)) {
130139
name <- "circle_continuous"
@@ -137,7 +146,7 @@ new_circle_layout <- function(data, design, radial, schemes = NULL,
137146
name = name, data = data,
138147
schemes = schemes, # used by the layout
139148
design = design, theme = theme,
140-
radial = radial
149+
radial = radial, direction = direction
141150
)
142151
}
143152

@@ -192,5 +201,5 @@ circle_layout <- function(data = NULL, ..., limits = waiver()) {
192201
#' @include layout-chain-.R
193202
methods::setClass("CircleLayout",
194203
contains = "ChainLayout",
195-
list(radial = "ANY")
204+
list(radial = "ANY", direction = "character")
196205
)

Diff for: R/layout-circle-build.R

+19-5
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,36 @@ circle_build <- function(circle, schemes = NULL, theme = NULL) {
4343
radial <- ggproto(NULL, input_radial, theta = "x", r_axis_inside = TRUE)
4444
}
4545

46-
# for every plot track, all relative to the total radius `1`
4746
sizes <- vapply(plot_list, function(plot) {
4847
# for circular layout, we only support relative size
4948
if (is.na(size <- as.numeric(plot@size))) {
5049
size <- 1
5150
}
5251
size
5352
}, numeric(1L), USE.NAMES = FALSE)
53+
54+
# For each plot track, relative to the total radius:
55+
# `0.4` is coord_radial used for scale size, I don't know what it means
5456
plot_track <- sizes / sum(sizes) * (1 - radial$inner_radius[1L] / 0.4)
55-
plot_sizes <- 1 - cumsum(c(0, plot_track[-length(plot_track)]))
57+
58+
# For each plot, the plot size is calculated by adding the space for the
59+
# inner radius of each track.
60+
index <- seq_along(plot_list)
61+
if (identical(circle@direction, "outward")) {
62+
plot_sizes <- radial$inner_radius[1L] / 0.4 + cumsum(plot_track)
63+
} else {
64+
plot_sizes <- 1 - cumsum(c(0, plot_track[-length(plot_track)]))
65+
# The plots are always build inward, so the order is reversed.
66+
index <- rev(index)
67+
}
68+
69+
# For each plot, the inner radius is calculated as the difference between
70+
# the plot size and its track size.
5671
plot_inner <- plot_sizes - plot_track
5772
guides <- vector("list", length(plot_list))
5873
plot_table <- origin <- NULL
5974
design <- setup_design(circle@design)
60-
for (i in rev(seq_along(plot_list))) { # from inner-most to the out-most
75+
for (i in index) {
6176
plot_size <- plot_sizes[[i]]
6277
plot <- .subset2(plot_list, i)
6378
align <- plot@align # `AlignProto` object
@@ -154,8 +169,7 @@ circle_build <- function(circle, schemes = NULL, theme = NULL) {
154169
if (length(default_position) == 2) {
155170
default_position <- "inside"
156171
}
157-
if (default_position == "none") {
158-
} else {
172+
if (!identical(default_position, "none")) {
159173
plot_theme$legend.key.width <- calc_element(
160174
"legend.key.width",
161175
plot_theme

Diff for: R/layout-circle-switch.R

+8-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
#' align_dendro(aes(color = branch), k = 3L) +
2222
#' scale_color_brewer(palette = "Dark2")
2323
#' @export
24-
circle_switch <- function(radial = waiver(), what = waiver(), ...) {
24+
circle_switch <- function(radial = waiver(), direction = NULL,
25+
what = waiver(), ...) {
2526
rlang::check_dots_empty()
2627
if (!is.waive(radial)) {
2728
assert_s3_class(radial, "CoordRadial", allow_null = TRUE)
@@ -31,6 +32,11 @@ circle_switch <- function(radial = waiver(), what = waiver(), ...) {
3132
abs(diff(radial$arc)) < pi / 2L) {
3233
cli_abort("Cannot use circle of acute angle < 90 in {.arg radial}")
3334
}
35+
if (!is.null(direction)) {
36+
direction <- arg_match0(direction, c("inward", "outward"))
37+
}
3438
if (!is.waive(what)) what <- check_stack_context(what)
35-
structure(list(what = what, radial = radial), class = "circle_switch")
39+
structure(list(what = what, radial = radial, direction = direction),
40+
class = "circle_switch"
41+
)
3642
}

Diff for: man/circle_continuous.Rd

+15-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: man/circle_discrete.Rd

+14-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: man/circle_switch.Rd

+8-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)