Hi-C arithmetic with plyinteractions

The plyinteractions package facilitates data aggregation, for up to hundreds of thousands and even millions of genomic interactions. In this vignette, we explore several use cases which can arise when exploring Hi-C data stored in pairs files.

We will use a real-life pairs file provided by the 4DN Consortium. This file has been generated from processing Hi-C performed in mouse from brain cell primary culture during neural development (Bonev et al., Cell 2017). Pairs have been filtered to only those mapped over chr13.

library(tidyverse)
#> ── Attaching core tidyverse packages ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
#> ✔ dplyr     1.1.4     ✔ readr     2.1.5
#> ✔ forcats   1.0.0     ✔ stringr   1.5.1
#> ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
#> ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
#> ✔ purrr     1.0.2     
#> ── Conflicts ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
#> ✖ lubridate::%within%() masks IRanges::%within%()
#> ✖ ggplot2::Position()   masks BiocGenerics::Position(), base::Position()
#> ✖ ggplot2::annotate()   masks plyinteractions::annotate()
#> ✖ dplyr::collapse()     masks IRanges::collapse()
#> ✖ dplyr::combine()      masks Biobase::combine(), BiocGenerics::combine()
#> ✖ dplyr::count()        masks plyinteractions::count(), matrixStats::count()
#> ✖ dplyr::desc()         masks IRanges::desc()
#> ✖ tidyr::expand()       masks S4Vectors::expand()
#> ✖ dplyr::filter()       masks plyinteractions::filter(), stats::filter()
#> ✖ dplyr::first()        masks S4Vectors::first()
#> ✖ dplyr::lag()          masks stats::lag()
#> ✖ purrr::reduce()       masks GenomicRanges::reduce(), IRanges::reduce()
#> ✖ dplyr::rename()       masks plyinteractions::rename(), S4Vectors::rename()
#> ✖ lubridate::second()   masks S4Vectors::second()
#> ✖ lubridate::second<-() masks S4Vectors::second<-()
#> ✖ dplyr::slice()        masks plyinteractions::slice(), IRanges::slice()
#> ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(plyinteractions)

## Importing it in R
pairs_file <- HiContactsData::HiContactsData('mESCs', 'pairs.gz')
#> see ?HiContactsData and browseVignettes('HiContactsData') for documentation
#> downloading 1 resources
#> retrieving 1 resource
#> loading from cache
pairs_df <- read.delim(
    pairs_file, sep = "\t", header = FALSE, comment.char = "#"
) |> 
    set_names(c(
        "ID", "seqnames1", "start1", 
        "seqnames2", "start2", "strand1", "strand2"
    ))
pairs <- as_ginteractions(
    pairs_df, end1 = start1, end2 = start2, keep.extra.columns = TRUE
)
pairs
#> GInteractions object with 5150011 interactions and 1 metadata column:
#>             seqnames1   ranges1 strand1     seqnames2   ranges2 strand2 |                   ID
#>                 <Rle> <IRanges>   <Rle>         <Rle> <IRanges>   <Rle> |          <character>
#>         [1]     chr13  17057558       + ---     chr13  17176616       - |        SRR5339749.58
#>         [2]     chr13  68759440       - ---     chr13 113578864       - |       SRR5339749.105
#>         [3]     chr13  47940999       + ---     chr13  48134537       + |       SRR5339749.169
#>         [4]     chr13  80638451       + ---     chr13  80638826       - |       SRR5339749.170
#>         [5]     chr13   4362498       - ---     chr13  96982617       + |       SRR5339749.249
#>         ...       ...       ...     ... ...       ...       ...     ... .                  ...
#>   [5150007]     chr13  95480277       - ---     chr13  96105587       + | SRR5339749.237063036
#>   [5150008]     chr13  55523047       + ---     chr13  55523339       - | SRR5339749.237063218
#>   [5150009]     chr13  88318766       - ---     chr13  89456475       + | SRR5339749.237063267
#>   [5150010]     chr13  69859492       + ---     chr13  69859712       - | SRR5339749.237063274
#>   [5150011]     chr13  18990870       + ---     chr13  19369755       - | SRR5339749.237063301
#>   -------
#>   regions: 9013760 ranges and 0 metadata columns
#>   seqinfo: 1 sequence from an unspecified genome; no seqlengths

Estimating pairs filtering thresholds

