Skip to content

Commit f85d4dc

Browse files
committed
feat: more geoms
1 parent e7b0393 commit f85d4dc

8 files changed

+373
-95
lines changed

DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Imports:
4040
fansi,
4141
pillar,
4242
rlang,
43+
scales,
4344
cli,
4445
purrr,
4546
vctrs,

NAMESPACE

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ export(as_tibble)
1212
export(coarsen)
1313
export(expand)
1414
export(geom_aggrcoverage)
15+
export(geom_coverage)
16+
export(scale_x_genome)
17+
export(scale_y_coverage)
1518
export(show)
1619
exportMethods(CoverageExperiment)
1720
exportMethods(aggregate)
@@ -45,6 +48,8 @@ importFrom(purrr,map_chr)
4548
importFrom(rlang,names2)
4649
importFrom(rtracklayer,BigWigFile)
4750
importFrom(rtracklayer,BigWigFileList)
51+
importFrom(scales,oob_squish)
52+
importFrom(scales,unit_format)
4853
importFrom(stats,qt)
4954
importFrom(stats,setNames)
5055
importFrom(tidyr,all_of)

R/geoms.R

Lines changed: 248 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
1-
#' geom_aggrcoverage
1+
#' Plotting functions
22
#'
33
#' #' @description
44
#'
5-
#' `geom_aggrcoverage()`
5+
#' Plotting functions for tidyCoverage objects
66
#'
7-
#' @name geom_aggrcoverage
8-
#' @rdname geom_aggrcoverage
7+
#' @name ggplot-tidyCoverage
8+
#' @rdname ggplot-tidyCoverage
99
#'
10-
#' @param mapping mapping
11-
#' @param data data
12-
#' @param ... ...
13-
#' @param ci ci
14-
#' @param na.rm na.rm
15-
#' @param show.legend show.legend
16-
#' @param inherit.aes inherit.aes
10+
#' @param mapping Aesthetics for geom_*. By default, no color/fill aesthetic
11+
#' is specified, but they can be assigned to a variable with `mapping = aes(...)`.
12+
#' Note that `x` and `y` are automatically filled.
13+
#' @param data Data frame passed to geom_*. Typically a `CoverageExperiment` object
14+
#' (expanded to a tibble) or a `AggregatedCoverage` object.
15+
#' @param type Choose between "line" and "area" style for `geom_coverage()`.
16+
#' @param ci Should the confidence interval be plotted by `geom_aggrcoverage()`?
17+
#' (default: TRUE)
18+
#' @param unit Rounding of x axis (any of c('b', 'kb', 'Mb')).
19+
#' @param grid Should the plot grid by displayed? (default: FALSE).
20+
#' @param ...,na.rm,show.legend,inherit.aes Argument passed to `ggplot`
21+
#' internal functions
1722
#' @return A `ggplot` object`
1823
#'
1924
#' @import ggplot2
25+
#' @importFrom scales oob_squish
26+
#' @importFrom scales unit_format
2027
#'
2128
#' @examples
2229
#' library(rtracklayer)
@@ -26,15 +33,42 @@
2633
#' TSSs_bed <- system.file("extdata", "TSSs.bed", package = "tidyCoverage")
2734
#' features <- list(
2835
#' TSS_fwd = import(TSSs_bed) |> filter(strand == '+'),
29-
#' TSS_rev = import(TSSs_bed) |> filter(strand == '-')
36+
#' TSS_rev = import(TSSs_bed) |> filter(strand == '-'),
37+
#' conv_sites = import(system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage"))
3038
#' )
3139
#' tracks <- list(
3240
#' RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"),
33-
#' RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage")
41+
#' RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage"),
42+
#' Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage")
3443
#' ) |> map(import, as = 'Rle')
35-
#' df <- CoverageExperiment(tracks, features, width = 5000, ignore.strand = FALSE) |>
36-
#' aggregate() |>
37-
#' as_tibble()
44+
#' ce <- CoverageExperiment(tracks, features, width = 5000, center = TRUE, scale = TRUE)
45+
#' ac <- aggregate(ce)
46+
#'
47+
#' #############################################################################
48+
#' ## 1. Plotting aggregated coverage
49+
#' #############################################################################
50+
#'
51+
#' ac |>
52+
#' as_tibble() |>
53+
#' ggplot() +
54+
#' geom_aggrcoverage(aes(col = track)) +
55+
#' facet_grid(track ~ features) +
56+
#' geom_vline(xintercept = 0, color = 'black', linetype = 'dashed', linewidth = 0.5)
57+
#'
58+
#' #############################################################################
59+
#' ## 2. Plotting track coverages over individual loci
60+
#' #############################################################################
61+
#'
62+
#' ce2 <- CoverageExperiment(
63+
#' tracks,
64+
#' GRangesList(list(locus1 = "II:400001-455000", locus2 = "IV:720001-775000")),
65+
#' window = 50
66+
#' )
67+
#' expand(ce2) |>
68+
#' mutate(coverage = ifelse(track != 'Scc1', scales::oob_squish(coverage, c(0, 50)), coverage)) |>
69+
#' ggplot() +
70+
#' geom_coverage(aes(fill = track)) +
71+
#' facet_grid(track~features, scales = 'free')
3872
NULL
3973

