├── .Rbuildignore ├── .github ├── .gitignore ├── CODE_OF_CONDUCT.md └── workflows │ └── rworkflows.yml ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── R ├── AllClasses.R ├── AllGenerics.R ├── CoverageExperiment.R ├── aggregate.R ├── as_tibble.R ├── coarsen.R ├── data.R ├── expand.R ├── geoms.R ├── globals.R ├── reexports.R ├── show.R └── utils.R ├── README.md ├── _pkgdown.yml ├── data ├── ac.rda └── ce.rda ├── inst ├── CITATION ├── extdata │ ├── MNase.bw │ ├── PolII.bw │ ├── RNA.fwd.bw │ ├── RNA.rev.bw │ ├── Scc1.bw │ ├── TSSs.bed │ └── conv_transcription_loci.bed └── scripts │ ├── data.R │ └── extdata.R ├── man ├── AggregatedCoverage.Rd ├── CoverageExperiment.Rd ├── as_tibble-methods.Rd ├── data.Rd ├── expand.Rd ├── figures │ ├── PTMs-TSSs.png │ ├── aggr-cov.png │ └── cov.png ├── ggplot-tidyCoverage.Rd ├── reexports.Rd └── show.Rd ├── manuscript_figure.qmd ├── tests ├── testthat.R └── testthat │ └── test-compute-filter-import-plot.R └── vignettes ├── .gitignore └── tidyCoverage.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^LICENSE\.md$ 2 | ^README\.Rmd$ 3 | ^\.github$ 4 | ^_pkgdown\.yml$ 5 | ^docs$ 6 | ^pkgdown$ 7 | ^doc$ 8 | ^Meta$ 9 | .*\.qmd$ 10 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | The Bioconductor community values 2 | 3 | * an open approach to science that promotes the sharing of ideas, code, and expertise 4 | * collaboration 5 | * diversity and inclusivity 6 | * a kind and welcoming environment 7 | * community contributions 8 | 9 | In line with these values, Bioconductor is dedicated to providing a welcoming, supportive, collegial, experience free of harassment, intimidation, and bullying regardless of: 10 | 11 | * identity: gender, gender identity and expression, sexual orientation, disability, physical appearance, ethnicity, body size, race, age, religion, etc. 12 | * intellectual position: approaches to data analysis, software preferences, coding style, scientific perspective, etc. 13 | * stage of career 14 | 15 | In order to uphold these values, members of the Bioconductor community are required to follow the Code of Conduct.The latest version of Bioconductor project Code of Conduct is available at http://bioconductor.org/about/code-of-conduct/. Please read the Code of Conduct before contributing to this project. 16 | 17 | Thank you! 18 | -------------------------------------------------------------------------------- /.github/workflows/rworkflows.yml: -------------------------------------------------------------------------------- 1 | name: rworkflows 2 | 'on': 3 | push: 4 | branches: 5 | - master 6 | - main 7 | - devel 8 | - RELEASE_** 9 | pull_request: 10 | branches: 11 | - master 12 | - main 13 | - devel 14 | - RELEASE_** 15 | jobs: 16 | rworkflows: 17 | permissions: write-all 18 | runs-on: ${{ matrix.config.os }} 19 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 20 | container: ${{ matrix.config.cont }} 21 | strategy: 22 | fail-fast: ${{ false }} 23 | matrix: 24 | config: 25 | - os: ubuntu-latest 26 | bioc: devel 27 | r: auto 28 | cont: ghcr.io/bioconductor/bioconductor_docker:devel 29 | rspm: ~ 30 | - os: macOS-latest 31 | bioc: release 32 | r: auto 33 | cont: ~ 34 | rspm: ~ 35 | - os: windows-latest 36 | bioc: release 37 | r: auto 38 | cont: ~ 39 | rspm: ~ 40 | steps: 41 | - uses: js2264/rworkflows@hotfix_quarto 42 | with: 43 | run_bioccheck: ${{ false }} 44 | run_rcmdcheck: ${{ true }} 45 | as_cran: ${{ true }} 46 | run_vignettes: ${{ true }} 47 | has_testthat: ${{ true }} 48 | run_covr: ${{ true }} 49 | run_pkgdown: ${{ true }} 50 | has_runit: ${{ false }} 51 | has_latex: ${{ false }} 52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 53 | run_docker: ${{ false }} 54 | DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} 55 | runner_os: ${{ runner.os }} 56 | cache_version: cache-v1 57 | docker_registry: ghcr.io 58 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: tidyCoverage 2 | Title: Extract and aggregate genomic coverage over features of interest 3 | Version: 1.1.2 4 | Date: 2023-11-09 5 | Authors@R: 6 | person("Jacques", "Serizay", , "jacquesserizay@gmail.com", 7 | role = c("aut", "cre")) 8 | Description: `tidyCoverage` framework enables tidy manipulation 9 | of collections of genomic tracks and features using 10 | `tidySummarizedExperiment` methods. It facilitates the 11 | extraction, aggregation and visualization of genomic coverage over 12 | individual or thousands of genomic loci, relying on `CoverageExperiment` 13 | and `AggregatedCoverage` classes. This accelerates the integration 14 | of genomic track data in genomic analysis workflows. 15 | License: MIT + file LICENSE 16 | URL: https://github.com/js2264/tidyCoverage 17 | BugReports: https://github.com/js2264/tidyCoverage/issues 18 | biocViews: 19 | Software, 20 | Sequencing, 21 | Coverage, 22 | Encoding: UTF-8 23 | Roxygen: list(markdown = TRUE) 24 | RoxygenNote: 7.2.3 25 | Depends: 26 | R (>= 4.3.0), 27 | SummarizedExperiment 28 | Imports: 29 | S4Vectors, 30 | IRanges, 31 | GenomicRanges, 32 | GenomeInfoDb, 33 | BiocParallel, 34 | BiocIO, 35 | rtracklayer, 36 | methods, 37 | tidyr, 38 | ggplot2, 39 | dplyr, 40 | fansi, 41 | pillar, 42 | rlang, 43 | scales, 44 | cli, 45 | purrr, 46 | vctrs, 47 | stats 48 | Suggests: 49 | tidySummarizedExperiment, 50 | plyranges, 51 | TxDb.Hsapiens.UCSC.hg19.knownGene, 52 | AnnotationHub, 53 | GenomicFeatures, 54 | BiocStyle, 55 | hues, 56 | knitr, 57 | rmarkdown, 58 | sessioninfo, 59 | testthat (>= 3.0.0) 60 | Config/testthat/edition: 3 61 | VignetteBuilder: knitr 62 | LazyData: false 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2023 2 | COPYRIGHT HOLDER: tidyCoverage authors 3 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(as_tibble,AggregatedCoverage) 4 | S3method(expand,CoverageExperiment) 5 | S3method(print,AggregatedCoverage) 6 | S3method(print,CoverageExperiment) 7 | S3method(tbl_format_header,tidyAggregatedCoverage) 8 | S3method(tbl_format_header,tidyCoverageExperiment) 9 | export(CoverageExperiment) 10 | export(aggregate) 11 | export(as_tibble) 12 | export(coarsen) 13 | export(expand) 14 | export(geom_aggrcoverage) 15 | export(geom_coverage) 16 | export(scale_x_genome) 17 | export(scale_y_coverage) 18 | export(show) 19 | exportMethods(CoverageExperiment) 20 | exportMethods(aggregate) 21 | exportMethods(coarsen) 22 | exportMethods(show) 23 | import(GenomeInfoDb) 24 | import(GenomicRanges) 25 | import(SummarizedExperiment) 26 | import(ggplot2) 27 | import(methods) 28 | importFrom(BiocIO,resource) 29 | importFrom(BiocParallel,bplapply) 30 | importFrom(BiocParallel,bpparam) 31 | importFrom(IRanges,NumericList) 32 | importFrom(S4Vectors,aggregate) 33 | importFrom(SummarizedExperiment,assayNames) 34 | importFrom(cli,console_width) 35 | importFrom(cli,symbol) 36 | importFrom(dplyr,as_tibble) 37 | importFrom(dplyr,bind_cols) 38 | importFrom(dplyr,bind_rows) 39 | importFrom(dplyr,filter) 40 | importFrom(dplyr,mutate) 41 | importFrom(dplyr,relocate) 42 | importFrom(fansi,strwrap_ctl) 43 | importFrom(pillar,align) 44 | importFrom(pillar,get_extent) 45 | importFrom(pillar,style_subtle) 46 | importFrom(pillar,tbl_format_header) 47 | importFrom(purrr,map_chr) 48 | importFrom(rlang,names2) 49 | importFrom(rtracklayer,BigWigFile) 50 | importFrom(rtracklayer,BigWigFileList) 51 | importFrom(scales,oob_squish) 52 | importFrom(scales,unit_format) 53 | importFrom(stats,qt) 54 | importFrom(stats,setNames) 55 | importFrom(tidyr,all_of) 56 | importFrom(tidyr,any_of) 57 | importFrom(tidyr,expand) 58 | importFrom(tidyr,pivot_longer) 59 | importFrom(vctrs,new_data_frame) 60 | -------------------------------------------------------------------------------- /R/AllClasses.R: -------------------------------------------------------------------------------- 1 | methods::setClass( 2 | "CoverageExperiment", 3 | contains = c("RangedSummarizedExperiment") 4 | ) 5 | methods::setClass( 6 | "AggregatedCoverage", 7 | contains = c("RangedSummarizedExperiment") 8 | ) 9 | -------------------------------------------------------------------------------- /R/AllGenerics.R: -------------------------------------------------------------------------------- 1 | #' @rdname CoverageExperiment 2 | #' @export 3 | setGeneric("CoverageExperiment", function(tracks, features, ...) standardGeneric("CoverageExperiment")) 4 | #' @rdname CoverageExperiment 5 | #' @export 6 | setGeneric("coarsen", function(x, window, ...) standardGeneric("coarsen")) 7 | -------------------------------------------------------------------------------- /R/CoverageExperiment.R: -------------------------------------------------------------------------------- 1 | #' CoverageExperiment 2 | #' 3 | #' #' @description 4 | #' 5 | #' `CoverageExperiment` objects store coverages for individual 6 | #' tracks over different sets of features. The `coverage` 7 | #' assay contains a separate matrix for each combination of 8 | #' track x features. `CoverageExperiment` objects are instantiated 9 | #' using the `CoverageExperiment()` #' function, and can be 10 | #' coarsened using the `coarsen()` function. 11 | #' 12 | #' @name CoverageExperiment 13 | #' @rdname CoverageExperiment 14 | #' 15 | #' @param tracks A genomic track imported as a `RleList` or a *named* list of 16 | #' genomic tracks. 17 | #' @param features A set of features imported as `GRanges` or a *named* 18 | #' `GRangesList`. 19 | #' @param width Width to resize each set of genomic features 20 | #' @param ignore.strand Logical, whether to not take the features strand 21 | #' information 22 | #' @param scale,center Logical, whether to scale and/or center tracks prior to 23 | #' summarization 24 | #' @param BPPARAM Passed to BiocParallel 25 | #' @param ... Passed to the relevant method 26 | #' @return A `CoverageExperiment` object 27 | #' 28 | #' @import GenomicRanges 29 | #' @import GenomeInfoDb 30 | #' @import SummarizedExperiment 31 | #' @import methods 32 | #' @importFrom rtracklayer BigWigFile 33 | #' @importFrom rtracklayer BigWigFileList 34 | #' @importFrom dplyr filter 35 | #' @importFrom dplyr bind_rows 36 | #' @importFrom dplyr bind_cols 37 | #' @importFrom dplyr mutate 38 | #' @importFrom dplyr relocate 39 | #' @importFrom BiocParallel bpparam 40 | #' @importFrom BiocParallel bplapply 41 | #' 42 | #' @examples 43 | #' library(rtracklayer) 44 | #' library(purrr) 45 | #' library(plyranges) 46 | #' TSSs_bed <- system.file("extdata", "TSSs.bed", package = "tidyCoverage") 47 | #' features <- import(TSSs_bed) |> filter(strand == '+') 48 | #' 49 | #' ############################################################################# 50 | #' ## 1. Creating a `CoverageExperiment` object from a single BigWigFile 51 | #' ############################################################################# 52 | #' 53 | #' RNA_fwd <- system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage") 54 | #' tracks <- BigWigFile(RNA_fwd) 55 | #' CoverageExperiment(tracks, features, width = 5000) 56 | #' 57 | #' ############################################################################# 58 | #' ## 2. Creating a `CoverageExperiment` object from a BigWigFileList 59 | #' ############################################################################# 60 | #' 61 | #' RNA_rev <- system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 62 | #' tracks <- BigWigFileList(list(RNA_fwd = RNA_fwd, RNA_rev = RNA_rev)) 63 | #' CoverageExperiment(tracks, features, width = 5000) 64 | #' 65 | #' ############################################################################# 66 | #' ## 3. Creating a `CoverageExperiment` object from imported bigwig files 67 | #' ############################################################################# 68 | #' 69 | #' tracks <- list( 70 | #' RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 71 | #' RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 72 | #' ) |> map(import, as = 'Rle') 73 | #' CoverageExperiment(tracks, features, width = 5000) 74 | #' 75 | #' ############################################################################# 76 | #' ## 4. Correct for strandness when recovering coverage 77 | #' ############################################################################# 78 | #' 79 | #' TSSs_bed <- system.file("extdata", "TSSs.bed", package = "tidyCoverage") 80 | #' features <- list( 81 | #' TSS_fwd = import(TSSs_bed) |> filter(strand == '+'), 82 | #' TSS_rev = import(TSSs_bed) |> filter(strand == '-') 83 | #' ) 84 | #' tracks <- list( 85 | #' RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 86 | #' RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 87 | #' ) |> map(import, as = 'Rle') 88 | #' CoverageExperiment(tracks, features, width = 5000, ignore.strand = FALSE) 89 | #' 90 | NULL 91 | 92 | ################################################################################ 93 | ################################################################################ 94 | ######################## MAIN METHOD FOR BIGWIGS ############################# 95 | ################################################################################ 96 | ################################################################################ 97 | 98 | #' @rdname CoverageExperiment 99 | #' @export 100 | 101 | setMethod( 102 | "CoverageExperiment", 103 | signature(tracks = "BigWigFileList", features = "GRangesList"), 104 | function( 105 | tracks, features, width = NULL, 106 | center = FALSE, scale = FALSE, 107 | ignore.strand = TRUE, 108 | window = 1, 109 | BPPARAM = BiocParallel::bpparam() 110 | ) { 111 | ## Check that input args are valid 112 | stopifnot(length(unique(names(tracks))) == length(tracks)) # named tracks list 113 | stopifnot(length(unique(names(features))) == length(features)) # named features GRangesList 114 | 115 | ## Extend and filter features 116 | tracks <- .set_seqinfo_bwfl(tracks) 117 | si <- seqinfo(tracks[[1]]) 118 | if (is.null(width)) .check_granges_widths(features) 119 | features <- lapply(features, .resize_granges, width, si) 120 | 121 | ## Prepare cData and rData 122 | cData <- data.frame( 123 | track = names(tracks) 124 | ) 125 | rData <- GRangesList(features) 126 | mcols(rData) <- data.frame( 127 | features = names(features), 128 | n = lengths(features) 129 | ) 130 | 131 | ## Extract coverage scores 132 | combs <- expand.grid(names(tracks), names(features)) |> 133 | setNames(c("tracks", "features")) 134 | l <- BiocParallel::bplapply(seq_len(nrow(combs)), function(K) { 135 | t <- combs[K, "tracks"] 136 | f <- combs[K, "features"] 137 | scores <- rtracklayer::import( 138 | tracks[[t]], 139 | selection = rtracklayer::BigWigSelection(ranges = features[[f]]), 140 | as = "NumericList", 141 | format = "bigWig" 142 | ) 143 | m <- .compute_cov( 144 | scores, features[[f]], 145 | scale = scale, center = center, ignore.strand = ignore.strand 146 | ) 147 | if (window > 1) { 148 | m <- .coarsen_mat(m, window) 149 | } 150 | return(m) 151 | }, BPPARAM = BPPARAM) 152 | names(l) <- paste(combs$tracks, combs$features, sep = '^') 153 | 154 | ## Fill out different assay matrices 155 | m <- matrix( 156 | list(), 157 | nrow = length(features), ncol = length(tracks) 158 | ) 159 | colnames(m) <- names(tracks) 160 | rownames(m) <- names(features) 161 | for (t in names(tracks)) { 162 | for (f in names(features)) { 163 | name <- paste(t, f, sep = '^') 164 | m[f, t][[1]] <- l[[name]] 165 | } 166 | } 167 | l_assays <- list(coverage = m) 168 | 169 | ## Instantiate and return the CoverageExperiment final object 170 | CE <- methods::new( 171 | "CoverageExperiment", 172 | SummarizedExperiment::SummarizedExperiment( 173 | rowRanges = rData, 174 | colData = cData, 175 | assays = l_assays 176 | ) 177 | ) 178 | return(CE) 179 | } 180 | ) 181 | 182 | #' @rdname CoverageExperiment 183 | #' @export 184 | 185 | setMethod( 186 | "CoverageExperiment", 187 | signature(tracks = "BigWigFileList", features = "GRanges"), 188 | function( 189 | tracks, features, ... 190 | ) { 191 | features <- GRangesList(features = features) 192 | CoverageExperiment( 193 | tracks, features, ... 194 | ) 195 | } 196 | ) 197 | 198 | #' @rdname CoverageExperiment 199 | #' @export 200 | 201 | setMethod( 202 | "CoverageExperiment", 203 | signature(tracks = "BigWigFileList", features = "list"), 204 | function( 205 | tracks, features, ... 206 | ) { 207 | features <- as(features, 'GRangesList') 208 | CoverageExperiment( 209 | tracks, features, ... 210 | ) 211 | } 212 | ) 213 | 214 | #' @rdname CoverageExperiment 215 | #' @importFrom BiocIO resource 216 | #' @export 217 | 218 | setMethod( 219 | "CoverageExperiment", 220 | signature(tracks = "BigWigFile", features = "GRangesList"), 221 | function( 222 | tracks, features, ... 223 | ) { 224 | tracks <- BigWigFileList(list(track = BiocIO::resource(tracks))) 225 | CoverageExperiment( 226 | tracks, features, ... 227 | ) 228 | } 229 | ) 230 | 231 | #' @rdname CoverageExperiment 232 | #' @export 233 | 234 | setMethod( 235 | "CoverageExperiment", 236 | signature(tracks = "BigWigFile", features = "GRanges"), 237 | function( 238 | tracks, features, ... 239 | ) { 240 | tracks <- BigWigFileList(list(track = BiocIO::resource(tracks))) 241 | features <- GRangesList(features = features) 242 | CoverageExperiment( 243 | tracks, features, ... 244 | ) 245 | } 246 | ) 247 | 248 | #' @rdname CoverageExperiment 249 | #' @export 250 | 251 | setMethod( 252 | "CoverageExperiment", 253 | signature(tracks = "BigWigFile", features = "list"), 254 | function( 255 | tracks, features, ... 256 | ) { 257 | tracks <- BigWigFileList(list(track = BiocIO::resource(tracks))) 258 | features <- as(features, 'GRangesList') 259 | CoverageExperiment( 260 | tracks, features, ... 261 | ) 262 | } 263 | ) 264 | 265 | ################################################################################ 266 | ################################################################################ 267 | ######################## MAIN METHOD FOR RleLists ############################ 268 | ################################################################################ 269 | ################################################################################ 270 | 271 | #' @rdname CoverageExperiment 272 | #' @export 273 | 274 | setMethod( 275 | "CoverageExperiment", 276 | signature(tracks = "list", features = "GRangesList"), 277 | function( 278 | tracks, features, width = NULL, 279 | center = FALSE, scale = FALSE, 280 | ignore.strand = TRUE, 281 | window = 1, 282 | BPPARAM = BiocParallel::bpparam() 283 | ) { 284 | ## Check that input args are valid 285 | stopifnot(length(unique(names(tracks))) == length(tracks)) # named tracks list 286 | stopifnot(length(unique(names(features))) == length(features)) # named features GRangesList 287 | 288 | ## Extend and filter features 289 | tracks <- .set_seqinfo(tracks) 290 | si <- seqinfo(tracks[[1]])[[1]] 291 | if (is.null(width)) .check_granges_widths(features) 292 | features <- lapply(features, .resize_granges, width, si) 293 | 294 | ## Prepare cData and rData 295 | cData <- data.frame( 296 | track = names(tracks) 297 | ) 298 | rData <- GRangesList(features) 299 | mcols(rData) <- data.frame( 300 | features = names(features), 301 | n = lengths(features) 302 | ) 303 | 304 | ## Extract coverage scores 305 | combs <- expand.grid(names(tracks), names(features)) |> 306 | setNames(c("tracks", "features")) 307 | l <- BiocParallel::bplapply(seq_len(nrow(combs)), function(K) { 308 | t <- combs[K, "tracks"] 309 | f <- combs[K, "features"] 310 | scores <- IRanges::NumericList(tracks[[t]][features[[f]]]) 311 | m <- .compute_cov( 312 | scores, features[[f]], 313 | scale = scale, center = center, ignore.strand = ignore.strand 314 | ) 315 | if (window > 1) { 316 | m <- .coarsen_mat(m, window) 317 | } 318 | return(m) 319 | }, BPPARAM = BPPARAM) 320 | names(l) <- paste(combs$tracks, combs$features, sep = '^') 321 | 322 | ## Fill out different assay matrices 323 | m <- matrix( 324 | list(), 325 | nrow = length(features), ncol = length(tracks) 326 | ) 327 | colnames(m) <- names(tracks) 328 | rownames(m) <- names(features) 329 | for (t in names(tracks)) { 330 | for (f in names(features)) { 331 | name <- paste(t, f, sep = '^') 332 | m[f, t][[1]] <- l[[name]] 333 | } 334 | } 335 | l_assays <- list(coverage = m) 336 | 337 | ## Instantiate and return the CoverageExperiment final object 338 | CE <- methods::new( 339 | "CoverageExperiment", 340 | SummarizedExperiment::SummarizedExperiment( 341 | rowRanges = rData, 342 | colData = cData, 343 | assays = l_assays 344 | ) 345 | ) 346 | return(CE) 347 | } 348 | ) 349 | 350 | #' @rdname CoverageExperiment 351 | #' @export 352 | 353 | setMethod( 354 | "CoverageExperiment", 355 | signature(tracks = "list", features = "GRanges"), 356 | function( 357 | tracks, features, ... 358 | ) { 359 | features <- GRangesList(features = features) 360 | CoverageExperiment( 361 | tracks, features, ... 362 | ) 363 | } 364 | ) 365 | 366 | #' @rdname CoverageExperiment 367 | #' @export 368 | 369 | setMethod( 370 | "CoverageExperiment", 371 | signature(tracks = "list", features = "list"), 372 | function( 373 | tracks, features, ... 374 | ) { 375 | features <- as(features, 'GRangesList') 376 | CoverageExperiment( 377 | tracks, features, ... 378 | ) 379 | } 380 | ) 381 | 382 | #' @rdname CoverageExperiment 383 | #' @export 384 | 385 | setMethod( 386 | "CoverageExperiment", 387 | signature(tracks = "RleList", features = "GRangesList"), 388 | function( 389 | tracks, features, ... 390 | ) { 391 | tracks <- list(track = tracks) 392 | CoverageExperiment( 393 | tracks, features, ... 394 | ) 395 | } 396 | ) 397 | 398 | #' @rdname CoverageExperiment 399 | #' @export 400 | 401 | setMethod( 402 | "CoverageExperiment", 403 | signature(tracks = "RleList", features = "GRanges"), 404 | function( 405 | tracks, features, ... 406 | ) { 407 | tracks <- list(track = tracks) 408 | features <- GRangesList(features = features) 409 | CoverageExperiment( 410 | tracks, features, ... 411 | ) 412 | } 413 | ) 414 | 415 | #' @rdname CoverageExperiment 416 | #' @export 417 | 418 | setMethod( 419 | "CoverageExperiment", 420 | signature(tracks = "RleList", features = "list"), 421 | function( 422 | tracks, features, ... 423 | ) { 424 | tracks <- list(track = tracks) 425 | features <- as(features, 'GRangesList') 426 | CoverageExperiment( 427 | tracks, features, ... 428 | ) 429 | } 430 | ) 431 | -------------------------------------------------------------------------------- /R/aggregate.R: -------------------------------------------------------------------------------- 1 | #' aggregate 2 | #' 3 | #' Bin coverage contained in a `CoverageExperiment` into an 4 | #' `AggregatedCoverage` object. 5 | #' 6 | #' @name AggregatedCoverage 7 | #' @aliases aggregate,CoverageExperiment-method 8 | #' @rdname AggregatedCoverage 9 | #' 10 | #' @param x a `CoverageExperiment` object 11 | #' @param ... ignored 12 | #' @param bin an integer to bin each assay by. The `width` of the 13 | #' `AggregatedCoverage` object should be a multiple of `bin`. 14 | #' @return an `AggregatedCoverage` object 15 | #' 16 | #' @importFrom S4Vectors aggregate 17 | #' @export 18 | #' @examples 19 | #' data(ce) 20 | #' aggregate(ce, bin = 10) 21 | 22 | setMethod("aggregate", signature(x = "CoverageExperiment"), 23 | function(x, bin = 1, ...) { 24 | m0 <- matrix( 25 | list(), 26 | nrow = length(rowData(x)$features), ncol = length(colData(x)$track) 27 | ) 28 | colnames(m0) <- colData(x)$track 29 | rownames(m0) <- rowData(x)$features 30 | assays <- c("mean", "median", "min", "max", "sd", "se", "ci_low", "ci_high") 31 | l_assays <- vector("list", length = length(assays)) 32 | names(l_assays) <- assays 33 | for (assay in assays) l_assays[[assay]] <- m0 34 | for (t in colData(x)$track) { 35 | for (f in rowData(x)$features) { 36 | m <- assay(x, 'coverage')[f, t][[1]] 37 | df <- .summarize_cov(m) 38 | for (assay in assays) { 39 | vec <- df[[assay]] 40 | if (bin > 1) { 41 | vec <- .coarsen_vec( 42 | vec, bin = bin, FUN = mean, na.rm = TRUE 43 | ) 44 | } 45 | l_assays[[assay]][f, t][[1]] <- vec 46 | } 47 | } 48 | } 49 | assays(x) <- l_assays 50 | AC <- methods::new( 51 | "AggregatedCoverage", 52 | SummarizedExperiment::SummarizedExperiment( 53 | rowRanges = rowRanges(x), 54 | colData = colData(x), 55 | assays = l_assays 56 | ) 57 | ) 58 | return(AC) 59 | } 60 | ) 61 | -------------------------------------------------------------------------------- /R/as_tibble.R: -------------------------------------------------------------------------------- 1 | #' as_tibble 2 | #' 3 | #' Coerce an `CoverageExperiment` or `AggregatedCoverage` object into a `tibble` 4 | #' 5 | #' @name as_tibble-methods 6 | #' @rdname as_tibble-methods 7 | #' @param x an `CoverageExperiment` object 8 | #' @param ... ignored 9 | #' @return `tibble` 10 | #' 11 | #' @importFrom tidyr any_of 12 | #' @importFrom tidyr all_of 13 | #' @importFrom tidyr pivot_longer 14 | #' @importFrom dplyr as_tibble 15 | #' @examples 16 | #' data(ac) 17 | #' as_tibble(ac) 18 | NULL 19 | 20 | #' @rdname as_tibble-methods 21 | #' @export 22 | 23 | as_tibble.AggregatedCoverage <- function(x, ...) { 24 | tracks <- colData(x)$track 25 | features <- rowData(x)$features 26 | assays <- names(assays(x)) 27 | w <- width(rowRanges(x)[[1]])[[1]] 28 | bin <- w / length(assay(x, "mean")[1, 1][[1]]) 29 | lapply(tracks, function(t) { 30 | lapply(features, function(f) { 31 | lapply(assays(x)[assays], `[[`, f, t) |> 32 | stats::setNames(assays) |> 33 | dplyr::bind_cols() |> 34 | dplyr::mutate( 35 | coord = seq(-w/2, w/2-1, by = bin), 36 | track = factor(t, levels = tracks), 37 | features = factor(f, levels = features) 38 | ) |> 39 | dplyr::relocate(coord) |> 40 | dplyr::relocate(features) |> 41 | dplyr::relocate(track) 42 | }) |> dplyr::bind_rows() 43 | }) |> 44 | dplyr::bind_rows() |> 45 | dplyr::left_join(colData(x) |> as.data.frame(), by = 'track') |> 46 | dplyr::mutate(.feature = features, .sample = track) |> 47 | dplyr::relocate(.feature) |> 48 | dplyr::relocate(.sample) 49 | } 50 | -------------------------------------------------------------------------------- /R/coarsen.R: -------------------------------------------------------------------------------- 1 | #' @name coarsen 2 | #' @aliases coarsen,CoverageExperiment-method 3 | #' @rdname CoverageExperiment 4 | #' 5 | #' @param x a `CoverageExperiment` object 6 | #' @param window an integer to coarsen coverage by. 7 | #' @param BPPARAM Passed to BiocParallel. 8 | #' 9 | #' @export 10 | #' @examples 11 | #' ############################################################################# 12 | #' ## Aggregating a `CoverageExperiment` object 13 | #' ############################################################################# 14 | #' data(ce) 15 | #' coarsen(ce, window = 10) 16 | setMethod("coarsen", signature(x = "CoverageExperiment"), 17 | function(x, window = 1, BPPARAM = BiocParallel::bpparam()) { 18 | combs <- expand.grid(colData(x)$track, rowData(x)$features) |> 19 | setNames(c("tracks", "features")) 20 | l <- BiocParallel::bplapply(seq_len(nrow(combs)), function(K) { 21 | t <- combs[K, "tracks"] 22 | f <- combs[K, "features"] 23 | mat <- .coarsen_mat( 24 | assay(x, 'coverage')[f, t][[1]], 25 | bin = window, FUN = mean, na.rm = TRUE 26 | ) 27 | }, BPPARAM = BPPARAM) 28 | names(l) <- paste(combs$tracks, combs$features, sep = '^') 29 | for (t in colData(x)$track) { 30 | for (f in rowData(x)$features) { 31 | name <- paste(t, f, sep = '^') 32 | assays(x)[['coverage']][f, t][[1]] <- l[[name]] 33 | } 34 | } 35 | return(x) 36 | } 37 | ) 38 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' Example `CoverageExperiment` and `AggregatedCoverage` objects 2 | #' 3 | #' Two example objects are provided in the `tidyCoverage` package: 4 | #' - `ce`: a `CoverageExperiment` dataset containing stranded RNA-seq coverage 5 | #' (forward and reverse) over Scc1 peaks (± 1kb). 6 | #' - `ac`: an `AggregatedCoverage` object obtained with `aggregate(ce)`. 7 | #' 8 | #' Data was generated in yeast (S288c) and aligned to reference R64-1-1. 9 | #' 10 | #' @name data 11 | #' @rdname data 12 | #' @format `CoverageExperiment` object containing 1 features set and 2 tracks. 13 | #' 14 | #' @usage data(ce) 15 | "ce" 16 | 17 | #' @rdname data 18 | #' @format `AggregatedCoverage` object containing 1 features set and 2 tracks. 19 | #' @usage data(ac) 20 | "ac" 21 | -------------------------------------------------------------------------------- /R/expand.R: -------------------------------------------------------------------------------- 1 | #' Expand a CoverageExperiment object 2 | #' 3 | #' @description 4 | #' A `CoverageExperiment` object can be coerced into a `tibble` using the 5 | #' `tidySummarizedExperiment` package, but this will not turn 6 | #' each coverage matrix into a "long" format. The `expand` function 7 | #' provided here allows one to coerce a `CoverageExperiment` 8 | #' object into a long data frame, and adds the `ranges` 9 | #' and `seqnames` to the resulting `tibble`. 10 | #' 11 | #' @name expand,CoverageExperiment 12 | #' @aliases expand,CoverageExperiment-method 13 | #' @rdname expand 14 | #' 15 | #' @param data a `CoverageExperiment` object 16 | #' @param ...,.name_repair ignored 17 | #' @return a `tibble` object 18 | #' 19 | #' @importFrom tidyr expand 20 | #' @export 21 | #' @examples 22 | #' data(ce) 23 | #' ce 24 | #' 25 | #' expand(ce) 26 | 27 | expand.CoverageExperiment <- function(data, ..., .name_repair = NULL) { 28 | tracks <- colData(data)$track 29 | features <- rowData(data)$features 30 | w <- width(rowRanges(data)[[1]])[[1]] 31 | bin <- w / ncol(assay(data, "coverage")[1, 1][[1]]) 32 | df <- lapply(features, function(f) { 33 | rr <- rowRanges(data)[[f]] 34 | rrdf <- as.data.frame(rr) 35 | coord <- lapply(seq_len(nrow(rrdf)), function(K) seq(rrdf[K, 'start'], rrdf[K, 'end'], by = bin)) |> unlist() 36 | coord.scaled <- lapply(seq_len(nrow(rrdf)), function(K) seq(-w/2, w/2-1, by = bin)) |> unlist() 37 | lapply(tracks, function(t) { 38 | m <- assay(data, "coverage")[f, t][[1]] |> 39 | as.data.frame() |> 40 | dplyr::mutate( 41 | track = factor(t, levels = tracks), 42 | features = factor(f, levels = features), 43 | chr = as.vector(seqnames(rr)), 44 | ranges = as.character(rr), 45 | strand = as.vector(strand(rr)) 46 | ) |> 47 | dplyr::relocate(tidyr::all_of(c("track", "features", "chr", "ranges", "strand"))) 48 | d <- tidyr::pivot_longer( 49 | m, 50 | !tidyr::any_of(c("track", "features", "chr", "ranges", "strand", "coord.scaled")), 51 | names_to = "coord", values_to = "coverage" 52 | ) 53 | d$coord <- coord 54 | d$coord.scaled <- coord.scaled 55 | d 56 | }) |> dplyr::bind_rows() 57 | }) |> 58 | dplyr::bind_rows() |> 59 | dplyr::left_join(colData(data) |> as.data.frame(), by = 'track') |> 60 | dplyr::group_by(track, features, ranges) 61 | return(df) 62 | } 63 | -------------------------------------------------------------------------------- /R/geoms.R: -------------------------------------------------------------------------------- 1 | #' Plotting functions 2 | #' 3 | #' #' @description 4 | #' 5 | #' Plotting functions for tidyCoverage objects 6 | #' 7 | #' @name ggplot-tidyCoverage 8 | #' @rdname ggplot-tidyCoverage 9 | #' 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 22 | #' @return A `ggplot` object` 23 | #' 24 | #' @import ggplot2 25 | #' @importFrom scales oob_squish 26 | #' @importFrom scales unit_format 27 | #' 28 | #' @examples 29 | #' library(rtracklayer) 30 | #' library(plyranges) 31 | #' library(ggplot2) 32 | #' library(purrr) 33 | #' TSSs_bed <- system.file("extdata", "TSSs.bed", package = "tidyCoverage") 34 | #' features <- list( 35 | #' TSS_fwd = 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")) 38 | #' ) 39 | #' tracks <- list( 40 | #' RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 41 | #' RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage"), 42 | #' Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage") 43 | #' ) |> map(import, as = 'Rle') 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') 72 | NULL 73 | 74 | GeomAggrCoverage <- ggplot2::ggproto("GeomAggrCoverage", ggplot2::Geom, 75 | setup_params = function(data, params) { 76 | params$ci <- params$ci 77 | params 78 | }, 79 | extra_params = c("na.rm"), 80 | required_aes = c("x", "y", "ymin", "ymax"), 81 | default_aes = ggplot2::aes( 82 | colour = "black", 83 | linewidth = 1, 84 | linetype = 1, 85 | alpha = 0.4 86 | ), 87 | draw_group = function(data, params, coord, ci = TRUE, ...) { 88 | forLine <- transform(data, alpha = 1) 89 | forRibbon <- transform( 90 | data, 91 | alpha = data$alpha, 92 | fill = data$colour, 93 | colour = NA 94 | ) 95 | grid::gList( 96 | if (ci) ggplot2::GeomRibbon$draw_panel(forRibbon, params, coord, ...), 97 | ggplot2::GeomLine$draw_panel(forLine, params, coord, ...) 98 | ) 99 | }, 100 | draw_key = ggplot2::draw_key_smooth 101 | ) 102 | 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 141 | #' @export 142 | 143 | geom_aggrcoverage <- function( 144 | mapping = NULL, 145 | data = NULL, 146 | ..., 147 | unit = c('kb', 'Mb', 'b'), 148 | ci = TRUE, 149 | grid = FALSE, 150 | na.rm = FALSE, 151 | show.legend = NA, 152 | inherit.aes = TRUE 153 | ) { 154 | m <- ggplot2::aes(x = coord, y = mean, ymin = ci_low, ymax = ci_high, group = interaction(.sample, .feature)) 155 | if (!is.null(mapping)) m <- utils::modifyList(m, mapping) 156 | 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")) 210 | ) 211 | 212 | } 213 | 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: -------------------------------------------------------------------------------- 1 | utils::globalVariables(c( 2 | ".", 3 | "ci_low", 4 | "ci_high", 5 | "coord", 6 | "feature", 7 | "features", 8 | ".feature", 9 | ".sample", 10 | "track" 11 | )) 12 | -------------------------------------------------------------------------------- /R/reexports.R: -------------------------------------------------------------------------------- 1 | #' @name reexports 2 | #' @return Depending on the re-exported function 3 | #' @keywords internal 4 | #' @examples 5 | #' 1 + 1 6 | NULL 7 | 8 | #' @rdname reexports 9 | #' @importFrom dplyr as_tibble 10 | #' @export 11 | dplyr::as_tibble 12 | 13 | #' @rdname reexports 14 | #' @importFrom tidyr expand 15 | #' @export 16 | tidyr::expand 17 | 18 | #' @rdname reexports 19 | #' @importFrom S4Vectors aggregate 20 | #' @export 21 | S4Vectors::aggregate 22 | -------------------------------------------------------------------------------- /R/show.R: -------------------------------------------------------------------------------- 1 | #' show 2 | #' 3 | #' show method for `CoverageExperiment` and `AggregatedCoverage` objects 4 | #' 5 | #' @name show 6 | #' @aliases show,CoverageExperiment-method 7 | #' @aliases show,AggregatedCoverage-method 8 | #' 9 | #' @param object a `CoverageExperiment` or `AggregatedCoverage` object 10 | #' @param setup a setup object returned from [pillar::tbl_format_setup()]. 11 | #' @importFrom rlang names2 12 | #' @importFrom pillar align 13 | #' @importFrom pillar get_extent 14 | #' @importFrom pillar style_subtle 15 | #' @importFrom pillar tbl_format_header 16 | #' @importFrom fansi strwrap_ctl 17 | #' @importFrom purrr map_chr 18 | #' @importFrom cli console_width 19 | #' @importFrom cli symbol 20 | #' @importFrom vctrs new_data_frame 21 | #' @importFrom SummarizedExperiment assayNames 22 | #' @importFrom stats setNames 23 | #' @export 24 | #' 25 | #' @inherit tibble::formatting 26 | #' @return `Prints a message to the console describing 27 | #' the contents of the `CoverageExperiment` or `AggregatedCoverage` objects. 28 | #' @examples 29 | #' data(ce) 30 | #' print(ce) 31 | #' data(ac) 32 | #' print(ac) 33 | NULL 34 | 35 | #' @name show 36 | #' @export 37 | 38 | setMethod("show", signature("CoverageExperiment"), function(object) { 39 | w <- width(rowRanges(object)[[1]][1]) 40 | if ( 41 | isTRUE(x = getOption(x = "restore_SummarizedExperiment_show", default = FALSE)) | 42 | isTRUE(x = getOption(x = "restore_CoverageExperiment_show", default = FALSE)) | 43 | isFALSE("tidySummarizedExperiment" %in% .packages()) 44 | ) { 45 | f <- getMethod(f = "show", signature = "SummarizedExperiment", 46 | where = asNamespace(ns = "SummarizedExperiment")) 47 | f(object = object) 48 | cat(paste0("width: ", w, '\n')) 49 | } 50 | else { 51 | print(object) 52 | } 53 | }) 54 | 55 | #' @name show 56 | #' @export 57 | 58 | setMethod("show", signature("AggregatedCoverage"), function(object) { 59 | w <- width(rowRanges(object)[[1]][1]) 60 | b <- w / length(assay(object, "mean")[1, 1][[1]]) 61 | if ( 62 | isTRUE(x = getOption(x = "restore_SummarizedExperiment_show", default = FALSE)) | 63 | isTRUE(x = getOption(x = "restore_CoverageExperiment_show", default = FALSE)) | 64 | isFALSE("tidySummarizedExperiment" %in% .packages()) 65 | ) { 66 | f <- getMethod(f = "show", signature = "SummarizedExperiment", 67 | where = asNamespace(ns = "SummarizedExperiment")) 68 | f(object = object) 69 | cat(paste0("width: ", w, '\n')) 70 | cat(paste0("binning: ", b, '\n')) 71 | } 72 | else { 73 | print(object) 74 | } 75 | }) 76 | 77 | #' @name show 78 | #' @export 79 | 80 | print.CoverageExperiment <- function (x, ..., n = NULL) { 81 | .x <- x 82 | if (!{ 83 | isTRUE(x = getOption(x = "restore_SummarizedExperiment_show", default = FALSE)) | 84 | isTRUE(x = getOption(x = "restore_CoverageExperiment_show", default = FALSE)) | 85 | isFALSE("tidySummarizedExperiment" %in% .packages()) 86 | }) { 87 | x <- as_tibble(.x) 88 | x <- vctrs::new_data_frame(x, class=c("tidyCoverageExperiment", "tbl")) 89 | attr(x, "width") <- width(rowRanges(.x)[[1]][1]) 90 | attr(x, "binning") <- attr(x, "width") / length(assay(.x, 1)[1, 1][[1]]) 91 | attr(x, "number_of_features") <- nrow(.x) 92 | attr(x, "number_of_tracks") <- ncol(.x) 93 | attr(x, "assay_names") <- names(assays(.x)) 94 | attr(x, "named_header") <- sprintf( 95 | "%s %s %s", 96 | nrow(x), 97 | cli::symbol$times, 98 | ncol(x) 99 | ) |> setNames("A CoverageExperiment-tibble abstraction") 100 | print(x) 101 | } 102 | else { 103 | show(x) 104 | return(invisible(x)) 105 | } 106 | } 107 | 108 | #' @name show 109 | #' @export 110 | 111 | print.AggregatedCoverage <- function (x, ..., n = NULL) { 112 | .x <- x 113 | if (!{ 114 | isTRUE(x = getOption(x = "restore_SummarizedExperiment_show", default = FALSE)) | 115 | isTRUE(x = getOption(x = "restore_CoverageExperiment_show", default = FALSE)) | 116 | isFALSE("tidySummarizedExperiment" %in% .packages()) 117 | }) { 118 | x <- as_tibble(.x) 119 | x <- vctrs::new_data_frame(x, class=c("tidyAggregatedCoverage", "tbl")) 120 | attr(x, "width") <- width(rowRanges(.x)[[1]][1]) 121 | attr(x, "binning") <- attr(x, "width") / length(assay(.x, 1)[1, 1][[1]]) 122 | attr(x, "number_of_features") <- nrow(.x) 123 | attr(x, "number_of_tracks") <- ncol(.x) 124 | attr(x, "assay_names") <- names(assays(.x)) 125 | attr(x, "named_header") <- sprintf( 126 | "%s %s %s", 127 | nrow(x), 128 | cli::symbol$times, 129 | ncol(x) 130 | ) |> setNames("An AggregatedCoverage-tibble abstraction") 131 | print(x) 132 | } 133 | else { 134 | show(x) 135 | return(invisible(x)) 136 | } 137 | } 138 | 139 | #' @name show 140 | #' @export 141 | 142 | tbl_format_header.tidyCoverageExperiment <- function(x, setup, ...) { 143 | width <- x |> attr("width") 144 | number_of_features <- x |> attr("number_of_features") 145 | number_of_tracks <- x |> attr("number_of_tracks") 146 | named_header <- x |> attr("named_header") 147 | assay_names <- x |> attr("assay_names") 148 | if (all(rlang::names2(named_header) == "")) { 149 | header <- named_header 150 | } else { 151 | header <- 152 | paste0( 153 | align(paste0(rlang::names2(named_header), ":"), space="\U00A0"), 154 | " ", 155 | named_header 156 | ) |> 157 | # Add further info 158 | append(sprintf( 159 | "\033[90m features=%s | tracks=%s | assays=%s\033[39m", 160 | number_of_features, 161 | number_of_tracks, 162 | assay_names |> paste(collapse=", ") 163 | ), after = 1) |> 164 | # Add further info re: width 165 | append(sprintf( 166 | "\033[90m width=%s\033[39m", 167 | width 168 | )) 169 | } 170 | pillar::style_subtle(.pillar___format_comment(header, width=setup$width)) 171 | } 172 | 173 | #' @name show 174 | #' @export 175 | 176 | tbl_format_header.tidyAggregatedCoverage <- function(x, setup, ...) { 177 | width <- x |> attr("width") 178 | binning <- x |> attr("binning") 179 | number_of_features <- x |> attr("number_of_features") 180 | number_of_tracks <- x |> attr("number_of_tracks") 181 | named_header <- x |> attr("named_header") 182 | assay_names <- x |> attr("assay_names") 183 | if (all(rlang::names2(named_header) == "")) { 184 | header <- named_header 185 | } else { 186 | header <- 187 | paste0( 188 | align(paste0(rlang::names2(named_header), ":"), space="\U00A0"), 189 | " ", 190 | named_header 191 | ) |> 192 | # Add further info 193 | append(sprintf( 194 | "\033[90m features=%s | tracks=%s | assays=%s\033[39m", 195 | number_of_features, 196 | number_of_tracks, 197 | assay_names |> paste(collapse=", ") 198 | ), after = 1) |> 199 | # Add further info re: width/binning 200 | append(sprintf( 201 | "\033[90m width=%s | binning=%s\033[39m", 202 | width, 203 | binning 204 | )) 205 | } 206 | pillar::style_subtle(.pillar___format_comment(header, width=setup$width)) 207 | } 208 | 209 | .pillar___format_comment <- function (x, width) { 210 | if (length(x) == 0L) { 211 | return(character()) 212 | } 213 | purrr::map_chr(x, .pillar___wrap, prefix="# ", 214 | width=min(width, cli::console_width())) 215 | } 216 | 217 | .pillar___strwrap2 <- function (x, width, indent) { 218 | fansi::strwrap_ctl(x, width=max(width, 0), indent=indent, 219 | exdent=indent + 2) 220 | } 221 | 222 | .pillar___wrap <- function (..., indent=0, prefix="", width) { 223 | x <- paste0(..., collapse="") 224 | wrapped <- .pillar___strwrap2(x, width - pillar::get_extent(prefix), indent) 225 | wrapped <- paste0(prefix, wrapped) 226 | wrapped <- gsub("\U00A0", " ", wrapped) 227 | paste0(wrapped, collapse="\n") 228 | } 229 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | .set_seqinfo <- function(tracks) { 2 | n <- names(tracks) 3 | sls <- lapply(tracks, lengths) 4 | has_seqlengths <- any(!is.na(lapply(sls, sum))) 5 | if (!has_seqlengths) { 6 | sis <- lapply(tracks, function(rle) { 7 | Seqinfo( 8 | names(lengths(rle)), 9 | lengths(rle) 10 | ) 11 | }) |> unique() 12 | if (length(unique(sis)) > 1) 13 | warning("EXPERIMENTAL: More than 1 seqinfo inferred from the tracks. Using `seqinfo` from the first track.") 14 | si <- sis[[1]] 15 | } 16 | else { 17 | sl <- sls[[which(!is.na(lapply(sls, sum)))[[1]]]] 18 | si <- list(Seqinfo( 19 | names(sl), 20 | sl 21 | )) 22 | } 23 | tracks <- lapply(tracks, function(rle) { 24 | GenomeInfoDb::seqinfo(rle) <- si 25 | return(rle) 26 | }) 27 | names(tracks) <- n 28 | return(tracks) 29 | } 30 | 31 | .set_seqinfo_bwfl <- function(tracks) { 32 | n <- names(tracks) 33 | sis <- lapply(tracks, seqinfo) |> unique() 34 | if (length(sis) > 1) 35 | warning("EXPERIMENTAL: More than 1 seqinfo inferred from the tracks. Using `seqinfo` from the first track.") 36 | si <- sis[[1]] 37 | return(tracks) 38 | } 39 | 40 | .resize_granges <- function(gr, w, seqinfo) { 41 | GenomeInfoDb::seqlevels(gr, pruning.mode = "coarse") <- GenomeInfoDb::seqlevels(seqinfo) 42 | GenomeInfoDb::seqinfo(gr) <- seqinfo 43 | if (is.null(w)) { 44 | w <- width(gr) |> unlist() |> unique() 45 | } 46 | else { 47 | gr <- suppressWarnings(resize(gr, fix = 'center', width = w)) 48 | } 49 | gr <- trim(gr) 50 | gr <- gr[width(gr) == w] 51 | gr 52 | } 53 | 54 | .check_granges_widths <- function(features) { 55 | ws <- lapply(features, width) |> unlist() |> unique() 56 | if (length(ws) > 1) 57 | stop("Input GRanges do not all have the same width. 58 | Use resize() to fix width prior to coverage data extraction.") 59 | } 60 | 61 | #' @importFrom IRanges NumericList 62 | #' @importFrom stats qt 63 | 64 | .compute_cov <- function(scores, gr, center, scale, ignore.strand = TRUE) { 65 | m <- as.matrix(scores) 66 | if (!ignore.strand) { 67 | m <- data.frame(m) 68 | which.flip <- which(as.vector(strand(gr)) == '-') 69 | m[which.flip, ] <- rev(m[which.flip, ]) 70 | m <- as.matrix(m) 71 | } 72 | if (any(c(center, scale))) { 73 | m <- t(scale(t(m), center = center, scale = scale)) 74 | } 75 | m 76 | } 77 | 78 | .summarize_cov <- function(scores) { 79 | mean <- colMeans(scores, na.rm = TRUE) 80 | median <- apply(scores, 2, median, na.rm = TRUE) 81 | min <- apply(scores, 2, min, na.rm = TRUE) 82 | max <- apply(scores, 2, max, na.rm = TRUE) 83 | sd <- apply(scores, 2, sd, na.rm = TRUE) 84 | se <- sd/sqrt(nrow(scores)) 85 | ci_low <- mean - stats::qt(1 - (0.05 / 2), nrow(scores) - 1) * se 86 | ci_high <- mean + stats::qt(1 - (0.05 / 2), nrow(scores) - 1) * se 87 | data.frame( 88 | coord = seq(-ncol(scores)/2, ncol(scores)/2-1, 1), 89 | mean = mean, median = median, min = min, max = max, 90 | sd = sd, se = se, ci_low = ci_low, ci_high = ci_high 91 | ) 92 | } 93 | 94 | .coarsen_vec <- function(x, bin, FUN, ...) { 95 | if ({length(x) %% bin} != 0) stop( 96 | "The length of the provided vector should be divided by the bin size without remainder. 97 | Please adjust `bin` argument." 98 | ) 99 | stats::aggregate( 100 | x, 101 | by = list(rep(seq(1, length(x)/bin), each = bin)), 102 | FUN = FUN, ... 103 | )$x 104 | } 105 | 106 | .coarsen_mat <- function(x, bin, FUN = mean, ...) { 107 | if ({ncol(x) %% bin} != 0) stop( 108 | "The column number of the provided matrix should be divided by the window size without remainder. 109 | Please adjust `window` argument." 110 | ) 111 | apply(x, 1, function(vec) { 112 | stats::aggregate( 113 | vec, 114 | by = list(rep(seq(1, length(vec)/bin), each = bin)), 115 | FUN = FUN, ... 116 | )$x 117 | }) |> t() 118 | } 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![DOI](https://img.shields.io/badge/Bioinformatics-10.1038/10.1093/bioinformatics/btae487x-blue)](https://doi.org/10.1093/bioinformatics/btae487) 2 | [![](https://img.shields.io/badge/lifecycle-stable-green.svg)](https://www.tidyverse.org/lifecycle/#stable) 3 | 4 | # tidyCoverage 5 | 6 | The `tidyCoverage` R package provides a framework for rapid investigation of collections of genomic tracks over genomic features, relying on the principle of tidy data manipulation. It relies on `CoverageExperiment` and `AggregatedCoverage` classes, directly extending the `SummarizedExperiment` fundamental class, 7 | 8 | If you are using `tidyCoverage`, please consider citing: 9 | 10 | Serizay J, Koszul R (2024). “Epigenomics coverage data extraction and aggregation in R with tidyCoverage.” _Bioinformatics_ *40*, doi:10.1093/bioinformatics/btae487 . 11 | 12 | ## Installation 13 | 14 | In `R >= 4.4` and `Bioconductor >= 3.19`: 15 | 16 | ```r 17 | if (!require("BiocManager", quietly = TRUE)) 18 | install.packages("BiocManager") 19 | 20 | BiocManager::install("tidyCoverage") 21 | ``` 22 | 23 | ## Load libraries and example datasets 24 | 25 | ```r 26 | library(tidyCoverage) 27 | library(tidySummarizedExperiment) 28 | library(rtracklayer) 29 | library(plyranges) 30 | library(purrr) 31 | library(ggplot2) 32 | 33 | # ~~~~~~~~~~~~~~~ Import genomic features into a named list ~~~~~~~~~~~~~~~ # 34 | features <- list( 35 | TSSs = system.file("extdata", "TSSs.bed", package = "tidyCoverage"), 36 | conv_sites = system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage") 37 | ) |> map(~ import(.x)) 38 | 39 | # ~~~~~~~~~~~~ Import coverage tracks into a `BigWigFileList` ~~~~~~~~~~~~~ # 40 | tracks <- list( 41 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage"), 42 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 43 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage"), 44 | PolII = system.file("extdata", "PolII.bw", package = "tidyCoverage"), 45 | MNase = system.file("extdata", "MNase.bw", package = "tidyCoverage") 46 | ) |> BigWigFileList() 47 | ``` 48 | 49 | ## Extract coverage for each track over each set of features 50 | 51 | ```r 52 | CE <- CoverageExperiment(tracks, features, width = 5000, ignore.strand = FALSE) 53 | ``` 54 | 55 | ## Plot tracks coverage aggregated over genomic features 56 | 57 | ```r 58 | CE |> 59 | filter(track %in% c('MNase', 'PolII')) |> 60 | filter(features == 'TSSs') |> 61 | aggregate() |> 62 | ggplot() + 63 | geom_aggrcoverage(aes(col = track)) + 64 | facet_grid(track ~ ., scales = "free") + 65 | labs(x = 'Distance from TSS', y = 'Signal coverage') 66 | ``` 67 | 68 | ![](man/figures/aggr-cov.png) 69 | 70 | ## Plot coverage over a single locus 71 | 72 | ```r 73 | CoverageExperiment(tracks, GRanges("II:450001-455000")) |> 74 | expand() |> 75 | ggplot() + 76 | geom_coverage(aes(fill = track)) + 77 | facet_grid(track~., scales = 'free') 78 | ``` 79 | 80 | ![](man/figures/cov.png) 81 | 82 | ## Related projects 83 | 84 | A number of `CRAN`, `Bioconductor` or `GitHub` packages already exist to enable genomic track 85 | data visualization, for instance: 86 | 87 | - `Gviz` [\[Bioconductor\]](https://www.bioconductor.org/packages/release/bioc/html/Gviz.html) 88 | - `soGGi` [\[Bioconductor\]](https://www.bioconductor.org/packages/release/bioc/html/soGGi.html) 89 | - `GenomicPlot` [\[Bioconductor\]](https://www.bioconductor.org/packages/release/bioc/html/GenomicPlot.html) 90 | - `plotgardener` [\[Bioconductor\]](https://www.bioconductor.org/packages/release/bioc/html/plotgardener.html) 91 | - `genomation` [\[Bioconductor\]](https://www.bioconductor.org/packages/release/bioc/html/genomation.html) 92 | - `ggcoverage` [\[GitHub\]](https://github.com/showteeth/ggcoverage) 93 | - `GenomicScores` [\[Bioconductor\]](https://www.bioconductor.org/packages/release/bioc/html/GenomicScores.html) 94 | 95 | Compared to these existing solutions, `tidyCoverage` directly extends `SummarizedExperiment` infrastructure and 96 | follows [tidy "omics" principles](https://www.biorxiv.org/content/10.1101/2023.09.10.557072v2). It does 97 | not directly provide **plotting** functionalities, but instead focuses on data recovery, structure and coercion, 98 | using a familiar grammar and standard representation of the data. 99 | This ensures seamless integration of genomic track investigation in exisiting 100 | `Bioconductor` and data analysis workflows. 101 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: ~ 2 | template: 3 | bootstrap: 5 4 | 5 | navbar: 6 | structure: 7 | left: [intro, reference] 8 | right: [search, github] 9 | -------------------------------------------------------------------------------- /data/ac.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/data/ac.rda -------------------------------------------------------------------------------- /data/ce.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/data/ce.rda -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | bibentry( 2 | bibtype = "Article", 3 | author = c( 4 | person(c("Jacques"), "Serizay"), 5 | person(c("Romain"), "Koszul") 6 | ), 7 | title = "Epigenomics coverage data extraction and aggregation in R with tidyCoverage", 8 | journal = "Bioinformatics", 9 | year = "2024", 10 | volume = "40", 11 | pages = "btae487", 12 | doi = "10.1093/bioinformatics/btae487" 13 | ) 14 | -------------------------------------------------------------------------------- /inst/extdata/MNase.bw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/inst/extdata/MNase.bw -------------------------------------------------------------------------------- /inst/extdata/PolII.bw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/inst/extdata/PolII.bw -------------------------------------------------------------------------------- /inst/extdata/RNA.fwd.bw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/inst/extdata/RNA.fwd.bw -------------------------------------------------------------------------------- /inst/extdata/RNA.rev.bw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/inst/extdata/RNA.rev.bw -------------------------------------------------------------------------------- /inst/extdata/Scc1.bw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/inst/extdata/Scc1.bw -------------------------------------------------------------------------------- /inst/extdata/conv_transcription_loci.bed: -------------------------------------------------------------------------------- 1 | I 1298 1299 . 0 + 2 | I 4970 4971 . 0 + 3 | I 10981 10982 . 0 + 4 | I 12893 12894 . 0 + 5 | I 22121 22122 . 0 + 6 | I 36398 36399 . 0 + 7 | I 42799 42800 . 0 + 8 | I 51780 51781 . 0 + 9 | I 54950 54951 . 0 + 10 | I 57899 57900 . 0 + 11 | I 65590 65591 . 0 + 12 | I 74932 74933 . 0 + 13 | I 79461 79462 . 0 + 14 | I 80647 80648 . 0 + 15 | I 83280 83281 . 0 + 16 | I 87802 87803 . 0 + 17 | I 100045 100046 . 0 + 18 | I 118438 118439 . 0 + 19 | I 124300 124301 . 0 + 20 | I 126843 126844 . 0 + 21 | I 134129 134130 . 0 + 22 | I 137603 137604 . 0 + 23 | I 139377 139378 . 0 + 24 | I 147561 147562 . 0 + 25 | I 153969 153970 . 0 + 26 | I 156518 156519 . 0 + 27 | I 160194 160195 . 0 + 28 | I 166539 166540 . 0 + 29 | I 170344 170345 . 0 + 30 | I 176092 176093 . 0 + 31 | I 181887 181888 . 0 + 32 | I 192295 192296 . 0 + 33 | I 198825 198826 . 0 + 34 | I 212909 212910 . 0 + 35 | I 223450 223451 . 0 + 36 | II 1854 1855 . 0 + 37 | II 6864 6865 . 0 + 38 | II 9812 9813 . 0 + 39 | II 24844 24845 . 0 + 40 | II 36737 36738 . 0 + 41 | II 43133 43134 . 0 + 42 | II 46466 46467 . 0 + 43 | II 50985 50986 . 0 + 44 | II 66992 66993 . 0 + 45 | II 73020 73021 . 0 + 46 | II 80071 80072 . 0 + 47 | II 88399 88400 . 0 + 48 | II 93515 93516 . 0 + 49 | II 100338 100339 . 0 + 50 | II 110059 110060 . 0 + 51 | II 112753 112754 . 0 + 52 | II 115369 115370 . 0 + 53 | II 127751 127752 . 0 + 54 | II 133945 133946 . 0 + 55 | II 137900 137901 . 0 + 56 | II 142041 142042 . 0 + 57 | II 143779 143780 . 0 + 58 | II 150365 150366 . 0 + 59 | II 162877 162878 . 0 + 60 | II 167390 167391 . 0 + 61 | II 174753 174754 . 0 + 62 | II 185955 185956 . 0 + 63 | II 197597 197598 . 0 + 64 | II 203332 203333 . 0 + 65 | II 205961 205962 . 0 + 66 | II 212402 212403 . 0 + 67 | II 235254 235255 . 0 + 68 | II 237019 237020 . 0 + 69 | II 244297 244298 . 0 + 70 | II 248653 248654 . 0 + 71 | II 256925 256926 . 0 + 72 | II 265315 265316 . 0 + 73 | II 266586 266587 . 0 + 74 | II 270789 270790 . 0 + 75 | II 284348 284349 . 0 + 76 | II 290514 290515 . 0 + 77 | II 304815 304816 . 0 + 78 | II 320344 320345 . 0 + 79 | II 334098 334099 . 0 + 80 | II 338528 338529 . 0 + 81 | II 344367 344368 . 0 + 82 | II 368386 368387 . 0 + 83 | II 382766 382767 . 0 + 84 | II 391320 391321 . 0 + 85 | II 395061 395062 . 0 + 86 | II 406328 406329 . 0 + 87 | II 414082 414083 . 0 + 88 | II 417905 417906 . 0 + 89 | II 424908 424909 . 0 + 90 | II 425985 425986 . 0 + 91 | II 434350 434351 . 0 + 92 | II 449317 449318 . 0 + 93 | II 450767 450768 . 0 + 94 | II 453507 453508 . 0 + 95 | II 457791 457792 . 0 + 96 | II 460698 460699 . 0 + 97 | II 462723 462724 . 0 + 98 | II 469683 469684 . 0 + 99 | II 480378 480379 . 0 + 100 | II 487031 487032 . 0 + 101 | II 491168 491169 . 0 + 102 | II 513671 513672 . 0 + 103 | II 517269 517270 . 0 + 104 | II 530752 530753 . 0 + 105 | II 541114 541115 . 0 + 106 | II 548277 548278 . 0 + 107 | II 551015 551016 . 0 + 108 | II 562982 562983 . 0 + 109 | II 567676 567677 . 0 + 110 | II 569762 569763 . 0 + 111 | II 573762 573763 . 0 + 112 | II 579066 579067 . 0 + 113 | II 584731 584732 . 0 + 114 | II 586495 586496 . 0 + 115 | II 591584 591585 . 0 + 116 | II 599027 599028 . 0 + 117 | II 603579 603580 . 0 + 118 | II 608932 608933 . 0 + 119 | II 610510 610511 . 0 + 120 | II 624351 624352 . 0 + 121 | II 632097 632098 . 0 + 122 | II 636622 636623 . 0 + 123 | II 642952 642953 . 0 + 124 | II 646067 646068 . 0 + 125 | II 655445 655446 . 0 + 126 | II 658548 658549 . 0 + 127 | II 666680 666681 . 0 + 128 | II 676291 676292 . 0 + 129 | II 680624 680625 . 0 + 130 | II 685348 685349 . 0 + 131 | II 690322 690323 . 0 + 132 | II 694811 694812 . 0 + 133 | II 705415 705416 . 0 + 134 | II 708082 708083 . 0 + 135 | II 712878 712879 . 0 + 136 | II 723684 723685 . 0 + 137 | II 726578 726579 . 0 + 138 | II 729728 729729 . 0 + 139 | II 732545 732546 . 0 + 140 | II 737752 737753 . 0 + 141 | II 741887 741888 . 0 + 142 | II 746235 746236 . 0 + 143 | II 751265 751266 . 0 + 144 | II 762688 762689 . 0 + 145 | II 768810 768811 . 0 + 146 | II 777932 777933 . 0 + 147 | II 783613 783614 . 0 + 148 | II 796647 796648 . 0 + 149 | II 802279 802280 . 0 + 150 | II 807851 807852 . 0 + 151 | II 809878 809879 . 0 + 152 | III 5113 5114 . 0 + 153 | III 11291 11292 . 0 + 154 | III 14957 14958 . 0 + 155 | III 18687 18688 . 0 + 156 | III 23977 23978 . 0 + 157 | III 26914 26915 . 0 + 158 | III 34057 34058 . 0 + 159 | III 37725 37726 . 0 + 160 | III 43607 43608 . 0 + 161 | III 47036 47037 . 0 + 162 | III 54910 54911 . 0 + 163 | III 60782 60783 . 0 + 164 | III 62748 62749 . 0 + 165 | III 64577 64578 . 0 + 166 | III 73372 73373 . 0 + 167 | III 92596 92597 . 0 + 168 | III 101253 101254 . 0 + 169 | III 107459 107460 . 0 + 170 | III 110738 110739 . 0 + 171 | III 116688 116689 . 0 + 172 | III 119372 119373 . 0 + 173 | III 130512 130513 . 0 + 174 | III 144638 144639 . 0 + 175 | III 150636 150637 . 0 + 176 | III 153969 153970 . 0 + 177 | III 155831 155832 . 0 + 178 | III 177390 177391 . 0 + 179 | III 191733 191734 . 0 + 180 | III 194355 194356 . 0 + 181 | III 199481 199482 . 0 + 182 | III 209506 209507 . 0 + 183 | III 211688 211689 . 0 + 184 | III 218307 218308 . 0 + 185 | III 228067 228068 . 0 + 186 | III 233043 233044 . 0 + 187 | III 240056 240057 . 0 + 188 | III 247970 247971 . 0 + 189 | III 249246 249247 . 0 + 190 | III 260135 260136 . 0 + 191 | III 272288 272289 . 0 + 192 | III 276664 276665 . 0 + 193 | III 288052 288053 . 0 + 194 | III 291487 291488 . 0 + 195 | III 296301 296302 . 0 + 196 | III 315488 315489 . 0 + 197 | IV 8247 8248 . 0 + 198 | IV 17400 17401 . 0 + 199 | IV 21737 21738 . 0 + 200 | IV 26138 26139 . 0 + 201 | IV 33323 33324 . 0 + 202 | IV 38731 38732 . 0 + 203 | IV 54247 54248 . 0 + 204 | IV 67713 67714 . 0 + 205 | IV 79175 79176 . 0 + 206 | IV 86095 86096 . 0 + 207 | IV 92612 92613 . 0 + 208 | IV 95933 95934 . 0 + 209 | IV 100460 100461 . 0 + 210 | IV 118611 118612 . 0 + 211 | IV 123726 123727 . 0 + 212 | IV 126527 126528 . 0 + 213 | IV 130203 130204 . 0 + 214 | IV 141160 141161 . 0 + 215 | IV 144352 144353 . 0 + 216 | IV 157983 157984 . 0 + 217 | IV 160878 160879 . 0 + 218 | IV 164925 164926 . 0 + 219 | IV 167307 167308 . 0 + 220 | IV 169221 169222 . 0 + 221 | IV 181111 181112 . 0 + 222 | IV 183251 183252 . 0 + 223 | IV 188035 188036 . 0 + 224 | IV 194397 194398 . 0 + 225 | IV 201649 201650 . 0 + 226 | IV 205234 205235 . 0 + 227 | IV 218522 218523 . 0 + 228 | IV 236004 236005 . 0 + 229 | IV 245056 245057 . 0 + 230 | IV 246567 246568 . 0 + 231 | IV 253869 253870 . 0 + 232 | IV 256580 256581 . 0 + 233 | IV 263268 263269 . 0 + 234 | IV 270098 270099 . 0 + 235 | IV 273624 273625 . 0 + 236 | IV 280235 280236 . 0 + 237 | IV 284511 284512 . 0 + 238 | IV 289541 289542 . 0 + 239 | IV 293305 293306 . 0 + 240 | IV 298344 298345 . 0 + 241 | IV 306750 306751 . 0 + 242 | IV 309594 309595 . 0 + 243 | IV 323101 323102 . 0 + 244 | IV 329700 329701 . 0 + 245 | IV 333029 333030 . 0 + 246 | IV 334022 334023 . 0 + 247 | IV 336184 336185 . 0 + 248 | IV 338170 338171 . 0 + 249 | IV 340454 340455 . 0 + 250 | IV 344110 344111 . 0 + 251 | IV 355525 355526 . 0 + 252 | IV 359747 359748 . 0 + 253 | IV 372610 372611 . 0 + 254 | IV 378663 378664 . 0 + 255 | IV 392392 392393 . 0 + 256 | IV 400816 400817 . 0 + 257 | IV 405201 405202 . 0 + 258 | IV 406981 406982 . 0 + 259 | IV 411105 411106 . 0 + 260 | IV 414999 415000 . 0 + 261 | IV 431016 431017 . 0 + 262 | IV 434128 434129 . 0 + 263 | IV 440883 440884 . 0 + 264 | IV 446674 446675 . 0 + 265 | IV 449747 449748 . 0 + 266 | IV 456708 456709 . 0 + 267 | IV 465022 465023 . 0 + 268 | IV 488036 488037 . 0 + 269 | IV 492439 492440 . 0 + 270 | IV 501582 501583 . 0 + 271 | IV 503980 503981 . 0 + 272 | IV 509422 509423 . 0 + 273 | IV 520170 520171 . 0 + 274 | IV 523068 523069 . 0 + 275 | IV 527317 527318 . 0 + 276 | IV 540506 540507 . 0 + 277 | IV 547802 547803 . 0 + 278 | IV 553015 553016 . 0 + 279 | IV 555438 555439 . 0 + 280 | IV 561041 561042 . 0 + 281 | IV 564941 564942 . 0 + 282 | IV 567638 567639 . 0 + 283 | IV 569133 569134 . 0 + 284 | IV 581845 581846 . 0 + 285 | IV 584791 584792 . 0 + 286 | IV 602002 602003 . 0 + 287 | IV 603495 603496 . 0 + 288 | IV 607144 607145 . 0 + 289 | IV 613327 613328 . 0 + 290 | IV 624892 624893 . 0 + 291 | IV 639965 639966 . 0 + 292 | IV 655564 655565 . 0 + 293 | IV 661137 661138 . 0 + 294 | IV 667931 667932 . 0 + 295 | IV 673441 673442 . 0 + 296 | IV 678020 678021 . 0 + 297 | IV 680173 680174 . 0 + 298 | IV 682607 682608 . 0 + 299 | IV 691380 691381 . 0 + 300 | IV 698223 698224 . 0 + 301 | IV 701342 701343 . 0 + 302 | IV 713166 713167 . 0 + 303 | IV 733226 733227 . 0 + 304 | IV 734851 734852 . 0 + 305 | IV 748484 748485 . 0 + 306 | IV 753454 753455 . 0 + 307 | IV 764025 764026 . 0 + 308 | IV 766618 766619 . 0 + 309 | IV 780297 780298 . 0 + 310 | IV 781994 781995 . 0 + 311 | IV 786254 786255 . 0 + 312 | IV 792097 792098 . 0 + 313 | IV 810472 810473 . 0 + 314 | IV 813020 813021 . 0 + 315 | IV 818600 818601 . 0 + 316 | IV 825842 825843 . 0 + 317 | IV 830336 830337 . 0 + 318 | IV 840497 840498 . 0 + 319 | IV 843508 843509 . 0 + 320 | IV 845451 845452 . 0 + 321 | IV 850236 850237 . 0 + 322 | IV 852464 852465 . 0 + 323 | IV 856855 856856 . 0 + 324 | IV 864859 864860 . 0 + 325 | IV 870798 870799 . 0 + 326 | IV 878041 878042 . 0 + 327 | IV 894007 894008 . 0 + 328 | IV 899277 899278 . 0 + 329 | IV 913908 913909 . 0 + 330 | IV 921785 921786 . 0 + 331 | IV 929283 929284 . 0 + 332 | IV 935186 935187 . 0 + 333 | IV 937693 937694 . 0 + 334 | IV 948486 948487 . 0 + 335 | IV 957577 957578 . 0 + 336 | IV 963924 963925 . 0 + 337 | IV 966522 966523 . 0 + 338 | IV 987153 987154 . 0 + 339 | IV 994096 994097 . 0 + 340 | IV 999989 999990 . 0 + 341 | IV 1005403 1005404 . 0 + 342 | IV 1011430 1011431 . 0 + 343 | IV 1013216 1013217 . 0 + 344 | IV 1021834 1021835 . 0 + 345 | IV 1035146 1035147 . 0 + 346 | IV 1038192 1038193 . 0 + 347 | IV 1043052 1043053 . 0 + 348 | IV 1057887 1057888 . 0 + 349 | IV 1061367 1061368 . 0 + 350 | IV 1068558 1068559 . 0 + 351 | IV 1077939 1077940 . 0 + 352 | IV 1089079 1089080 . 0 + 353 | IV 1095273 1095274 . 0 + 354 | IV 1104974 1104975 . 0 + 355 | IV 1111846 1111847 . 0 + 356 | IV 1120420 1120421 . 0 + 357 | IV 1133164 1133165 . 0 + 358 | IV 1147278 1147279 . 0 + 359 | IV 1151492 1151493 . 0 + 360 | IV 1170233 1170234 . 0 + 361 | IV 1176009 1176010 . 0 + 362 | IV 1189069 1189070 . 0 + 363 | IV 1191833 1191834 . 0 + 364 | IV 1195221 1195222 . 0 + 365 | IV 1202619 1202620 . 0 + 366 | IV 1212350 1212351 . 0 + 367 | IV 1214928 1214929 . 0 + 368 | IV 1223401 1223402 . 0 + 369 | IV 1225095 1225096 . 0 + 370 | IV 1229131 1229132 . 0 + 371 | IV 1233236 1233237 . 0 + 372 | IV 1238157 1238158 . 0 + 373 | IV 1239891 1239892 . 0 + 374 | IV 1248067 1248068 . 0 + 375 | IV 1254718 1254719 . 0 + 376 | IV 1276432 1276433 . 0 + 377 | IV 1284055 1284056 . 0 + 378 | IV 1292245 1292246 . 0 + 379 | IV 1301282 1301283 . 0 + 380 | IV 1315108 1315109 . 0 + 381 | IV 1323419 1323420 . 0 + 382 | IV 1332911 1332912 . 0 + 383 | IV 1344378 1344379 . 0 + 384 | IV 1354730 1354731 . 0 + 385 | IV 1357473 1357474 . 0 + 386 | IV 1360958 1360959 . 0 + 387 | IV 1364986 1364987 . 0 + 388 | IV 1379824 1379825 . 0 + 389 | IV 1385404 1385405 . 0 + 390 | IV 1399623 1399624 . 0 + 391 | IV 1404308 1404309 . 0 + 392 | IV 1415189 1415190 . 0 + 393 | IV 1418459 1418460 . 0 + 394 | IV 1424753 1424754 . 0 + 395 | IV 1431931 1431932 . 0 + 396 | IV 1438064 1438065 . 0 + 397 | IV 1450134 1450135 . 0 + 398 | IV 1453113 1453114 . 0 + 399 | IV 1470458 1470459 . 0 + 400 | IV 1471497 1471498 . 0 + 401 | IV 1474872 1474873 . 0 + 402 | IV 1480957 1480958 . 0 + 403 | IV 1483634 1483635 . 0 + 404 | IV 1489544 1489545 . 0 + 405 | IV 1490954 1490955 . 0 + 406 | IV 1492444 1492445 . 0 + 407 | IV 1496010 1496011 . 0 + 408 | IV 1499364 1499365 . 0 + 409 | IV 1510284 1510285 . 0 + 410 | IV 1515369 1515370 . 0 + 411 | IV 1524121 1524122 . 0 + 412 | V 2647 2648 . 0 + 413 | V 6846 6847 . 0 + 414 | V 21316 21317 . 0 + 415 | V 29669 29670 . 0 + 416 | V 36393 36394 . 0 + 417 | V 44971 44972 . 0 + 418 | V 48421 48422 . 0 + 419 | V 53577 53578 . 0 + 420 | V 61838 61839 . 0 + 421 | V 64398 64399 . 0 + 422 | V 79545 79546 . 0 + 423 | V 81275 81276 . 0 + 424 | V 94243 94244 . 0 + 425 | V 96717 96718 . 0 + 426 | V 102451 102452 . 0 + 427 | V 108204 108205 . 0 + 428 | V 117075 117076 . 0 + 429 | V 117569 117570 . 0 + 430 | V 122553 122554 . 0 + 431 | V 124702 124703 . 0 + 432 | V 128292 128293 . 0 + 433 | V 130820 130821 . 0 + 434 | V 135328 135329 . 0 + 435 | V 138826 138827 . 0 + 436 | V 145619 145620 . 0 + 437 | V 148659 148660 . 0 + 438 | V 157616 157617 . 0 + 439 | V 164313 164314 . 0 + 440 | V 166159 166160 . 0 + 441 | V 172562 172563 . 0 + 442 | V 189406 189407 . 0 + 443 | V 194250 194251 . 0 + 444 | V 207535 207536 . 0 + 445 | V 213986 213987 . 0 + 446 | V 217874 217875 . 0 + 447 | V 223220 223221 . 0 + 448 | V 226855 226856 . 0 + 449 | V 235629 235630 . 0 + 450 | V 253815 253816 . 0 + 451 | V 256253 256254 . 0 + 452 | V 278230 278231 . 0 + 453 | V 282534 282535 . 0 + 454 | V 291250 291251 . 0 + 455 | V 295056 295057 . 0 + 456 | V 301780 301781 . 0 + 457 | V 308267 308268 . 0 + 458 | V 314134 314135 . 0 + 459 | V 319726 319727 . 0 + 460 | V 324182 324183 . 0 + 461 | V 343275 343276 . 0 + 462 | V 357916 357917 . 0 + 463 | V 360407 360408 . 0 + 464 | V 367632 367633 . 0 + 465 | V 373340 373341 . 0 + 466 | V 376737 376738 . 0 + 467 | V 387862 387863 . 0 + 468 | V 397801 397802 . 0 + 469 | V 402794 402795 . 0 + 470 | V 406863 406864 . 0 + 471 | V 413005 413006 . 0 + 472 | V 420911 420912 . 0 + 473 | V 425034 425035 . 0 + 474 | V 434248 434249 . 0 + 475 | V 441171 441172 . 0 + 476 | V 442854 442855 . 0 + 477 | V 450069 450070 . 0 + 478 | V 455031 455032 . 0 + 479 | V 457704 457705 . 0 + 480 | V 462916 462917 . 0 + 481 | V 469607 469608 . 0 + 482 | V 476285 476286 . 0 + 483 | V 487261 487262 . 0 + 484 | V 512365 512366 . 0 + 485 | V 520899 520900 . 0 + 486 | V 529473 529474 . 0 + 487 | V 538355 538356 . 0 + 488 | V 549619 549620 . 0 + 489 | V 553295 553296 . 0 + 490 | V 561034 561035 . 0 + 491 | V 569182 569183 . 0 + 492 | VI 1399 1400 . 0 + 493 | VI 10260 10261 . 0 + 494 | VI 14127 14128 . 0 + 495 | VI 19762 19763 . 0 + 496 | VI 29842 29843 . 0 + 497 | VI 38757 38758 . 0 + 498 | VI 43532 43533 . 0 + 499 | VI 53115 53116 . 0 + 500 | VI 57761 57762 . 0 + 501 | VI 62925 62926 . 0 + 502 | VI 68905 68906 . 0 + 503 | VI 78020 78021 . 0 + 504 | VI 84009 84010 . 0 + 505 | VI 93436 93437 . 0 + 506 | VI 98363 98364 . 0 + 507 | VI 101552 101553 . 0 + 508 | VI 103956 103957 . 0 + 509 | VI 131020 131021 . 0 + 510 | VI 134407 134408 . 0 + 511 | VI 144314 144315 . 0 + 512 | VI 152595 152596 . 0 + 513 | VI 154419 154420 . 0 + 514 | VI 157833 157834 . 0 + 515 | VI 172410 172411 . 0 + 516 | VI 191424 191425 . 0 + 517 | VI 199165 199166 . 0 + 518 | VI 201833 201834 . 0 + 519 | VI 208354 208355 . 0 + 520 | VI 216505 216506 . 0 + 521 | VI 222027 222028 . 0 + 522 | VI 231975 231976 . 0 + 523 | VI 237308 237309 . 0 + 524 | VI 239086 239087 . 0 + 525 | VI 243035 243036 . 0 + 526 | VI 248979 248980 . 0 + 527 | VI 253378 253379 . 0 + 528 | VII 6063 6064 . 0 + 529 | VII 12104 12105 . 0 + 530 | VII 25555 25556 . 0 + 531 | VII 37570 37571 . 0 + 532 | VII 44579 44580 . 0 + 533 | VII 49397 49398 . 0 + 534 | VII 52581 52582 . 0 + 535 | VII 63024 63025 . 0 + 536 | VII 72647 72648 . 0 + 537 | VII 73769 73770 . 0 + 538 | VII 77960 77961 . 0 + 539 | VII 82806 82807 . 0 + 540 | VII 84568 84569 . 0 + 541 | VII 102308 102309 . 0 + 542 | VII 110513 110514 . 0 + 543 | VII 117706 117707 . 0 + 544 | VII 122516 122517 . 0 + 545 | VII 139630 139631 . 0 + 546 | VII 145502 145503 . 0 + 547 | VII 163082 163083 . 0 + 548 | VII 169659 169660 . 0 + 549 | VII 175435 175436 . 0 + 550 | VII 184117 184118 . 0 + 551 | VII 199122 199123 . 0 + 552 | VII 215243 215244 . 0 + 553 | VII 221012 221013 . 0 + 554 | VII 227640 227641 . 0 + 555 | VII 232398 232399 . 0 + 556 | VII 241218 241219 . 0 + 557 | VII 248308 248309 . 0 + 558 | VII 252816 252817 . 0 + 559 | VII 267622 267623 . 0 + 560 | VII 274550 274551 . 0 + 561 | VII 286647 286648 . 0 + 562 | VII 298057 298058 . 0 + 563 | VII 301452 301453 . 0 + 564 | VII 308639 308640 . 0 + 565 | VII 328763 328764 . 0 + 566 | VII 341956 341957 . 0 + 567 | VII 344686 344687 . 0 + 568 | VII 346317 346318 . 0 + 569 | VII 350527 350528 . 0 + 570 | VII 360193 360194 . 0 + 571 | VII 374270 374271 . 0 + 572 | VII 379670 379671 . 0 + 573 | VII 388849 388850 . 0 + 574 | VII 394734 394735 . 0 + 575 | VII 400514 400515 . 0 + 576 | VII 406727 406728 . 0 + 577 | VII 412226 412227 . 0 + 578 | VII 415937 415938 . 0 + 579 | VII 425183 425184 . 0 + 580 | VII 431438 431439 . 0 + 581 | VII 436484 436485 . 0 + 582 | VII 440569 440570 . 0 + 583 | VII 450159 450160 . 0 + 584 | VII 457114 457115 . 0 + 585 | VII 459050 459051 . 0 + 586 | VII 464976 464977 . 0 + 587 | VII 474381 474382 . 0 + 588 | VII 476190 476191 . 0 + 589 | VII 489574 489575 . 0 + 590 | VII 495309 495310 . 0 + 591 | VII 504490 504491 . 0 + 592 | VII 508024 508025 . 0 + 593 | VII 520975 520976 . 0 + 594 | VII 526807 526808 . 0 + 595 | VII 528879 528880 . 0 + 596 | VII 531781 531782 . 0 + 597 | VII 533975 533976 . 0 + 598 | VII 544390 544391 . 0 + 599 | VII 545622 545623 . 0 + 600 | VII 554098 554099 . 0 + 601 | VII 556871 556872 . 0 + 602 | VII 557966 557967 . 0 + 603 | VII 561505 561506 . 0 + 604 | VII 580362 580363 . 0 + 605 | VII 586221 586222 . 0 + 606 | VII 591980 591981 . 0 + 607 | VII 594844 594845 . 0 + 608 | VII 604609 604610 . 0 + 609 | VII 611690 611691 . 0 + 610 | VII 618032 618033 . 0 + 611 | VII 631376 631377 . 0 + 612 | VII 635540 635541 . 0 + 613 | VII 643077 643078 . 0 + 614 | VII 644726 644727 . 0 + 615 | VII 675584 675585 . 0 + 616 | VII 682349 682350 . 0 + 617 | VII 694492 694493 . 0 + 618 | VII 697338 697339 . 0 + 619 | VII 698909 698910 . 0 + 620 | VII 700853 700854 . 0 + 621 | VII 705204 705205 . 0 + 622 | VII 720093 720094 . 0 + 623 | VII 724905 724906 . 0 + 624 | VII 727887 727888 . 0 + 625 | VII 731328 731329 . 0 + 626 | VII 735385 735386 . 0 + 627 | VII 736535 736536 . 0 + 628 | VII 747842 747843 . 0 + 629 | VII 751219 751220 . 0 + 630 | VII 755418 755419 . 0 + 631 | VII 763511 763512 . 0 + 632 | VII 784055 784056 . 0 + 633 | VII 790393 790394 . 0 + 634 | VII 794571 794572 . 0 + 635 | VII 796770 796771 . 0 + 636 | VII 805158 805159 . 0 + 637 | VII 808155 808156 . 0 + 638 | VII 817398 817399 . 0 + 639 | VII 833253 833254 . 0 + 640 | VII 840690 840691 . 0 + 641 | VII 845805 845806 . 0 + 642 | VII 846836 846837 . 0 + 643 | VII 870105 870106 . 0 + 644 | VII 876566 876567 . 0 + 645 | VII 882520 882521 . 0 + 646 | VII 889676 889677 . 0 + 647 | VII 899841 899842 . 0 + 648 | VII 908916 908917 . 0 + 649 | VII 910789 910790 . 0 + 650 | VII 912861 912862 . 0 + 651 | VII 918478 918479 . 0 + 652 | VII 922569 922570 . 0 + 653 | VII 930883 930884 . 0 + 654 | VII 940835 940836 . 0 + 655 | VII 952426 952427 . 0 + 656 | VII 954659 954660 . 0 + 657 | VII 961230 961231 . 0 + 658 | VII 977905 977906 . 0 + 659 | VII 990296 990297 . 0 + 660 | VII 998272 998273 . 0 + 661 | VII 1002380 1002381 . 0 + 662 | VII 1006152 1006153 . 0 + 663 | VII 1014204 1014205 . 0 + 664 | VII 1024881 1024882 . 0 + 665 | VII 1037746 1037747 . 0 + 666 | VII 1043783 1043784 . 0 + 667 | VII 1048630 1048631 . 0 + 668 | VII 1057519 1057520 . 0 + 669 | VII 1072837 1072838 . 0 + 670 | VII 1076103 1076104 . 0 + 671 | VII 1079118 1079119 . 0 + 672 | VII 1081125 1081126 . 0 + 673 | VIII 2508 2509 . 0 + 674 | VIII 7947 7948 . 0 + 675 | VIII 11114 11115 . 0 + 676 | VIII 18463 18464 . 0 + 677 | VIII 23577 23578 . 0 + 678 | VIII 27928 27929 . 0 + 679 | VIII 45808 45809 . 0 + 680 | VIII 53102 53103 . 0 + 681 | VIII 58955 58956 . 0 + 682 | VIII 62892 62893 . 0 + 683 | VIII 71954 71955 . 0 + 684 | VIII 75936 75937 . 0 + 685 | VIII 80534 80535 . 0 + 686 | VIII 91971 91972 . 0 + 687 | VIII 98213 98214 . 0 + 688 | VIII 100524 100525 . 0 + 689 | VIII 109955 109956 . 0 + 690 | VIII 119764 119765 . 0 + 691 | VIII 130588 130589 . 0 + 692 | VIII 132973 132974 . 0 + 693 | VIII 136706 136707 . 0 + 694 | VIII 139930 139931 . 0 + 695 | VIII 146151 146152 . 0 + 696 | VIII 157597 157598 . 0 + 697 | VIII 161606 161607 . 0 + 698 | VIII 167673 167674 . 0 + 699 | VIII 176891 176892 . 0 + 700 | VIII 184815 184816 . 0 + 701 | VIII 189076 189077 . 0 + 702 | VIII 192710 192711 . 0 + 703 | VIII 197314 197315 . 0 + 704 | VIII 207212 207213 . 0 + 705 | VIII 218032 218033 . 0 + 706 | VIII 221401 221402 . 0 + 707 | VIII 233436 233437 . 0 + 708 | VIII 237769 237770 . 0 + 709 | VIII 244232 244233 . 0 + 710 | VIII 248387 248388 . 0 + 711 | VIII 252298 252299 . 0 + 712 | VIII 258130 258131 . 0 + 713 | VIII 268274 268275 . 0 + 714 | VIII 282530 282531 . 0 + 715 | VIII 290300 290301 . 0 + 716 | VIII 294052 294053 . 0 + 717 | VIII 314054 314055 . 0 + 718 | VIII 326718 326719 . 0 + 719 | VIII 334459 334460 . 0 + 720 | VIII 340045 340046 . 0 + 721 | VIII 344293 344294 . 0 + 722 | VIII 358460 358461 . 0 + 723 | VIII 359431 359432 . 0 + 724 | VIII 362881 362882 . 0 + 725 | VIII 368246 368247 . 0 + 726 | VIII 370584 370585 . 0 + 727 | VIII 372625 372626 . 0 + 728 | VIII 381857 381858 . 0 + 729 | VIII 387615 387616 . 0 + 730 | VIII 392167 392168 . 0 + 731 | VIII 394269 394270 . 0 + 732 | VIII 399128 399129 . 0 + 733 | VIII 402019 402020 . 0 + 734 | VIII 411349 411350 . 0 + 735 | VIII 413569 413570 . 0 + 736 | VIII 419141 419142 . 0 + 737 | VIII 424540 424541 . 0 + 738 | VIII 437063 437064 . 0 + 739 | VIII 450809 450810 . 0 + 740 | VIII 470756 470757 . 0 + 741 | VIII 474542 474543 . 0 + 742 | VIII 481961 481962 . 0 + 743 | VIII 486203 486204 . 0 + 744 | VIII 487686 487687 . 0 + 745 | VIII 496250 496251 . 0 + 746 | VIII 499916 499917 . 0 + 747 | VIII 504335 504336 . 0 + 748 | VIII 514751 514752 . 0 + 749 | VIII 520511 520512 . 0 + 750 | VIII 533188 533189 . 0 + 751 | VIII 543727 543728 . 0 + 752 | VIII 556273 556274 . 0 + 753 | IX 5059 5060 . 0 + 754 | IX 16461 16462 . 0 + 755 | IX 22168 22169 . 0 + 756 | IX 40164 40165 . 0 + 757 | IX 46881 46882 . 0 + 758 | IX 51531 51532 . 0 + 759 | IX 57294 57295 . 0 + 760 | IX 69658 69659 . 0 + 761 | IX 80328 80329 . 0 + 762 | IX 87907 87908 . 0 + 763 | IX 94931 94932 . 0 + 764 | IX 98427 98428 . 0 + 765 | IX 105890 105891 . 0 + 766 | IX 116963 116964 . 0 + 767 | IX 136380 136381 . 0 + 768 | IX 140529 140530 . 0 + 769 | IX 157280 157281 . 0 + 770 | IX 163126 163127 . 0 + 771 | IX 167511 167512 . 0 + 772 | IX 168892 168893 . 0 + 773 | IX 173195 173196 . 0 + 774 | IX 175204 175205 . 0 + 775 | IX 179711 179712 . 0 + 776 | IX 182046 182047 . 0 + 777 | IX 186442 186443 . 0 + 778 | IX 190997 190998 . 0 + 779 | IX 197796 197797 . 0 + 780 | IX 210829 210830 . 0 + 781 | IX 214846 214847 . 0 + 782 | IX 217704 217705 . 0 + 783 | IX 237953 237954 . 0 + 784 | IX 242737 242738 . 0 + 785 | IX 247549 247550 . 0 + 786 | IX 251976 251977 . 0 + 787 | IX 256045 256046 . 0 + 788 | IX 264994 264995 . 0 + 789 | IX 272862 272863 . 0 + 790 | IX 279993 279994 . 0 + 791 | IX 287608 287609 . 0 + 792 | IX 295975 295976 . 0 + 793 | IX 300166 300167 . 0 + 794 | IX 303087 303088 . 0 + 795 | IX 318065 318066 . 0 + 796 | IX 324203 324204 . 0 + 797 | IX 328100 328101 . 0 + 798 | IX 335596 335597 . 0 + 799 | IX 342913 342914 . 0 + 800 | IX 347870 347871 . 0 + 801 | IX 350549 350550 . 0 + 802 | IX 355811 355812 . 0 + 803 | IX 365399 365400 . 0 + 804 | IX 373036 373037 . 0 + 805 | IX 377223 377224 . 0 + 806 | IX 379899 379900 . 0 + 807 | IX 383489 383490 . 0 + 808 | IX 385454 385455 . 0 + 809 | IX 397076 397077 . 0 + 810 | IX 404818 404819 . 0 + 811 | IX 411936 411937 . 0 + 812 | IX 419539 419540 . 0 + 813 | IX 423713 423714 . 0 + 814 | IX 434787 434788 . 0 + 815 | X 5042 5043 . 0 + 816 | X 16444 16445 . 0 + 817 | X 24034 24035 . 0 + 818 | X 33503 33504 . 0 + 819 | X 40080 40081 . 0 + 820 | X 56310 56311 . 0 + 821 | X 72641 72642 . 0 + 822 | X 74759 74760 . 0 + 823 | X 82004 82005 . 0 + 824 | X 85384 85385 . 0 + 825 | X 87538 87539 . 0 + 826 | X 89198 89199 . 0 + 827 | X 91854 91855 . 0 + 828 | X 96040 96041 . 0 + 829 | X 99584 99585 . 0 + 830 | X 106805 106806 . 0 + 831 | X 117873 117874 . 0 + 832 | X 121976 121977 . 0 + 833 | X 126838 126839 . 0 + 834 | X 139467 139468 . 0 + 835 | X 141277 141278 . 0 + 836 | X 147697 147698 . 0 + 837 | X 151668 151669 . 0 + 838 | X 156400 156401 . 0 + 839 | X 159519 159520 . 0 + 840 | X 164221 164222 . 0 + 841 | X 180929 180930 . 0 + 842 | X 185475 185476 . 0 + 843 | X 190307 190308 . 0 + 844 | X 191457 191458 . 0 + 845 | X 193662 193663 . 0 + 846 | X 197218 197219 . 0 + 847 | X 209724 209725 . 0 + 848 | X 227934 227935 . 0 + 849 | X 234164 234165 . 0 + 850 | X 251755 251756 . 0 + 851 | X 261012 261013 . 0 + 852 | X 269907 269908 . 0 + 853 | X 274779 274780 . 0 + 854 | X 283590 283591 . 0 + 855 | X 294404 294405 . 0 + 856 | X 305168 305169 . 0 + 857 | X 307912 307913 . 0 + 858 | X 315663 315664 . 0 + 859 | X 326215 326216 . 0 + 860 | X 337459 337460 . 0 + 861 | X 347385 347386 . 0 + 862 | X 358113 358114 . 0 + 863 | X 368559 368560 . 0 + 864 | X 380171 380172 . 0 + 865 | X 388315 388316 . 0 + 866 | X 391738 391739 . 0 + 867 | X 395720 395721 . 0 + 868 | X 398676 398677 . 0 + 869 | X 409326 409327 . 0 + 870 | X 415483 415484 . 0 + 871 | X 423072 423073 . 0 + 872 | X 431412 431413 . 0 + 873 | X 433109 433110 . 0 + 874 | X 440819 440820 . 0 + 875 | X 448250 448251 . 0 + 876 | X 453563 453564 . 0 + 877 | X 457924 457925 . 0 + 878 | X 464351 464352 . 0 + 879 | X 467189 467190 . 0 + 880 | X 468443 468444 . 0 + 881 | X 483784 483785 . 0 + 882 | X 492319 492320 . 0 + 883 | X 500661 500662 . 0 + 884 | X 503596 503597 . 0 + 885 | X 510161 510162 . 0 + 886 | X 516374 516375 . 0 + 887 | X 523936 523937 . 0 + 888 | X 526773 526774 . 0 + 889 | X 541684 541685 . 0 + 890 | X 544721 544722 . 0 + 891 | X 553396 553397 . 0 + 892 | X 557704 557705 . 0 + 893 | X 566922 566923 . 0 + 894 | X 568754 568755 . 0 + 895 | X 570869 570870 . 0 + 896 | X 575261 575262 . 0 + 897 | X 585061 585062 . 0 + 898 | X 590726 590727 . 0 + 899 | X 603148 603149 . 0 + 900 | X 613057 613058 . 0 + 901 | X 616317 616318 . 0 + 902 | X 619094 619095 . 0 + 903 | X 622519 622520 . 0 + 904 | X 629333 629334 . 0 + 905 | X 635767 635768 . 0 + 906 | X 638199 638200 . 0 + 907 | X 643428 643429 . 0 + 908 | X 652734 652735 . 0 + 909 | X 663970 663971 . 0 + 910 | X 673673 673674 . 0 + 911 | X 677336 677337 . 0 + 912 | X 689382 689383 . 0 + 913 | X 698246 698247 . 0 + 914 | X 701858 701859 . 0 + 915 | X 708591 708592 . 0 + 916 | X 728421 728422 . 0 + 917 | X 737561 737562 . 0 + 918 | XI 1303 1304 . 0 + 919 | XI 3111 3112 . 0 + 920 | XI 8308 8309 . 0 + 921 | XI 16532 16533 . 0 + 922 | XI 26492 26493 . 0 + 923 | XI 36555 36556 . 0 + 924 | XI 42329 42330 . 0 + 925 | XI 48979 48980 . 0 + 926 | XI 55767 55768 . 0 + 927 | XI 74813 74814 . 0 + 928 | XI 77144 77145 . 0 + 929 | XI 86063 86064 . 0 + 930 | XI 98275 98276 . 0 + 931 | XI 110295 110296 . 0 + 932 | XI 115096 115097 . 0 + 933 | XI 120341 120342 . 0 + 934 | XI 145649 145650 . 0 + 935 | XI 153760 153761 . 0 + 936 | XI 162410 162411 . 0 + 937 | XI 167531 167532 . 0 + 938 | XI 175445 175446 . 0 + 939 | XI 184672 184673 . 0 + 940 | XI 195142 195143 . 0 + 941 | XI 212458 212459 . 0 + 942 | XI 218443 218444 . 0 + 943 | XI 221158 221159 . 0 + 944 | XI 237107 237108 . 0 + 945 | XI 239037 239038 . 0 + 946 | XI 253585 253586 . 0 + 947 | XI 254983 254984 . 0 + 948 | XI 258172 258173 . 0 + 949 | XI 265975 265976 . 0 + 950 | XI 277092 277093 . 0 + 951 | XI 292733 292734 . 0 + 952 | XI 307984 307985 . 0 + 953 | XI 313238 313239 . 0 + 954 | XI 316305 316306 . 0 + 955 | XI 320843 320844 . 0 + 956 | XI 326259 326260 . 0 + 957 | XI 330694 330695 . 0 + 958 | XI 342611 342612 . 0 + 959 | XI 351143 351144 . 0 + 960 | XI 360936 360937 . 0 + 961 | XI 379908 379909 . 0 + 962 | XI 389141 389142 . 0 + 963 | XI 394639 394640 . 0 + 964 | XI 403548 403549 . 0 + 965 | XI 405139 405140 . 0 + 966 | XI 411550 411551 . 0 + 967 | XI 420107 420108 . 0 + 968 | XI 427122 427123 . 0 + 969 | XI 430152 430153 . 0 + 970 | XI 432905 432906 . 0 + 971 | XI 436940 436941 . 0 + 972 | XI 438659 438660 . 0 + 973 | XI 446762 446763 . 0 + 974 | XI 454214 454215 . 0 + 975 | XI 458796 458797 . 0 + 976 | XI 465156 465157 . 0 + 977 | XI 471515 471516 . 0 + 978 | XI 482075 482076 . 0 + 979 | XI 485076 485077 . 0 + 980 | XI 488677 488678 . 0 + 981 | XI 497467 497468 . 0 + 982 | XI 501222 501223 . 0 + 983 | XI 506854 506855 . 0 + 984 | XI 507812 507813 . 0 + 985 | XI 508626 508627 . 0 + 986 | XI 518060 518061 . 0 + 987 | XI 520759 520760 . 0 + 988 | XI 523381 523382 . 0 + 989 | XI 532375 532376 . 0 + 990 | XI 558984 558985 . 0 + 991 | XI 560719 560720 . 0 + 992 | XI 565217 565218 . 0 + 993 | XI 570237 570238 . 0 + 994 | XI 574782 574783 . 0 + 995 | XI 579750 579751 . 0 + 996 | XI 586748 586749 . 0 + 997 | XI 591430 591431 . 0 + 998 | XI 596358 596359 . 0 + 999 | XI 603132 603133 . 0 + 1000 | XI 612464 612465 . 0 + 1001 | XI 617764 617765 . 0 + 1002 | XI 632912 632913 . 0 + 1003 | XI 638592 638593 . 0 + 1004 | XI 658235 658236 . 0 + 1005 | XII 5946 5947 . 0 + 1006 | XII 12578 12579 . 0 + 1007 | XII 20421 20422 . 0 + 1008 | XII 25525 25526 . 0 + 1009 | XII 32187 32188 . 0 + 1010 | XII 41241 41242 . 0 + 1011 | XII 52016 52017 . 0 + 1012 | XII 70554 70555 . 0 + 1013 | XII 74184 74185 . 0 + 1014 | XII 95342 95343 . 0 + 1015 | XII 105450 105451 . 0 + 1016 | XII 107837 107838 . 0 + 1017 | XII 121860 121861 . 0 + 1018 | XII 129160 129161 . 0 + 1019 | XII 134143 134144 . 0 + 1020 | XII 137902 137903 . 0 + 1021 | XII 150775 150776 . 0 + 1022 | XII 161593 161594 . 0 + 1023 | XII 165488 165489 . 0 + 1024 | XII 167227 167228 . 0 + 1025 | XII 169829 169830 . 0 + 1026 | XII 172015 172016 . 0 + 1027 | XII 176772 176773 . 0 + 1028 | XII 178663 178664 . 0 + 1029 | XII 181634 181635 . 0 + 1030 | XII 184167 184168 . 0 + 1031 | XII 195311 195312 . 0 + 1032 | XII 199463 199464 . 0 + 1033 | XII 210389 210390 . 0 + 1034 | XII 229830 229831 . 0 + 1035 | XII 243616 243617 . 0 + 1036 | XII 248025 248026 . 0 + 1037 | XII 257922 257923 . 0 + 1038 | XII 266324 266325 . 0 + 1039 | XII 267767 267768 . 0 + 1040 | XII 271545 271546 . 0 + 1041 | XII 280980 280981 . 0 + 1042 | XII 285678 285679 . 0 + 1043 | XII 292164 292165 . 0 + 1044 | XII 306676 306677 . 0 + 1045 | XII 318093 318094 . 0 + 1046 | XII 326368 326369 . 0 + 1047 | XII 336131 336132 . 0 + 1048 | XII 347012 347013 . 0 + 1049 | XII 366505 366506 . 0 + 1050 | XII 369503 369504 . 0 + 1051 | XII 374684 374685 . 0 + 1052 | XII 382360 382361 . 0 + 1053 | XII 386342 386343 . 0 + 1054 | XII 394328 394329 . 0 + 1055 | XII 402640 402641 . 0 + 1056 | XII 415663 415664 . 0 + 1057 | XII 421467 421468 . 0 + 1058 | XII 429530 429531 . 0 + 1059 | XII 432797 432798 . 0 + 1060 | XII 434107 434108 . 0 + 1061 | XII 437513 437514 . 0 + 1062 | XII 441500 441501 . 0 + 1063 | XII 455125 455126 . 0 + 1064 | XII 460253 460254 . 0 + 1065 | XII 476153 476154 . 0 + 1066 | XII 491229 491230 . 0 + 1067 | XII 494440 494441 . 0 + 1068 | XII 499490 499491 . 0 + 1069 | XII 501190 501191 . 0 + 1070 | XII 507690 507691 . 0 + 1071 | XII 513050 513051 . 0 + 1072 | XII 516543 516544 . 0 + 1073 | XII 520446 520447 . 0 + 1074 | XII 530591 530592 . 0 + 1075 | XII 538611 538612 . 0 + 1076 | XII 549432 549433 . 0 + 1077 | XII 552663 552664 . 0 + 1078 | XII 560619 560620 . 0 + 1079 | XII 563590 563591 . 0 + 1080 | XII 570700 570701 . 0 + 1081 | XII 573348 573349 . 0 + 1082 | XII 578076 578077 . 0 + 1083 | XII 587633 587634 . 0 + 1084 | XII 590550 590551 . 0 + 1085 | XII 599361 599362 . 0 + 1086 | XII 605088 605089 . 0 + 1087 | XII 607300 607301 . 0 + 1088 | XII 616260 616261 . 0 + 1089 | XII 622868 622869 . 0 + 1090 | XII 625093 625094 . 0 + 1091 | XII 628589 628590 . 0 + 1092 | XII 644369 644370 . 0 + 1093 | XII 654685 654686 . 0 + 1094 | XII 663057 663058 . 0 + 1095 | XII 668071 668072 . 0 + 1096 | XII 673580 673581 . 0 + 1097 | XII 680854 680855 . 0 + 1098 | XII 683615 683616 . 0 + 1099 | XII 694922 694923 . 0 + 1100 | XII 706163 706164 . 0 + 1101 | XII 708155 708156 . 0 + 1102 | XII 709842 709843 . 0 + 1103 | XII 717084 717085 . 0 + 1104 | XII 724576 724577 . 0 + 1105 | XII 732189 732190 . 0 + 1106 | XII 735042 735043 . 0 + 1107 | XII 746685 746686 . 0 + 1108 | XII 748953 748954 . 0 + 1109 | XII 760494 760495 . 0 + 1110 | XII 769256 769257 . 0 + 1111 | XII 776443 776444 . 0 + 1112 | XII 778056 778057 . 0 + 1113 | XII 780963 780964 . 0 + 1114 | XII 783010 783011 . 0 + 1115 | XII 790173 790174 . 0 + 1116 | XII 794236 794237 . 0 + 1117 | XII 799643 799644 . 0 + 1118 | XII 805492 805493 . 0 + 1119 | XII 822162 822163 . 0 + 1120 | XII 825952 825953 . 0 + 1121 | XII 829433 829434 . 0 + 1122 | XII 836255 836256 . 0 + 1123 | XII 852256 852257 . 0 + 1124 | XII 861620 861621 . 0 + 1125 | XII 868525 868526 . 0 + 1126 | XII 872776 872777 . 0 + 1127 | XII 875602 875603 . 0 + 1128 | XII 881994 881995 . 0 + 1129 | XII 888740 888741 . 0 + 1130 | XII 896321 896322 . 0 + 1131 | XII 899478 899479 . 0 + 1132 | XII 904593 904594 . 0 + 1133 | XII 909562 909563 . 0 + 1134 | XII 930977 930978 . 0 + 1135 | XII 933768 933769 . 0 + 1136 | XII 949728 949729 . 0 + 1137 | XII 953267 953268 . 0 + 1138 | XII 956811 956812 . 0 + 1139 | XII 962852 962853 . 0 + 1140 | XII 964983 964984 . 0 + 1141 | XII 971805 971806 . 0 + 1142 | XII 975751 975752 . 0 + 1143 | XII 990527 990528 . 0 + 1144 | XII 1000234 1000235 . 0 + 1145 | XII 1004236 1004237 . 0 + 1146 | XII 1007207 1007208 . 0 + 1147 | XII 1013841 1013842 . 0 + 1148 | XII 1015508 1015509 . 0 + 1149 | XII 1026684 1026685 . 0 + 1150 | XII 1039010 1039011 . 0 + 1151 | XII 1051976 1051977 . 0 + 1152 | XII 1055747 1055748 . 0 + 1153 | XII 1059136 1059137 . 0 + 1154 | XIII 11388 11389 . 0 + 1155 | XIII 18933 18934 . 0 + 1156 | XIII 28063 28064 . 0 + 1157 | XIII 40004 40005 . 0 + 1158 | XIII 49866 49867 . 0 + 1159 | XIII 55186 55187 . 0 + 1160 | XIII 57658 57659 . 0 + 1161 | XIII 78051 78052 . 0 + 1162 | XIII 85887 85888 . 0 + 1163 | XIII 94335 94336 . 0 + 1164 | XIII 103896 103897 . 0 + 1165 | XIII 112427 112428 . 0 + 1166 | XIII 139002 139003 . 0 + 1167 | XIII 145045 145046 . 0 + 1168 | XIII 147376 147377 . 0 + 1169 | XIII 153109 153110 . 0 + 1170 | XIII 159859 159860 . 0 + 1171 | XIII 162093 162094 . 0 + 1172 | XIII 165428 165429 . 0 + 1173 | XIII 168998 168999 . 0 + 1174 | XIII 174146 174147 . 0 + 1175 | XIII 183629 183630 . 0 + 1176 | XIII 189985 189986 . 0 + 1177 | XIII 194855 194856 . 0 + 1178 | XIII 202334 202335 . 0 + 1179 | XIII 206359 206360 . 0 + 1180 | XIII 212334 212335 . 0 + 1181 | XIII 222774 222775 . 0 + 1182 | XIII 226844 226845 . 0 + 1183 | XIII 229616 229617 . 0 + 1184 | XIII 234612 234613 . 0 + 1185 | XIII 239093 239094 . 0 + 1186 | XIII 246822 246823 . 0 + 1187 | XIII 255945 255946 . 0 + 1188 | XIII 261656 261657 . 0 + 1189 | XIII 268408 268409 . 0 + 1190 | XIII 277385 277386 . 0 + 1191 | XIII 280464 280465 . 0 + 1192 | XIII 295072 295073 . 0 + 1193 | XIII 300647 300648 . 0 + 1194 | XIII 317033 317034 . 0 + 1195 | XIII 319306 319307 . 0 + 1196 | XIII 324210 324211 . 0 + 1197 | XIII 328620 328621 . 0 + 1198 | XIII 332066 332067 . 0 + 1199 | XIII 339346 339347 . 0 + 1200 | XIII 341764 341765 . 0 + 1201 | XIII 350913 350914 . 0 + 1202 | XIII 357084 357085 . 0 + 1203 | XIII 363248 363249 . 0 + 1204 | XIII 368013 368014 . 0 + 1205 | XIII 386037 386038 . 0 + 1206 | XIII 391507 391508 . 0 + 1207 | XIII 394920 394921 . 0 + 1208 | XIII 404279 404280 . 0 + 1209 | XIII 410693 410694 . 0 + 1210 | XIII 412193 412194 . 0 + 1211 | XIII 426384 426385 . 0 + 1212 | XIII 443396 443397 . 0 + 1213 | XIII 449992 449993 . 0 + 1214 | XIII 457272 457273 . 0 + 1215 | XIII 459361 459362 . 0 + 1216 | XIII 463778 463779 . 0 + 1217 | XIII 468302 468303 . 0 + 1218 | XIII 478278 478279 . 0 + 1219 | XIII 490319 490320 . 0 + 1220 | XIII 496311 496312 . 0 + 1221 | XIII 499331 499332 . 0 + 1222 | XIII 507435 507436 . 0 + 1223 | XIII 520602 520603 . 0 + 1224 | XIII 533094 533095 . 0 + 1225 | XIII 538619 538620 . 0 + 1226 | XIII 542928 542929 . 0 + 1227 | XIII 549458 549459 . 0 + 1228 | XIII 554590 554591 . 0 + 1229 | XIII 561905 561906 . 0 + 1230 | XIII 570246 570247 . 0 + 1231 | XIII 572798 572799 . 0 + 1232 | XIII 578670 578671 . 0 + 1233 | XIII 597262 597263 . 0 + 1234 | XIII 610119 610120 . 0 + 1235 | XIII 622191 622192 . 0 + 1236 | XIII 626786 626787 . 0 + 1237 | XIII 634579 634580 . 0 + 1238 | XIII 640758 640759 . 0 + 1239 | XIII 650941 650942 . 0 + 1240 | XIII 652562 652563 . 0 + 1241 | XIII 658442 658443 . 0 + 1242 | XIII 665682 665683 . 0 + 1243 | XIII 669858 669859 . 0 + 1244 | XIII 677014 677015 . 0 + 1245 | XIII 685853 685854 . 0 + 1246 | XIII 690601 690602 . 0 + 1247 | XIII 698589 698590 . 0 + 1248 | XIII 703472 703473 . 0 + 1249 | XIII 713800 713801 . 0 + 1250 | XIII 718351 718352 . 0 + 1251 | XIII 725791 725792 . 0 + 1252 | XIII 741411 741412 . 0 + 1253 | XIII 747809 747810 . 0 + 1254 | XIII 753064 753065 . 0 + 1255 | XIII 754611 754612 . 0 + 1256 | XIII 758416 758417 . 0 + 1257 | XIII 761999 762000 . 0 + 1258 | XIII 775122 775123 . 0 + 1259 | XIII 778755 778756 . 0 + 1260 | XIII 796477 796478 . 0 + 1261 | XIII 802795 802796 . 0 + 1262 | XIII 805207 805208 . 0 + 1263 | XIII 811213 811214 . 0 + 1264 | XIII 824679 824680 . 0 + 1265 | XIII 833303 833304 . 0 + 1266 | XIII 840068 840069 . 0 + 1267 | XIII 842318 842319 . 0 + 1268 | XIII 849940 849941 . 0 + 1269 | XIII 855345 855346 . 0 + 1270 | XIII 864340 864341 . 0 + 1271 | XIII 878728 878729 . 0 + 1272 | XIII 899301 899302 . 0 + 1273 | XIII 910922 910923 . 0 + 1274 | XIII 917314 917315 . 0 + 1275 | XIII 921800 921801 . 0 + 1276 | XIII 923253 923254 . 0 + 1277 | XIV 12167 12168 . 0 + 1278 | XIV 15985 15986 . 0 + 1279 | XIV 27254 27255 . 0 + 1280 | XIV 33240 33241 . 0 + 1281 | XIV 42042 42043 . 0 + 1282 | XIV 45260 45261 . 0 + 1283 | XIV 49305 49306 . 0 + 1284 | XIV 54022 54023 . 0 + 1285 | XIV 58852 58853 . 0 + 1286 | XIV 61906 61907 . 0 + 1287 | XIV 71557 71558 . 0 + 1288 | XIV 78588 78589 . 0 + 1289 | XIV 84092 84093 . 0 + 1290 | XIV 102960 102961 . 0 + 1291 | XIV 105029 105030 . 0 + 1292 | XIV 109010 109011 . 0 + 1293 | XIV 121057 121058 . 0 + 1294 | XIV 126701 126702 . 0 + 1295 | XIV 156698 156699 . 0 + 1296 | XIV 167212 167213 . 0 + 1297 | XIV 171362 171363 . 0 + 1298 | XIV 179370 179371 . 0 + 1299 | XIV 196263 196264 . 0 + 1300 | XIV 215893 215894 . 0 + 1301 | XIV 222685 222686 . 0 + 1302 | XIV 229908 229909 . 0 + 1303 | XIV 235854 235855 . 0 + 1304 | XIV 246337 246338 . 0 + 1305 | XIV 249931 249932 . 0 + 1306 | XIV 256708 256709 . 0 + 1307 | XIV 260540 260541 . 0 + 1308 | XIV 292033 292034 . 0 + 1309 | XIV 299605 299606 . 0 + 1310 | XIV 303543 303544 . 0 + 1311 | XIV 308800 308801 . 0 + 1312 | XIV 325157 325158 . 0 + 1313 | XIV 338042 338043 . 0 + 1314 | XIV 340962 340963 . 0 + 1315 | XIV 343487 343488 . 0 + 1316 | XIV 347653 347654 . 0 + 1317 | XIV 351383 351384 . 0 + 1318 | XIV 352674 352675 . 0 + 1319 | XIV 354968 354969 . 0 + 1320 | XIV 360777 360778 . 0 + 1321 | XIV 368457 368458 . 0 + 1322 | XIV 371762 371763 . 0 + 1323 | XIV 379390 379391 . 0 + 1324 | XIV 389955 389956 . 0 + 1325 | XIV 397849 397850 . 0 + 1326 | XIV 402585 402586 . 0 + 1327 | XIV 410013 410014 . 0 + 1328 | XIV 416609 416610 . 0 + 1329 | XIV 420860 420861 . 0 + 1330 | XIV 424738 424739 . 0 + 1331 | XIV 438441 438442 . 0 + 1332 | XIV 443257 443258 . 0 + 1333 | XIV 469837 469838 . 0 + 1334 | XIV 476099 476100 . 0 + 1335 | XIV 486621 486622 . 0 + 1336 | XIV 493751 493752 . 0 + 1337 | XIV 505675 505676 . 0 + 1338 | XIV 508738 508739 . 0 + 1339 | XIV 512531 512532 . 0 + 1340 | XIV 517917 517918 . 0 + 1341 | XIV 533973 533974 . 0 + 1342 | XIV 539864 539865 . 0 + 1343 | XIV 549378 549379 . 0 + 1344 | XIV 557850 557851 . 0 + 1345 | XIV 560585 560586 . 0 + 1346 | XIV 568368 568369 . 0 + 1347 | XIV 575494 575495 . 0 + 1348 | XIV 577120 577121 . 0 + 1349 | XIV 583846 583847 . 0 + 1350 | XIV 586387 586388 . 0 + 1351 | XIV 595484 595485 . 0 + 1352 | XIV 611749 611750 . 0 + 1353 | XIV 616146 616147 . 0 + 1354 | XIV 621144 621145 . 0 + 1355 | XIV 624797 624798 . 0 + 1356 | XIV 629118 629119 . 0 + 1357 | XIV 631662 631663 . 0 + 1358 | XIV 632839 632840 . 0 + 1359 | XIV 636656 636657 . 0 + 1360 | XIV 639017 639018 . 0 + 1361 | XIV 644255 644256 . 0 + 1362 | XIV 648981 648982 . 0 + 1363 | XIV 654606 654607 . 0 + 1364 | XIV 667337 667338 . 0 + 1365 | XIV 669681 669682 . 0 + 1366 | XIV 677150 677151 . 0 + 1367 | XIV 680573 680574 . 0 + 1368 | XIV 687178 687179 . 0 + 1369 | XIV 692937 692938 . 0 + 1370 | XIV 697548 697549 . 0 + 1371 | XIV 700499 700500 . 0 + 1372 | XIV 712916 712917 . 0 + 1373 | XIV 716531 716532 . 0 + 1374 | XIV 742494 742495 . 0 + 1375 | XIV 748950 748951 . 0 + 1376 | XIV 769907 769908 . 0 + 1377 | XIV 774570 774571 . 0 + 1378 | XIV 781274 781275 . 0 + 1379 | XIV 782782 782783 . 0 + 1380 | XV 869 870 . 0 + 1381 | XV 11156 11157 . 0 + 1382 | XV 14942 14943 . 0 + 1383 | XV 27959 27960 . 0 + 1384 | XV 45695 45696 . 0 + 1385 | XV 49500 49501 . 0 + 1386 | XV 54572 54573 . 0 + 1387 | XV 60205 60206 . 0 + 1388 | XV 67336 67337 . 0 + 1389 | XV 78232 78233 . 0 + 1390 | XV 81487 81488 . 0 + 1391 | XV 85359 85360 . 0 + 1392 | XV 89569 89570 . 0 + 1393 | XV 103272 103273 . 0 + 1394 | XV 108222 108223 . 0 + 1395 | XV 110799 110800 . 0 + 1396 | XV 114005 114006 . 0 + 1397 | XV 125912 125913 . 0 + 1398 | XV 136465 136466 . 0 + 1399 | XV 150336 150337 . 0 + 1400 | XV 159495 159496 . 0 + 1401 | XV 180432 180433 . 0 + 1402 | XV 185745 185746 . 0 + 1403 | XV 189535 189536 . 0 + 1404 | XV 197106 197107 . 0 + 1405 | XV 200331 200332 . 0 + 1406 | XV 213874 213875 . 0 + 1407 | XV 224298 224299 . 0 + 1408 | XV 231420 231421 . 0 + 1409 | XV 240148 240149 . 0 + 1410 | XV 248345 248346 . 0 + 1411 | XV 251090 251091 . 0 + 1412 | XV 254770 254771 . 0 + 1413 | XV 256382 256383 . 0 + 1414 | XV 266215 266216 . 0 + 1415 | XV 269727 269728 . 0 + 1416 | XV 280178 280179 . 0 + 1417 | XV 282326 282327 . 0 + 1418 | XV 290716 290717 . 0 + 1419 | XV 294724 294725 . 0 + 1420 | XV 301288 301289 . 0 + 1421 | XV 309181 309182 . 0 + 1422 | XV 311137 311138 . 0 + 1423 | XV 321702 321703 . 0 + 1424 | XV 334431 334432 . 0 + 1425 | XV 345995 345996 . 0 + 1426 | XV 353951 353952 . 0 + 1427 | XV 360405 360406 . 0 + 1428 | XV 370420 370421 . 0 + 1429 | XV 372376 372377 . 0 + 1430 | XV 383176 383177 . 0 + 1431 | XV 389226 389227 . 0 + 1432 | XV 392395 392396 . 0 + 1433 | XV 402707 402708 . 0 + 1434 | XV 407933 407934 . 0 + 1435 | XV 409711 409712 . 0 + 1436 | XV 414247 414248 . 0 + 1437 | XV 430078 430079 . 0 + 1438 | XV 433529 433530 . 0 + 1439 | XV 438821 438822 . 0 + 1440 | XV 442638 442639 . 0 + 1441 | XV 445963 445964 . 0 + 1442 | XV 451526 451527 . 0 + 1443 | XV 466608 466609 . 0 + 1444 | XV 469313 469314 . 0 + 1445 | XV 473421 473422 . 0 + 1446 | XV 476864 476865 . 0 + 1447 | XV 483151 483152 . 0 + 1448 | XV 489964 489965 . 0 + 1449 | XV 497236 497237 . 0 + 1450 | XV 503448 503449 . 0 + 1451 | XV 506871 506872 . 0 + 1452 | XV 513149 513150 . 0 + 1453 | XV 538555 538556 . 0 + 1454 | XV 548675 548676 . 0 + 1455 | XV 564333 564334 . 0 + 1456 | XV 572104 572105 . 0 + 1457 | XV 579975 579976 . 0 + 1458 | XV 581585 581586 . 0 + 1459 | XV 589610 589611 . 0 + 1460 | XV 594199 594200 . 0 + 1461 | XV 600880 600881 . 0 + 1462 | XV 608556 608557 . 0 + 1463 | XV 612742 612743 . 0 + 1464 | XV 626559 626560 . 0 + 1465 | XV 633200 633201 . 0 + 1466 | XV 636847 636848 . 0 + 1467 | XV 638677 638678 . 0 + 1468 | XV 643349 643350 . 0 + 1469 | XV 647010 647011 . 0 + 1470 | XV 659707 659708 . 0 + 1471 | XV 663696 663697 . 0 + 1472 | XV 678014 678015 . 0 + 1473 | XV 680613 680614 . 0 + 1474 | XV 698050 698051 . 0 + 1475 | XV 711628 711629 . 0 + 1476 | XV 715461 715462 . 0 + 1477 | XV 718517 718518 . 0 + 1478 | XV 725143 725144 . 0 + 1479 | XV 729825 729826 . 0 + 1480 | XV 736306 736307 . 0 + 1481 | XV 738727 738728 . 0 + 1482 | XV 744357 744358 . 0 + 1483 | XV 756299 756300 . 0 + 1484 | XV 759288 759289 . 0 + 1485 | XV 760741 760742 . 0 + 1486 | XV 766716 766717 . 0 + 1487 | XV 778400 778401 . 0 + 1488 | XV 788690 788691 . 0 + 1489 | XV 793971 793972 . 0 + 1490 | XV 798493 798494 . 0 + 1491 | XV 804968 804969 . 0 + 1492 | XV 808179 808180 . 0 + 1493 | XV 812358 812359 . 0 + 1494 | XV 815816 815817 . 0 + 1495 | XV 818545 818546 . 0 + 1496 | XV 822440 822441 . 0 + 1497 | XV 827959 827960 . 0 + 1498 | XV 834322 834323 . 0 + 1499 | XV 839021 839022 . 0 + 1500 | XV 843670 843671 . 0 + 1501 | XV 850832 850833 . 0 + 1502 | XV 854148 854149 . 0 + 1503 | XV 865622 865623 . 0 + 1504 | XV 867924 867925 . 0 + 1505 | XV 874406 874407 . 0 + 1506 | XV 877133 877134 . 0 + 1507 | XV 888197 888198 . 0 + 1508 | XV 889807 889808 . 0 + 1509 | XV 906017 906018 . 0 + 1510 | XV 911613 911614 . 0 + 1511 | XV 913540 913541 . 0 + 1512 | XV 918447 918448 . 0 + 1513 | XV 930588 930589 . 0 + 1514 | XV 936613 936614 . 0 + 1515 | XV 939588 939589 . 0 + 1516 | XV 944448 944449 . 0 + 1517 | XV 946119 946120 . 0 + 1518 | XV 958174 958175 . 0 + 1519 | XV 966322 966323 . 0 + 1520 | XV 976842 976843 . 0 + 1521 | XV 981298 981299 . 0 + 1522 | XV 984862 984863 . 0 + 1523 | XV 992847 992848 . 0 + 1524 | XV 998347 998348 . 0 + 1525 | XV 1009169 1009170 . 0 + 1526 | XV 1012999 1013000 . 0 + 1527 | XV 1028120 1028121 . 0 + 1528 | XV 1041537 1041538 . 0 + 1529 | XV 1060215 1060216 . 0 + 1530 | XV 1069077 1069078 . 0 + 1531 | XV 1078227 1078228 . 0 + 1532 | XV 1083706 1083707 . 0 + 1533 | XVI 4966 4967 . 0 + 1534 | XVI 12913 12914 . 0 + 1535 | XVI 26336 26337 . 0 + 1536 | XVI 43075 43076 . 0 + 1537 | XVI 48898 48899 . 0 + 1538 | XVI 51100 51101 . 0 + 1539 | XVI 64417 64418 . 0 + 1540 | XVI 71006 71007 . 0 + 1541 | XVI 74117 74118 . 0 + 1542 | XVI 76328 76329 . 0 + 1543 | XVI 86981 86982 . 0 + 1544 | XVI 90468 90469 . 0 + 1545 | XVI 100279 100280 . 0 + 1546 | XVI 101479 101480 . 0 + 1547 | XVI 104795 104796 . 0 + 1548 | XVI 120096 120097 . 0 + 1549 | XVI 126539 126540 . 0 + 1550 | XVI 139513 139514 . 0 + 1551 | XVI 148495 148496 . 0 + 1552 | XVI 151421 151422 . 0 + 1553 | XVI 154164 154165 . 0 + 1554 | XVI 162485 162486 . 0 + 1555 | XVI 167742 167743 . 0 + 1556 | XVI 171992 171993 . 0 + 1557 | XVI 174122 174123 . 0 + 1558 | XVI 182600 182601 . 0 + 1559 | XVI 194327 194328 . 0 + 1560 | XVI 195798 195799 . 0 + 1561 | XVI 199434 199435 . 0 + 1562 | XVI 209998 209999 . 0 + 1563 | XVI 212912 212913 . 0 + 1564 | XVI 220126 220127 . 0 + 1565 | XVI 224193 224194 . 0 + 1566 | XVI 228904 228905 . 0 + 1567 | XVI 232550 232551 . 0 + 1568 | XVI 250583 250584 . 0 + 1569 | XVI 255836 255837 . 0 + 1570 | XVI 266141 266142 . 0 + 1571 | XVI 272243 272244 . 0 + 1572 | XVI 276013 276014 . 0 + 1573 | XVI 280990 280991 . 0 + 1574 | XVI 306334 306335 . 0 + 1575 | XVI 317577 317578 . 0 + 1576 | XVI 323883 323884 . 0 + 1577 | XVI 327762 327763 . 0 + 1578 | XVI 331898 331899 . 0 + 1579 | XVI 341005 341006 . 0 + 1580 | XVI 350028 350029 . 0 + 1581 | XVI 357837 357838 . 0 + 1582 | XVI 363440 363441 . 0 + 1583 | XVI 366478 366479 . 0 + 1584 | XVI 368043 368044 . 0 + 1585 | XVI 377121 377122 . 0 + 1586 | XVI 384589 384590 . 0 + 1587 | XVI 396636 396637 . 0 + 1588 | XVI 406107 406108 . 0 + 1589 | XVI 407773 407774 . 0 + 1590 | XVI 418262 418263 . 0 + 1591 | XVI 420028 420029 . 0 + 1592 | XVI 422834 422835 . 0 + 1593 | XVI 428682 428683 . 0 + 1594 | XVI 435827 435828 . 0 + 1595 | XVI 445435 445436 . 0 + 1596 | XVI 456890 456891 . 0 + 1597 | XVI 460668 460669 . 0 + 1598 | XVI 466451 466452 . 0 + 1599 | XVI 469790 469791 . 0 + 1600 | XVI 472517 472518 . 0 + 1601 | XVI 481247 481248 . 0 + 1602 | XVI 486124 486125 . 0 + 1603 | XVI 487284 487285 . 0 + 1604 | XVI 500537 500538 . 0 + 1605 | XVI 504289 504290 . 0 + 1606 | XVI 511987 511988 . 0 + 1607 | XVI 525383 525384 . 0 + 1608 | XVI 528837 528838 . 0 + 1609 | XVI 533524 533525 . 0 + 1610 | XVI 535702 535703 . 0 + 1611 | XVI 542025 542026 . 0 + 1612 | XVI 550468 550469 . 0 + 1613 | XVI 553516 553517 . 0 + 1614 | XVI 560065 560066 . 0 + 1615 | XVI 577470 577471 . 0 + 1616 | XVI 582252 582253 . 0 + 1617 | XVI 584596 584597 . 0 + 1618 | XVI 593420 593421 . 0 + 1619 | XVI 600432 600433 . 0 + 1620 | XVI 613049 613050 . 0 + 1621 | XVI 619718 619719 . 0 + 1622 | XVI 624334 624335 . 0 + 1623 | XVI 637300 637301 . 0 + 1624 | XVI 646299 646300 . 0 + 1625 | XVI 650177 650178 . 0 + 1626 | XVI 661094 661095 . 0 + 1627 | XVI 665590 665591 . 0 + 1628 | XVI 677725 677726 . 0 + 1629 | XVI 682858 682859 . 0 + 1630 | XVI 691860 691861 . 0 + 1631 | XVI 695461 695462 . 0 + 1632 | XVI 696989 696990 . 0 + 1633 | XVI 702041 702042 . 0 + 1634 | XVI 708418 708419 . 0 + 1635 | XVI 716047 716048 . 0 + 1636 | XVI 718691 718692 . 0 + 1637 | XVI 720997 720998 . 0 + 1638 | XVI 728780 728781 . 0 + 1639 | XVI 731120 731121 . 0 + 1640 | XVI 733416 733417 . 0 + 1641 | XVI 741414 741415 . 0 + 1642 | XVI 745699 745700 . 0 + 1643 | XVI 749127 749128 . 0 + 1644 | XVI 769096 769097 . 0 + 1645 | XVI 773500 773501 . 0 + 1646 | XVI 785905 785906 . 0 + 1647 | XVI 791168 791169 . 0 + 1648 | XVI 795871 795872 . 0 + 1649 | XVI 802170 802171 . 0 + 1650 | XVI 804539 804540 . 0 + 1651 | XVI 810865 810866 . 0 + 1652 | XVI 815634 815635 . 0 + 1653 | XVI 819682 819683 . 0 + 1654 | XVI 824513 824514 . 0 + 1655 | XVI 835386 835387 . 0 + 1656 | XVI 850483 850484 . 0 + 1657 | XVI 860028 860029 . 0 + 1658 | XVI 862294 862295 . 0 + 1659 | XVI 876138 876139 . 0 + 1660 | XVI 880231 880232 . 0 + 1661 | XVI 886460 886461 . 0 + 1662 | XVI 891071 891072 . 0 + 1663 | XVI 893762 893763 . 0 + 1664 | XVI 897181 897182 . 0 + 1665 | XVI 909582 909583 . 0 + 1666 | XVI 911893 911894 . 0 + 1667 | XVI 917018 917019 . 0 + 1668 | XVI 922842 922843 . 0 + 1669 | XVI 933342 933343 . 0 + 1670 | XVI 936905 936906 . 0 + 1671 | MT 77796 77797 . 0 + 1672 | -------------------------------------------------------------------------------- /inst/scripts/data.R: -------------------------------------------------------------------------------- 1 | ## ce 2 | library(purrr) 3 | library(plyranges) 4 | library(rtracklayer) 5 | features <- list( 6 | Scc1 = system.file("extdata", "TSSs.bed", package = "tidyCoverage") 7 | ) |> map(import) |> map(filter, strand == '+') |> map(`[`, 1:1000) 8 | tracks <- list( 9 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 10 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 11 | ) |> map(import, as = 'Rle') 12 | ce <- CoverageExperiment(tracks, features, width = 3000, scale = TRUE, center = TRUE) 13 | ce <- coarsen(ce, 10) 14 | usethis::use_data(ce, overwrite = TRUE) 15 | 16 | ## ac 17 | ac <- aggregate(ce) 18 | usethis::use_data(ac, overwrite = TRUE) 19 | -------------------------------------------------------------------------------- /inst/scripts/extdata.R: -------------------------------------------------------------------------------- 1 | ## conv_transcription_loci.bed 2 | conv_transcription_loci <- rtracklayer::import('~/genomes/S288c/S288c.gtf') |> 3 | filter(type == "transcript") |> 4 | sort(ignore.strand = TRUE) |> 5 | as_tibble() |> 6 | group_by(seqnames) |> 7 | dplyr::group_modify( 8 | ~ dplyr::filter(.x, 9 | strand == '+' & dplyr::lead(strand, n = 1) == '-' | 10 | strand == '-' & dplyr::lag(strand, n = 1) == '+' 11 | ) |> 12 | dplyr::mutate(start2 = end, end = dplyr::lead(start), start = start2) |> 13 | dplyr::filter(strand == '+' & dplyr::lead(strand, n = 1) == '-') 14 | ) |> 15 | dplyr::filter(end > start) |> 16 | makeGRangesFromDataFrame(keep.extra.columns = FALSE) |> 17 | anchor_center() |> 18 | mutate(width = 1) 19 | si <- Seqinfo(genome = "R64") 20 | seqlevelsStyle(conv_transcription_loci) <- 'Ensembl' 21 | seqlevels(conv_transcription_loci) <- seqlevels(si) 22 | seqinfo(conv_transcription_loci) <- si 23 | export(conv_transcription_loci, 'inst/extdata/conv_transcription_loci.bed') 24 | 25 | ## TSSs.bed 26 | library(plyranges) 27 | txdb <- TxDb.Scerevisiae.UCSC.sacCer3.sgdGene::TxDb.Scerevisiae.UCSC.sacCer3.sgdGene 28 | TSSs <- GenomicFeatures::genes(txdb) |> 29 | # filter(strand == '+') |> 30 | anchor_5p() |> 31 | mutate(width = 1) 32 | seqlevelsStyle(TSSs) <- "Ensembl" 33 | export(TSSs, 'inst/extdata/TSSs.bed') 34 | 35 | 36 | ## Scc1-vs-input.bw <-------- /home/rsg/Projects/20220309_Christophe_GC-paper/data/WT/ChIP/tracks/CH224/CH224^unmapped_CBS138^mapped_S288c^YMT7BP.vs-CH225.bw 37 | ## RNA.fwd.bw <--- /home/rsg/Projects/20220309_Christophe_GC-paper/data/WT/RNA/tracks/SRR2045244/SRR2045244^mapped_S288c^KEYTQL.fwd.CPM.bw 38 | ## RNA.rev.bw <--- /home/rsg/Projects/20220309_Christophe_GC-paper/data/WT/RNA/tracks/SRR2045244/SRR2045244^mapped_S288c^KEYTQL.rev.CPM.bw 39 | ## PolII.bw <---------------- /home/rsg/Projects/20220309_Christophe_GC-paper/data/WT/ChIP/tracks/CH244/CH244^mapped_S288c^CIJXLY.CPM.bw" 40 | ## MNase.bw <---------------- ~/Projects/20230517_Lea_MNase-timecourse/nuc_cov_Pneumo-time-course.bw 41 | library(rtracklayer) 42 | library(plyranges) 43 | library(purrr) 44 | t <- import("/home/rsg/Projects/20220309_Christophe_GC-paper/data/WT/ChIP/tracks/CH224/CH224^unmapped_CBS138^mapped_S288c^YMT7BP.vs-CH225.bw", as = 'Rle') 45 | seqlengths(t) <- lengths(t) 46 | t <- t[1:16] 47 | si <- seqinfo(t) 48 | seqlevels(si) <- seqlevels(si)[1:16] 49 | tracks <- list( 50 | `RNA.fwd.bw` = "/home/rsg/Projects/20220309_Christophe_GC-paper/data/WT/RNA/tracks/SRR2045244/SRR2045244^mapped_S288c^KEYTQL.fwd.CPM.bw", 51 | `RNA.rev.bw` = "/home/rsg/Projects/20220309_Christophe_GC-paper/data/WT/RNA/tracks/SRR2045244/SRR2045244^mapped_S288c^KEYTQL.rev.CPM.bw", 52 | `Scc1.bw` = "/home/rsg/Projects/20220309_Christophe_GC-paper/data/WT/ChIP/tracks/CH224/CH224^unmapped_CBS138^mapped_S288c^YMT7BP.vs-CH225.bw", 53 | `PolII.bw` = "/home/rsg/Projects/20220309_Christophe_GC-paper/data/WT/ChIP/tracks/CH244/CH244^mapped_S288c^CIJXLY.CPM.bw", 54 | `MNase.bw` = "~/Projects/20230517_Lea_MNase-timecourse/nuc_cov_Pneumo-time-course.bw" 55 | ) |> map(import, as = 'Rle') 56 | bins <- plyranges::tile_ranges(si |> as("GRanges"), width = 75) 57 | tracks |> 58 | map(function(x) { 59 | x <- binnedAverage(bins, x[1:16], 'mean', na.rm = FALSE) |> coverage(weigh = 'mean') 60 | x[c("II", "IV", "XVI")] 61 | }) |> 62 | imap(~ export(.x, con = paste0("inst/extdata/", .y))) 63 | -------------------------------------------------------------------------------- /man/AggregatedCoverage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/aggregate.R 3 | \name{AggregatedCoverage} 4 | \alias{AggregatedCoverage} 5 | \alias{aggregate,CoverageExperiment-method} 6 | \title{aggregate} 7 | \usage{ 8 | \S4method{aggregate}{CoverageExperiment}(x, bin = 1, ...) 9 | } 10 | \arguments{ 11 | \item{x}{a \code{CoverageExperiment} object} 12 | 13 | \item{bin}{an integer to bin each assay by. The \code{width} of the 14 | \code{AggregatedCoverage} object should be a multiple of \code{bin}.} 15 | 16 | \item{...}{ignored} 17 | } 18 | \value{ 19 | an \code{AggregatedCoverage} object 20 | } 21 | \description{ 22 | Bin coverage contained in a \code{CoverageExperiment} into an 23 | \code{AggregatedCoverage} object. 24 | } 25 | \examples{ 26 | data(ce) 27 | aggregate(ce, bin = 10) 28 | } 29 | -------------------------------------------------------------------------------- /man/CoverageExperiment.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/AllGenerics.R, R/CoverageExperiment.R, 3 | % R/coarsen.R 4 | \name{CoverageExperiment} 5 | \alias{CoverageExperiment} 6 | \alias{coarsen} 7 | \alias{CoverageExperiment,BigWigFileList,GRangesList-method} 8 | \alias{CoverageExperiment,BigWigFileList,GRanges-method} 9 | \alias{CoverageExperiment,BigWigFileList,list-method} 10 | \alias{CoverageExperiment,BigWigFile,GRangesList-method} 11 | \alias{CoverageExperiment,BigWigFile,GRanges-method} 12 | \alias{CoverageExperiment,BigWigFile,list-method} 13 | \alias{CoverageExperiment,list,GRangesList-method} 14 | \alias{CoverageExperiment,list,GRanges-method} 15 | \alias{CoverageExperiment,list,list-method} 16 | \alias{CoverageExperiment,RleList,GRangesList-method} 17 | \alias{CoverageExperiment,RleList,GRanges-method} 18 | \alias{CoverageExperiment,RleList,list-method} 19 | \alias{coarsen,CoverageExperiment-method} 20 | \title{CoverageExperiment} 21 | \usage{ 22 | CoverageExperiment(tracks, features, ...) 23 | 24 | coarsen(x, window, ...) 25 | 26 | \S4method{CoverageExperiment}{BigWigFileList,GRangesList}( 27 | tracks, 28 | features, 29 | width = NULL, 30 | center = FALSE, 31 | scale = FALSE, 32 | ignore.strand = TRUE, 33 | window = 1, 34 | BPPARAM = BiocParallel::bpparam() 35 | ) 36 | 37 | \S4method{CoverageExperiment}{BigWigFileList,GRanges}(tracks, features, ...) 38 | 39 | \S4method{CoverageExperiment}{BigWigFileList,list}(tracks, features, ...) 40 | 41 | \S4method{CoverageExperiment}{BigWigFile,GRangesList}(tracks, features, ...) 42 | 43 | \S4method{CoverageExperiment}{BigWigFile,GRanges}(tracks, features, ...) 44 | 45 | \S4method{CoverageExperiment}{BigWigFile,list}(tracks, features, ...) 46 | 47 | \S4method{CoverageExperiment}{list,GRangesList}( 48 | tracks, 49 | features, 50 | width = NULL, 51 | center = FALSE, 52 | scale = FALSE, 53 | ignore.strand = TRUE, 54 | window = 1, 55 | BPPARAM = BiocParallel::bpparam() 56 | ) 57 | 58 | \S4method{CoverageExperiment}{list,GRanges}(tracks, features, ...) 59 | 60 | \S4method{CoverageExperiment}{list,list}(tracks, features, ...) 61 | 62 | \S4method{CoverageExperiment}{RleList,GRangesList}(tracks, features, ...) 63 | 64 | \S4method{CoverageExperiment}{RleList,GRanges}(tracks, features, ...) 65 | 66 | \S4method{CoverageExperiment}{RleList,list}(tracks, features, ...) 67 | 68 | \S4method{coarsen}{CoverageExperiment}(x, window = 1, BPPARAM = BiocParallel::bpparam()) 69 | } 70 | \arguments{ 71 | \item{tracks}{A genomic track imported as a \code{RleList} or a \emph{named} list of 72 | genomic tracks.} 73 | 74 | \item{features}{A set of features imported as \code{GRanges} or a \emph{named} 75 | \code{GRangesList}.} 76 | 77 | \item{...}{Passed to the relevant method} 78 | 79 | \item{x}{a \code{CoverageExperiment} object} 80 | 81 | \item{window}{an integer to coarsen coverage by.} 82 | 83 | \item{width}{Width to resize each set of genomic features} 84 | 85 | \item{scale, center}{Logical, whether to scale and/or center tracks prior to 86 | summarization} 87 | 88 | \item{ignore.strand}{Logical, whether to not take the features strand 89 | information} 90 | 91 | \item{BPPARAM}{Passed to BiocParallel.} 92 | } 93 | \value{ 94 | A \code{CoverageExperiment} object 95 | } 96 | \description{ 97 | #' @description 98 | } 99 | \details{ 100 | \code{CoverageExperiment} objects store coverages for individual 101 | tracks over different sets of features. The \code{coverage} 102 | assay contains a separate matrix for each combination of 103 | track x features. \code{CoverageExperiment} objects are instantiated 104 | using the \code{CoverageExperiment()} #' function, and can be 105 | coarsened using the \code{coarsen()} function. 106 | } 107 | \examples{ 108 | library(rtracklayer) 109 | library(purrr) 110 | library(plyranges) 111 | TSSs_bed <- system.file("extdata", "TSSs.bed", package = "tidyCoverage") 112 | features <- import(TSSs_bed) |> filter(strand == '+') 113 | 114 | ############################################################################# 115 | ## 1. Creating a `CoverageExperiment` object from a single BigWigFile 116 | ############################################################################# 117 | 118 | RNA_fwd <- system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage") 119 | tracks <- BigWigFile(RNA_fwd) 120 | CoverageExperiment(tracks, features, width = 5000) 121 | 122 | ############################################################################# 123 | ## 2. Creating a `CoverageExperiment` object from a BigWigFileList 124 | ############################################################################# 125 | 126 | RNA_rev <- system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 127 | tracks <- BigWigFileList(list(RNA_fwd = RNA_fwd, RNA_rev = RNA_rev)) 128 | CoverageExperiment(tracks, features, width = 5000) 129 | 130 | ############################################################################# 131 | ## 3. Creating a `CoverageExperiment` object from imported bigwig files 132 | ############################################################################# 133 | 134 | tracks <- list( 135 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 136 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 137 | ) |> map(import, as = 'Rle') 138 | CoverageExperiment(tracks, features, width = 5000) 139 | 140 | ############################################################################# 141 | ## 4. Correct for strandness when recovering coverage 142 | ############################################################################# 143 | 144 | TSSs_bed <- system.file("extdata", "TSSs.bed", package = "tidyCoverage") 145 | features <- list( 146 | TSS_fwd = import(TSSs_bed) |> filter(strand == '+'), 147 | TSS_rev = import(TSSs_bed) |> filter(strand == '-') 148 | ) 149 | tracks <- list( 150 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 151 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 152 | ) |> map(import, as = 'Rle') 153 | CoverageExperiment(tracks, features, width = 5000, ignore.strand = FALSE) 154 | 155 | ############################################################################# 156 | ## Aggregating a `CoverageExperiment` object 157 | ############################################################################# 158 | data(ce) 159 | coarsen(ce, window = 10) 160 | } 161 | -------------------------------------------------------------------------------- /man/as_tibble-methods.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/as_tibble.R 3 | \name{as_tibble-methods} 4 | \alias{as_tibble-methods} 5 | \alias{as_tibble.AggregatedCoverage} 6 | \title{as_tibble} 7 | \usage{ 8 | \method{as_tibble}{AggregatedCoverage}(x, ...) 9 | } 10 | \arguments{ 11 | \item{x}{an \code{CoverageExperiment} object} 12 | 13 | \item{...}{ignored} 14 | } 15 | \value{ 16 | \code{tibble} 17 | } 18 | \description{ 19 | Coerce an \code{CoverageExperiment} or \code{AggregatedCoverage} object into a \code{tibble} 20 | } 21 | \examples{ 22 | data(ac) 23 | as_tibble(ac) 24 | } 25 | -------------------------------------------------------------------------------- /man/data.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{data} 5 | \alias{data} 6 | \alias{ce} 7 | \alias{ac} 8 | \title{Example \code{CoverageExperiment} and \code{AggregatedCoverage} objects} 9 | \format{ 10 | \code{CoverageExperiment} object containing 1 features set and 2 tracks. 11 | 12 | \code{AggregatedCoverage} object containing 1 features set and 2 tracks. 13 | } 14 | \usage{ 15 | data(ce) 16 | 17 | data(ac) 18 | } 19 | \description{ 20 | Two example objects are provided in the \code{tidyCoverage} package: 21 | \itemize{ 22 | \item \code{ce}: a \code{CoverageExperiment} dataset containing stranded RNA-seq coverage 23 | (forward and reverse) over Scc1 peaks (± 1kb). 24 | \item \code{ac}: an \code{AggregatedCoverage} object obtained with \code{aggregate(ce)}. 25 | } 26 | } 27 | \details{ 28 | Data was generated in yeast (S288c) and aligned to reference R64-1-1. 29 | } 30 | \keyword{datasets} 31 | -------------------------------------------------------------------------------- /man/expand.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/expand.R 3 | \name{expand,CoverageExperiment} 4 | \alias{expand,CoverageExperiment} 5 | \alias{expand.CoverageExperiment} 6 | \alias{expand,CoverageExperiment-method} 7 | \title{Expand a CoverageExperiment object} 8 | \usage{ 9 | \method{expand}{CoverageExperiment}(data, ..., .name_repair = NULL) 10 | } 11 | \arguments{ 12 | \item{data}{a \code{CoverageExperiment} object} 13 | 14 | \item{..., .name_repair}{ignored} 15 | } 16 | \value{ 17 | a \code{tibble} object 18 | } 19 | \description{ 20 | A \code{CoverageExperiment} object can be coerced into a \code{tibble} using the 21 | \code{tidySummarizedExperiment} package, but this will not turn 22 | each coverage matrix into a "long" format. The \code{expand} function 23 | provided here allows one to coerce a \code{CoverageExperiment} 24 | object into a long data frame, and adds the \code{ranges} 25 | and \code{seqnames} to the resulting \code{tibble}. 26 | } 27 | \examples{ 28 | data(ce) 29 | ce 30 | 31 | expand(ce) 32 | } 33 | -------------------------------------------------------------------------------- /man/figures/PTMs-TSSs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/man/figures/PTMs-TSSs.png -------------------------------------------------------------------------------- /man/figures/aggr-cov.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/man/figures/aggr-cov.png -------------------------------------------------------------------------------- /man/figures/cov.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/js2264/tidyCoverage/d2f5e792641f0f37970710e026ba1ae3903a06e4/man/figures/cov.png -------------------------------------------------------------------------------- /man/ggplot-tidyCoverage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geoms.R 3 | \name{ggplot-tidyCoverage} 4 | \alias{ggplot-tidyCoverage} 5 | \alias{geom_aggrcoverage} 6 | \alias{geom_coverage} 7 | \alias{scale_y_coverage} 8 | \alias{scale_x_genome} 9 | \title{Plotting functions} 10 | \usage{ 11 | geom_aggrcoverage( 12 | mapping = NULL, 13 | data = NULL, 14 | ..., 15 | unit = c("kb", "Mb", "b"), 16 | ci = TRUE, 17 | grid = FALSE, 18 | na.rm = FALSE, 19 | show.legend = NA, 20 | inherit.aes = TRUE 21 | ) 22 | 23 | geom_coverage( 24 | mapping = NULL, 25 | data = NULL, 26 | ..., 27 | type = c("area", "line"), 28 | unit = c("kb", "Mb", "b"), 29 | grid = FALSE, 30 | na.rm = FALSE, 31 | show.legend = NA, 32 | inherit.aes = TRUE 33 | ) 34 | 35 | scale_y_coverage() 36 | 37 | scale_x_genome(unit = c("kb", "Mb", "b")) 38 | } 39 | \arguments{ 40 | \item{mapping}{Aesthetics for geom_*. By default, no color/fill aesthetic 41 | is specified, but they can be assigned to a variable with \code{mapping = aes(...)}. 42 | Note that \code{x} and \code{y} are automatically filled.} 43 | 44 | \item{data}{Data frame passed to geom_*. Typically a \code{CoverageExperiment} object 45 | (expanded to a tibble) or a \code{AggregatedCoverage} object.} 46 | 47 | \item{..., na.rm, show.legend, inherit.aes}{Argument passed to \code{ggplot} 48 | internal functions} 49 | 50 | \item{unit}{Rounding of x axis (any of c('b', 'kb', 'Mb')).} 51 | 52 | \item{ci}{Should the confidence interval be plotted by \code{geom_aggrcoverage()}? 53 | (default: TRUE)} 54 | 55 | \item{grid}{Should the plot grid by displayed? (default: FALSE).} 56 | 57 | \item{type}{Choose between "line" and "area" style for \code{geom_coverage()}.} 58 | } 59 | \value{ 60 | A \code{ggplot} object` 61 | } 62 | \description{ 63 | #' @description 64 | } 65 | \details{ 66 | Plotting functions for tidyCoverage objects 67 | } 68 | \examples{ 69 | library(rtracklayer) 70 | library(plyranges) 71 | library(ggplot2) 72 | library(purrr) 73 | TSSs_bed <- system.file("extdata", "TSSs.bed", package = "tidyCoverage") 74 | features <- list( 75 | TSS_fwd = import(TSSs_bed) |> filter(strand == '+'), 76 | TSS_rev = import(TSSs_bed) |> filter(strand == '-'), 77 | conv_sites = import(system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage")) 78 | ) 79 | tracks <- list( 80 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 81 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage"), 82 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage") 83 | ) |> map(import, as = 'Rle') 84 | ce <- CoverageExperiment(tracks, features, width = 5000, center = TRUE, scale = TRUE) 85 | ac <- aggregate(ce) 86 | 87 | ############################################################################# 88 | ## 1. Plotting aggregated coverage 89 | ############################################################################# 90 | 91 | ac |> 92 | as_tibble() |> 93 | ggplot() + 94 | geom_aggrcoverage(aes(col = track)) + 95 | facet_grid(track ~ features) + 96 | geom_vline(xintercept = 0, color = 'black', linetype = 'dashed', linewidth = 0.5) 97 | 98 | ############################################################################# 99 | ## 2. Plotting track coverages over individual loci 100 | ############################################################################# 101 | 102 | ce2 <- CoverageExperiment( 103 | tracks, 104 | GRangesList(list(locus1 = "II:400001-455000", locus2 = "IV:720001-775000")), 105 | window = 50 106 | ) 107 | expand(ce2) |> 108 | mutate(coverage = ifelse(track != 'Scc1', scales::oob_squish(coverage, c(0, 50)), coverage)) |> 109 | ggplot() + 110 | geom_coverage(aes(fill = track)) + 111 | facet_grid(track~features, scales = 'free') 112 | } 113 | -------------------------------------------------------------------------------- /man/reexports.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/reexports.R 3 | \docType{import} 4 | \name{reexports} 5 | \alias{reexports} 6 | \alias{as_tibble} 7 | \alias{expand} 8 | \alias{aggregate} 9 | \title{Objects exported from other packages} 10 | \value{ 11 | Depending on the re-exported function 12 | } 13 | \examples{ 14 | 1 + 1 15 | } 16 | \keyword{internal} 17 | \description{ 18 | These objects are imported from other packages. Follow the links 19 | below to see their documentation. 20 | 21 | \describe{ 22 | \item{dplyr}{\code{\link[dplyr:reexports]{as_tibble}}} 23 | 24 | \item{S4Vectors}{\code{\link[S4Vectors:aggregate-methods]{aggregate}}} 25 | 26 | \item{tidyr}{\code{\link[tidyr]{expand}}} 27 | }} 28 | 29 | -------------------------------------------------------------------------------- /man/show.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/show.R 3 | \name{show} 4 | \alias{show} 5 | \alias{show,CoverageExperiment-method} 6 | \alias{show,AggregatedCoverage-method} 7 | \alias{print.CoverageExperiment} 8 | \alias{print.AggregatedCoverage} 9 | \alias{tbl_format_header.tidyCoverageExperiment} 10 | \alias{tbl_format_header.tidyAggregatedCoverage} 11 | \title{show} 12 | \usage{ 13 | \S4method{show}{CoverageExperiment}(object) 14 | 15 | \S4method{show}{AggregatedCoverage}(object) 16 | 17 | \method{print}{CoverageExperiment}(x, ..., n = NULL) 18 | 19 | \method{print}{AggregatedCoverage}(x, ..., n = NULL) 20 | 21 | \method{tbl_format_header}{tidyCoverageExperiment}(x, setup, ...) 22 | 23 | \method{tbl_format_header}{tidyAggregatedCoverage}(x, setup, ...) 24 | } 25 | \arguments{ 26 | \item{object}{a \code{CoverageExperiment} or \code{AggregatedCoverage} object} 27 | 28 | \item{x}{Object to format or print.} 29 | 30 | \item{...}{Passed on to \code{\link[=tbl_format_setup]{tbl_format_setup()}}.} 31 | 32 | \item{n}{Number of rows to show. If \code{NULL}, the default, will print all rows 33 | if less than the \code{print_max} \link[pillar:pillar_options]{option}. 34 | Otherwise, will print as many rows as specified by the 35 | \code{print_min} \link[pillar:pillar_options]{option}.} 36 | 37 | \item{setup}{a setup object returned from \code{\link[pillar:tbl_format_setup]{pillar::tbl_format_setup()}}.} 38 | } 39 | \value{ 40 | \verb{Prints a message to the console describing the contents of the }CoverageExperiment\code{or}AggregatedCoverage` objects. 41 | } 42 | \description{ 43 | show method for \code{CoverageExperiment} and \code{AggregatedCoverage} objects 44 | } 45 | \examples{ 46 | data(ce) 47 | print(ce) 48 | data(ac) 49 | print(ac) 50 | } 51 | -------------------------------------------------------------------------------- /manuscript_figure.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Figure for tidyCoverage manuscript" 3 | --- 4 | 5 | ```{r setup, include = FALSE} 6 | knitr::opts_chunk$set( 7 | collapse = TRUE, 8 | comment = "#>", 9 | crop = NULL, 10 | width = 180, 11 | error = TRUE 12 | ) 13 | library(tidyCoverage) 14 | library(AnnotationHub) 15 | library(purrr) 16 | library(plyranges) 17 | library(rtracklayer) 18 | library(ggplot2) 19 | ``` 20 | 21 | # Plotting aggregate signals (ENCODE data) over REs 22 | 23 | _Note: this is a Quarto vignette (`.qmd`)_ 24 | 25 | ```{r, eval = FALSE} 26 | library(tidyCoverage) 27 | library(AnnotationHub) 28 | library(purrr) 29 | library(plyranges) 30 | library(rtracklayer) 31 | library(ggplot2) 32 | 33 | # ~~~~~~~~~~ Tracks ~~~~~~~~~~ # 34 | ids <- c( 35 | fwdGRO = "ENCFF896TNM", 36 | revGRO = "ENCFF764SVR", 37 | Pol2RA = "ENCFF890SYC", 38 | CTCF = "ENCFF484SOD", 39 | DNAse = "ENCFF428XFI", 40 | ATAC = "ENCFF165WGA", 41 | H3K4me1 = "ENCFF785YET", 42 | H3K4me3 = "ENCFF736DCK", 43 | H3K9me3 = "ENCFF698SKV", 44 | H3K27me3 = "ENCFF119CAV", 45 | H3K27ac = "ENCFF458CRP" 46 | ) 47 | future::plan(future::multisession(workers = 13)) 48 | options(timeout=10000) 49 | furrr::future_map(ids[7:13], ~ { 50 | download.file(glue::glue("https://www.encodeproject.org/files/{.x}/@@download/{.x}.bigWig"), glue::glue("encode/{.x}.bigWig")) 51 | }) 52 | tracks <- rtracklayer::BigWigFileList(paste0('encode/', ids, '.bigWig')) 53 | names(tracks) <- names(ids) 54 | 55 | # ~~~~~~~~~~ REs ~~~~~~~~~~ # 56 | download.file('https://static-content.springer.com/esm/art%3A10.1038%2Fs41586-020-2493-4/MediaObjects/41586_2020_2493_MOESM12_ESM.txt', 'data/REs_GRCh38.txt') 57 | features <- vroom::vroom('data/REs_GRCh38.txt', col_names = TRUE, show_col_types = FALSE) |> 58 | filter(chr == 'chr1') |> 59 | filter(group %in% c('PLS,CTCF-bound', 'pELS,CTCF-bound', 'pELS', 'dELS,CTCF-bound', 'dELS')) |> 60 | group_by(group) |> 61 | dplyr::slice_head(n = 10000) |> 62 | makeGRangesFromDataFrame(keep.extra.columns = TRUE) 63 | genome(features) <- 'hg38' 64 | REs <- split(features, features$group) 65 | 66 | # ~~~~~~~~~~ Computing coverage of all tracks over all features ~~~~~~~~~~ # 67 | library(BiocParallel) 68 | register(MulticoreParam(workers = 13, progressbar = TRUE)) 69 | CE <- CoverageExperiment( 70 | tracks = tracks, 71 | features = REs, 72 | width = 5000, 73 | window = 5 74 | ) 75 | AC <- aggregate(CE) 76 | 77 | # ~~~~~~~~~~ Plot the resulting AggregatedCoverage object ~~~~~~~~~~ # 78 | AC |> 79 | as_tibble() |> 80 | group_by(track, features) |> 81 | mutate(group = dplyr::case_when( 82 | stringr::str_detect(track, 'RNA|GRO') ~ "RNA", 83 | stringr::str_detect(track, 'CTCF|DNAse|ATAC') ~ "Accessibility", 84 | stringr::str_detect(track, 'H3') ~ "Histone PTMs" 85 | )) |> 86 | # mutate(across(all_of(c("mean", "ci_low", "ci_high")), ~ ifelse(group == 'RNA', scale(.x), .x))) |> 87 | mutate(group = factor(group, c("RNA", "Accessibility", "Histone PTMs"))) |> 88 | mutate(track = factor(track, names(ids))) |> 89 | tidyr::drop_na() |> 90 | ggplot(aes(x = coord, y = mean)) + 91 | geom_ribbon(aes(ymin = ci_low, ymax = ci_high, fill = track), alpha = 0.2) + 92 | geom_line(aes(col = track)) + 93 | facet_grid(group~features, scales = 'free') + 94 | labs(x = 'Distance from center of reg. elements', y = 'Track signal') + 95 | theme_bw() + 96 | theme(legend.position = 'top') + 97 | hues::scale_colour_iwanthue() + 98 | hues::scale_fill_iwanthue() 99 | ``` 100 | 101 | # Plotting matrix signals (ENCODE data) over REs 102 | 103 | ```{r, eval = FALSE} 104 | expand(CE) |> 105 | filter(track == "ATAC") |> 106 | select(-coord) |> 107 | nest(data = c(coord.scaled, coverage)) |> 108 | mutate(score = map_dbl( 109 | data, 110 | ~ filter(.x, abs(coord.scaled) < 50) |> pull(coverage) |> mean(na.rm = TRUE) 111 | )) |> 112 | unnest(data) |> 113 | arrange(score) |> 114 | mutate(coverage = scales::oob_squish(coverage, c(0, 10))) |> 115 | ggplot(aes(x = coord.scaled, y = factor(ranges, unique(ranges)), fill = coverage)) + 116 | geom_tile() |> ggrastr::rasterize() + 117 | facet_wrap(~ features, scales = 'free') + 118 | scale_fill_distiller(palette = 'Spectral', direction = -1) + 119 | scale_x_continuous(expand = c(0,0)) + 120 | theme_bw() + 121 | theme( 122 | legend.position = 'bottom', 123 | axis.text.y = element_blank(), 124 | axis.ticks.y = element_blank() 125 | ) 126 | 127 | as_tibble(AC) |> filter(track == "ATAC", features == 'PLS,CTCF-bound') |> 128 | pivot_longer(all_of(c("mean", "median", "ci_low", "ci_high")), names_to = 'coverage', values_to = 'score') |> 129 | ggplot(aes(x = coord, y = score, col = coverage)) + 130 | geom_path() + 131 | facet_grid(~ coverage) 132 | ``` 133 | 134 | # Session info 135 | 136 | ```{r} 137 | sessioninfo::session_info() 138 | ``` 139 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/tests.html 7 | # * https://testthat.r-lib.org/reference/test_package.html#special-files 8 | 9 | library(testthat) 10 | library(tidyCoverage) 11 | 12 | test_check("tidyCoverage") 13 | -------------------------------------------------------------------------------- /tests/testthat/test-compute-filter-import-plot.R: -------------------------------------------------------------------------------- 1 | test_that("CoverageExperiment works", { 2 | 3 | library(rtracklayer) 4 | library(plyranges) 5 | library(purrr) 6 | 7 | # ~~~~~~~~~~~~~~~ Import genomic features into a named list ~~~~~~~~~~~~~~~ # 8 | features <- list( 9 | TSSs = system.file("extdata", "TSSs.bed", package = "tidyCoverage"), 10 | `Convergent transcription` = system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage") 11 | ) |> map(import) |> map(filter, strand == '+') 12 | 13 | # ~~~~~~~~~~~~~~~ Import coverage tracks into a named list ~~~~~~~~~~~~~~~ # 14 | tracks <- list( 15 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage"), 16 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 17 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 18 | ) |> map(import, as = 'Rle') 19 | 20 | ## ~~~~~~~~~~~~~~~ TEST GETTERS ~~~~~~~~~~~~~~~ ## 21 | expect_s4_class( 22 | CE <- CoverageExperiment( 23 | tracks, features, width = 100, scale = TRUE, center = TRUE 24 | ), 25 | "CoverageExperiment" 26 | ) 27 | expect_true(all(dim(CE) == c(2, 3))) 28 | expect_true(names(assays(CE)) == 'coverage') 29 | expect_true(length(assay(CE, 'coverage')) == 6L) 30 | expect_true(length(assay(CE, 'coverage')[[1]]) == 87300L) 31 | expect_true(length(assay(CE, 'coverage')[[2]]) == 46900L) 32 | expect_true(length(assay(CE, 'coverage')[[3]]) == 87300L) 33 | expect_true(length(assay(CE, 'coverage')[[4]]) == 46900L) 34 | expect_true(length(assay(CE, 'coverage')[[5]]) == 87300L) 35 | expect_true(length(assay(CE, 'coverage')[[6]]) == 46900L) 36 | expect_true(all(dim(assay(CE, 'coverage')[[1]]) == c(873, 100))) 37 | expect_true(all(dim(assay(CE, 'coverage')[[2]]) == c(469, 100))) 38 | expect_true(all(rowData(CE)$n == c(873, 469))) 39 | expect_true(all(colnames(CE) == c('Scc1', 'RNA_fwd', 'RNA_rev'))) 40 | 41 | }) 42 | 43 | test_that("other CoverageExperiment methods work", { 44 | # ~~~~~~~~ BigWigFile + GRanges 45 | x <- BigWigFile(system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage")) 46 | y <- import(system.file("extdata", "TSSs.bed", package = "tidyCoverage"))[1:200] 47 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 48 | expect_s4_class(CoverageExperiment(x, y), "CoverageExperiment") 49 | 50 | # ~~~~~~~~ BigWigFile + GRangesList 51 | y <- GRangesList(tss = y, tss2 = y) 52 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 53 | 54 | # ~~~~~~~~ BigWigFile + list 55 | y <- as.list(y) 56 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 57 | 58 | # ~~~~~~~~ BigWigFileList + GRanges 59 | x <- BigWigFileList(list( 60 | track = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 61 | track2 = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage") 62 | )) 63 | y <- import(system.file("extdata", "TSSs.bed", package = "tidyCoverage")) 64 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 65 | 66 | # ~~~~~~~~ BigWigFileList + GRangesList 67 | y <- GRangesList(tss = y) 68 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 69 | 70 | # ~~~~~~~~ BigWigFileList + list 71 | y <- as.list(y) 72 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 73 | 74 | # ~~~~~~~~ RleList + GRanges 75 | x <- import(system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), as = 'Rle') 76 | y <- import(system.file("extdata", "TSSs.bed", package = "tidyCoverage")) 77 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 78 | expect_s4_class(CoverageExperiment(x, y), "CoverageExperiment") 79 | 80 | # ~~~~~~~~ RleList + GRangesList 81 | y <- GRangesList(tss = y) 82 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 83 | 84 | # ~~~~~~~~ RleList + list 85 | y <- as.list(y) 86 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 87 | 88 | # ~~~~~~~~ list + GRanges 89 | x <- list( 90 | track = import(system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), as = 'Rle'), 91 | track2 = import(system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), as = 'Rle') 92 | ) 93 | y <- import(system.file("extdata", "TSSs.bed", package = "tidyCoverage"))[1:200] 94 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 95 | 96 | # ~~~~~~~~ list + GRangesList 97 | y <- GRangesList(tss = y, tss2 = y) 98 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 99 | 100 | # ~~~~~~~~ list + list 101 | y <- as.list(y) 102 | expect_s4_class(CoverageExperiment(x, y, width = 100), "CoverageExperiment") 103 | }) 104 | 105 | test_that("aggregate works", { 106 | 107 | features <- list( 108 | TSSs = system.file("extdata", "TSSs.bed", package = "tidyCoverage"), 109 | `Convergent transcription` = system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage") 110 | ) |> map(import) |> map(filter, strand == '+') 111 | tracks <- list( 112 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage"), 113 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 114 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 115 | ) |> map(import, as = 'Rle') 116 | CE <- CoverageExperiment( 117 | tracks, features, width = 100, scale = TRUE, center = TRUE 118 | ) 119 | 120 | expect_s4_class( 121 | AC <- aggregate(CE), 122 | "AggregatedCoverage" 123 | ) 124 | expect_true(all(dim(AC) == dim(CE))) 125 | expect_true(all(names(assays(AC)) == c("mean", "median", "min", "max", "sd", "se", "ci_low", "ci_high"))) 126 | expect_true(length(assay(AC, 'mean')) == 6L) 127 | expect_true(length(assay(AC, 'mean')[[1]]) == 100L) 128 | expect_true(length(assay(AC, 'mean')[[2]]) == 100L) 129 | expect_true(all(rowData(AC)$n == c(873, 469))) 130 | expect_true(all(colnames(AC) == c('Scc1', 'RNA_fwd', 'RNA_rev'))) 131 | }) 132 | 133 | test_that("print/show work", { 134 | features <- list( 135 | TSSs = system.file("extdata", "TSSs.bed", package = "tidyCoverage"), 136 | `Convergent transcription` = system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage") 137 | ) |> map(import) |> map(filter, strand == '+') 138 | tracks <- list( 139 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage"), 140 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 141 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 142 | ) |> map(import, as = 'Rle') 143 | CE <- CoverageExperiment( 144 | tracks, features, width = 100, scale = TRUE, center = TRUE 145 | ) 146 | AC <- aggregate(CE) 147 | 148 | options(restore_SummarizedExperiment_show = TRUE) 149 | expect_no_error(show(CE)) 150 | expect_no_error(show(AC)) 151 | expect_no_error(print(CE)) 152 | expect_no_error(print(AC)) 153 | options(restore_SummarizedExperiment_show = FALSE) 154 | expect_no_error(show(CE)) 155 | expect_no_error(show(AC)) 156 | expect_no_error(print(CE)) 157 | expect_no_error(print(AC)) 158 | }) 159 | 160 | test_that("as_tibble methods work", { 161 | features <- list( 162 | TSSs = system.file("extdata", "TSSs.bed", package = "tidyCoverage"), 163 | `Convergent transcription` = system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage") 164 | ) |> map(import) |> map(filter, strand == '+') 165 | tracks <- list( 166 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage"), 167 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 168 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 169 | ) |> map(import, as = 'Rle') 170 | CE <- CoverageExperiment( 171 | tracks, features, width = 100, scale = TRUE, center = TRUE 172 | ) 173 | AC <- aggregate(CE) 174 | 175 | expect_true(all(dim(as_tibble(AC)) == c(600, 13))) 176 | expect_true(all(colnames(as_tibble(AC)) == c(".sample", ".feature", "track", "features", "coord", "mean", "median", "min", "max", "sd", "se", "ci_low", "ci_high"))) 177 | }) 178 | 179 | test_that("expand method works", { 180 | features <- list( 181 | TSSs = system.file("extdata", "TSSs.bed", package = "tidyCoverage"), 182 | `Convergent transcription` = system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage") 183 | ) |> map(import) |> map(filter, strand == '+') 184 | tracks <- list( 185 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage"), 186 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 187 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 188 | ) |> map(import, as = 'Rle') 189 | CE <- CoverageExperiment( 190 | tracks, features, width = 100, scale = TRUE, center = TRUE 191 | ) 192 | expect_true(all(dim(expand(CE)) == c(402600, 8))) 193 | expect_true(all(colnames(expand(CE)) == c("track", "features", "chr", "ranges", "strand", "coord", "coverage", "coord.scaled"))) 194 | }) 195 | 196 | test_that("coarsen method works", { 197 | features <- list( 198 | TSSs = system.file("extdata", "TSSs.bed", package = "tidyCoverage"), 199 | `Convergent transcription` = system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage") 200 | ) |> map(import) |> map(filter, strand == '+') 201 | tracks <- list( 202 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage"), 203 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 204 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage") 205 | ) |> map(import, as = 'Rle') 206 | CE <- CoverageExperiment( 207 | tracks, features, width = 100, scale = TRUE, center = TRUE 208 | ) 209 | AC <- aggregate(CE) 210 | 211 | expect_s4_class( 212 | CCE <- coarsen(CE, 10), 213 | "CoverageExperiment" 214 | ) 215 | expect_true(all(dim(assay(CCE, 'coverage')[[1]]) == c(873, 10))) 216 | expect_true(all(dim(assay(CCE, 'coverage')[[2]]) == c(469, 10))) 217 | expect_true(all(rowData(CCE)$n == c(873, 469))) 218 | }) 219 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | *.bed 4 | *qmd 5 | /.quarto/ 6 | -------------------------------------------------------------------------------- /vignettes/tidyCoverage.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to tidyCoverage" 3 | output: 4 | BiocStyle::html_document: 5 | self_contained: yes 6 | toc: true 7 | toc_float: true 8 | toc_depth: 2 9 | code_folding: show 10 | date: "`r doc_date()`" 11 | package: "`r pkg_ver('tidyCoverage')`" 12 | vignette: > 13 | %\VignetteIndexEntry{Introduction to tidyCoverage} 14 | %\VignetteEngine{knitr::rmarkdown} 15 | %\VignetteEncoding{UTF-8} 16 | --- 17 | 18 | ```{r setup, include = FALSE} 19 | knitr::opts_chunk$set( 20 | collapse = TRUE, 21 | comment = "#>", 22 | crop = NULL, 23 | width = 180, 24 | dpi = 72, 25 | fig.align = "center", 26 | fig.width = 5, 27 | fig.asp = 0.7, 28 | dev = 'jpeg' 29 | ) 30 | ``` 31 | 32 | ```{r warning = FALSE, include = FALSE, echo = FALSE, message = FALSE, results = FALSE} 33 | library(tidyCoverage) 34 | ``` 35 | 36 | # Introduction 37 | 38 | Genome-wide assays provide powerful methods to profile the composition, the 39 | conformation and the activity of the chromatin. Linear "coverage" tracks 40 | (generally stored as `.bigwig` files) are one of the outputs obtained 41 | when processing raw high-throughput sequencing data. These coverage tracks 42 | can be inspected in genome interactive browsers (e.g. `IGV`) to visually 43 | appreciate local or global variations in the coverage of specific genomic assays. 44 | 45 | The coverage signal aggregated over multiple genomic features can also be computed. 46 | This approach is very efficient to summarize and compare the coverage 47 | of chromatin modalities (e.g. protein binding profiles from ChIP-seq, transcription 48 | profiles from RNA-seq, chromatin accessibility from ATAC-seq, ...) over 49 | hundreds and up to thousands of genomic features of interest. This unlocks a more 50 | quantitative description of the coverage over groups of genomic features. 51 | 52 | `tidyCoverage` implements the `CoverageExperiment` and the `AggregatedCoverage` 53 | classes built on top of the `SummarizedExperiment` class. These classes 54 | formalize the extraction and aggregation of coverage tracks over 55 | sets of genomic features of interests. 56 | 57 | # Installation 58 | 59 | `tidyCoverage` package can be installed from Bioconductor using the following 60 | command: 61 | 62 | ```{r eval = FALSE} 63 | if (!require("BiocManager", quietly = TRUE)) 64 | install.packages("BiocManager") 65 | 66 | BiocManager::install("tidyCoverage") 67 | ``` 68 | 69 | # `CoverageExperiment` and `AggregatedCoverage` classes 70 | 71 | ## `CoverageExperiment` 72 | 73 | `tidyCoverage` package defines the `CoverageExperiment`, directly extending 74 | the `SummarizedExperiment` class. This means that all standard methods 75 | available for `SummarizedExperiment`s are available for `CoverageExperiment` 76 | objects. 77 | 78 | ```{r} 79 | library(tidyCoverage) 80 | showClass("CoverageExperiment") 81 | 82 | data(ce) 83 | ce 84 | 85 | rowData(ce) 86 | 87 | rowRanges(ce) 88 | 89 | colData(ce) 90 | 91 | assays(ce) 92 | 93 | assay(ce, 'coverage') 94 | ``` 95 | 96 | Note that whereas traditional `SummarizedExperiment` objects 97 | store atomic values stored in individual cells of an assay, each cell of 98 | the `CoverageExperiment` `coverage` assay contains a list of length 1, 99 | itself containing an array. This array stores the per-base 100 | coverage score of a genomic track (from `colData`) over a set of genomic 101 | ranges of interest (from `rowData`). 102 | 103 | ```{r} 104 | assay(ce, 'coverage') 105 | 106 | assay(ce, 'coverage')[1, 1] |> class() 107 | 108 | assay(ce, 'coverage')[1, 1] |> length() 109 | 110 | assay(ce, 'coverage')[1, 1][[1]] |> class() 111 | 112 | assay(ce, 'coverage')[1, 1][[1]] |> dim() 113 | 114 | # Compare this to `rowData(ce)$n` and `width(ce)` 115 | rowData(ce)$n 116 | 117 | width(ce) 118 | 119 | assay(ce[1, 1], 'coverage')[[1]][1:10, 1:10] 120 | ``` 121 | 122 | ## `AggregatedCoverage` 123 | 124 | `AggregatedCoverage` also directly extends the `SummarizedExperiment` class. 125 | 126 | ```{r} 127 | showClass("AggregatedCoverage") 128 | 129 | data(ac) 130 | ac 131 | 132 | rowData(ac) 133 | 134 | rowRanges(ac) 135 | 136 | colData(ac) 137 | 138 | assays(ac) 139 | 140 | assay(ac, 'mean') 141 | ``` 142 | 143 | It stores per-base coverage statistical metrics in assays (e.g. `mean`, `median`, ...). 144 | Each assay thus contains an **matrix of vectors**. 145 | 146 | ```{r} 147 | assay(ac[1, 1], 'mean')[[1]] |> dim() 148 | 149 | assay(ac[1, 1], 'mean')[[1]] |> length() 150 | 151 | assay(ac[1, 1], 'mean')[[1]][1:10] 152 | ``` 153 | 154 | # Manipulate `CoverageExperiment` objects 155 | 156 | ## Create a `CoverageExperiment` object 157 | 158 | One can use `CoverageExperiment()` constructor along with: 159 | 160 | - A single `bigwig` file imported `as = "Rle"` and a `GRanges` or a *named* `GRangesList`; 161 | - A *named* list of `bigwig` files imported `as = "Rle"` and a `GRanges` or a *named* `GRangesList`; 162 | - A `BigWigFile` object and a `GRanges` or a *named* `GRangesList`; 163 | - A *named* `BigWigFileList` object and a `GRanges` or a *named* `GRangesList`; 164 | 165 | A numeric `width` argument also needs to be specified. It is used to center 166 | `features` to their midpoint and resize them to the chosen `width`. 167 | 168 | For example: 169 | 170 | ```{r} 171 | library(rtracklayer) 172 | bw_file <- system.file("extdata", "MNase.bw", package = "tidyCoverage") 173 | bw_file 174 | 175 | bed_file <- system.file("extdata", "TSSs.bed", package = "tidyCoverage") 176 | bed_file 177 | 178 | CE <- CoverageExperiment( 179 | tracks = import(bw_file, as = "Rle"), 180 | features = import(bed_file), 181 | width = 3000 182 | ) 183 | CE 184 | ``` 185 | 186 | And this works as well (note that in this case the names of the `GRangesList` 187 | are being used as `rownames`): 188 | 189 | ```{r} 190 | library(rtracklayer) 191 | bw_file <- system.file("extdata", "MNase.bw", package = "tidyCoverage") 192 | bw_file 193 | 194 | bed_file <- system.file("extdata", "TSSs.bed", package = "tidyCoverage") 195 | bed_file 196 | 197 | CoverageExperiment( 198 | tracks = BigWigFile(bw_file), 199 | features = GRangesList('TSSs' = import(bed_file)), 200 | width = 3000 201 | ) 202 | ``` 203 | 204 | ## Bin a `CoverageExperiment` object 205 | 206 | By default, `CoverageExperiment` objects store _per-base_ track coverage. 207 | This implies that any cell from the `coverage` assay has as many columns 208 | as the `width` provided in the constructor function. 209 | 210 | ```{r} 211 | assay(CE, 'coverage')[1, 1][[1]] |> ncol() 212 | ``` 213 | 214 | If _per-base_ resolution is not needed, one can use the `window` argument in 215 | the constructor function to average the coverage score over non-overlapping bins. 216 | 217 | ```{r} 218 | CE2 <- CoverageExperiment( 219 | tracks = import(bw_file, as = "Rle"), 220 | features = import(bed_file), 221 | width = 3000, 222 | window = 20 223 | ) 224 | 225 | CE2 226 | 227 | assay(CE2, 'coverage')[1, 1][[1]] |> ncol() 228 | ``` 229 | 230 | If a `CoverageExperiment` object has already been computed, the `coarsen()` 231 | function can be used afterwards to reduce the resolution of the object. 232 | 233 | ```{r} 234 | CE3 <- coarsen(CE, window = 20) 235 | 236 | CE3 237 | 238 | identical(CE2, CE3) 239 | ``` 240 | 241 | ## Expand a `CoverageExperiment` object 242 | 243 | The `expand` method from the `tidyr` package is adapted to `CoverageExperiment` 244 | objects to return a tidy `tibble`. This reformated object contains several 245 | columns: 246 | 247 | 1. `track`: storing `colnames`, i.e. names of tracks used in the original `CoverageExperiment`; 248 | 2. `features`: storing `rownames`, i.e. names of features used in the original `CoverageExperiment`; 249 | 3. `chr`: features `seqnames` from the `CoverageExperiment`; 250 | 4. `ranges`: features from the `CoverageExperiment` coerced as `character`; 251 | 5. `strand`: features `strand` from the `CoverageExperiment`; 252 | 6. `coord`: exact genomic position from the `CoverageExperiment`; 253 | 7. `coverage`: coverage score extracted from corresponding `track` at `chr:coord`; 254 | 8. `coord.scaled`: 0-centered genomic position; 255 | 256 | ```{r} 257 | expand(CE) 258 | ``` 259 | 260 | Note that if the `CoverageExperiment` object has been coarsened using `window = ...`, 261 | the `coord` and `coord.scaled` are handled correspondingly. 262 | 263 | ```{r} 264 | expand(CE3) 265 | ``` 266 | 267 | ## Plot coverage of a set of tracks over a single genomic locus 268 | 269 | To illustrate how to visualize coverage tracks from a `CoverageExperiment` 270 | object over a single genomic locus of interest, 271 | let's use sample data provided in the `tidyCoverage` package. 272 | 273 | ```{r} 274 | # ~~~~~~~~~~~~~~~ Import coverage tracks into a named list ~~~~~~~~~~~~~~~ # 275 | tracks <- list( 276 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage"), 277 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 278 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage"), 279 | PolII = system.file("extdata", "PolII.bw", package = "tidyCoverage"), 280 | MNase = system.file("extdata", "MNase.bw", package = "tidyCoverage") 281 | ) |> BigWigFileList() 282 | 283 | locus <- GRanges("II:450001-475000") 284 | 285 | # ~~~~~~~~~~~~~~~ Instantiate a CoverageExperiment object ~~~~~~~~~~~~~~~ # 286 | CE_chrII <- CoverageExperiment( 287 | tracks = tracks, 288 | features = locus, 289 | width = width(locus) 290 | ) 291 | 292 | CE_chrII 293 | ``` 294 | 295 | From there, it is easy to (optionally) `coarsen` then `expand` the 296 | `CoverageExperiment` into a `tibble` and use `ggplot2` for visualization. 297 | 298 | ```{r} 299 | library(ggplot2) 300 | CE_chrII |> 301 | coarsen(window = 10) |> 302 | expand() |> 303 | ggplot(aes(x = coord, y = coverage)) + 304 | geom_col(aes(fill = track, col = track)) + 305 | facet_grid(track~., scales = 'free') + 306 | scale_x_continuous(expand = c(0, 0)) + 307 | theme_bw() + 308 | theme(legend.position = "none", aspect.ratio = 0.1) 309 | ``` 310 | 311 | In this plot, each facet represents the coverage of a different genomic track 312 | over a single region of interest (`chrII:450001-475000`). Each facet has 313 | independent scaling thanks to `facet_grid(..., scales = free)`. 314 | 315 | # Manipulate `AggregatedCoverage` objects 316 | 317 | ## Aggregate a `CoverageExperiment` into an `AggregatedCoverage` object 318 | 319 | It is often useful to `aggregate()` genomic `tracks` coverage over a set of 320 | genomic `features`. 321 | 322 | ```{r} 323 | AC <- aggregate(CE) 324 | 325 | AC 326 | 327 | assay(AC, 'mean')[1, 1][[1]] |> length() 328 | ``` 329 | 330 | ```{r} 331 | AC20 <- aggregate(CE, bin = 20) 332 | AC20 333 | 334 | assay(AC20, 'mean')[1, 1][[1]] |> length() 335 | ``` 336 | 337 | The resulting `AggregatedCoverage` objects can be readily coerced into a `tibble`. 338 | 339 | ```{r} 340 | as_tibble(AC20) 341 | ``` 342 | 343 | Note that the `coarsen-then-aggregate` or `aggregate-by-bin` are **NOT** 344 | equivalent. This is due to the certain operations being not commutative with `mean` (e.g. `sd`, `min`/`max`, ...). 345 | 346 | ```{r} 347 | # Coarsen `CoverageExperiment` with `window = ...` then per-bin `aggregate`: 348 | CoverageExperiment( 349 | tracks = import(bw_file, as = "Rle"), features = import(bed_file), 350 | width = 3000 351 | ) |> 352 | coarsen(window = 20) |> ## FIRST COARSEN... 353 | aggregate() |> ## ... THEN AGGREGATE 354 | as_tibble() 355 | 356 | # Per-base `CoverageExperiment` then `aggregate` with `bin = ...`: 357 | CoverageExperiment( 358 | tracks = import(bw_file, as = "Rle"), features = import(bed_file), 359 | width = 3000 360 | ) |> 361 | aggregate(bin = 20) |> ## DIRECTLY AGGREGATE BY BIN 362 | as_tibble() 363 | ``` 364 | 365 | ## `AggregatedCoverage` over multiple tracks / feature sets 366 | 367 | As en example for the rest of this vignette, we compute an `AggregatedCoverage` 368 | object using multiple genomic track files and multiple sets of genomic ranges. 369 | 370 | ```{r} 371 | library(purrr) 372 | library(plyranges) 373 | 374 | # ~~~~~~~~~~~~~~~ Import genomic features into a named list ~~~~~~~~~~~~~~~ # 375 | features <- list( 376 | TSSs = system.file("extdata", "TSSs.bed", package = "tidyCoverage"), 377 | `Convergent transcription` = system.file("extdata", "conv_transcription_loci.bed", package = "tidyCoverage") 378 | ) |> map(import) |> map(filter, strand == '+') 379 | 380 | # ~~~~~~~~~~~~~~~ Import coverage tracks into a named list ~~~~~~~~~~~~~~~ # 381 | tracks <- list( 382 | Scc1 = system.file("extdata", "Scc1.bw", package = "tidyCoverage"), 383 | RNA_fwd = system.file("extdata", "RNA.fwd.bw", package = "tidyCoverage"), 384 | RNA_rev = system.file("extdata", "RNA.rev.bw", package = "tidyCoverage"), 385 | PolII = system.file("extdata", "PolII.bw", package = "tidyCoverage"), 386 | MNase = system.file("extdata", "MNase.bw", package = "tidyCoverage") 387 | ) |> map(import, as = 'Rle') 388 | 389 | # ~~~~~~~~~~~~~~~ Compute aggregated coverage ~~~~~~~~~~~~~~~ # 390 | CE <- CoverageExperiment(tracks, features, width = 5000, scale = TRUE, center = TRUE) 391 | CE 392 | 393 | AC <- aggregate(CE) 394 | AC 395 | ``` 396 | 397 | ## Plot aggregated coverages with `ggplot2` 398 | 399 | Because `AggregatedCoverage` objects can be easily coerced into `tibble`s, 400 | the full range of `ggplot2` functionalities can be exploited to plot 401 | aggregated coverage signal of multiple tracks over multiple sets of genomic ranges. 402 | 403 | ```{r} 404 | AC |> 405 | as_tibble() |> 406 | ggplot() + 407 | geom_aggrcoverage() 408 | ``` 409 | 410 | Oopsie, a little busy here. Let's color by tracks and split facets by `features`: 411 | 412 | ```{r} 413 | AC |> 414 | as_tibble() |> 415 | ggplot(aes(col = track)) + 416 | geom_aggrcoverage() + 417 | facet_grid(features ~ .) 418 | ``` 419 | 420 | Nearly there, few cosmetic changes and we are done! 421 | 422 | ```{r} 423 | AC |> 424 | as_tibble() |> 425 | ggplot(aes(col = track, linetype = track %in% c('RNA_fwd', 'RNA_rev'))) + 426 | geom_aggrcoverage() + 427 | facet_grid(features ~ .) + 428 | labs(x = 'Distance from genomic feature', y = 'Mean coverage (± 95% conf. intervale)') + 429 | theme_bw() + 430 | theme(legend.position = 'top') 431 | ``` 432 | 433 | # Use a tidy grammar 434 | 435 | `tidySummarizedExperiment` package implements native `tidyverse` functionalities 436 | to `SummarizedExperiment` objects and their extensions. It tweaks the way 437 | `CoverageExperiment` and `AggregatedCoverage` objects look and feel, but 438 | do not change the underlying data or object. 439 | 440 | In particular, this means that data wrangling _verbs_ provided by `dplyr` 441 | can directly work on `CoverageExperiment` and `AggregatedCoverage` objects, 442 | provided that the `tidySummarizedExperiment` package is loaded. 443 | 444 | ```{r} 445 | library(tidySummarizedExperiment) 446 | CE 447 | 448 | AC <- CE |> 449 | filter(track == 'Scc1') |> 450 | filter(features == 'Convergent transcription') |> 451 | aggregate() 452 | 453 | AC 454 | ``` 455 | 456 | This also means that `as_tibble()` coercing step is facultative 457 | if the `tidySummarizedExperiment` package id loaded. 458 | 459 | ```{r} 460 | AC |> 461 | ggplot() + 462 | geom_aggrcoverage() + 463 | labs(x = 'Distance from locus of convergent transcription', y = 'Scc1 coverage') + 464 | theme_bw() + 465 | theme(legend.position = 'top') 466 | ``` 467 | 468 | **Note:** To read more about the `tidySummarizedExperiment` package and the overall 469 | `tidyomics` project, read the preprint [here](https://www.biorxiv.org/content/10.1101/2023.09.10.557072v2). 470 | 471 | ## Example workflow using tidy grammar 472 | 473 | ```{r} 474 | CoverageExperiment(tracks, features, width = 5000, scale = TRUE, center = TRUE) |> 475 | filter(track == 'RNA_fwd') |> 476 | aggregate(bin = 20) |> 477 | ggplot(col = features) + 478 | geom_aggrcoverage(aes(col = features)) + 479 | labs(x = 'Distance to center of genomic features', y = 'Forward RNA-seq coverage') + 480 | theme_bw() + 481 | theme(legend.position = 'top') 482 | ``` 483 | 484 | # Example use case: `AnnotationHub` and `TxDb` resources 485 | 486 | ## Recover TSSs of forward human genes 487 | 488 | Let's first fetch features of interest from the human `TxDb` resources. 489 | 490 | ```{r} 491 | txdb <- TxDb.Hsapiens.UCSC.hg19.knownGene::TxDb.Hsapiens.UCSC.hg19.knownGene 492 | TSSs <- GenomicFeatures::genes(txdb) |> 493 | filter(strand == '+') |> 494 | anchor_5p() |> 495 | mutate(width = 1) 496 | ``` 497 | 498 | These 1bp-wide `GRanges` correspond to forward TSSs genomic positions. 499 | 500 | ## Recover H3K4me3 coverage track from ENCODE 501 | 502 | Let's also fetch a real-life ChIP-seq dataset (e.g. `H3K4me3`) 503 | from ENCODE stored in the `AnnotationHub`: 504 | 505 | ```{r} 506 | library(AnnotationHub) 507 | ah <- AnnotationHub() 508 | ah['AH34904'] 509 | H3K4me3_bw <- ah[['AH34904']] 510 | 511 | H3K4me3_bw 512 | ``` 513 | 514 | ## Compute the aggregated coverage of H3K4me3 ± 3kb around the TSSs of forward human genes 515 | 516 | We can now extract the coverage of `H3K4me3` over all the human forward TSSs 517 | (± 3kb) and aggregate this coverage. 518 | 519 | ```{r} 520 | CoverageExperiment( 521 | H3K4me3_bw, TSSs, 522 | width = 6000, 523 | scale = TRUE, center = TRUE 524 | ) |> 525 | aggregate() |> 526 | ggplot() + 527 | geom_aggrcoverage(aes(col = track)) + 528 | facet_grid(track ~ .) + 529 | labs(x = 'Distance from TSSs', y = 'Mean coverage') + 530 | theme_bw() + 531 | theme(legend.position = 'top') 532 | ``` 533 | 534 | We obtain the typical profile of enrichment of `H3K4me3` over the +1 nucleosome. 535 | 536 | ## With more genomic tracks 537 | 538 | This more complex example fetches a collection of 15 different ChIP-seq genomic 539 | tracks to check their profile of enrichment over human forward TSSs. 540 | 541 | ```{r eval = FALSE} 542 | # ~~~~~~~~~~ Recover 15 different histone PTM ChIP-seq tracks ~~~~~~~~~~ # 543 | ids <- c( 544 | 'AH35163', 'AH35165', 'AH35167', 'AH35170', 'AH35173', 'AH35176', 545 | 'AH35178', 'AH35180', 'AH35182', 'AH35185', 'AH35187', 'AH35189', 546 | 'AH35191', 'AH35193', 'AH35196' 547 | ) 548 | names(ids) <- mcols(ah[ids])$title |> 549 | gsub(".*IMR90.", "", x = _) |> 550 | gsub("\\..*", "", x = _) 551 | bws <- map(ids, ~ ah[[.x]]) |> 552 | map(resource) |> 553 | BigWigFileList() 554 | names(bws) <- names(ids) 555 | 556 | # ~~~~~~~~~~ Computing coverage over TSSs ~~~~~~~~~~ # 557 | AC <- CoverageExperiment( 558 | bws, TSSs, 559 | width = 4000, 560 | scale = TRUE, center = TRUE 561 | ) |> aggregate() 562 | 563 | # ~~~~~~~~~~ Plot the resulting AggregatedCoverage object ~~~~~~~~~~ # 564 | AC |> 565 | as_tibble() |> 566 | mutate( 567 | histone = dplyr::case_when( 568 | stringr::str_detect(track, 'H2A') ~ "H2A", 569 | stringr::str_detect(track, 'H2B') ~ "H2B", 570 | stringr::str_detect(track, 'H3') ~ "H3" 571 | ) 572 | ) |> 573 | ggplot() + 574 | geom_aggrcoverage(aes(col = track)) + 575 | facet_grid(~histone) + 576 | labs(x = 'Distance from TSSs', y = 'Mean histone PTM coverage') + 577 | theme_bw() + 578 | theme(legend.position = 'top') + 579 | hues::scale_colour_iwanthue() + 580 | hues::scale_fill_iwanthue() 581 | ``` 582 | 583 | ![](../man/figures/PTMs-TSSs.png) 584 | 585 | # Session info 586 | 587 | ```{r} 588 | sessionInfo() 589 | ``` 590 | --------------------------------------------------------------------------------