We can first in silico digest the mouse genome to obtain the coordinates of each genomic fragment after digestion by DpnII and HinfI.

## Prepare DpnII/HinfI-digested genomic fragments
library(GenomicRanges)
library(Biostrings)
#> Loading required package: XVector
#> 
#> Attaching package: 'XVector'
#> The following object is masked from 'package:purrr':
#> 
#>     compact
#> 
#> Attaching package: 'Biostrings'
#> The following object is masked from 'package:base':
#> 
#>     strsplit
library(plyranges)
#> 
#> Attaching package: 'plyranges'
#> The following object is masked from 'package:XVector':
#> 
#>     slice
#> The following objects are masked from 'package:dplyr':
#> 
#>     between, n, n_distinct
#> The following objects are masked from 'package:plyinteractions':
#> 
#>     flank_downstream, flank_left, flank_right, flank_upstream, shift_downstream, shift_left, shift_right, shift_upstream
#> The following object is masked from 'package:IRanges':
#> 
#>     slice
#> The following object is masked from 'package:stats':
#> 
#>     filter
genome <- BSgenome.Mmusculus.UCSC.mm10::BSgenome.Mmusculus.UCSC.mm10
cutter <- DNAStringSet(c("GATC", "GANTC"))  ## DpnII/HinfI cutting site
fragments <- BiocParallel::bplapply(BPPARAM = BiocParallel::MulticoreParam(workers = 8), 
    names(genome), function(.x) {
        seq <- genome[[.x]]
        mids <- lapply(
            cutter, 
            function(cutsite) {
                hits <- matchPattern(cutsite, seq, fixed = "subject")
                start(hits) + {end(hits) - start(hits)}
            }
        ) |> unlist() |> sort()
        GRanges(seqnames = .x, IRanges(
            start = c(1, mids), end = c(mids-1, length(seq))
        ))
    }
) |> 
    set_names(names(genome)) |> 
    GRangesList() |> 
    unlist()
fragments$binID <- seq_along(fragments)

We can then use the annotate() function from plyinteractions to recover, for each interaction, which restriction enzyme fragment each anchor overlaps with, and how many restriction enzyme cutting sites are found between them.

## Annotate for each anchor set which genomic fragment it overlaps with
annotated_pairs <- pairs |> 
    plyinteractions::annotate(fragments, by = "binID") |> 
    mutate(n_fragments = binID.2 - binID.1, group = paste0(strand1, strand2))
annotated_pairs
#> GInteractions object with 5150011 interactions and 5 metadata columns:
#>             seqnames1   ranges1 strand1     seqnames2   ranges2 strand2 |                   ID   binID.1   binID.2 n_fragments       group
#>                 <Rle> <IRanges>   <Rle>         <Rle> <IRanges>   <Rle> |          <character> <integer> <integer>   <integer> <character>
#>         [1]     chr13  17057558       + ---     chr13  17176616       - |        SRR5339749.58   9591352   9592012         660          +-
#>         [2]     chr13  68759440       - ---     chr13 113578864       - |       SRR5339749.105   9880169  10124404      244235          --
#>         [3]     chr13  47940999       + ---     chr13  48134537       + |       SRR5339749.169   9762274   9763393        1119          ++
#>         [4]     chr13  80638451       + ---     chr13  80638826       - |       SRR5339749.170   9946878   9946878           0          +-
#>         [5]     chr13   4362498       - ---     chr13  96982617       + |       SRR5339749.249   9521271  10034142      512871          -+
#>         ...       ...       ...     ... ...       ...       ...     ... .                  ...       ...       ...         ...         ...
#>   [5150007]     chr13  95480277       - ---     chr13  96105587       + | SRR5339749.237063036  10025960  10029363        3403          -+
#>   [5150008]     chr13  55523047       + ---     chr13  55523339       - | SRR5339749.237063218   9805472   9805473           1          +-
#>   [5150009]     chr13  88318766       - ---     chr13  89456475       + | SRR5339749.237063267   9987886   9993753        5867          -+
#>   [5150010]     chr13  69859492       + ---     chr13  69859712       - | SRR5339749.237063274   9886256   9886256           0          +-
#>   [5150011]     chr13  18990870       + ---     chr13  19369755       - | SRR5339749.237063301   9601640   9603730        2090          +-
#>   -------
#>   regions: 9013760 ranges and 0 metadata columns
#>   seqinfo: 1 sequence from an unspecified genome; no seqlengths