4074
GeomAggrCoverage <- ggplot2::ggproto("GeomAggrCoverage", ggplot2::Geom,
@@ -66,30 +100,218 @@ GeomAggrCoverage <- ggplot2::ggproto("GeomAggrCoverage", ggplot2::Geom,
66100
draw_key = ggplot2::draw_key_smooth
67101
)
68102

69-
#' @rdname geom_aggrcoverage
103+
GeomCoverage <- ggplot2::ggproto("GeomCoverage", ggplot2::Geom,
104+
setup_params = function(data, params) {
105+
params$type <- params$type
106+
params
107+
},
108+
extra_params = c("na.rm"),
109+
required_aes = c("x", "y"),
110+
default_aes = ggplot2::aes(
111+
colour = "black",
112+
fill = "grey",
113+
linewidth = 0.4,
114+
linetype = 1,
115+
alpha = 1
116+
),
117+
118+
draw_group = function(data, params, coord, type, ...) {
119+
120+
forArea <- transform(data, ymax = y, ymin = 0, colour = NA)
121+
122+
grid::gList(
123+
if (type == 'line') ggplot2::GeomLine$draw_panel(data, params, coord, ...),
124+
if (type == 'area') ggplot2::GeomArea$draw_panel(forArea, params, coord, ...)
125+
)
126+
127+
},
128+
129+
draw_key = function(data, params, type, ...) {
130+
if (params$type == 'line') {
131+
ggplot2::draw_key_path(data, params)
132+
}
133+
else {
134+
data <- transform(data, colour = NA)
135+
ggplot2::draw_key_rect(data, params)
136+
}
137+
}
138+
)
139+
140+
#' @rdname ggplot-tidyCoverage
70141
#' @export
71142

72143
geom_aggrcoverage <- function(
73144
mapping = NULL,
74145
data = NULL,
75146
...,
147+
unit = c('kb', 'Mb', 'b'),
76148
ci = TRUE,
149+
grid = FALSE,
77150
na.rm = FALSE,
78151
show.legend = NA,
79152
inherit.aes = TRUE
80153
) {
81154
m <- ggplot2::aes(x = coord, y = mean, ymin = ci_low, ymax = ci_high, group = interaction(.sample, .feature))
82155
if (!is.null(mapping)) m <- utils::modifyList(m, mapping)
83156

84-
ggplot2::layer(
85-
data = data,
86-
mapping = m,
87-
stat = "identity",
88-
geom = GeomAggrCoverage,
89-
position = "identity",
90-
show.legend = show.legend,
91-
inherit.aes = inherit.aes,
92-
params = list(na.rm = na.rm, ci = ci, ...)
157+
unit = match.arg(unit, c('kb', 'Mb', 'b'))
158+
159+
list(
160+
ggplot2::layer(
161+
data = data,
162+
mapping = m,
163+
stat = "identity",
164+
geom = GeomAggrCoverage,
165+
position = "identity",
166+
show.legend = show.legend,
167+
inherit.aes = inherit.aes,
168+
params = list(na.rm = na.rm, ci = ci, ...)
169+
),
170+
theme_coverage2(grid = grid),
171+
scale_x_genome(unit = unit)
172+
)
173+
}
174+
175+
#' @rdname ggplot-tidyCoverage
176+
#' @export
177+
178+
geom_coverage <- function(
179+
mapping = NULL,
180+
data = NULL,
181+
...,
182+
type = c('area', 'line'),
183+
unit = c('kb', 'Mb', 'b'),
184+
grid = FALSE,
185+
na.rm = FALSE,
186+
show.legend = NA,
187+
inherit.aes = TRUE
188+
) {
189+
m <- ggplot2::aes(x = coord, y = coverage, group = interaction(track, features), fill = track)
190+
if (!is.null(mapping)) m <- utils::modifyList(m, mapping)
191+
192+
unit = match.arg(unit, c('kb', 'Mb', 'b'))
193+
type <- match.arg(type, c('area', 'line'))
194+
195+
list(
196+
ggplot2::layer(
197+
data = data,
198+
mapping = m,
199+
stat = "identity",
200+
geom = GeomCoverage,
201+
position = "identity",
202+
show.legend = show.legend,
203+
inherit.aes = inherit.aes,
204+
params = list(na.rm = na.rm, type = type, ...)
205+
),
206+
scale_x_genome(unit = unit),
207+
scale_y_coverage(),
208+
theme_coverage(grid = grid),
209+
ggplot2::guides(y = ggplot2::guide_axis(cap = "both"))
93210
)
211+
94212
}
95213

214+
#' @rdname ggplot-tidyCoverage
215+
#' @export
216+
217+
scale_y_coverage <- function() {
218+
ggplot2::scale_y_continuous(
219+
expand = ggplot2::expansion(mult = c(0, 0)),
220+
n.breaks = 3
221+
)
222+
}
223+
224+
#' @rdname ggplot-tidyCoverage
225+
#' @export
226+
227+
scale_x_genome <- function(unit = c('kb', 'Mb', 'b')) {
228+
unit = match.arg(unit, c('kb', 'Mb', 'b'))
229+
scale = dplyr::case_when(
230+
unit == 'b' ~ 1,
231+
unit == 'kb' ~ 1e-3,
232+
unit == 'Mb' ~ 1e-6
233+
)
234+
ggplot2::scale_x_continuous(
235+
expand = c(0, 0),
236+
labels = scales::unit_format(
237+
unit = unit, scale = scale,
238+
sep = "",
239+
big.mark = ""
240+
)
241+
)
242+
}
243+
244+
.theme_coverage <- function(
245+
grid = TRUE,
246+
base_size = 11,
247+
base_family = "",
248+
base_line_size = base_size/22,
249+
base_rect_size = base_size/22
250+
) {
251+
th <- ggplot2::theme_bw(
252+
base_size = base_size,
253+
base_family = base_family,
254+
base_line_size = base_line_size,
255+
base_rect_size = base_rect_size
256+
)
257+
if (!grid) th <- th %+replace% ggplot2::theme(
258+
panel.grid = ggplot2::element_blank(),
259+
panel.grid.major = ggplot2::element_blank(),
260+
panel.grid.minor = ggplot2::element_blank()
261+
)
262+
th <- th %+replace%
263+
ggplot2::theme(
264+
legend.position = 'top',
265+
legend.background = ggplot2::element_blank(),
266+
legend.key = ggplot2::element_blank(),
267+
panel.spacing = unit(8, "pt"),
268+
panel.background = ggplot2::element_blank(),
269+
strip.background = ggplot2::element_blank(),
270+
plot.background = ggplot2::element_blank(),
271+
complete = TRUE
272+
)
273+
th
274+
}
275+
276+
theme_coverage <- function(
277+
grid = TRUE,
278+
base_size = 11,
279+
base_family = "",
280+
base_line_size = base_size/22,
281+
base_rect_size = base_size/22
282+
) {
283+
th <- .theme_coverage(
284+
grid = grid,
285+
base_size = base_size,
286+
base_family = base_family,
287+
base_line_size = base_line_size,
288+
base_rect_size = base_rect_size
289+
) %+replace%
290+
ggplot2::theme(
291+
#panel.border = ggplot2::element_blank(),
292+
axis.line = element_line(color = 'black'),
293+
complete = TRUE
294+
)
295+
th
296+
}
297+
298+
theme_coverage2 <- function(
299+
grid = TRUE,
300+
base_size = 11,
301+
base_family = "",
302+
base_line_size = base_size/22,
303+
base_rect_size = base_size/22
304+
) {
305+
th <- .theme_coverage(
306+
grid = grid,
307+
base_size = base_size,
308+
base_family = base_family,
309+
base_line_size = base_line_size,
310+
base_rect_size = base_rect_size
311+
) %+replace%
312+
ggplot2::theme(
313+
axis.ticks = ggplot2::element_blank(),
314+
complete = TRUE
315+
)
316+
th
317+
}

R/globals.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ utils::globalVariables(c(
44
"ci_high",
55
"coord",
66
"feature",
7+
"features",
78
".feature",
89
".sample",
910
"track"

README.md

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ tracks <- list(
4242
## Extract coverage for each track over each set of features
4343

4444
```r
45-
CE <- CoverageExperiment(tracks, features, width = 1000, ignore.strand = FALSE)
45+
CE <- CoverageExperiment(tracks, features, width = 5000, ignore.strand = FALSE)
4646
```
4747

4848
## Plot tracks coverage aggregated over genomic features
@@ -55,9 +55,7 @@ CE |>
5555
ggplot() +
5656
geom_aggrcoverage(aes(col = track)) +
5757
facet_grid(track ~ ., scales = "free") +
58-
labs(x = 'Distance from TSS', y = 'Signal coverage') +
59-
theme_bw() +
60-
theme(legend.position = 'top')
58+
labs(x = 'Distance from TSS', y = 'Signal coverage')
6159
```
6260

6361
![](man/figures/aggr-cov.png)
@@ -68,11 +66,8 @@ CE |>
6866
CoverageExperiment(tracks, GRanges("II:450001-455000")) |>
6967
expand() |>
7068
ggplot() +
71-
geom_aggrcoverage(aes(col = track)) +
72-
facet_grid(track~., scales = 'free') +
73-
scale_x_continuous(expand = c(0, 0)) +
74-
theme_bw() +
75-
theme(legend.position = "none", aspect.ratio = 0.1)
69+
geom_coverage(aes(fill = track)) +
70+
facet_grid(track~., scales = 'free')
7671
```
7772

7873
![](man/figures/cov.png)

0 commit comments

Comments
 (0)