Next, we can plot the distribution of strand1 and strand2 cominations as a function of the number of restriction enzyme cutting sites between anchors of each interaction.

df <- annotated_pairs |> 
    head(n = 1e6) |> 
    group_by(strand1, strand2, n_fragments) |> 
    count() |> 
    as_tibble() |> 
    mutate(group = paste0(strand1, strand2)) |> 
    select(group, n_fragments, n)
ggplot(df, aes(x = n_fragments, y = n, group = group, col = group)) + 
    geom_line() + 
    geom_point() + 
    xlim(c(0, 15)) + 
    annotation_logticks(sides = 'l') + 
    theme_bw() + 
    labs(
        x = "Number of restriction sites between anchors", 
        y = "Number of pairs"
    )
#> Warning: Removed 267493 rows containing missing values or values outside the scale range (`geom_line()`).
#> Warning: Removed 267493 rows containing missing values or values outside the scale range (`geom_point()`).

From this distribution, we can see that -- and ++ pairs have a decreasing frequency over increasing numbers of cut sites between anchors of each interaction. These pairs are unambiguous, as the orientation of each sequenced end can only come from true cutting and religation event, (except the set of -- and ++ pairs which have 0 cut sites between each anchor, which cannot be explained); all these pairs can be kept.

The over-representation of +- pairs at short distance likely represent uncut fragments subsequently sequenced on each end. The under-representation of -+ pairs at short distance likely represent self-religated fragments. We can estimate a threshold for each of these pairs sets by computing the MAD and expected , as described in Cournac et al., 2012.

filters <- df |> 
    filter(n_fragments <= 50) |> 
    arrange(n_fragments) |> 
    group_by(n_fragments) |> 
    mutate(median = median(n)) |> 
    ungroup() |> 
    mutate(MAD = median(abs(n - median))) |> 
    mutate(withinMAD = abs(n - median) <= MAD / 0.67449) |> 
    filter(withinMAD) |> 
    slice_head(by = group, n = 1) |> 
    select(group, n_fragments) |> 
    dplyr::rename(threshold = n_fragments)
filters
#> # A tibble: 4 × 2
#>   group threshold
#>   <chr>     <int>
#> 1 ++            1
#> 2 --            1
#> 3 -+            8
#> 4 +-           10

Filtering pairs using appropriate thresholds

annotated_pairs <- annotated_pairs |> 
    mutate(threshold = left_join(as_tibble(mcols(annotated_pairs)), filters)$threshold) |> 
    mutate(type = case_when(
        group %in% c('--', '++') & n_fragments < threshold ~ "excluded", 
        group == '+-' & n_fragments < threshold ~ "uncut", 
        group == '-+' & n_fragments < threshold ~ "religated", 
        .default = "kept"
    ))
#> Joining with `by = join_by(group)`
mcols(annotated_pairs) |>
    as_tibble() |> 
    count(type) |> 
    mutate(n = scales::percent(n/sum(n)))
#> # A tibble: 4 × 2
#>   type      n     
#>   <chr>     <chr> 
#> 1 excluded  1.09% 
#> 2 kept      78.64%
#> 3 religated 0.40% 
#> 4 uncut     19.87%

filtered_pairs <- filter(annotated_pairs, type == 'kept')

Computing distance law from pairs

Another typical step when analyzing Hi-C processed data is the modeling of a so-called “distance law”, (a.k.a “P(s)”), which describes the genomic distance-dependent contact frequency between pairs of genomic loci from a Hi-C experiment.

We can easily recover the distance between the two anchors of each interaction (noted s) and plot the interaction frequency (noted P(s)) as a function of this genomic distance.

Plotting distance law: first try

dat <- filtered_pairs |> 
    mutate(s = abs(end2 - start1)) |> 
    group_by(s) |> 
    count(name = "n") |>
    as_tibble() |> 
    mutate(Ps = n/sum(n)) 
p <- ggplot(dat, aes(x = s, y = Ps)) + geom_line()
p

This is not very informative, as the distances span several orders of magnitude in both dimensions.

Second try: switching to logarithmic scale

Switching to a log scale in ggplot2 is very easy.

p + scale_x_log10() + scale_y_log10() + annotation_logticks()

Third try: aggregating data before plotting

The previous P(s) plot is precise at the base-pair resolution. We can aggregate counts by binned distances:

# Calculate distance breaks evenly spaced on a log scale (base 1.1)
x <- 1.1^(1:200-1)
lmc <- coef(lm(c(1,1161443398)~c(x[1], x[200])))
bins_breaks <- unique(round(lmc[2]*x + lmc[1]))
bins_widths <- lead(bins_breaks) - bins_breaks

# Bin distances
dat <- filtered_pairs |> 
    mutate(s = abs(end2 - start1)) |> 
    mutate(
        binned_s = bins_breaks[as.numeric(cut(s, bins_breaks))], 
        bin_width = bins_widths[as.numeric(cut(s, bins_breaks))]
    ) |> 
    group_by(binned_s, bin_width) |> 
    count(name = "n") |>
    as_tibble() |> 
    mutate(Ps = n / sum(n) / bin_width)

# Plot results
ggplot(dat, aes(x = binned_s, y = Ps)) + geom_line() + 
    scale_x_log10() + scale_y_log10() + annotation_logticks()

With some polishing

ggplot(dat, aes(x = binned_s, y = Ps)) + 
    geom_line() + 
    scale_x_log10(limits = c(1e3, 1e8)) +    ## This changes x axis to log scale
    scale_y_log10() +                        ## This changes y axis to log scale
    annotation_logticks() +                  ## This adds log ticks
    labs(
        x = "Genomic distance (s)", 
        y = "P(s)", 
        title = "Distance-dependent genomic frequency P(s) in mESC (chr. 13)"
    ) +                                      ## This fixes axes titles
    theme_bw()                               ## This changes default plot theme
#> Warning: Removed 44 rows containing missing values or values outside the scale range (`geom_line()`).

Reproducibility

R session information:

#> ─ Session info ───────────────────────────────────────────────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.4.2 (2024-10-31)
#>  os       Ubuntu 24.04.1 LTS
#>  system   x86_64, linux-gnu
#>  ui       X11
#>  language (EN)
#>  collate  C
#>  ctype    en_US.UTF-8
#>  tz       Etc/UTC
#>  date     2024-12-18
#>  pandoc   3.2.1 @ /usr/local/bin/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────
#>  package                      * version   date (UTC) lib source
#>  abind                          1.4-8     2024-09-12 [2] RSPM (R 4.4.0)
#>  AnnotationDbi                  1.69.0    2024-11-29 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  AnnotationHub                * 3.15.0    2024-11-29 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  backports                      1.5.0     2024-05-23 [2] RSPM (R 4.4.0)
#>  bibtex                         0.5.1     2023-01-26 [2] RSPM (R 4.4.0)
#>  Biobase                      * 2.67.0    2024-11-30 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  BiocFileCache                * 2.15.0    2024-11-19 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  BiocGenerics                 * 0.53.3    2024-12-15 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  BiocIO                         1.17.1    2024-11-22 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  BiocManager                    1.30.25   2024-08-28 [2] RSPM (R 4.4.0)
#>  BiocParallel                   1.41.0    2024-11-29 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  BiocStyle                    * 2.35.0    2024-11-19 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  BiocVersion                    3.21.1    2024-12-08 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  Biostrings                   * 2.75.3    2024-12-16 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  bit                            4.5.0.1   2024-12-03 [2] RSPM (R 4.4.0)
#>  bit64                          4.5.2     2024-09-22 [2] RSPM (R 4.4.0)
#>  bitops                         1.0-9     2024-10-03 [2] RSPM (R 4.4.0)
#>  blob                           1.2.4     2023-03-17 [2] RSPM (R 4.4.0)
#>  BSgenome                       1.75.0    2024-11-29 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  BSgenome.Mmusculus.UCSC.mm10   1.4.3     2024-12-18 [2] Bioconductor
#>  bslib                          0.8.0     2024-07-29 [2] RSPM (R 4.4.0)
#>  buildtools                     1.0.0     2024-12-16 [3] local (/pkg)
#>  cachem                         1.1.0     2024-05-16 [2] RSPM (R 4.4.0)
#>  cli                            3.6.3     2024-06-21 [2] RSPM (R 4.4.0)
#>  codetools                      0.2-20    2024-03-31 [2] RSPM (R 4.4.0)
#>  colorspace                     2.1-1     2024-07-26 [2] RSPM (R 4.4.0)
#>  crayon                         1.5.3     2024-06-20 [2] RSPM (R 4.4.0)
#>  curl                           6.0.1     2024-11-14 [2] RSPM (R 4.4.0)
#>  DBI                            1.2.3     2024-06-02 [2] RSPM (R 4.4.0)
#>  dbplyr                       * 2.5.0     2024-03-19 [2] RSPM (R 4.4.0)
#>  DelayedArray                   0.33.3    2024-12-03 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  digest                         0.6.37    2024-08-19 [2] RSPM (R 4.4.0)
#>  dplyr                        * 1.1.4     2023-11-17 [2] RSPM (R 4.4.0)
#>  evaluate                       1.0.1     2024-10-10 [2] RSPM (R 4.4.0)
#>  ExperimentHub                * 2.15.0    2024-11-29 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  farver                         2.1.2     2024-05-13 [2] RSPM (R 4.4.0)
#>  fastmap                        1.2.0     2024-05-15 [2] RSPM (R 4.4.0)
#>  filelock                       1.0.3     2023-12-11 [2] RSPM (R 4.4.0)
#>  forcats                      * 1.0.0     2023-01-29 [2] RSPM (R 4.4.0)
#>  generics                     * 0.1.3     2022-07-05 [2] RSPM (R 4.4.0)
#>  GenomeInfoDb                 * 1.43.2    2024-11-28 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  GenomeInfoDbData               1.2.13    2024-12-18 [2] Bioconductor
#>  GenomicAlignments              1.43.0    2024-11-29 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  GenomicRanges                * 1.59.1    2024-11-19 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  ggplot2                      * 3.5.1     2024-04-23 [2] RSPM (R 4.4.0)
#>  glue                           1.8.0     2024-09-30 [2] RSPM (R 4.4.0)
#>  gtable                         0.3.6     2024-10-25 [2] RSPM (R 4.4.0)
#>  HiContactsData               * 1.8.0     2024-10-31 [2] Bioconductor 3.20 (R 4.4.2)
#>  hms                            1.1.3     2023-03-21 [2] RSPM (R 4.4.0)
#>  htmltools                      0.5.8.1   2024-04-04 [2] RSPM (R 4.4.0)
#>  httr                           1.4.7     2023-08-15 [2] RSPM (R 4.4.0)
#>  InteractionSet               * 1.35.0    2024-11-29 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  IRanges                      * 2.41.2    2024-12-03 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  jquerylib                      0.1.4     2021-04-26 [2] RSPM (R 4.4.0)
#>  jsonlite                       1.8.9     2024-09-20 [2] RSPM (R 4.4.0)
#>  KEGGREST                       1.47.0    2024-11-29 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  knitr                          1.49      2024-11-08 [2] RSPM (R 4.4.0)
#>  labeling                       0.4.3     2023-08-29 [2] RSPM (R 4.4.0)
#>  lattice                        0.22-6    2024-03-20 [2] RSPM (R 4.4.0)
#>  lifecycle                      1.0.4     2023-11-07 [2] RSPM (R 4.4.0)
#>  lubridate                    * 1.9.4     2024-12-08 [2] RSPM (R 4.4.0)
#>  magrittr                       2.0.3     2022-03-30 [2] RSPM (R 4.4.0)
#>  maketools                      1.3.1     2024-10-04 [3] RSPM (R 4.4.0)
#>  Matrix                         1.7-1     2024-10-18 [2] RSPM (R 4.4.0)
#>  MatrixGenerics               * 1.19.0    2024-12-06 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  matrixStats                  * 1.4.1     2024-09-08 [2] RSPM (R 4.4.0)
#>  memoise                        2.0.1     2021-11-26 [2] RSPM (R 4.4.0)
#>  mime                           0.12      2021-09-28 [2] RSPM (R 4.4.0)
#>  munsell                        0.5.1     2024-04-01 [2] RSPM (R 4.4.0)
#>  pillar                         1.10.0    2024-12-17 [2] CRAN (R 4.4.2)
#>  pkgconfig                      2.0.3     2019-09-22 [2] RSPM (R 4.4.0)
#>  plyinteractions              * 1.5.0     2024-12-18 [1] https://bioc.r-universe.dev (R 4.4.2)
#>  plyr                           1.8.9     2023-10-02 [2] RSPM (R 4.4.0)
#>  plyranges                    * 1.27.0    2024-12-08 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  png                            0.1-8     2022-11-29 [2] RSPM (R 4.4.0)
#>  purrr                        * 1.0.2     2023-08-10 [2] RSPM (R 4.4.0)
#>  R6                             2.5.1     2021-08-19 [2] RSPM (R 4.4.0)
#>  rappdirs                       0.3.3     2021-01-31 [2] RSPM (R 4.4.0)
#>  Rcpp                           1.0.13-1  2024-11-02 [2] RSPM (R 4.4.0)
#>  RCurl                          1.98-1.16 2024-07-11 [2] RSPM (R 4.4.0)
#>  readr                        * 2.1.5     2024-01-10 [2] RSPM (R 4.4.0)
#>  RefManageR                   * 1.4.0     2022-09-30 [2] RSPM (R 4.4.0)
#>  restfulr                       0.0.15    2022-06-16 [2] RSPM (R 4.4.2)
#>  rjson                          0.2.23    2024-09-16 [2] RSPM (R 4.4.0)
#>  rlang                          1.1.4     2024-06-04 [2] RSPM (R 4.4.0)
#>  rmarkdown                      2.29      2024-11-04 [2] RSPM (R 4.4.0)
#>  Rsamtools                      2.23.1    2024-11-27 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  RSQLite                        2.3.9     2024-12-03 [2] RSPM (R 4.4.0)
#>  rtracklayer                    1.67.0    2024-12-06 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  S4Arrays                       1.7.1     2024-12-18 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  S4Vectors                    * 0.45.2    2024-12-16 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  sass                           0.4.9     2024-03-15 [2] RSPM (R 4.4.0)
#>  scales                         1.3.0     2023-11-28 [2] RSPM (R 4.4.0)
#>  sessioninfo                  * 1.2.2     2021-12-06 [2] RSPM (R 4.4.0)
#>  SparseArray                    1.7.2     2024-12-15 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  stringi                        1.8.4     2024-05-06 [2] RSPM (R 4.4.0)
#>  stringr                      * 1.5.1     2023-11-14 [2] RSPM (R 4.4.0)
#>  SummarizedExperiment         * 1.37.0    2024-11-21 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  sys                            3.4.3     2024-10-04 [2] RSPM (R 4.4.0)
#>  tibble                       * 3.2.1     2023-03-20 [2] RSPM (R 4.4.0)
#>  tidyr                        * 1.3.1     2024-01-24 [2] RSPM (R 4.4.0)
#>  tidyselect                     1.2.1     2024-03-11 [2] RSPM (R 4.4.0)
#>  tidyverse                    * 2.0.0     2023-02-22 [2] RSPM (R 4.4.0)
#>  timechange                     0.3.0     2024-01-18 [2] RSPM (R 4.4.0)
#>  tzdb                           0.4.0     2023-05-12 [2] RSPM (R 4.4.0)
#>  UCSC.utils                     1.3.0     2024-11-30 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  utf8                           1.2.4     2023-10-22 [2] RSPM (R 4.4.0)
#>  vctrs                          0.6.5     2023-12-01 [2] RSPM (R 4.4.0)
#>  withr                          3.0.2     2024-10-28 [2] RSPM (R 4.4.0)
#>  xfun                           0.49      2024-10-31 [2] RSPM (R 4.4.0)
#>  XML                            3.99-0.17 2024-06-25 [2] RSPM (R 4.4.0)
#>  xml2                           1.3.6     2023-12-04 [2] RSPM (R 4.4.0)
#>  XVector                      * 0.47.0    2024-11-21 [2] https://bioc.r-universe.dev (R 4.4.2)
#>  yaml                           2.3.10    2024-07-26 [2] RSPM (R 4.4.0)
#>  zlibbioc                       1.52.0    2024-10-29 [2] Bioconductor 3.20 (R 4.4.2)
#> 
#>  [1] /tmp/RtmpqjJvY4/Rinst2176b171de3
#>  [2] /github/workspace/pkglib
#>  [3] /usr/local/lib/R/site-library
#>  [4] /usr/lib/R/site-library
#>  [5] /usr/lib/R/library
#> 
#> ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────