From 1dfd61f2eae8cc73e168c241e904618e7a4a4a37 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Wed, 16 Jul 2025 15:30:00 -0700 Subject: [PATCH 01/84] [cpp] add version detection for highway --- r/configure | 46 +++++++++++++++++++++++++++++++++++++-- r/configure.win | 48 +++++++++++++++++++++++++++++++++++++++++ r/tools/hwy-test.cpp.in | 31 ++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 r/tools/hwy-test.cpp.in diff --git a/r/configure b/r/configure index cdb69975..9e252756 100755 --- a/r/configure +++ b/r/configure @@ -154,11 +154,53 @@ fi ############################ # Build Highway SIMD library ############################ -printf "\nTesting availability of highway SIMD library..." +printf "\nTesting availability of highway SIMD library\n" HWY_OK="" +# Minimum required version (may override via env var HWY_MIN_VERSION=X.Y.Z) +HWY_MIN_VERSION=${HWY_MIN_VERSION:-1.0.5} +IFS=. read -r HWY_MIN_MAJOR HWY_MIN_MINOR HWY_MIN_PATCH <<< "$HWY_MIN_VERSION" +sed \ + -e "s/@HWY_MIN_MAJOR@/$HWY_MIN_MAJOR/g" \ + -e "s/@HWY_MIN_MINOR@/$HWY_MIN_MINOR/g" \ + -e "s/@HWY_MIN_PATCH@/$HWY_MIN_PATCH/g" \ + -e "s/@HWY_MIN_VERSION@/$HWY_MIN_VERSION/g" \ + tools/hwy-test.cpp.in > tools/hwy-test.cpp + HWY_CFLAGS="-Ibpcells-cpp" HWY_LIBS="-lhwy" -$CXX tools/hwy-test.cpp $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS 2>&3 && HWY_OK="yes"; +# Use a compile log to keep error/pragma messages +HWY_COMPILE_LOG=$(mktemp) +# Try to compile with hardcoded flags first +if $CXX tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > /dev/null 2> "$HWY_COMPILE_LOG"; then + HWY_VERSION_OUTPUT=$(tools/hwy-test) + printf "$HWY_VERSION_OUTPUT" + HWY_OK="yes" +else + # Fallback to pkg-config if available + if pkg-config --exists libhwy 2>/dev/null; then + HWY_CFLAGS="$(pkg-config --cflags libhwy 2>&3) $HWY_CFLAGS" + HWY_LIBS="$(pkg-config --libs libhwy 2>&3)" + elif pkg-config --exists hwy 2>/dev/null; then + HWY_CFLAGS="$(pkg-config --cflags hwy 2>&3) $HWY_CFLAGS" + HWY_LIBS="$(pkg-config --libs hwy 2>&3)" + else + HWY_LIBS="" + fi + # Only attempt second compile if pkg-config succeeded + if [ -n "$HWY_LIBS" ]; then + if $CXX tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > /dev/null 2> "$HWY_COMPILE_LOG"; then + HWY_VERSION_OUTPUT=$(tools/hwy-test) + printf "$HWY_VERSION_OUTPUT" + HWY_OK="yes" + elif grep -q "Highway too old" "$HWY_COMPILE_LOG"; then + printf "\nHighway is installed but too old: %s\n" "$(sed -n 's/.*#pragma message: //p' "$HWY_COMPILE_LOG")" + else + printf "Highway not found or unusable\n" + fi + fi +fi +rm -f tools/hwy-test "$HWY_COMPILE_LOG" + if [ -z $HWY_OK ]; then if [ ! -f tools/highway/lib/libhwy.a ]; then printf "\nBuilding highway SIMD library from source\n" diff --git a/r/configure.win b/r/configure.win index 4cdc0a5d..e6dabfd5 100755 --- a/r/configure.win +++ b/r/configure.win @@ -101,8 +101,56 @@ fi ############################ printf "\nTesting availability of highway SIMD library..." HWY_OK="" +HWY_MIN_VERSION=${HWY_MIN_VERSION:-1.0.5} + +# Use sed to split version +HWY_MIN_MAJOR=$(echo "$HWY_MIN_VERSION" | sed 's/\..*//') +HWY_MIN_MINOR=$(echo "$HWY_MIN_VERSION" | sed 's/^[^.]*\.//;s/\..*//') +HWY_MIN_PATCH=$(echo "$HWY_MIN_VERSION" | sed 's/^.*\..*\.//') + +# Generate test TU +sed \ + -e "s/@HWY_MIN_MAJOR@/$HWY_MIN_MAJOR/g" \ + -e "s/@HWY_MIN_MINOR@/$HWY_MIN_MINOR/g" \ + -e "s/@HWY_MIN_PATCH@/$HWY_MIN_PATCH/g" \ + -e "s/@HWY_MIN_VERSION@/$HWY_MIN_VERSION/g" \ + tools/hwy-test.cpp.in > tools/hwy-test.cpp + HWY_CFLAGS="-Ibpcells-cpp" HWY_LIBS="-lhwy" +# Use a compile log to keep error/pragma messages +HWY_COMPILE_LOG=tools/hwy-test-log.txt +# Try hardcoded flags +if $CXX tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > NUL 2> "$HWY_COMPILE_LOG"; then + HWY_VERSION_OUTPUT=$(tools/hwy-test.exe) + echo "$HWY_VERSION_OUTPUT" + HWY_OK="yes" +else + # Fallback to pkg-config + if pkg-config --exists libhwy 2> NUL; then + HWY_CFLAGS="$(pkg-config --cflags libhwy 2>&1) $HWY_CFLAGS" + HWY_LIBS="$(pkg-config --libs libhwy 2>&1)" + elif pkg-config --exists hwy 2> NUL; then + HWY_CFLAGS="$(pkg-config --cflags hwy 2>&1) $HWY_CFLAGS" + HWY_LIBS="$(pkg-config --libs hwy 2>&1)" + else + HWY_LIBS="" + fi + # Only attempt second compile if pkg-config succeeded + if [ -n "$HWY_LIBS" ]; then + if "$CXX" tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > NUL 2> "$HWY_COMPILE_LOG"; then + HWY_VERSION_OUTPUT=$(tools/hwy-test.exe) + echo "$HWY_VERSION_OUTPUT" + HWY_OK="yes" + elif grep -q "Highway too old" "$HWY_COMPILE_LOG"; then + echo "Highway is installed but too old: $(sed -n 's/.*#pragma message: //p' "$HWY_COMPILE_LOG")" + else + echo "Highway not found or unusable" + fi + fi +fi +rm -f tools/hwy-test.exe tools/hwy-test.cpp "$HWY_COMPILE_LOG" + $CXX tools/hwy-test.cpp $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS 2>&3 && HWY_OK="yes"; if [ -z $HWY_OK ]; then if [ ! -f tools/highway/lib/libhwy.a ]; then diff --git a/r/tools/hwy-test.cpp.in b/r/tools/hwy-test.cpp.in new file mode 100644 index 00000000..845c3db2 --- /dev/null +++ b/r/tools/hwy-test.cpp.in @@ -0,0 +1,31 @@ +#include +#include +#include + +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + +#ifndef HWY_MAJOR +#error "Missing HWY_MAJOR" +#endif +#ifndef HWY_MINOR +#error "Missing HWY_MINOR" +#endif +#ifndef HWY_PATCH +#error "Missing HWY_PATCH" +#endif + +#if (HWY_MAJOR < @HWY_MIN_MAJOR@) || \ + (HWY_MAJOR == @HWY_MIN_MAJOR@ && HWY_MINOR < @HWY_MIN_MINOR@) || \ + (HWY_MAJOR == @HWY_MIN_MAJOR@ && HWY_MINOR == @HWY_MIN_MINOR@ && HWY_PATCH < @HWY_MIN_PATCH@) +#pragma message("Highway too old: need >=@HWY_MIN_VERSION@ for BPCells (found " STR(HWY_MAJOR) "." STR(HWY_MINOR) "." STR(HWY_PATCH) ")") +#error "Highway too old" +#endif + +int main() { + auto ptr = hwy::AllocateAligned(1024); + ptr[0] = 1.0f; + std::cout << "Highway version: " + << HWY_MAJOR << "." << HWY_MINOR << "." << HWY_PATCH << std::endl; + return 0; +} \ No newline at end of file From ae2e4a9c8335c92e11455f461dd559dbf2dc9685 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Wed, 16 Jul 2025 15:40:46 -0700 Subject: [PATCH 02/84] [cpp] cleanup highway detection in configure --- r/configure | 16 +++++++--------- r/configure.win | 18 ++++++++---------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/r/configure b/r/configure index 9e252756..2926f68e 100755 --- a/r/configure +++ b/r/configure @@ -187,19 +187,17 @@ else HWY_LIBS="" fi # Only attempt second compile if pkg-config succeeded - if [ -n "$HWY_LIBS" ]; then - if $CXX tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > /dev/null 2> "$HWY_COMPILE_LOG"; then - HWY_VERSION_OUTPUT=$(tools/hwy-test) - printf "$HWY_VERSION_OUTPUT" - HWY_OK="yes" - elif grep -q "Highway too old" "$HWY_COMPILE_LOG"; then + if [ -n "$HWY_LIBS" ] && $CXX tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > /dev/null 2> "$HWY_COMPILE_LOG"; then + HWY_VERSION_OUTPUT=$(tools/hwy-test) + printf "$HWY_VERSION_OUTPUT" + HWY_OK="yes" + elif grep -q "Highway too old" "$HWY_COMPILE_LOG"; then printf "\nHighway is installed but too old: %s\n" "$(sed -n 's/.*#pragma message: //p' "$HWY_COMPILE_LOG")" - else + else printf "Highway not found or unusable\n" - fi fi fi -rm -f tools/hwy-test "$HWY_COMPILE_LOG" +rm -f tools/hwy-test "$HWY_COMPILE_LOG" tools/hwy-test.cpp if [ -z $HWY_OK ]; then if [ ! -f tools/highway/lib/libhwy.a ]; then diff --git a/r/configure.win b/r/configure.win index e6dabfd5..adf492a3 100755 --- a/r/configure.win +++ b/r/configure.win @@ -137,16 +137,14 @@ else HWY_LIBS="" fi # Only attempt second compile if pkg-config succeeded - if [ -n "$HWY_LIBS" ]; then - if "$CXX" tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > NUL 2> "$HWY_COMPILE_LOG"; then - HWY_VERSION_OUTPUT=$(tools/hwy-test.exe) - echo "$HWY_VERSION_OUTPUT" - HWY_OK="yes" - elif grep -q "Highway too old" "$HWY_COMPILE_LOG"; then - echo "Highway is installed but too old: $(sed -n 's/.*#pragma message: //p' "$HWY_COMPILE_LOG")" - else - echo "Highway not found or unusable" - fi + if [ -n "$HWY_LIBS" ] && if "$CXX" tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > NUL 2> "$HWY_COMPILE_LOG"; then + HWY_VERSION_OUTPUT=$(tools/hwy-test.exe) + echo "$HWY_VERSION_OUTPUT" + HWY_OK="yes" + elif grep -q "Highway too old" "$HWY_COMPILE_LOG"; then + echo "Highway is installed but too old: $(sed -n 's/.*#pragma message: //p' "$HWY_COMPILE_LOG")" + else + echo "Highway not found or unusable" fi fi rm -f tools/hwy-test.exe tools/hwy-test.cpp "$HWY_COMPILE_LOG" From fc3f935413330aa6b7082fb4ee988ac844ff90c0 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Wed, 16 Jul 2025 15:47:42 -0700 Subject: [PATCH 03/84] [cpp] fix syntax error in `configure.win` --- r/configure.win | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r/configure.win b/r/configure.win index adf492a3..39892a05 100755 --- a/r/configure.win +++ b/r/configure.win @@ -137,7 +137,7 @@ else HWY_LIBS="" fi # Only attempt second compile if pkg-config succeeded - if [ -n "$HWY_LIBS" ] && if "$CXX" tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > NUL 2> "$HWY_COMPILE_LOG"; then + if [ -n "$HWY_LIBS" ] && $CXX tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > NUL 2> "$HWY_COMPILE_LOG"; then HWY_VERSION_OUTPUT=$(tools/hwy-test.exe) echo "$HWY_VERSION_OUTPUT" HWY_OK="yes" From c1e658661a501f3186a220a169abd3a2798d1aff Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Wed, 16 Jul 2025 15:52:42 -0700 Subject: [PATCH 04/84] [cpp] fix configure styling and gitignore --- .gitignore | 3 ++- r/configure | 2 +- r/configure.win | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 58b6af2b..14c22ce8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ rsync.sh src/Makevars tools/h5write tools/cxx17_filesystem +r/tools/hwy-test.cpp tools/*.exe vignettes/*.html vignettes/pbmc-3k-data @@ -29,7 +30,7 @@ cpp-tests venv wheelhouse -# A few convenience igores for my development cruft +# A few convenience ignores for my development cruft failing_test.R mytest*.R .clang-format diff --git a/r/configure b/r/configure index 2926f68e..d6af5179 100755 --- a/r/configure +++ b/r/configure @@ -154,7 +154,7 @@ fi ############################ # Build Highway SIMD library ############################ -printf "\nTesting availability of highway SIMD library\n" +printf "\nTesting availability of highway SIMD library...\n" HWY_OK="" # Minimum required version (may override via env var HWY_MIN_VERSION=X.Y.Z) HWY_MIN_VERSION=${HWY_MIN_VERSION:-1.0.5} diff --git a/r/configure.win b/r/configure.win index 39892a05..396abbb9 100755 --- a/r/configure.win +++ b/r/configure.win @@ -99,7 +99,7 @@ fi ############################ # Build Highway SIMD library ############################ -printf "\nTesting availability of highway SIMD library..." +printf "\nTesting availability of highway SIMD library...\n" HWY_OK="" HWY_MIN_VERSION=${HWY_MIN_VERSION:-1.0.5} From e6e1286a62ac9aecb36b7620d3437f89b680cd08 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Wed, 16 Jul 2025 16:23:40 -0700 Subject: [PATCH 05/84] update NEWS.md --- r/NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/r/NEWS.md b/r/NEWS.md index d24a1352..64f6102e 100644 --- a/r/NEWS.md +++ b/r/NEWS.md @@ -24,6 +24,7 @@ - Fix error in `write_matrix_hdf5()` when overwriting to a `.h5` file that does not exist. (pull request #234) - Fix `configure` script to use a pre-installed `libhwy` if available during installation time. (Thanks to @mfansler for submitting PR #228) - Fix line-ending issue that caused windows-created matrices to not be readable on other platforms. (pull request #257; thanks to @pavsol for reporting issue #253) +- Fix compilation when there exists a system-installed `libhwy` that is too old. (pull request #288, thanks to @GerardoZA for reporting issue #285) # BPCells 0.3.0 (12/21/2024) From 3af9e75bdca9a325fd87db787ddc1885d6fe6185 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Mon, 21 Jul 2025 12:24:12 -0700 Subject: [PATCH 06/84] [r][cpp] wip --- r/DESCRIPTION | 21 +++++++-- r/NAMESPACE | 24 +++++----- r/NEWS.md | 9 +++- r/R/atac_utils.R | 3 +- r/R/errorChecking.R | 5 ++- r/R/geneScores.R | 8 ++-- r/R/genomeAnnotations.R | 13 +++--- r/R/matrix.R | 23 +++++++--- r/R/matrix_stats.R | 44 ++++++++++--------- r/R/plots.R | 17 +++++--- r/R/trackplots.R | 65 ++++++++++++++++++---------- r/configure | 1 + r/configure.win | 1 + r/man/IterableMatrix-methods.Rd | 10 +---- r/man/apply_by_row.Rd | 8 ++-- r/man/call_peaks_tile.Rd | 3 +- r/man/checksum.Rd | 2 - r/man/colQuantiles.Rd | 34 +++++++++++++++ r/man/gene_region.Rd | 2 +- r/man/gene_scores.Rd | 6 ++- r/man/normalize_ranges.Rd | 5 ++- r/man/plot_dot.Rd | 8 ++-- r/man/plot_embedding.Rd | 5 ++- r/man/plot_tss_profile.Rd | 2 +- r/man/plot_tss_scatter.Rd | 2 +- r/man/read_bed.Rd | 5 ++- r/man/read_gtf.Rd | 4 +- r/man/trackplot_combine.Rd | 17 +++++--- r/man/trackplot_coverage.Rd | 16 ++++--- r/man/trackplot_gene.Rd | 6 ++- r/man/trackplot_genome_annotation.Rd | 10 +++-- r/man/trackplot_loop.Rd | 4 +- r/man/trackplot_scalebar.Rd | 8 ++-- r/man/transpose_storage_order.Rd | 3 +- r/tools/hwy-test.cpp | 7 --- 35 files changed, 256 insertions(+), 145 deletions(-) create mode 100644 r/man/colQuantiles.Rd delete mode 100644 r/tools/hwy-test.cpp diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 5ab47452..21e62c22 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -36,7 +36,6 @@ Imports: stringr, tibble, dplyr (>= 1.0.0), - tidyr, readr, ggplot2 (>= 3.4.0), scales, @@ -44,12 +43,26 @@ Imports: scattermore, ggrepel, RColorBrewer, - hexbin Suggests: IRanges, + hexbin, + tidyr, GenomicRanges, matrixStats, - igraph + igraph, + pkgdown, + devtools, + uwot, + irlba, + RcppHNSW, + BiocManager, + BSgenome.Hsapiens.UCSC.hg38, + motifmatchr, + chromVARmotifs, + png +Additional_repositories: + https://bioconductor.org/packages/release/data/annotation, + https://immanuelazn.github.io/drat Depends: R (>= 4.0.0) -Config/Needs/website: pkgdown, devtools, uwot, irlba, RcppHNSW, igraph, BiocManager, bioc::BSgenome.Hsapiens.UCSC.hg38, github::GreenleafLab/motifmatchr, github::GreenleafLab/chromVARmotifs, png, magrittr +Config/Needs/website: pkgdown, devtools, uwot, irlba, RcppHNSW, igraph, BiocManager, bioc::BSgenome.Hsapiens.UCSC.hg38, github::GreenleafLab/motifmatchr, github::GreenleafLab/chromVARmotifs, png diff --git a/r/NAMESPACE b/r/NAMESPACE index 29a7cdcc..47a4cd0c 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -2,6 +2,18 @@ S3method(base::as.data.frame,IterableFragments) S3method(base::as.matrix,IterableMatrix) +S3method(colMaxs,IterableMatrix) +S3method(colMaxs,default) +S3method(colQuantiles,IterableMatrix) +S3method(colQuantiles,default) +S3method(colVars,IterableMatrix) +S3method(colVars,default) +S3method(rowMaxs,IterableMatrix) +S3method(rowMaxs,default) +S3method(rowQuantiles,IterableMatrix) +S3method(rowQuantiles,default) +S3method(rowVars,IterableMatrix) +S3method(rowVars,default) S3method(svds,IterableMatrix) S3method(svds,default) export("%>%") @@ -25,16 +37,10 @@ export(cluster_graph_leiden) export(cluster_graph_louvain) export(cluster_graph_seurat) export(colMaxs) -export(colMaxs.IterableMatrix) -export(colMaxs.default) export(colMeans) export(colQuantiles) -export(colQuantiles.IterableMatrix) -export(colQuantiles.default) export(colSums) export(colVars) -export(colVars.IterableMatrix) -export(colVars.default) export(collect_features) export(continuous_palette) export(convert_matrix_type) @@ -102,16 +108,10 @@ export(regress_out) export(remove_demo_data) export(rotate_x_labels) export(rowMaxs) -export(rowMaxs.IterableMatrix) -export(rowMaxs.default) export(rowMeans) export(rowQuantiles) -export(rowQuantiles.IterableMatrix) -export(rowQuantiles.default) export(rowSums) export(rowVars) -export(rowVars.IterableMatrix) -export(rowVars.default) export(sctransform_pearson) export(select_cells) export(select_chromosomes) diff --git a/r/NEWS.md b/r/NEWS.md index 64f6102e..5de270b8 100644 --- a/r/NEWS.md +++ b/r/NEWS.md @@ -1,4 +1,11 @@ -# BPCells 0.3.1 (in-progress main branch) +# BPCells 0.3.1 (7/16/2025) + +The BPCells 0.3.1 release covers 7 months of changes and 39 commits from 5 contributors. Notable changes include writing matrices in AnnData's dense format, +and methods for retrieving demo data for testing and examples. +Full details of changes below. + +Thanks to @ycli1995 and @mfansler for pull requests that contributed to this release, as well as to users who +sumitted github issues to help identify and fix bugs. ## Features - Add `write_matrix_anndata_hdf5_dense()` which allows writing matrices in AnnData's dense format, most commonly used for `obsm` or `varm` matrices. (Thanks to @ycli1995 for pull request #166) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index 961f63e0..f9284b61 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -363,7 +363,8 @@ merge_peaks_iterative <- function(peaks) { #' ## Remove blacklist regions from fragments #' blacklist <- read_encode_blacklist(reference_dir, genome="hg38") #' frags_filter_blacklist <- select_regions(frags, blacklist, invert_selection = TRUE) -#' chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") %>% dplyr::filter(chr %in% c("chr4", "chr11")) +#' chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") %>% +#' dplyr::filter(chr %in% c("chr4", "chr11")) #' #' #' ## Call peaks diff --git a/r/R/errorChecking.R b/r/R/errorChecking.R index a2378fa6..78e378a2 100644 --- a/r/R/errorChecking.R +++ b/r/R/errorChecking.R @@ -195,10 +195,11 @@ normalize_unique_file_names <- function(names, replacement="_") { #' and FALSE for negative strand. (Converted from a character vector of "+"/"-" if necessary) #' @examples #' ## Prep data +#' library(S4Vectors) #' ranges <- GenomicRanges::GRanges( -#' seqnames = S4Vectors::Rle(c("chr1", "chr2", "chr3"), c(1, 2, 2)), +#' seqnames = Rle(c("chr1", "chr2", "chr3"), c(1, 2, 2)), #' ranges = IRanges::IRanges(101:105, end = 111:115, names = head(letters, 5)), -#' strand = S4Vectors::Rle(GenomicRanges::strand(c("-", "+", "*")), c(1, 2, 2)), +#' strand = Rle(GenomicRanges::strand(c("-", "+", "*")), c(1, 2, 2)), #' score = 1:5, #' GC = seq(1, 0, length=5)) #' ranges diff --git a/r/R/geneScores.R b/r/R/geneScores.R index 71969020..e899e411 100644 --- a/r/R/geneScores.R +++ b/r/R/geneScores.R @@ -88,7 +88,7 @@ range_distance_to_nearest <- function(ranges, addArchRBug = FALSE, zero_based_co #' @inheritParams normalize_ranges #' @param upstream Number of bases to extend each range upstream (negative to shrink width) #' @param downstream Number of bases to extend each range downstream (negative to shrink width) -#' @param chromosome_sizes (optional) Size of chromosomes as a [genomic-ranges] object +#' @param chromosome_sizes (optional) Size of chromosomes as a [genomic-ranges] object% #' @details Note that ranges will be blocked from extending past the beginning of the chromosome (base 0), #' and if `chromosome_sizes` is given then they will also be blocked from extending past the end of the chromosome #' @examples @@ -234,8 +234,10 @@ gene_score_tiles_archr <- function(genes, chromosome_sizes = NULL, tile_width = #' release="42", #' annotation_set = "basic", #' ) %>% dplyr::filter(chr %in% c("chr4", "chr11")) -#' blacklist <- read_encode_blacklist(reference_dir, genome="hg38") %>% dplyr::filter(chr %in% c("chr4", "chr11")) -#' chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") %>% dplyr::filter(chr %in% c("chr4", "chr11")) +#' blacklist <- read_encode_blacklist(reference_dir, genome="hg38") %>% +#' dplyr::filter(chr %in% c("chr4", "chr11")) +#' chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") %>% +#' dplyr::filter(chr %in% c("chr4", "chr11")) #' chrom_sizes$tile_width = 500 #' #' diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index 70864795..2534409e 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -107,7 +107,7 @@ read_gtf <- function(path, attributes = c("gene_id"), tags = character(0), featu #' ####################################################################### #' ## read_gencode_genes() example #' ####################################################################### -#' read_gencode_genes("./references", release = "42") +#' read_gencode_genes("./references", release = "42", timeout = 3000) #' #' #' @export @@ -159,7 +159,7 @@ read_gencode_genes <- function(dir, release = "latest", #' ####################################################################### #' ## If read_gencode_genes() was already ran on the same release, #' ## will reuse previously downloaded annotations -#' read_gencode_transcripts("./references", release = "42") +#' read_gencode_transcripts("./references", release = "42", timeout = 3000) #' #' #' @export @@ -211,17 +211,18 @@ read_gencode_transcripts <- function(dir, release = "latest", transcript_choice #' @return Data frame with coordinates using the 0-based convention. #' @examples #' ## Dummy bed file creation +#' file_name <- tempfile(fileext = ".bed") #' data.frame( #' chrom = rep("chr1", 6), #' start = seq(20, 121, 20), #' end = seq(39, 140, 20) -#' ) %>% write.table("./references/example.bed", row.names = FALSE, col.names = FALSE, sep = "\t") +#' ) %>% write.table(file_name, row.names = FALSE, col.names = FALSE, sep = "\t") #' #' #' ####################################################################### #' ## read_bed() example #' ####################################################################### -#' read_bed("./references/example.bed") +#' read_bed(file_name) #' #' #' @seealso [read_gtf()], [read_gencode_genes()] @@ -420,7 +421,7 @@ canonical_gene_symbol <- function(query, gene_mapping = human_gene_mapping) { #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", #' annotation_set = "basic", -#' features = "transcript" +#' features = "transcript", timeout = 3000 #' ) #' #' ## Get gene region @@ -430,7 +431,7 @@ gene_region <- function(genes, gene_symbol, extend_bp = c(1e4, 1e4), gene_mappin genes <- normalize_ranges(genes, metadata_cols = c("strand", "gene_name")) idx <- match_gene_symbol(gene_symbol, genes$gene_name) if (is.na(idx)) { - rlang::stop("Could not locate gene") + rlang::abort("Could not locate gene") } if (length(extend_bp) == 1) { extend_bp <- c(extend_bp, extend_bp) diff --git a/r/R/matrix.R b/r/R/matrix.R index c188a8f8..6a6be953 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -674,6 +674,7 @@ setMethod("colMeans", signature(x = "IterableMatrix"), function(x) colSums(x) / #' @export colVars <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) UseMethod("colVars") #' @export +#' @method colVars default colVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { MatrixGenerics::colVars(x, rows=rows, cols=cols, na.rm=na.rm, center=center, ..., useNames=useNames) @@ -684,6 +685,7 @@ colVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = } } #' @export +#' @method colVars IterableMatrix colVars.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (!is.null(rows) || !is.null(cols) || !isFALSE(na.rm) || !is.null(center) || !isTRUE(useNames)) { stop("colVars(IterableMatrix) doesn't support extra arguments rows, cols, na.rm, center, or useNames") @@ -701,6 +703,7 @@ rlang::on_load({ #' @export rowVars <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) UseMethod("rowVars") #' @export +#' @method rowVars default rowVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { MatrixGenerics::rowVars(x, rows=rows, cols=cols, na.rm=na.rm, center=center, ..., useNames=useNames) @@ -711,6 +714,7 @@ rowVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = } } #' @export +#' @method rowVars IterableMatrix rowVars.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (!is.null(rows) || !is.null(cols) || !isFALSE(na.rm) || !is.null(center) || !isTRUE(useNames)) { stop("rowVars(IterableMatrix) doesn't support extra arguments rows, cols, na.rm, center, or useNames") @@ -737,6 +741,7 @@ rlang::on_load({ #' @export rowMaxs <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) UseMethod("rowMaxs") #' @export +#' @method rowMaxs default rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { MatrixGenerics::rowMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ...) @@ -748,6 +753,7 @@ rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { } } #' @export +#' @method rowMaxs IterableMatrix rowMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { if(!is.null(rows) || !is.null(cols) || !isFALSE(na.rm)) { stop("rowMaxs(IterableMatrix) doesn't support extra arguments rows, cols, or na.rm") @@ -781,6 +787,7 @@ rlang::on_load({ #' @export colMaxs <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) UseMethod("colMaxs") #' @export +#' @method colMaxs default colMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { MatrixGenerics::colMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ...) @@ -792,6 +799,7 @@ colMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { } } #' @export +#' @method colMaxs IterableMatrix colMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { iter <- iterate_matrix(convert_matrix_type(x, "double")) if(x@transpose == TRUE) { @@ -1689,7 +1697,8 @@ setMethod("iterate_matrix", "UnpackedMatrixMem_double", function(x) { #' ## A regular transpose operation switches a user's rows and cols #' t(mat) #' -#' ## Running `transpose_storage_order()` instead changes whether the storage is in row-major or col-major, +#' ## Running `transpose_storage_order()` instead changes whether +#' ## the storage is in row-major or col-major, #' ## but does not switch the rows and cols #' transpose_storage_order(mat) #' @export @@ -3277,8 +3286,6 @@ svds.IterableMatrix <- function(A, k, nu = k, nv = k, opts = list(), threads=0, #' @param matrix IterableMatrix object #' @return MD5 checksum string in hexidecimal format. #' @examples -#' library(Matrix) -#' library(BPCells) #' m1 <- matrix(seq(1,12), nrow=3) #' m2 <- as(m1, 'dgCMatrix') #' m3 <- as(m2, 'IterableMatrix') @@ -3287,7 +3294,7 @@ svds.IterableMatrix <- function(A, k, nu = k, nv = k, opts = list(), threads=0, checksum <- function(matrix) { assert_is(matrix, "IterableMatrix") - iter <- iterate_matrix(BPCells:::convert_matrix_type(matrix, "double")) + iter <- iterate_matrix(convert_matrix_type(matrix, "double")) checksum_double_cpp(iter) } @@ -3329,10 +3336,12 @@ checksum <- function(matrix) { #' ## Get mean of every row #' #' ## expect an error in the case that col-major matrix is passed -#' apply_by_row(mat, function(val, row, col) {sum(val) / nrow(mat)}) %>% -#' unlist() -#' +#' try( +#' apply_by_row(mat, function(val, row, col) {sum(val) / nrow(mat)}) %>% +#' unlist() +#' ) #' ## Need to transpose matrix to make sure it is in row-order +#' #' mat_row_order <- transpose_storage_order(mat) #' #' ## works as expected for row major diff --git a/r/R/matrix_stats.R b/r/R/matrix_stats.R index e68dc102..50353a5d 100644 --- a/r/R/matrix_stats.R +++ b/r/R/matrix_stats.R @@ -40,6 +40,7 @@ rowQuantiles <- function(x, rows = NULL, cols = NULL, UseMethod("rowQuantiles") } #' @export +#' @method rowQuantiles default rowQuantiles.default <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -53,6 +54,7 @@ rowQuantiles.default <- function(x, rows = NULL, cols = NULL, } } #' @export +#' @method rowQuantiles IterableMatrix rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -94,27 +96,7 @@ rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, #' Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. #' @return - `colQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of columns in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. -#' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) #' @inheritParams rowQuantiles -#' @usage colQuantiles( -#' x, -#' rows = NULL, -#' cols = NULL, -#' probs = seq(from = 0, to = 1, by = 0.25), -#' na.rm = FALSE, -#' type = 7L, -#' digits = 7L, -#' ..., -#' useNames = TRUE, -#' drop = TRUE -#' ) -#' @examples -#' ####################################################################### -#' ## colQuantiles() example -#' ####################################################################### -#' colQuantiles(mat) -#' -#' #' @export colQuantiles <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), @@ -123,6 +105,7 @@ colQuantiles <- function(x, rows = NULL, cols = NULL, UseMethod("colQuantiles") } #' @export +#' @method colQuantiles default colQuantiles.default <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -136,6 +119,27 @@ colQuantiles.default <- function(x, rows = NULL, cols = NULL, } } #' @export +#' @inheritParams colQuantiles +#' @usage colQuantiles( +#' x, +#' rows = NULL, +#' cols = NULL, +#' probs = seq(from = 0, to = 1, by = 0.25), +#' na.rm = FALSE, +#' type = 7L, +#' digits = 7L, +#' ..., +#' useNames = TRUE, +#' drop = TRUE +#' ) +#' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) +#' @examples +#' ####################################################################### +#' ## colQuantiles() example +#' ####################################################################### +#' colQuantiles(mat) +#' +#' @method colQuantiles IterableMatrix colQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., diff --git a/r/R/plots.R b/r/R/plots.R index e37ad784..66375560 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -191,7 +191,7 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", #' annotation_set = "basic", -#' features = "transcript" +#' features = "transcript", timeout = 3000 #' ) #' blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") #' atac_qc <- qc_scATAC(frags, genes, blacklist) @@ -327,7 +327,7 @@ plot_fragment_length <- function(fragments, max_length = 500, return_data = FALS #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", #' annotation_set = "basic", -#' features = "transcript" +#' features = "transcript", timeout = 3000 #' ) #' #' ## Plot tss profile @@ -525,10 +525,11 @@ collect_features <- function(source, features = NULL, gene_mapping = human_gene_ #' set.seed(123) #' mat <- get_demo_mat() #' ## Normalize matrix -#' mat_norm <- log1p(multiply_cols(mat, 1/colSums(mat)) * 10000) %>% write_matrix_memory(compress = FALSE) +#' mat_norm <- log1p(multiply_cols(mat, 1/colSums(mat)) * 10000) %>% +#' write_matrix_memory(compress = FALSE) #' ## Get variable genes #' stats <- matrix_stats(mat, row_stats = "variance") -#' variable_genes <- order(stats$row_stats["variance",], decreasing=TRUE) %>% +#' variable_genes <- order(stats$row_stats["variance",], decreasing=TRUE) %>% #' head(1000) %>% #' sort() #' # Z score normalize genes @@ -826,9 +827,11 @@ rotate_x_labels <- function(degrees = 45) { #' ## Plot dot #' plot <- plot_dot(mat, c("MS4A1", "CD3E"), cell_types) #' -#' BPCells:::render_plot_from_storage( -#' plot, width = 4, height = 5 -#' ) +#' \dontrun{ +#' BPCells:::render_plot_from_storage( +#' plot, width = 4, height = 5 +#' } +#' #' @export plot_dot <- function(source, features, groups, group_order = NULL, gene_mapping = human_gene_mapping, colors = c("lightgrey", "#4682B4"), diff --git a/r/R/trackplots.R b/r/R/trackplots.R index 5f04cbb9..358ee091 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -292,7 +292,7 @@ render_plot_from_storage <- function(plot, width, height) { #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", #' annotation_set = "basic", -#' features = "transcript" +#' features = "transcript", timeout = 3000 #' ) #' blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") #' read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags @@ -300,23 +300,30 @@ render_plot_from_storage <- function(plot, width, height) { #' cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) #' transcripts <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", -#' annotation_set = "basic" +#' annotation_set = "basic", timeout = 3000 #' ) #' region <- "chr4:3034877-4034877" #' -#' +#' #' ## Get all trackplots and scalebars to combine #' plot_scalebar <- trackplot_scalebar(region) #' plot_gene <- trackplot_gene(transcripts, region) -#' plot_coverage <- trackplot_coverage(frags, region, groups = cell_types, cell_read_counts = read_counts) -#' -#' +#' plot_coverage <- trackplot_coverage( +#' frags, +#' region, +#' groups = cell_types, +#' cell_read_counts = read_counts +#' ) +#' #' ## Combine trackplots and render #' ## Also remove colors from gene track #' plot <- trackplot_combine( #' list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) #' ) -#' BPCells:::render_plot_from_storage(plot, width = 6, height = 4) +#' \dontrun{ +#' BPCells:::render_plot_from_storage( +#' plot, width = 6, height = 4) +#' } #' @export trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_width = 0.3) { for (plot in tracks) { @@ -464,18 +471,22 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", #' annotation_set = "basic", -#' features = "transcript" +#' features = "transcript", timeout = 3000 #' ) #' blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") #' read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags #' region <- "chr4:3034877-4034877" #' cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) #' -#' -#' BPCells:::render_plot_from_storage( -#' trackplot_coverage(frags, region, groups = cell_types, cell_read_counts = read_counts), -#' width = 6, height = 3 -#' ) +#' \dontrun{ +#' BPCells:::render_plot_from_storage( +#' trackplot_coverage( +#' frags, region, groups = cell_types, +#' cell_read_counts = read_counts +#' ), +#' width = 6, height = 3 +#' ) +#' } #' @export trackplot_coverage <- function(fragments, region, groups, cell_read_counts, @@ -583,14 +594,16 @@ trackplot_coverage <- function(fragments, region, groups, #' ## Prep data #' transcripts <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", -#' annotation_set = "basic", features = "transcript" +#' annotation_set = "basic", features = "transcript", timeout = 3000 #' ) #' region <- "chr4:3034877-4034877" #' #' #' ## Plot gene trackplot #' plot <- trackplot_gene(transcripts, region) -#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1) +#' \dontrun{ +#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1) +#' } #' @export trackplot_gene <- function(transcripts, region, exon_size = 2.5, gene_size = 0.5, label_size = 11*.8/ggplot2::.pt, track_label="Genes", return_data = FALSE) { region <- normalize_ranges(region) @@ -706,10 +719,12 @@ trackplot_gene <- function(transcripts, region, exon_size = 2.5, gene_size = 0.5 #' region <- "chr4:3034877-3044877" #' #' ## Plot peaks -#' BPCells:::render_plot_from_storage( -#' trackplot_genome_annotation(peaks, region, color_by = "enrichment"), -#' width = 6, height = 1 -#' ) +#' \dontrun{ +#' BPCells:::render_plot_from_storage( +#' trackplot_genome_annotation(peaks, region, color_by = "enrichment"), +#' width = 6, height = 1 +#' ) +#' } #' @export trackplot_genome_annotation <- function(loci, region, color_by = NULL, colors = NULL, label_by = NULL, label_size = 11*.8/ggplot2::.pt, show_strand=FALSE, annotation_size = 2.5, track_label="Peaks", return_data = FALSE) { @@ -844,7 +859,9 @@ trackplot_genome_annotation <- function(loci, region, color_by = NULL, colors = #' #' ## Plot loops #' plot <- trackplot_loop(loops, region, color_by = "score") -#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) +#' \dontrun{ +#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) +#' } #' @export trackplot_loop <- function(loops, region, color_by=NULL, colors=NULL, allow_truncated=TRUE, curvature=0.75, track_label="Links", return_data = FALSE) { region <- normalize_ranges(region) @@ -944,9 +961,11 @@ trackplot_loop <- function(loops, region, color_by=NULL, colors=NULL, allow_trun #' @seealso `trackplot_combine()`, `trackplot_coverage()`, `trackplot_gene()`, `trackplot_loop()` #' @examples #' region <- "chr4:3034877-3044877" -#' BPCells:::render_plot_from_storage( -#' trackplot_scalebar(region), width = 6, height = 1 -#' ) +#' \dontrun{ +#' BPCells:::render_plot_from_storage( +#' trackplot_scalebar(region), width = 6, height = 1 +#' ) +#' } #' @export trackplot_scalebar <- function(region, font_pt=11) { region <- normalize_ranges(region) diff --git a/r/configure b/r/configure index d6af5179..20c6b445 100755 --- a/r/configure +++ b/r/configure @@ -150,6 +150,7 @@ if [ -z $CXX17_OK ]; then printf "\n\nUnable to compile program with C++17 std::filesystem.\nPlease install a newer compiler version and set CC and CXX in ~/.R/Makevars\n" exit 1 fi +rm -f tools/cxx17_filesystem ############################ # Build Highway SIMD library diff --git a/r/configure.win b/r/configure.win index 396abbb9..24e56ca3 100755 --- a/r/configure.win +++ b/r/configure.win @@ -95,6 +95,7 @@ if [ -z $CXX17_OK ]; then printf "\n\nUnable to compile program with C++17 std::filesystem.\nPlease install a newer compiler version and set CC and CXX in ~/.R/Makevars\n" exit 1 fi +rm -f tools/cxx17_filesystem ############################ # Build Highway SIMD library diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods.Rd index f737299c..28e23b9a 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods.Rd @@ -16,7 +16,7 @@ \alias{rowMaxs} \alias{colMaxs} \alias{rowQuantiles} -\alias{colQuantiles} +\alias{colQuantiles.IterableMatrix} \alias{log1p,IterableMatrix-method} \alias{log1p_slow} \alias{expm1,IterableMatrix-method} @@ -185,11 +185,6 @@ expm1_slow(x) \item \verb{rowQuantiles():} If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of rows in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. } - -\itemize{ -\item \verb{colQuantiles():} If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of columns in the matrix. -Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. -} } \description{ Generic methods and built-in functions for IterableMatrix objects @@ -224,7 +219,7 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{rowQuantiles()}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) -\item \code{colQuantiles()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) +\item \code{colQuantiles(IterableMatrix)}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) \item \code{log1p(IterableMatrix)}: Calculate log(x + 1) @@ -346,7 +341,6 @@ rowQuantiles(transpose_storage_order(mat)) ####################################################################### colQuantiles(mat) - ####################################################################### ## log1p() example ####################################################################### diff --git a/r/man/apply_by_row.Rd b/r/man/apply_by_row.Rd index 47bcf076..19470162 100644 --- a/r/man/apply_by_row.Rd +++ b/r/man/apply_by_row.Rd @@ -54,10 +54,12 @@ mat <- mat \%>\% as("dgCMatrix") \%>\% as("IterableMatrix") ## Get mean of every row ## expect an error in the case that col-major matrix is passed -apply_by_row(mat, function(val, row, col) {sum(val) / nrow(mat)}) \%>\% - unlist() - +try( + apply_by_row(mat, function(val, row, col) {sum(val) / nrow(mat)}) \%>\% + unlist() +) ## Need to transpose matrix to make sure it is in row-order + mat_row_order <- transpose_storage_order(mat) ## works as expected for row major diff --git a/r/man/call_peaks_tile.Rd b/r/man/call_peaks_tile.Rd index 6d830a5b..0552cd04 100644 --- a/r/man/call_peaks_tile.Rd +++ b/r/man/call_peaks_tile.Rd @@ -87,7 +87,8 @@ frags <- get_demo_frags() ## Remove blacklist regions from fragments blacklist <- read_encode_blacklist(reference_dir, genome="hg38") frags_filter_blacklist <- select_regions(frags, blacklist, invert_selection = TRUE) -chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") \%>\% dplyr::filter(chr \%in\% c("chr4", "chr11")) +chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") \%>\% + dplyr::filter(chr \%in\% c("chr4", "chr11")) ## Call peaks diff --git a/r/man/checksum.Rd b/r/man/checksum.Rd index 41f1b43e..2c4c3cd3 100644 --- a/r/man/checksum.Rd +++ b/r/man/checksum.Rd @@ -27,8 +27,6 @@ It converts to little-endian order on big-endian architecture although this has been tested. } \examples{ -library(Matrix) -library(BPCells) m1 <- matrix(seq(1,12), nrow=3) m2 <- as(m1, 'dgCMatrix') m3 <- as(m2, 'IterableMatrix') diff --git a/r/man/colQuantiles.Rd b/r/man/colQuantiles.Rd new file mode 100644 index 00000000..a699642b --- /dev/null +++ b/r/man/colQuantiles.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix_stats.R +\name{colQuantiles} +\alias{colQuantiles} +\title{Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices.} +\usage{ +colQuantiles( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + ..., + useNames = TRUE, + drop = TRUE +) +} +\arguments{ +\item{x}{IterableMatrix object or a matrix-like object.} + +\item{probs}{(Numeric) Quantile value(s) to be computed, between 0 and 1.} + +\item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} +} +\value{ +\itemize{ +\item \verb{colQuantiles():} If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of columns in the matrix. +Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. +} +} +\description{ +Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. +} diff --git a/r/man/gene_region.Rd b/r/man/gene_region.Rd index 4855da39..b60b5dd9 100644 --- a/r/man/gene_region.Rd +++ b/r/man/gene_region.Rd @@ -40,7 +40,7 @@ can be used as the \code{region} argument for trackplot functions such as genes <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", annotation_set = "basic", - features = "transcript" + features = "transcript", timeout = 3000 ) ## Get gene region diff --git a/r/man/gene_scores.Rd b/r/man/gene_scores.Rd index df8ccd8e..6f786b7e 100644 --- a/r/man/gene_scores.Rd +++ b/r/man/gene_scores.Rd @@ -94,8 +94,10 @@ genes <- read_gencode_genes( release="42", annotation_set = "basic", ) \%>\% dplyr::filter(chr \%in\% c("chr4", "chr11")) -blacklist <- read_encode_blacklist(reference_dir, genome="hg38") \%>\% dplyr::filter(chr \%in\% c("chr4", "chr11")) -chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") \%>\% dplyr::filter(chr \%in\% c("chr4", "chr11")) +blacklist <- read_encode_blacklist(reference_dir, genome="hg38") \%>\% + dplyr::filter(chr \%in\% c("chr4", "chr11")) +chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") \%>\% + dplyr::filter(chr \%in\% c("chr4", "chr11")) chrom_sizes$tile_width = 500 diff --git a/r/man/normalize_ranges.Rd b/r/man/normalize_ranges.Rd index 38acd248..55779eb4 100644 --- a/r/man/normalize_ranges.Rd +++ b/r/man/normalize_ranges.Rd @@ -34,10 +34,11 @@ Normalize an object representing genomic ranges } \examples{ ## Prep data +library(S4Vectors) ranges <- GenomicRanges::GRanges( - seqnames = S4Vectors::Rle(c("chr1", "chr2", "chr3"), c(1, 2, 2)), + seqnames = Rle(c("chr1", "chr2", "chr3"), c(1, 2, 2)), ranges = IRanges::IRanges(101:105, end = 111:115, names = head(letters, 5)), - strand = S4Vectors::Rle(GenomicRanges::strand(c("-", "+", "*")), c(1, 2, 2)), + strand = Rle(GenomicRanges::strand(c("-", "+", "*")), c(1, 2, 2)), score = 1:5, GC = seq(1, 0, length=5)) ranges diff --git a/r/man/plot_dot.Rd b/r/man/plot_dot.Rd index e92da530..412a4b65 100644 --- a/r/man/plot_dot.Rd +++ b/r/man/plot_dot.Rd @@ -46,7 +46,9 @@ cell_types <- paste("Group", rep(1:3, length.out = length(colnames(mat)))) ## Plot dot plot <- plot_dot(mat, c("MS4A1", "CD3E"), cell_types) -BPCells:::render_plot_from_storage( - plot, width = 4, height = 5 -) +\dontrun{ + BPCells:::render_plot_from_storage( + plot, width = 4, height = 5 +} + } diff --git a/r/man/plot_embedding.Rd b/r/man/plot_embedding.Rd index 281c49ae..d390469f 100644 --- a/r/man/plot_embedding.Rd +++ b/r/man/plot_embedding.Rd @@ -100,10 +100,11 @@ value stays the same. set.seed(123) mat <- get_demo_mat() ## Normalize matrix -mat_norm <- log1p(multiply_cols(mat, 1/colSums(mat)) * 10000) \%>\% write_matrix_memory(compress = FALSE) +mat_norm <- log1p(multiply_cols(mat, 1/colSums(mat)) * 10000) \%>\% + write_matrix_memory(compress = FALSE) ## Get variable genes stats <- matrix_stats(mat, row_stats = "variance") -variable_genes <- order(stats$row_stats["variance",], decreasing=TRUE) \%>\% +variable_genes <- order(stats$row_stats["variance",], decreasing=TRUE) \%>\% head(1000) \%>\% sort() # Z score normalize genes diff --git a/r/man/plot_tss_profile.Rd b/r/man/plot_tss_profile.Rd index 08a5334f..7581d0b0 100644 --- a/r/man/plot_tss_profile.Rd +++ b/r/man/plot_tss_profile.Rd @@ -46,7 +46,7 @@ frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) genes <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", annotation_set = "basic", - features = "transcript" + features = "transcript", timeout = 3000 ) ## Plot tss profile diff --git a/r/man/plot_tss_scatter.Rd b/r/man/plot_tss_scatter.Rd index 9c75ffd4..444a1014 100644 --- a/r/man/plot_tss_scatter.Rd +++ b/r/man/plot_tss_scatter.Rd @@ -34,7 +34,7 @@ frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) genes <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", annotation_set = "basic", - features = "transcript" + features = "transcript", timeout = 3000 ) blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") atac_qc <- qc_scATAC(frags, genes, blacklist) diff --git a/r/man/read_bed.Rd b/r/man/read_bed.Rd index 6e90d4d8..3ec34b3b 100644 --- a/r/man/read_bed.Rd +++ b/r/man/read_bed.Rd @@ -49,17 +49,18 @@ Downloads the Boyle Lab blacklist, as described in \url{https://doi.org/10.1038/ } \examples{ ## Dummy bed file creation +file_name <- tempfile(fileext = ".bed") data.frame( chrom = rep("chr1", 6), start = seq(20, 121, 20), end = seq(39, 140, 20) -) \%>\% write.table("./references/example.bed", row.names = FALSE, col.names = FALSE, sep = "\t") +) \%>\% write.table(file_name, row.names = FALSE, col.names = FALSE, sep = "\t") ####################################################################### ## read_bed() example ####################################################################### -read_bed("./references/example.bed") +read_bed(file_name) ####################################################################### diff --git a/r/man/read_gtf.Rd b/r/man/read_gtf.Rd index d7e6a5d6..eb886d5b 100644 --- a/r/man/read_gtf.Rd +++ b/r/man/read_gtf.Rd @@ -125,7 +125,7 @@ head(read_gtf( ####################################################################### ## read_gencode_genes() example ####################################################################### -read_gencode_genes("./references", release = "42") +read_gencode_genes("./references", release = "42", timeout = 3000) ####################################################################### @@ -133,7 +133,7 @@ read_gencode_genes("./references", release = "42") ####################################################################### ## If read_gencode_genes() was already ran on the same release, ## will reuse previously downloaded annotations -read_gencode_transcripts("./references", release = "42") +read_gencode_transcripts("./references", release = "42", timeout = 3000) } diff --git a/r/man/trackplot_combine.Rd b/r/man/trackplot_combine.Rd index a18d0b34..971ea06e 100644 --- a/r/man/trackplot_combine.Rd +++ b/r/man/trackplot_combine.Rd @@ -40,7 +40,7 @@ frags <- get_demo_frags() genes <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", annotation_set = "basic", - features = "transcript" + features = "transcript", timeout = 3000 ) blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags @@ -48,7 +48,7 @@ region <- "chr4:3034877-4034877" cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) transcripts <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", - annotation_set = "basic" + annotation_set = "basic", timeout = 3000 ) region <- "chr4:3034877-4034877" @@ -56,15 +56,22 @@ region <- "chr4:3034877-4034877" ## Get all trackplots and scalebars to combine plot_scalebar <- trackplot_scalebar(region) plot_gene <- trackplot_gene(transcripts, region) -plot_coverage <- trackplot_coverage(frags, region, groups = cell_types, cell_read_counts = read_counts) - +plot_coverage <- trackplot_coverage( + frags, + region, + groups = cell_types, + cell_read_counts = read_counts +) ## Combine trackplots and render ## Also remove colors from gene track plot <- trackplot_combine( list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) ) -BPCells:::render_plot_from_storage(plot, width = 6, height = 4) +\dontrun{ + BPCells:::render_plot_from_storage( + plot, width = 6, height = 4) +} } \seealso{ \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} diff --git a/r/man/trackplot_coverage.Rd b/r/man/trackplot_coverage.Rd index 9abf0fe1..cdf110ca 100644 --- a/r/man/trackplot_coverage.Rd +++ b/r/man/trackplot_coverage.Rd @@ -65,18 +65,22 @@ frags <- get_demo_frags() genes <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", annotation_set = "basic", - features = "transcript" + features = "transcript", timeout = 3000 ) blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags region <- "chr4:3034877-4034877" cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) - -BPCells:::render_plot_from_storage( - trackplot_coverage(frags, region, groups = cell_types, cell_read_counts = read_counts), - width = 6, height = 3 -) +\dontrun{ + BPCells:::render_plot_from_storage( + trackplot_coverage( + frags, region, groups = cell_types, + cell_read_counts = read_counts + ), + width = 6, height = 3 + ) +} } \seealso{ \code{trackplot_combine()}, \code{trackplot_gene()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} diff --git a/r/man/trackplot_gene.Rd b/r/man/trackplot_gene.Rd index 96285492..b608bf3d 100644 --- a/r/man/trackplot_gene.Rd +++ b/r/man/trackplot_gene.Rd @@ -51,14 +51,16 @@ Plot transcript models ## Prep data transcripts <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", - annotation_set = "basic", features = "transcript" + annotation_set = "basic", features = "transcript", timeout = 3000 ) region <- "chr4:3034877-4034877" ## Plot gene trackplot plot <- trackplot_gene(transcripts, region) -BPCells:::render_plot_from_storage(plot, width = 6, height = 1) +\dontrun{ + BPCells:::render_plot_from_storage(plot, width = 6, height = 1) +} } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} diff --git a/r/man/trackplot_genome_annotation.Rd b/r/man/trackplot_genome_annotation.Rd index f5bf7129..d51bd92d 100644 --- a/r/man/trackplot_genome_annotation.Rd +++ b/r/man/trackplot_genome_annotation.Rd @@ -65,10 +65,12 @@ peaks <- tibble::tibble( region <- "chr4:3034877-3044877" ## Plot peaks -BPCells:::render_plot_from_storage( - trackplot_genome_annotation(peaks, region, color_by = "enrichment"), - width = 6, height = 1 -) +\dontrun{ + BPCells:::render_plot_from_storage( + trackplot_genome_annotation(peaks, region, color_by = "enrichment"), + width = 6, height = 1 + ) +} } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_loop()}, \code{trackplot_scalebar()}, \code{trackplot_gene()} diff --git a/r/man/trackplot_loop.Rd b/r/man/trackplot_loop.Rd index 5ebbb94b..68386679 100644 --- a/r/man/trackplot_loop.Rd +++ b/r/man/trackplot_loop.Rd @@ -53,7 +53,9 @@ region <- "chr4:3034877-4034877" ## Plot loops plot <- trackplot_loop(loops, region, color_by = "score") -BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) +\dontrun{ + BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) +} } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_scalebar()}, \code{trackplot_genome_annotation()} diff --git a/r/man/trackplot_scalebar.Rd b/r/man/trackplot_scalebar.Rd index f52f663e..a307e68f 100644 --- a/r/man/trackplot_scalebar.Rd +++ b/r/man/trackplot_scalebar.Rd @@ -20,9 +20,11 @@ Plots a human-readable scale bar and coordinates of the region being plotted } \examples{ region <- "chr4:3034877-3044877" -BPCells:::render_plot_from_storage( - trackplot_scalebar(region), width = 6, height = 1 -) +\dontrun{ + BPCells:::render_plot_from_storage( + trackplot_scalebar(region), width = 6, height = 1 + ) +} } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_loop()} diff --git a/r/man/transpose_storage_order.Rd b/r/man/transpose_storage_order.Rd index 29b4021e..cd4b8348 100644 --- a/r/man/transpose_storage_order.Rd +++ b/r/man/transpose_storage_order.Rd @@ -47,7 +47,8 @@ mat ## A regular transpose operation switches a user's rows and cols t(mat) -## Running `transpose_storage_order()` instead changes whether the storage is in row-major or col-major, +## Running `transpose_storage_order()` instead changes whether +## the storage is in row-major or col-major, ## but does not switch the rows and cols transpose_storage_order(mat) } diff --git a/r/tools/hwy-test.cpp b/r/tools/hwy-test.cpp deleted file mode 100644 index 4b49f547..00000000 --- a/r/tools/hwy-test.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -int main() { - auto alignedAlloc = hwy::AllocateAligned(1024); - return 0; -} \ No newline at end of file From e87a3f421866f19ea3c60760b663b022f3e2fde2 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Thu, 16 Oct 2025 15:20:35 -0700 Subject: [PATCH 07/84] [r] various changes + licensing for CRAN --- DESCRIPTION | 2 +- r/.Rbuildignore | 3 +- r/DESCRIPTION | 23 ++++++++--- r/LICENSE | 20 ++++++++++ r/NAMESPACE | 16 ++++++++ r/R/BPCells-package.R | 24 +++++++++++- r/R/errorChecking.R | 1 + r/R/fragments.R | 14 ++++--- r/R/geneScores.R | 2 +- r/R/genomeAnnotations.R | 7 +++- r/R/matrix-svds-docs.R | 2 +- r/R/matrix.R | 44 +++++++++++---------- r/R/matrix_stats.R | 43 +++++++++++---------- r/R/plots.R | 6 +-- r/R/trackplots.R | 57 +++++++++++----------------- r/R/transforms.R | 1 + r/configure | 17 +++++++++ r/man/IterableFragments-methods.Rd | 2 + r/man/IterableMatrix-methods.Rd | 20 ++++++++-- r/man/colQuantiles.Rd | 34 ----------------- r/man/ensure_downloaded.Rd | 4 +- r/man/extend_ranges.Rd | 2 +- r/man/fragment_R_conversion.Rd | 10 +++-- r/man/gene_score_tiles_archr.Rd | 2 +- r/man/matrix_R_conversion.Rd | 13 +++++-- r/man/matrix_io.Rd | 4 +- r/man/min_elementwise.Rd | 2 + r/man/normalize_ranges.Rd | 2 + r/man/open_matrix_anndata_hdf5.Rd | 2 + r/man/plot_dot.Rd | 4 +- r/man/plot_tf_footprint.Rd | 2 + r/man/plot_tss_profile.Rd | 2 + r/man/read_ucsc_chrom_sizes.Rd | 10 +++++ r/man/svds.Rd | 10 ++++- r/man/trackplot_bulk.Rd | 2 +- r/man/trackplot_combine.Rd | 6 +-- r/man/trackplot_coverage.Rd | 17 ++++----- r/man/trackplot_gene.Rd | 10 ++--- r/man/trackplot_genome_annotation.Rd | 12 +++--- r/man/trackplot_loop.Rd | 6 +-- r/man/trackplot_scalebar.Rd | 8 ++-- r/src/Makevars.in | 6 +-- 42 files changed, 289 insertions(+), 185 deletions(-) create mode 100644 r/LICENSE delete mode 100644 r/man/colQuantiles.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 45acbe15..4706b080 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,5 +2,5 @@ Package: BPCells.installation.moved Title: Dummy package to provide new BPCells installation location Version: 0.0.0.9000 Description: This package prints an error message upon attempted installation -License: Apache-2.0 or MIT +License: Apache License (== 2.0) | MIT + file LICENSE Encoding: UTF-8 diff --git a/r/.Rbuildignore b/r/.Rbuildignore index a8a96d78..e97cfde3 100644 --- a/r/.Rbuildignore +++ b/r/.Rbuildignore @@ -15,4 +15,5 @@ build/$ cmake-build-debug/ \.vscode/ -\.snakemake/ \ No newline at end of file +\.snakemake/ + diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 27ee7f6a..1f738599 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -14,7 +14,7 @@ Description: > Efficient operations for single cell ATAC-seq fragments and RNA counts matrices. Interoperable with standard file formats, and introduces efficient bit-packed formats that allow large storage savings and increased read speeds. -License: Apache-2.0 or MIT +License: Apache License (>= 2) | MIT + file LICENSE Encoding: UTF-8 LazyData: true RoxygenNote: 7.3.2 @@ -23,9 +23,12 @@ URL: https://bnprks.github.io/BPCells, https://github.com/bnprks/BPCells LinkingTo: Rcpp, RcppEigen -Imports: +Imports: methods, grDevices, + graphics, + stats, + utils, magrittr, Matrix, Rcpp, @@ -40,6 +43,7 @@ Imports: ggplot2 (>= 3.4.0), scales, patchwork, + purrr, scattermore, ggrepel, RColorBrewer, @@ -48,22 +52,29 @@ Suggests: hexbin, tidyr, GenomicRanges, + GenomeInfoDb, + S4Vectors, matrixStats, + MatrixGenerics, + RSpectra, igraph, RcppHNSW, RcppAnnoy, + Seurat, pkgdown, devtools, uwot, irlba, - BiocManager, + BiocManager, BSgenome.Hsapiens.UCSC.hg38, - motifmatchr, - chromVARmotifs, - png + motifmatchr, + chromVARmotifs, + png, + testthat (>= 3.0.0) Additional_repositories: https://bioconductor.org/packages/release/data/annotation, https://immanuelazn.github.io/drat Depends: R (>= 4.0.0) +SystemRequirements: C++17 Config/Needs/website: pkgdown, devtools, uwot, irlba, RcppHNSW, igraph, BiocManager, bioc::BSgenome.Hsapiens.UCSC.hg38, github::GreenleafLab/motifmatchr, github::GreenleafLab/chromVARmotifs, png diff --git a/r/LICENSE b/r/LICENSE new file mode 100644 index 00000000..4ddd34d9 --- /dev/null +++ b/r/LICENSE @@ -0,0 +1,20 @@ +YEAR: 2025 +COPYRIGHT HOLDER: BPCells contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/r/NAMESPACE b/r/NAMESPACE index 3d9fd13e..4a23be3c 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -154,6 +154,9 @@ importFrom(Matrix,rowMeans) importFrom(Matrix,rowSums) importFrom(Matrix,t) importFrom(Rcpp,sourceCpp) +importFrom(ggplot2,element_text) +importFrom(ggplot2,theme) +importFrom(graphics,text) importFrom(magrittr,"%>%") importFrom(methods,.hasSlot) importFrom(methods,Arith) @@ -162,6 +165,7 @@ importFrom(methods,Math) importFrom(methods,Math2) importFrom(methods,as) importFrom(methods,callNextMethod) +importFrom(methods,canCoerce) importFrom(methods,cbind2) importFrom(methods,is) importFrom(methods,new) @@ -171,6 +175,18 @@ importFrom(methods,setClass) importFrom(methods,setGeneric) importFrom(methods,setMethod) importFrom(methods,show) +importFrom(stats,as.formula) +importFrom(stats,end) +importFrom(stats,model.matrix) +importFrom(stats,p.adjust) +importFrom(stats,ppois) +importFrom(stats,qpois) +importFrom(stats,quantile) +importFrom(stats,start) +importFrom(utils,download.file) +importFrom(utils,head) +importFrom(utils,tail) +importFrom(utils,untar) importMethodsFrom(Matrix,colMeans) importMethodsFrom(Matrix,colSums) importMethodsFrom(Matrix,rowMeans) diff --git a/r/R/BPCells-package.R b/r/R/BPCells-package.R index c8d63d69..fa679b39 100644 --- a/r/R/BPCells-package.R +++ b/r/R/BPCells-package.R @@ -10,9 +10,31 @@ #' @importFrom Rcpp sourceCpp #' @importClassesFrom Matrix dgCMatrix #' @importFrom Matrix t -#' @importFrom methods .hasSlot Arith as callNextMethod cbind2 Compare is Math Math2 new rbind2 setAs setClass setGeneric setMethod show +#' @importFrom methods .hasSlot Arith as callNextMethod canCoerce cbind2 Compare is Math Math2 new rbind2 setAs setClass setGeneric setMethod show +#' @importFrom stats as.formula end model.matrix p.adjust ppois qpois quantile start +#' @importFrom utils download.file head tail untar +#' @importFrom graphics text +#' @importFrom ggplot2 theme element_text NULL +# Suppress CMD check warnings for legitimate NSE usage +utils::globalVariables(c( + # Data manipulation variables (dplyr/data.table style) + ".", "chr", "start", "end", "strand", "counts", "group", "tile", "enrichment", + "p_val", "q_val", "group_rank", "from", "to", "neighbor_dist", "start_dist", + "end_dist", "idx", "pos", "normalized_insertions", "row_number", "start_tmp", + "feature", "transcript_id", "y", "size", "gene_name", "label", "color", "x", + "loop_id", "right", "left", "text", "origin", + + # Plot variables + "average", "percent", "proportion", "reads", "xmin", "xmax", "ymin", "ymax", + "nFrags", "TSSEnrichment", "cellName", "smoothed_enrichment", "position", + "genes", ".env", "track_label", + + # Data objects/mappings + "human_gene_mapping" +)) + #' @importFrom magrittr %>% #' @export magrittr::`%>%` diff --git a/r/R/errorChecking.R b/r/R/errorChecking.R index 2b181c0d..3be1dc35 100644 --- a/r/R/errorChecking.R +++ b/r/R/errorChecking.R @@ -195,6 +195,7 @@ normalize_unique_file_names <- function(names, replacement="_") { #' @param metadata_cols Optional list of metadata columns to require & extract #' @param zero_based_coords If true, coordinates start and 0 and the end coordinate is not included in the range. #' If false, coordinates start at 1 and the end coordinate is included in the range +#' @param n How many call frames to go up when printing errors #' @return data frame with zero-based coordinates, and elements chr (factor), start (int), and end (int). #' If `ranges` does not have chr level information, chr levels are the sorted unique values of chr. #' diff --git a/r/R/fragments.R b/r/R/fragments.R index 6206bbae..50884def 100644 --- a/r/R/fragments.R +++ b/r/R/fragments.R @@ -106,6 +106,7 @@ setMethod("cellNames", "IterableFragments", function(x) { #' Set cell names #' @param x an IterableFragments object #' @param value Character vector of new names +#' @param ... Additional arguments (not used) #' @details * `cellNames<-` It is only possible to replace names, not add new names. #' @describeIn IterableFragments-methods Set cell names #' @examples @@ -652,26 +653,29 @@ open_fragments_hdf5 <- function(path, group = "fragments", buffer_size = 16384L) #' Convert between BPCells fragments and R objects. #' #' BPCells fragments can be interconverted with GRanges and data.frame R objects. -#' The main conversion method is R's builtin `as()` function, though the -#' `convert_to_fragments()` helper is also available. For all R objects except +#' The main conversion method is R's builtin `as()` function, though the +#' `convert_to_fragments()` helper is also available. For all R objects except #' GRanges, BPCells assumes a 0-based, end-exclusive coordinate system. (See #' [genomic-ranges-like] reference for details) #' +#' @aliases as as.data.frame +#' #' @usage #' # Convert from R to BPCells #' convert_to_fragments(x, zero_based_coords = !is(x, "GRanges")) #' as(x, "IterableFragments") #' #' # Convert from BPCells to R -#' as.data.frame(bpcells_fragments) -#' as(bpcells_fragments, "data.frame") -#' as(bpcells_fragments, "GRanges") +#' as.data.frame(x, ...) +#' as(x, "data.frame") +#' as(x, "GRanges") #' #' @param x `r document_granges("Fragment coordinates", extras=c("cell_id" = "cell barcodes or unique identifiers as string or factor"))` #' @param zero_based_coords Whether to convert the ranges from a 1-based end-inclusive #' coordinate system to a 0-based end-exclusive coordinate system. Defaults to true #' for GRanges and false for other formats #' (see this [archived UCSC blogpost](https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/)) +#' @param ... Additional arguments passed to methods #' @return **convert_to_fragments()**: IterableFragments object #' @examples #' frags_table <- tibble::tibble( diff --git a/r/R/geneScores.R b/r/R/geneScores.R index e899e411..4df90f53 100644 --- a/r/R/geneScores.R +++ b/r/R/geneScores.R @@ -88,7 +88,7 @@ range_distance_to_nearest <- function(ranges, addArchRBug = FALSE, zero_based_co #' @inheritParams normalize_ranges #' @param upstream Number of bases to extend each range upstream (negative to shrink width) #' @param downstream Number of bases to extend each range downstream (negative to shrink width) -#' @param chromosome_sizes (optional) Size of chromosomes as a [genomic-ranges] object% +#' @param chromosome_sizes (optional) Size of chromosomes as a [genomic-ranges-like] object #' @details Note that ranges will be blocked from extending past the beginning of the chromosome (base 0), #' and if `chromosome_sizes` is given then they will also be blocked from extending past the end of the chromosome #' @examples diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index 2534409e..99423236 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -9,7 +9,7 @@ #' Download a file with a custom timeout #' #' @param path Output path to write file -#' @param url to download from +#' @param backup_url to download from #' @param timeout timeout in seconds #' @keywords internal ensure_downloaded <- function(path, backup_url, timeout) { @@ -267,6 +267,11 @@ read_encode_blacklist <- function(dir, genome = c("hg38", "mm10", "hg19", "dm6", #' read_ucsc_chrom_sizes("./reference") #' @export +#' @param dir Output directory to cache the downloaded chrom sizes file +#' @param genome Genome name. Defaults to hg38 +#' @param keep_chromosomes Regular expression with which chromosomes to keep. +#' Defaults to standard chromosomes (chr1-22, chrX, chrY) +#' @param timeout Maximum time in seconds to wait for download from UCSC read_ucsc_chrom_sizes <- function(dir, genome = c("hg38", "mm39", "mm10", "mm9", "hg19"), keep_chromosomes = "chr[0-9]+|chrX|chrY", timeout = 300) { genome <- match.arg(genome) diff --git a/r/R/matrix-svds-docs.R b/r/R/matrix-svds-docs.R index f9115675..853dd7e0 100644 --- a/r/R/matrix-svds-docs.R +++ b/r/R/matrix-svds-docs.R @@ -18,7 +18,7 @@ #' @param A The matrix whose truncated SVD is to be computed. #' @param k Number of singular values requested. #' @param nu Number of left singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix) -#' @param nu Number of right singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix) +#' @param nv Number of right singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix) #' @param opts Control parameters related to computing algorithm. See *Details* below #' @param threads Control threads to use calculating mat-vec producs (BPCells specific) #' @return A list with the following components: diff --git a/r/R/matrix.R b/r/R/matrix.R index 6a6be953..9f612e1f 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -739,14 +739,14 @@ rlang::on_load({ #' #' #' @export -rowMaxs <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) UseMethod("rowMaxs") +rowMaxs <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) UseMethod("rowMaxs") #' @export #' @method rowMaxs default -rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { +rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { - MatrixGenerics::rowMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ...) + MatrixGenerics::rowMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ..., useNames = useNames) } else if (requireNamespace("matrixStats", quietly = TRUE)) { - matrixStats::rowMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ...) + matrixStats::rowMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ..., useNames = useNames) } else { stop("Can't run rowMaxs on a non-BPCells object unless MatrixGenerics or matrixStats are installed.") @@ -754,7 +754,7 @@ rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { } #' @export #' @method rowMaxs IterableMatrix -rowMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { +rowMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if(!is.null(rows) || !is.null(cols) || !isFALSE(na.rm)) { stop("rowMaxs(IterableMatrix) doesn't support extra arguments rows, cols, or na.rm") } @@ -764,7 +764,7 @@ rowMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, . } else { res <- matrix_max_per_row_cpp(iter) } - names(res) <- rownames(x) + if (useNames) names(res) <- rownames(x) return(res) } rlang::on_load({ @@ -785,14 +785,14 @@ rlang::on_load({ #' #' #' @export -colMaxs <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) UseMethod("colMaxs") +colMaxs <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) UseMethod("colMaxs") #' @export #' @method colMaxs default -colMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { +colMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { - MatrixGenerics::colMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ...) + MatrixGenerics::colMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ..., useNames = useNames) } else if (requireNamespace("matrixStats", quietly = TRUE)) { - matrixStats::colMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ...) + matrixStats::colMaxs(x, rows = rows, cols = cols, na.rm = na.rm, ..., useNames = useNames) } else { stop("Can't run colMaxs on a non-BPCells object unless MatrixGenerics or matrixStats are installed.") @@ -800,14 +800,14 @@ colMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { } #' @export #' @method colMaxs IterableMatrix -colMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ...) { +colMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { iter <- iterate_matrix(convert_matrix_type(x, "double")) if(x@transpose == TRUE) { res <- matrix_max_per_row_cpp(iter) } else { res <- matrix_max_per_col_cpp(iter) } - names(res) <- colnames(x) + if (useNames) names(res) <- colnames(x) return(res) } rlang::on_load({ @@ -1745,7 +1745,7 @@ transpose_storage_order <- function(matrix, outdir = tempfile("transpose"), tmpd #' as it can only be applied to the indexes of each entry but not the values. #' There will still be some space savings, but far less than for counts matrices. #' -#' @param matrix Input matrix, either IterableMatrix or dgCMatrix +#' @param mat Input matrix, either IterableMatrix or dgCMatrix #' @param compress Whether or not to compress the data. #' @return BPCells matrix object #' @examples @@ -2393,6 +2393,7 @@ setMethod("short_description", "AnnDataMatrixH5", function(x) { #' than the dense variant (see details for more information). #' #' @inheritParams open_matrix_hdf5 +#' @param mat IterableMatrix to write to hdf5 file #' @return AnnDataMatrixH5 object, with cells as the columns. #' @details #' **Efficiency considerations**: Reading from a dense AnnData matrix will generally be slower @@ -2999,17 +3000,21 @@ convert_matrix_type <- function(matrix, type = c("uint32_t", "double", "float")) #' Convert between BPCells matrix and R objects. #' -#' BPCells matrices can be interconverted with Matrix package +#' BPCells matrices can be interconverted with Matrix package #' dgCMatrix sparse matrices, as well as base R #' dense matrices (though this may result in high memory usage for large matrices) #' +#' @aliases as as.matrix +#' #' @usage #' # Convert to R from BPCells -#' as(bpcells_mat, "dgCMatrix") # Sparse matrix conversion -#' as.matrix(bpcells_mat) # Dense matrix conversion -#' +#' as(x, "dgCMatrix") # Sparse matrix conversion +#' as.matrix(x, ...) # Dense matrix conversion +#' #' # Convert to BPCells from R -#' as(dgc_mat, "IterableMatrix") +#' as(x, "IterableMatrix") +#' @param x Matrix object to convert +#' @param ... Additional arguments passed to methods #' @examples #' mat <- get_demo_mat()[1:2, 1:2] #' mat @@ -3214,7 +3219,8 @@ matrix_stats <- function(matrix, #' @export -svds <- function (A, k, nu = k, nv = k, opts = list(), ...) UseMethod("svds") +#' @param ... Additional arguments passed to `Rspectra::svds()` if svd is ran on a non-BPCells matrix +svds <- function (A, k, nu = k, nv = k, opts = list(), threads = 0L, ...) UseMethod("svds") # RSpectra exports svds as an S3 Generic, but is a suggested dependency # With this approach, IterableMatrix objects will work with RSpectra::svds, diff --git a/r/R/matrix_stats.R b/r/R/matrix_stats.R index 50353a5d..30a075ab 100644 --- a/r/R/matrix_stats.R +++ b/r/R/matrix_stats.R @@ -8,8 +8,13 @@ #' Find the nth quantile value(s) of each row in a matrix. Only supports transposed matrices. #' @param x IterableMatrix object or a matrix-like object. +#' @param rows (Integer) Optional vector of row indices to operate over. +#' @param cols (Integer) Optional vector of column indices to operate over. #' @param probs (Numeric) Quantile value(s) to be computed, between 0 and 1. +#' @param na.rm (Logical) Should missing values (NA) be removed? #' @param type (Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in `matrixStats::rowQuantiles()` +#' @param useNames (Logical) Whether to use row and column names in the output. +#' @param drop (Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects). #' @return - `rowQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of rows in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. #' @describeIn IterableMatrix-methods Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) @@ -97,6 +102,24 @@ rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, #' @return - `colQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of columns in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. #' @inheritParams rowQuantiles +#' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) +#' @usage colQuantiles( +#' x, +#' rows = NULL, +#' cols = NULL, +#' probs = seq(from = 0, to = 1, by = 0.25), +#' na.rm = FALSE, +#' type = 7L, +#' digits = 7L, +#' ..., +#' useNames = TRUE, +#' drop = TRUE +#' ) +#' @examples +#' ####################################################################### +#' ## colQuantiles() example +#' ####################################################################### +#' colQuantiles(mat) #' @export colQuantiles <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), @@ -119,26 +142,6 @@ colQuantiles.default <- function(x, rows = NULL, cols = NULL, } } #' @export -#' @inheritParams colQuantiles -#' @usage colQuantiles( -#' x, -#' rows = NULL, -#' cols = NULL, -#' probs = seq(from = 0, to = 1, by = 0.25), -#' na.rm = FALSE, -#' type = 7L, -#' digits = 7L, -#' ..., -#' useNames = TRUE, -#' drop = TRUE -#' ) -#' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) -#' @examples -#' ####################################################################### -#' ## colQuantiles() example -#' ####################################################################### -#' colQuantiles(mat) -#' #' @method colQuantiles IterableMatrix colQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), diff --git a/r/R/plots.R b/r/R/plots.R index 66375560..67ff0731 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -320,6 +320,7 @@ plot_fragment_length <- function(fragments, max_length = 500, return_data = FALS #' @inheritParams footprint #' @param genes Coordinate ranges for genes (must include strand) #' @param smooth Number of bases to smooth over (rolling average) +#' @param colors Discrete color palette to use for cell groups #' @seealso `footprint()`, `plot_tf_footprint()` #' @examples #' ## Prep data @@ -390,6 +391,7 @@ plot_tss_profile <- function(fragments, genes, cell_groups = rlang::rep_along(ce #' @inheritParams footprint #' @param motif_positions Coordinate ranges for motifs (must include strand) and #' have constant width +#' @param colors Discrete color palette to use for cell groups #' @seealso `footprint()`, `plot_tss_profile()` #' @export plot_tf_footprint <- function(fragments, motif_positions, cell_groups = rlang::rep_along(cellNames(fragments), "all"), @@ -827,11 +829,9 @@ rotate_x_labels <- function(degrees = 45) { #' ## Plot dot #' plot <- plot_dot(mat, c("MS4A1", "CD3E"), cell_types) #' -#' \dontrun{ #' BPCells:::render_plot_from_storage( #' plot, width = 4, height = 5 -#' } -#' +#' ) #' @export plot_dot <- function(source, features, groups, group_order = NULL, gene_mapping = human_gene_mapping, colors = c("lightgrey", "#4682B4"), diff --git a/r/R/trackplots.R b/r/R/trackplots.R index 358ee091..a74ec75c 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -320,10 +320,8 @@ render_plot_from_storage <- function(plot, width, height) { #' plot <- trackplot_combine( #' list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) #' ) -#' \dontrun{ -#' BPCells:::render_plot_from_storage( -#' plot, width = 6, height = 4) -#' } +#' BPCells:::render_plot_from_storage( +#' plot, width = 6, height = 4) #' @export trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_width = 0.3) { for (plot in tracks) { @@ -464,7 +462,7 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ #' `TRUE`, the return value will be modified accordingly. #' @seealso `trackplot_combine()`, `trackplot_gene()`, `trackplot_loop()`, `trackplot_scalebar()` #' @examples -## Prep data +#' ## Prep data #' frags <- get_demo_frags() #' #' ## Use genes and blacklist to determine proper number of reads per cell @@ -478,15 +476,13 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ #' region <- "chr4:3034877-4034877" #' cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) #' -#' \dontrun{ -#' BPCells:::render_plot_from_storage( -#' trackplot_coverage( -#' frags, region, groups = cell_types, -#' cell_read_counts = read_counts -#' ), -#' width = 6, height = 3 -#' ) -#' } +#' BPCells:::render_plot_from_storage( +#' trackplot_coverage( +#' frags, region, groups = cell_types, +#' cell_read_counts = read_counts +#' ), +#' width = 6, height = 3 +#' ) #' @export trackplot_coverage <- function(fragments, region, groups, cell_read_counts, @@ -583,11 +579,10 @@ trackplot_coverage <- function(fragments, region, groups, #' #' Usually given as the output from `read_gencode_transcripts()` #' @inheritParams trackplot_coverage -#' @param labels Character vector with labels for each item in transcripts. NA for items that should not be labeled #' @param exon_size size for exon lines in units of mm #' @param gene_size size for intron/gene lines in units of mm -#' @param transcript_size size for transcript lines in units of mm #' @param label_size size for transcript labels in units of mm +#' @param track_label Label to put on the side of the track #' @return Plot of gene locations #' @seealso `trackplot_combine()`, `trackplot_coverage()`, `trackplot_loop()`, `trackplot_scalebar()` #' @examples @@ -601,9 +596,7 @@ trackplot_coverage <- function(fragments, region, groups, #' #' ## Plot gene trackplot #' plot <- trackplot_gene(transcripts, region) -#' \dontrun{ -#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1) -#' } +#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1) #' @export trackplot_gene <- function(transcripts, region, exon_size = 2.5, gene_size = 0.5, label_size = 11*.8/ggplot2::.pt, track_label="Genes", return_data = FALSE) { region <- normalize_ranges(region) @@ -699,6 +692,7 @@ trackplot_gene <- function(transcripts, region, exon_size = 2.5, gene_size = 0.5 #' @param colors Vector of hex color codes to use for the color scale. For numeric `color_by` data, this is passed to `ggplot2::scale_color_gradientn()`, #' otherwise it is interpreted as a discrete color palette in `ggplot2::scale_color_manual()` #' @param show_strand If TRUE, show strand direction as arrows +#' @param track_label Label to put on the side of the track #' @return Plot of genomic loci if return_data is FALSE, otherwise returns the data frame used to generate the plot #' @seealso `trackplot_combine()`, `trackplot_coverage()`, `trackplot_loop()`, `trackplot_scalebar()`, `trackplot_gene()` #' @examples @@ -719,12 +713,10 @@ trackplot_gene <- function(transcripts, region, exon_size = 2.5, gene_size = 0.5 #' region <- "chr4:3034877-3044877" #' #' ## Plot peaks -#' \dontrun{ -#' BPCells:::render_plot_from_storage( -#' trackplot_genome_annotation(peaks, region, color_by = "enrichment"), -#' width = 6, height = 1 -#' ) -#' } +#' BPCells:::render_plot_from_storage( +#' trackplot_genome_annotation(peaks, region, color_by = "enrichment"), +#' width = 6, height = 1 +#' ) #' @export trackplot_genome_annotation <- function(loci, region, color_by = NULL, colors = NULL, label_by = NULL, label_size = 11*.8/ggplot2::.pt, show_strand=FALSE, annotation_size = 2.5, track_label="Peaks", return_data = FALSE) { @@ -843,6 +835,7 @@ trackplot_genome_annotation <- function(loci, region, color_by = NULL, colors = #' otherwise it is interpreted as a discrete color palette in `ggplot2::scale_color_manual()` #' @param allow_truncated If FALSE, remove any loops that are not fully contained within `region` #' @param curvature Curvature value between 0 and 1. 1 is a 180-degree arc, and 0 is flat lines. +#' @param track_label Label to put on the side of the track #' @inheritParams trackplot_coverage #' #' @return Plot of loops connecting genomic coordinates @@ -859,9 +852,7 @@ trackplot_genome_annotation <- function(loci, region, color_by = NULL, colors = #' #' ## Plot loops #' plot <- trackplot_loop(loops, region, color_by = "score") -#' \dontrun{ -#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) -#' } +#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) #' @export trackplot_loop <- function(loops, region, color_by=NULL, colors=NULL, allow_truncated=TRUE, curvature=0.75, track_label="Links", return_data = FALSE) { region <- normalize_ranges(region) @@ -961,11 +952,9 @@ trackplot_loop <- function(loops, region, color_by=NULL, colors=NULL, allow_trun #' @seealso `trackplot_combine()`, `trackplot_coverage()`, `trackplot_gene()`, `trackplot_loop()` #' @examples #' region <- "chr4:3034877-3044877" -#' \dontrun{ -#' BPCells:::render_plot_from_storage( -#' trackplot_scalebar(region), width = 6, height = 1 -#' ) -#' } +#' BPCells:::render_plot_from_storage( +#' trackplot_scalebar(region), width = 6, height = 1 +#' ) #' @export trackplot_scalebar <- function(region, font_pt=11) { region <- normalize_ranges(region) @@ -1150,7 +1139,7 @@ draw_trackplot_grid <- function(..., labels, title = NULL, #' @inheritParams plot_embedding #' @inheritParams convert_to_fragments #' @param region GRanges of length 1 with region to plot, or list/data.frame with -#' one entry each for chr, start, end. See `gene_region()` or [genomic-ranges] for details +#' one entry each for chr, start, end. See `gene_region()` or [genomic-ranges-like] for details #' @param fragments Fragments object #' @param cell_read_counts Numeric vector of read counts for each cell (used for normalization) #' @param bins Number of bins to plot across the region diff --git a/r/R/transforms.R b/r/R/transforms.R index adcd7226..cf35470f 100644 --- a/r/R/transforms.R +++ b/r/R/transforms.R @@ -256,6 +256,7 @@ setMethod("short_description", "TransformMinByRow", function(x) { }) #' @rdname min_elementwise +#' @param vals Numeric vector of positive values, with length equal to the number of rows (min_by_row) or columns (min_by_col) #' @description **min_by_row**: Take the minimum with a per-row constant #' @examples #' ####################################################################### diff --git a/r/configure b/r/configure index 20c6b445..0b53fd6e 100755 --- a/r/configure +++ b/r/configure @@ -218,6 +218,22 @@ else printf "\nFound working highway SIMD library\n" fi +############################ +# Compiler flag compatibility check +############################ + +OPTIONAL_CXXFLAGS="" + +# Test for -Wno-ignored-attributes support +if $CXX -xc++ -c -Wno-ignored-attributes /dev/null -o /dev/null 2>/dev/null; then + OPTIONAL_CXXFLAGS="$OPTIONAL_CXXFLAGS -Wno-ignored-attributes" +fi + +# Test for -Wno-unknown-pragmas support +if $CXX -xc++ -c -Wno-unknown-pragmas /dev/null -o /dev/null 2>/dev/null; then + OPTIONAL_CXXFLAGS="$OPTIONAL_CXXFLAGS -Wno-unknown-pragmas" +fi + # Make substitutions in Makevars.in sed \ -e "s|%HDF5_CFLAGS%|${HDF5_CFLAGS}|g" \ @@ -227,6 +243,7 @@ sed \ -e "s|%HWY_LIBS%|${HWY_LIBS}|g" \ -e "s|%ENV_CFLAGS%|${ENV_CFLAGS}|g" \ -e "s|%ENV_LDFLAGS%|${ENV_LDFLAGS}|g" \ + -e "s|%OPTIONAL_CXXFLAGS%|${OPTIONAL_CXXFLAGS}|g" \ src/Makevars.in > src/Makevars if [ "$ENABLE_INSTALL_COUNTING" == "yes" ]; then diff --git a/r/man/IterableFragments-methods.Rd b/r/man/IterableFragments-methods.Rd index 20b89712..4d00e60c 100644 --- a/r/man/IterableFragments-methods.Rd +++ b/r/man/IterableFragments-methods.Rd @@ -24,6 +24,8 @@ chrNames(x, ...) <- value \item{x}{an IterableFragments object} +\item{...}{Additional arguments (not used)} + \item{value}{Character vector of new names} } \value{ diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods.Rd index 28e23b9a..182c0a5e 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods.Rd @@ -16,7 +16,7 @@ \alias{rowMaxs} \alias{colMaxs} \alias{rowQuantiles} -\alias{colQuantiles.IterableMatrix} +\alias{colQuantiles} \alias{log1p,IterableMatrix-method} \alias{log1p_slow} \alias{expm1,IterableMatrix-method} @@ -136,9 +136,19 @@ expm1_slow(x) \item{y}{matrix} +\item{rows}{(Integer) Optional vector of row indices to operate over.} + +\item{cols}{(Integer) Optional vector of column indices to operate over.} + +\item{na.rm}{(Logical) Should missing values (NA) be removed?} + +\item{useNames}{(Logical) Whether to use row and column names in the output.} + \item{probs}{(Numeric) Quantile value(s) to be computed, between 0 and 1.} \item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} + +\item{drop}{(Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects).} } \value{ \itemize{ @@ -185,6 +195,11 @@ expm1_slow(x) \item \verb{rowQuantiles():} If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of rows in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. } + +\itemize{ +\item \verb{colQuantiles():} If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of columns in the matrix. +Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. +} } \description{ Generic methods and built-in functions for IterableMatrix objects @@ -219,7 +234,7 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{rowQuantiles()}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) -\item \code{colQuantiles(IterableMatrix)}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) +\item \code{colQuantiles()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) \item \code{log1p(IterableMatrix)}: Calculate log(x + 1) @@ -340,7 +355,6 @@ rowQuantiles(transpose_storage_order(mat)) ## colQuantiles() example ####################################################################### colQuantiles(mat) - ####################################################################### ## log1p() example ####################################################################### diff --git a/r/man/colQuantiles.Rd b/r/man/colQuantiles.Rd deleted file mode 100644 index a699642b..00000000 --- a/r/man/colQuantiles.Rd +++ /dev/null @@ -1,34 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/matrix_stats.R -\name{colQuantiles} -\alias{colQuantiles} -\title{Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices.} -\usage{ -colQuantiles( - x, - rows = NULL, - cols = NULL, - probs = seq(from = 0, to = 1, by = 0.25), - na.rm = FALSE, - type = 7L, - ..., - useNames = TRUE, - drop = TRUE -) -} -\arguments{ -\item{x}{IterableMatrix object or a matrix-like object.} - -\item{probs}{(Numeric) Quantile value(s) to be computed, between 0 and 1.} - -\item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} -} -\value{ -\itemize{ -\item \verb{colQuantiles():} If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of columns in the matrix. -Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. -} -} -\description{ -Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. -} diff --git a/r/man/ensure_downloaded.Rd b/r/man/ensure_downloaded.Rd index 0d0cc03c..93787cdf 100644 --- a/r/man/ensure_downloaded.Rd +++ b/r/man/ensure_downloaded.Rd @@ -9,9 +9,9 @@ ensure_downloaded(path, backup_url, timeout) \arguments{ \item{path}{Output path to write file} -\item{timeout}{timeout in seconds} +\item{backup_url}{to download from} -\item{url}{to download from} +\item{timeout}{timeout in seconds} } \description{ Download a file with a custom timeout diff --git a/r/man/extend_ranges.Rd b/r/man/extend_ranges.Rd index 357b1be6..196b4a61 100644 --- a/r/man/extend_ranges.Rd +++ b/r/man/extend_ranges.Rd @@ -25,7 +25,7 @@ extend_ranges( \item{metadata_cols}{Optional list of metadata columns to require & extract} -\item{chromosome_sizes}{(optional) Size of chromosomes as a \link{genomic-ranges} object} +\item{chromosome_sizes}{(optional) Size of chromosomes as a \link{genomic-ranges-like} object} \item{zero_based_coords}{If true, coordinates start and 0 and the end coordinate is not included in the range. If false, coordinates start at 1 and the end coordinate is included in the range} diff --git a/r/man/fragment_R_conversion.Rd b/r/man/fragment_R_conversion.Rd index a78dda7e..8ff87992 100644 --- a/r/man/fragment_R_conversion.Rd +++ b/r/man/fragment_R_conversion.Rd @@ -2,6 +2,8 @@ % Please edit documentation in R/fragments.R \name{convert_to_fragments} \alias{convert_to_fragments} +\alias{as} +\alias{as.data.frame} \title{Convert between BPCells fragments and R objects.} \usage{ # Convert from R to BPCells @@ -9,9 +11,9 @@ convert_to_fragments(x, zero_based_coords = !is(x, "GRanges")) as(x, "IterableFragments") # Convert from BPCells to R -as.data.frame(bpcells_fragments) -as(bpcells_fragments, "data.frame") -as(bpcells_fragments, "GRanges") +as.data.frame(x, ...) +as(x, "data.frame") +as(x, "GRanges") } \arguments{ \item{x}{Fragment coordinates given as GRanges, data.frame, or list. See \code{help("genomic-ranges-like")} for details on format and coordinate systems. Required attributes: @@ -24,6 +26,8 @@ as(bpcells_fragments, "GRanges") coordinate system to a 0-based end-exclusive coordinate system. Defaults to true for GRanges and false for other formats (see this \href{https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} + +\item{...}{Additional arguments passed to methods} } \value{ \strong{convert_to_fragments()}: IterableFragments object diff --git a/r/man/gene_score_tiles_archr.Rd b/r/man/gene_score_tiles_archr.Rd index de53094f..a9b91914 100644 --- a/r/man/gene_score_tiles_archr.Rd +++ b/r/man/gene_score_tiles_archr.Rd @@ -18,7 +18,7 @@ gene_score_tiles_archr( \item \code{strand}: +/- or TRUE/FALSE for positive or negative strand }} -\item{chromosome_sizes}{(optional) Size of chromosomes as a \link{genomic-ranges} object} +\item{chromosome_sizes}{(optional) Size of chromosomes as a \link{genomic-ranges-like} object} \item{tile_width}{Size of tiles to consider} diff --git a/r/man/matrix_R_conversion.Rd b/r/man/matrix_R_conversion.Rd index b00d2669..f50dea11 100644 --- a/r/man/matrix_R_conversion.Rd +++ b/r/man/matrix_R_conversion.Rd @@ -2,14 +2,21 @@ % Please edit documentation in R/matrix.R \name{matrix_R_conversion} \alias{matrix_R_conversion} +\alias{as} +\alias{as.matrix} \title{Convert between BPCells matrix and R objects.} \usage{ # Convert to R from BPCells -as(bpcells_mat, "dgCMatrix") # Sparse matrix conversion -as.matrix(bpcells_mat) # Dense matrix conversion +as(x, "dgCMatrix") # Sparse matrix conversion +as.matrix(x, ...) # Dense matrix conversion # Convert to BPCells from R -as(dgc_mat, "IterableMatrix") +as(x, "IterableMatrix") +} +\arguments{ +\item{x}{Matrix object to convert} + +\item{...}{Additional arguments passed to methods} } \description{ BPCells matrices can be interconverted with Matrix package diff --git a/r/man/matrix_io.Rd b/r/man/matrix_io.Rd index 70e6c4c7..44dc0186 100644 --- a/r/man/matrix_io.Rd +++ b/r/man/matrix_io.Rd @@ -34,6 +34,8 @@ write_matrix_hdf5( open_matrix_hdf5(path, group, buffer_size = 16384L) } \arguments{ +\item{mat}{Input matrix, either IterableMatrix or dgCMatrix} + \item{compress}{Whether or not to compress the data.} \item{dir}{Directory to save the data into} @@ -54,8 +56,6 @@ to an existing hdf5 file this group must not already be in use} \item{gzip_level}{Gzip compression level. Default is 0 (no compression). This is recommended when both compression and compatibility with outside programs is required. Otherwise, using compress=TRUE is recommended as it is >10x faster with often similar compression levels.} - -\item{matrix}{Input matrix, either IterableMatrix or dgCMatrix} } \value{ BPCells matrix object diff --git a/r/man/min_elementwise.Rd b/r/man/min_elementwise.Rd index 8d06523d..ae9b9237 100644 --- a/r/man/min_elementwise.Rd +++ b/r/man/min_elementwise.Rd @@ -16,6 +16,8 @@ min_by_col(mat, vals) \item{mat}{IterableMatrix} \item{val}{Single positive numeric value} + +\item{vals}{Numeric vector of positive values, with length equal to the number of rows (min_by_row) or columns (min_by_col)} } \value{ IterableMatrix diff --git a/r/man/normalize_ranges.Rd b/r/man/normalize_ranges.Rd index 55779eb4..bb9ca16b 100644 --- a/r/man/normalize_ranges.Rd +++ b/r/man/normalize_ranges.Rd @@ -21,6 +21,8 @@ normalize_ranges( \item{zero_based_coords}{If true, coordinates start and 0 and the end coordinate is not included in the range. If false, coordinates start at 1 and the end coordinate is included in the range} + +\item{n}{How many call frames to go up when printing errors} } \value{ data frame with zero-based coordinates, and elements chr (factor), start (int), and end (int). diff --git a/r/man/open_matrix_anndata_hdf5.Rd b/r/man/open_matrix_anndata_hdf5.Rd index 22d79b13..e44c1530 100644 --- a/r/man/open_matrix_anndata_hdf5.Rd +++ b/r/man/open_matrix_anndata_hdf5.Rd @@ -35,6 +35,8 @@ to an existing hdf5 file this group must not already be in use} \item{buffer_size}{For performance tuning only. The number of items to be buffered in memory before calling writes to disk.} +\item{mat}{IterableMatrix to write to hdf5 file} + \item{chunk_size}{For performance tuning only. The chunk size used for the HDF5 array storage.} \item{gzip_level}{Gzip compression level. Default is 0 (no compression)} diff --git a/r/man/plot_dot.Rd b/r/man/plot_dot.Rd index 412a4b65..3f5fbdb5 100644 --- a/r/man/plot_dot.Rd +++ b/r/man/plot_dot.Rd @@ -46,9 +46,7 @@ cell_types <- paste("Group", rep(1:3, length.out = length(colnames(mat)))) ## Plot dot plot <- plot_dot(mat, c("MS4A1", "CD3E"), cell_types) -\dontrun{ BPCells:::render_plot_from_storage( plot, width = 4, height = 5 -} - +) } diff --git a/r/man/plot_tf_footprint.Rd b/r/man/plot_tf_footprint.Rd index 83dfc346..d8b1b463 100644 --- a/r/man/plot_tf_footprint.Rd +++ b/r/man/plot_tf_footprint.Rd @@ -33,6 +33,8 @@ weights for smoothing.} \item{zero_based_coords}{If true, coordinates start and 0 and the end coordinate is not included in the range. If false, coordinates start at 1 and the end coordinate is included in the range} +\item{colors}{Discrete color palette to use for cell groups} + \item{return_data}{If true, return data from just before plotting rather than a plot.} \item{apply_styling}{If false, return a plot without pretty styling applied} diff --git a/r/man/plot_tss_profile.Rd b/r/man/plot_tss_profile.Rd index 7581d0b0..e4733fe8 100644 --- a/r/man/plot_tss_profile.Rd +++ b/r/man/plot_tss_profile.Rd @@ -31,6 +31,8 @@ plot_tss_profile( \item{zero_based_coords}{If true, coordinates start and 0 and the end coordinate is not included in the range. If false, coordinates start at 1 and the end coordinate is included in the range} +\item{colors}{Discrete color palette to use for cell groups} + \item{return_data}{If true, return data from just before plotting rather than a plot.} \item{apply_styling}{If false, return a plot without pretty styling applied} diff --git a/r/man/read_ucsc_chrom_sizes.Rd b/r/man/read_ucsc_chrom_sizes.Rd index 646e4488..6cb99488 100644 --- a/r/man/read_ucsc_chrom_sizes.Rd +++ b/r/man/read_ucsc_chrom_sizes.Rd @@ -11,6 +11,16 @@ read_ucsc_chrom_sizes( timeout = 300 ) } +\arguments{ +\item{dir}{Output directory to cache the downloaded chrom sizes file} + +\item{genome}{Genome name. Defaults to hg38} + +\item{keep_chromosomes}{Regular expression with which chromosomes to keep. +Defaults to standard chromosomes (chr1-22, chrX, chrY)} + +\item{timeout}{Maximum time in seconds to wait for download from UCSC} +} \description{ Read chromosome sizes from UCSC and return as a tibble with one row per chromosome. diff --git a/r/man/svds.Rd b/r/man/svds.Rd index 3121210d..3bd47c40 100644 --- a/r/man/svds.Rd +++ b/r/man/svds.Rd @@ -1,21 +1,27 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/matrix-svds-docs.R +% Please edit documentation in R/matrix-svds-docs.R, R/matrix.R \name{svds} \alias{svds} \title{Calculate svds} \usage{ svds(A, k, nu = k, nv = k, opts = list(), threads=0L, ...) + +svds(A, k, nu = k, nv = k, opts = list(), threads = 0L, ...) } \arguments{ \item{A}{The matrix whose truncated SVD is to be computed.} \item{k}{Number of singular values requested.} -\item{nu}{Number of right singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix)} +\item{nu}{Number of left singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix)} + +\item{nv}{Number of right singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix)} \item{opts}{Control parameters related to computing algorithm. See \emph{Details} below} \item{threads}{Control threads to use calculating mat-vec producs (BPCells specific)} + +\item{...}{Additional arguments passed to \code{Rspectra::svds()} if svd is ran on a non-BPCells matrix} } \value{ A list with the following components: diff --git a/r/man/trackplot_bulk.Rd b/r/man/trackplot_bulk.Rd index a65a1a01..095b87c3 100644 --- a/r/man/trackplot_bulk.Rd +++ b/r/man/trackplot_bulk.Rd @@ -24,7 +24,7 @@ trackplot_bulk( \item{fragments}{Fragments object} \item{region}{GRanges of length 1 with region to plot, or list/data.frame with -one entry each for chr, start, end. See \code{gene_region()} or \link{genomic-ranges} for details} +one entry each for chr, start, end. See \code{gene_region()} or \link{genomic-ranges-like} for details} \item{groups}{Vector with one entry per cell, specifying the cell's group} diff --git a/r/man/trackplot_combine.Rd b/r/man/trackplot_combine.Rd index 971ea06e..71670273 100644 --- a/r/man/trackplot_combine.Rd +++ b/r/man/trackplot_combine.Rd @@ -68,10 +68,8 @@ plot_coverage <- trackplot_coverage( plot <- trackplot_combine( list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) ) -\dontrun{ - BPCells:::render_plot_from_storage( - plot, width = 6, height = 4) -} +BPCells:::render_plot_from_storage( + plot, width = 6, height = 4) } \seealso{ \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} diff --git a/r/man/trackplot_coverage.Rd b/r/man/trackplot_coverage.Rd index cdf110ca..4d3d3f29 100644 --- a/r/man/trackplot_coverage.Rd +++ b/r/man/trackplot_coverage.Rd @@ -59,6 +59,7 @@ Plot a pseudobulk genome track, showing the number of fragment insertions across a region for each cell type or group. } \examples{ +## Prep data frags <- get_demo_frags() ## Use genes and blacklist to determine proper number of reads per cell @@ -72,15 +73,13 @@ read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags region <- "chr4:3034877-4034877" cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) -\dontrun{ - BPCells:::render_plot_from_storage( - trackplot_coverage( - frags, region, groups = cell_types, - cell_read_counts = read_counts - ), - width = 6, height = 3 - ) -} +BPCells:::render_plot_from_storage( + trackplot_coverage( + frags, region, groups = cell_types, + cell_read_counts = read_counts + ), + width = 6, height = 3 +) } \seealso{ \code{trackplot_combine()}, \code{trackplot_gene()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} diff --git a/r/man/trackplot_gene.Rd b/r/man/trackplot_gene.Rd index b608bf3d..92c11d57 100644 --- a/r/man/trackplot_gene.Rd +++ b/r/man/trackplot_gene.Rd @@ -35,11 +35,9 @@ or list/data.frame/GRanges of length 1 specifying chr, start, end. See \code{hel \item{label_size}{size for transcript labels in units of mm} -\item{return_data}{If true, return data from just before plotting rather than a plot.} - -\item{labels}{Character vector with labels for each item in transcripts. NA for items that should not be labeled} +\item{track_label}{Label to put on the side of the track} -\item{transcript_size}{size for transcript lines in units of mm} +\item{return_data}{If true, return data from just before plotting rather than a plot.} } \value{ Plot of gene locations @@ -58,9 +56,7 @@ region <- "chr4:3034877-4034877" ## Plot gene trackplot plot <- trackplot_gene(transcripts, region) -\dontrun{ - BPCells:::render_plot_from_storage(plot, width = 6, height = 1) -} +BPCells:::render_plot_from_storage(plot, width = 6, height = 1) } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} diff --git a/r/man/trackplot_genome_annotation.Rd b/r/man/trackplot_genome_annotation.Rd index d51bd92d..fe616b7e 100644 --- a/r/man/trackplot_genome_annotation.Rd +++ b/r/man/trackplot_genome_annotation.Rd @@ -39,6 +39,8 @@ otherwise it is interpreted as a discrete color palette in \code{ggplot2::scale_ \item{annotation_size}{size for annotation lines in mm} +\item{track_label}{Label to put on the side of the track} + \item{return_data}{If true, return data from just before plotting rather than a plot.} } \value{ @@ -65,12 +67,10 @@ peaks <- tibble::tibble( region <- "chr4:3034877-3044877" ## Plot peaks -\dontrun{ - BPCells:::render_plot_from_storage( - trackplot_genome_annotation(peaks, region, color_by = "enrichment"), - width = 6, height = 1 - ) -} +BPCells:::render_plot_from_storage( + trackplot_genome_annotation(peaks, region, color_by = "enrichment"), + width = 6, height = 1 +) } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_loop()}, \code{trackplot_scalebar()}, \code{trackplot_gene()} diff --git a/r/man/trackplot_loop.Rd b/r/man/trackplot_loop.Rd index 68386679..4cab9fbb 100644 --- a/r/man/trackplot_loop.Rd +++ b/r/man/trackplot_loop.Rd @@ -33,6 +33,8 @@ otherwise it is interpreted as a discrete color palette in \code{ggplot2::scale_ \item{curvature}{Curvature value between 0 and 1. 1 is a 180-degree arc, and 0 is flat lines.} +\item{track_label}{Label to put on the side of the track} + \item{return_data}{If true, return data from just before plotting rather than a plot.} } \value{ @@ -53,9 +55,7 @@ region <- "chr4:3034877-4034877" ## Plot loops plot <- trackplot_loop(loops, region, color_by = "score") -\dontrun{ - BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) -} +BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_scalebar()}, \code{trackplot_genome_annotation()} diff --git a/r/man/trackplot_scalebar.Rd b/r/man/trackplot_scalebar.Rd index a307e68f..f52f663e 100644 --- a/r/man/trackplot_scalebar.Rd +++ b/r/man/trackplot_scalebar.Rd @@ -20,11 +20,9 @@ Plots a human-readable scale bar and coordinates of the region being plotted } \examples{ region <- "chr4:3034877-3044877" -\dontrun{ - BPCells:::render_plot_from_storage( - trackplot_scalebar(region), width = 6, height = 1 - ) -} +BPCells:::render_plot_from_storage( + trackplot_scalebar(region), width = 6, height = 1 +) } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_loop()} diff --git a/r/src/Makevars.in b/r/src/Makevars.in index c816cc37..42be685f 100644 --- a/r/src/Makevars.in +++ b/r/src/Makevars.in @@ -1,9 +1,9 @@ # CXX_STD = CXX17 - -PKG_CXXFLAGS = %HDF5_CFLAGS% %HWY_CFLAGS% %ENV_CFLAGS% -Ivendor -std=c++17 -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS -Wno-ignored-attributes -Wno-unknown-pragmas # -Wall -Wextra -Wpedantic +CXX_STD = CXX17 +PKG_CXXFLAGS = %HDF5_CFLAGS% %HWY_CFLAGS% %ENV_CFLAGS% -Ivendor -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS%OPTIONAL_CXXFLAGS% # -Wall -Wextra -Wpedantic PKG_LIBS = -lz %HDF5_LIBS% %CXX_FS_FLAG% %HWY_LIBS% %ENV_LDFLAGS% -# PKG_CXXFLAGS = -Wno-deprecated-declarations -Wno-unused-but-set-variable -fsanitize=undefined %HDF5_CFLAGS% %HWY_CFLAGS% -std=c++17 -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS -Wno-ignored-attributes -Wno-unknown-pragmas # -Wall -Wextra -Wpedantic +# PKG_CXXFLAGS = -Wno-deprecated-declarations -Wno-unused-but-set-variable -fsanitize=undefined %HDF5_CFLAGS% %HWY_CFLAGS% -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS%OPTIONAL_CXXFLAGS% # -Wall -Wextra -Wpedantic # PKG_LIBS = -fsanitize=undefined -lz %HDF5_LIBS% %CXX_FS_FLAG% %HWY_LIBS% OBJECTS=\ From 090f660f5062b915ab412aecb68acd1c561f3251 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Fri, 17 Oct 2025 16:56:16 -0700 Subject: [PATCH 08/84] [r] fix majority of issues with notes and warnings (except roxygen issues) --- event.json | 6 ++++ r/.Rbuildignore | 10 +++++++ r/LICENSE | 20 +------------ r/NAMESPACE | 2 +- r/R/atac_utils.R | 2 +- r/R/fragments.R | 5 +++- r/R/genomeAnnotations.R | 10 +++---- r/R/matrix.R | 5 +++- r/R/matrix_stats.R | 5 ++-- r/R/trackplots.R | 30 ++++++++++++++++++-- r/R/transforms.R | 2 ++ r/cleanup | 4 +++ r/configure | 47 ++++++++++++++++++------------- r/man/IterableMatrix-methods.Rd | 8 ++++++ r/man/fragment_R_conversion.Rd | 7 ++++- r/man/matrix_R_conversion.Rd | 5 +++- r/man/read_bed.Rd | 2 +- r/man/read_gtf.Rd | 6 ++-- r/man/read_ucsc_chrom_sizes.Rd | 2 +- r/man/trackplot_coverage.Rd | 2 -- r/man/write_insertion_bedgraph.Rd | 2 +- r/vignettes/pbmc3k.Rmd | 8 +++--- 22 files changed, 125 insertions(+), 65 deletions(-) create mode 100644 event.json diff --git a/event.json b/event.json new file mode 100644 index 00000000..ecde619a --- /dev/null +++ b/event.json @@ -0,0 +1,6 @@ +{ + "inputs": { + "version": "0.3.0rc1", + "target": "testpypi" + } +} \ No newline at end of file diff --git a/r/.Rbuildignore b/r/.Rbuildignore index e97cfde3..5f4bbfbf 100644 --- a/r/.Rbuildignore +++ b/r/.Rbuildignore @@ -1,11 +1,20 @@ ^_pkgdown\.yml$ +^compile_commands\.json$ +^index\.md$ ^docs$ +^scripts$ +^data-raw$ ^pkgdown$ ^.*\.Rproj$ ^\.Rproj\.user$ +^LICENSE$ + ^\.idea +^\.cache$ ^bench$ +^vignettes$ +^tools/highway/ .*\.o$ .*\.so$ @@ -17,3 +26,4 @@ cmake-build-debug/ \.vscode/ \.snakemake/ + diff --git a/r/LICENSE b/r/LICENSE index 4ddd34d9..70bf9a3e 100644 --- a/r/LICENSE +++ b/r/LICENSE @@ -1,20 +1,2 @@ YEAR: 2025 -COPYRIGHT HOLDER: BPCells contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +COPYRIGHT HOLDER: BPCells contributors \ No newline at end of file diff --git a/r/NAMESPACE b/r/NAMESPACE index 4a23be3c..799ed795 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -4,7 +4,6 @@ S3method(base::as.data.frame,IterableFragments) S3method(base::as.matrix,IterableMatrix) S3method(colMaxs,IterableMatrix) S3method(colMaxs,default) -S3method(colQuantiles,IterableMatrix) S3method(colQuantiles,default) S3method(colVars,IterableMatrix) S3method(colVars,default) @@ -40,6 +39,7 @@ export(cluster_graph_seurat) export(colMaxs) export(colMeans) export(colQuantiles) +export(colQuantiles.IterableMatrix) export(colSums) export(colVars) export(collect_features) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index 7e580abf..cfd7a734 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -496,7 +496,7 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' list.files(bedgraph_outputs) #' #' # With tiling -#' chrom_sizes <- read_ucsc_chrom_sizes("./reference", genome="hg38") %>% +#' chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "reference"), genome="hg38") %>% #' dplyr::filter(chr %in% c("chr4", "chr11")) #' write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all_tiled.bedGraph"), #' chrom_sizes = chrom_sizes, normalization_method = "cpm", tile_width = 100) diff --git a/r/R/fragments.R b/r/R/fragments.R index 50884def..9733d6a7 100644 --- a/r/R/fragments.R +++ b/r/R/fragments.R @@ -658,7 +658,7 @@ open_fragments_hdf5 <- function(path, group = "fragments", buffer_size = 16384L) #' GRanges, BPCells assumes a 0-based, end-exclusive coordinate system. (See #' [genomic-ranges-like] reference for details) #' -#' @aliases as as.data.frame +#' @aliases as.data.frame #' #' @usage #' # Convert from R to BPCells @@ -671,6 +671,9 @@ open_fragments_hdf5 <- function(path, group = "fragments", buffer_size = 16384L) #' as(x, "GRanges") #' #' @param x `r document_granges("Fragment coordinates", extras=c("cell_id" = "cell barcodes or unique identifiers as string or factor"))` +#' @param IterableFragments BPCells IterableFragments object +#' @param data.frame Data frame with columns chr, start, end, and cell_id +#' @param GRanges GenomicRanges object with metadata column cell_id #' @param zero_based_coords Whether to convert the ranges from a 1-based end-inclusive #' coordinate system to a 0-based end-exclusive coordinate system. Defaults to true #' for GRanges and false for other formats diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index 99423236..8c7e464e 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -57,7 +57,7 @@ ensure_downloaded <- function(path, backup_url, timeout) { #' species <- "Saccharomyces_cerevisiae" #' version <- "GCF_000146045.2_R64" #' head(read_gtf( -#' path = sprintf("./reference/%s_genomic.gtf.gz", version), +#' path = sprintf("%s/%s_genomic.gtf.gz", file.path(tempdir(), "reference"), version), #' backup_url = sprintf( #' "https://ftp.ncbi.nlm.nih.gov/genomes/refseq/fungi/%s/reference/%s/%s_genomic.gtf.gz", #' species, version, version @@ -107,7 +107,7 @@ read_gtf <- function(path, attributes = c("gene_id"), tags = character(0), featu #' ####################################################################### #' ## read_gencode_genes() example #' ####################################################################### -#' read_gencode_genes("./references", release = "42", timeout = 3000) +#' read_gencode_genes(file.path(tempdir(), "reference"), release = "42", timeout = 3000) #' #' #' @export @@ -159,7 +159,7 @@ read_gencode_genes <- function(dir, release = "latest", #' ####################################################################### #' ## If read_gencode_genes() was already ran on the same release, #' ## will reuse previously downloaded annotations -#' read_gencode_transcripts("./references", release = "42", timeout = 3000) +#' read_gencode_transcripts(file.path(tempdir(), "reference"), release = "42", timeout = 3000) #' #' #' @export @@ -246,7 +246,7 @@ read_bed <- function(path, additional_columns = character(0), backup_url = NULL, #' ####################################################################### #' ## read_encode_blacklist() example #' ####################################################################### -#' read_encode_blacklist("./reference") +#' read_encode_blacklist(file.path(tempdir(), "reference")) #' #' #' @export @@ -264,7 +264,7 @@ read_encode_blacklist <- function(dir, genome = c("hg38", "mm10", "hg19", "dm6", #' The underlying data is pulled from here: #' #' @examples -#' read_ucsc_chrom_sizes("./reference") +#' read_ucsc_chrom_sizes(file.path(tempdir(), "reference")) #' @export #' @param dir Output directory to cache the downloaded chrom sizes file diff --git a/r/R/matrix.R b/r/R/matrix.R index 9f612e1f..cee98952 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -663,6 +663,7 @@ setMethod("colMeans", signature(x = "IterableMatrix"), function(x) colSums(x) / # MatrixGenerics::colVars. matrixStats::rowVars and matrixStats::colVars will only work on base R matrix objects. #' @describeIn IterableMatrix-methods Calculate colVars (replacement for `matrixStats::colVars()`) +#' @param center Optional center values (vector of length nrow(x) or ncol(x)) #' @return * `colVars()`: vector of col variance #' @examples #' ####################################################################### @@ -3004,7 +3005,7 @@ convert_matrix_type <- function(matrix, type = c("uint32_t", "double", "float")) #' dgCMatrix sparse matrices, as well as base R #' dense matrices (though this may result in high memory usage for large matrices) #' -#' @aliases as as.matrix +#' @aliases as.matrix #' #' @usage #' # Convert to R from BPCells @@ -3014,6 +3015,8 @@ convert_matrix_type <- function(matrix, type = c("uint32_t", "double", "float")) #' # Convert to BPCells from R #' as(x, "IterableMatrix") #' @param x Matrix object to convert +#' @param dgCMatrix Sparse matrix in dgCMatrix format +#' @param IterableMatrix IterableMatrix object #' @param ... Additional arguments passed to methods #' @examples #' mat <- get_demo_mat()[1:2, 1:2] diff --git a/r/R/matrix_stats.R b/r/R/matrix_stats.R index 30a075ab..98c916d7 100644 --- a/r/R/matrix_stats.R +++ b/r/R/matrix_stats.R @@ -101,8 +101,8 @@ rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, #' Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. #' @return - `colQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of columns in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. -#' @inheritParams rowQuantiles #' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) +#' @inheritParams rowQuantiles #' @usage colQuantiles( #' x, #' rows = NULL, @@ -120,6 +120,8 @@ rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, #' ## colQuantiles() example #' ####################################################################### #' colQuantiles(mat) +#' +#' #' @export colQuantiles <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), @@ -142,7 +144,6 @@ colQuantiles.default <- function(x, rows = NULL, cols = NULL, } } #' @export -#' @method colQuantiles IterableMatrix colQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., diff --git a/r/R/trackplots.R b/r/R/trackplots.R index a74ec75c..cce7ea28 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -47,6 +47,33 @@ wrap_trackplot <- function(plot, height=NULL, takes_sideplot=FALSE, region=NULL, plot } +# Internal helper function to extract patches from patchwork objects +# Replicates the logic of patchwork:::get_patches() to avoid using unexported functions +get_patchwork_patches <- function(plot) { + if (inherits(plot, "patchwork")) { + patches <- plot$patches + if (is.null(patches)) patches <- list(plots = list()) + + # Extract the base plot (without patchwork components) + base_plot <- plot + base_plot$patches <- NULL + class(base_plot) <- setdiff(class(base_plot), "patchwork") + if (inherits(base_plot, "free_plot")) { + attr(base_plot, "patchwork_free_settings") <- NULL + if (is.null(attr(base_plot, "free_settings"))) { + class(base_plot) <- setdiff(class(base_plot), "free_plot") + } + } + + # Combine existing patches with the base plot + patches$plots <- c(patches$plots, list(base_plot)) + return(patches) + } else { + # Return a patches object with just the single plot + return(list(plots = list(plot))) + } +} + # Internal helper function to return empty track plots if there's no data to be plotted trackplot_empty <- function(region, label) { ggplot2::ggplot(tibble::tibble(label=label)) + @@ -449,7 +476,6 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ #' or list/data.frame/GRanges of length 1 specifying chr, start, end. See `help("genomic-ranges-like")` for details #' @param fragments Fragments object #' @param cell_read_counts Numeric vector of read counts for each cell (used for normalization) -#' @param scale_bar Whether to include a scale bar in the top track (`TRUE` or `FALSE`) #' @param bins Number of bins to plot across the region #' @param clip_quantile (optional) Quantile of values for clipping y-axis limits. Default of 0.999 will crop out #' just the most extreme outliers across the region. NULL to disable clipping @@ -1081,7 +1107,7 @@ draw_trackplot_grid <- function(..., labels, title = NULL, new_heights[next_index] <- heights[i] next_index <- next_index + 1 } else { - plot_list <- patchwork:::get_patches(plots[[i]])$plots + plot_list <- get_patchwork_patches(plots[[i]])$plots names(plot_list) <- plots[[i]]$patchwork$labels if (is.null(names(plot_list))) { names(plot_list) <- rep("", length(plot_list)) diff --git a/r/R/transforms.R b/r/R/transforms.R index cf35470f..3c3a21ba 100644 --- a/r/R/transforms.R +++ b/r/R/transforms.R @@ -373,6 +373,8 @@ setMethod("<", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) stop("matrix < numeric not supported for IterableMatrix objects") }) #' @describeIn IterableMatrix-methods Binarize matrix according to numeric < matrix comparison +#' @param e1 First element of comparison +#' @param e2 Second element of comparison #' @examples #' ####################################################################### #' ## `e1 < e2` example diff --git a/r/cleanup b/r/cleanup index 77521205..388b1686 100755 --- a/r/cleanup +++ b/r/cleanup @@ -6,4 +6,8 @@ fi if [ -f tools/h5write ]; then rm tools/h5write +fi + +if [ -f tools/highway/lib ]; then + rm -r tools/highway/lib fi \ No newline at end of file diff --git a/r/configure b/r/configure index 0b53fd6e..b8f6e09e 100755 --- a/r/configure +++ b/r/configure @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh if [ -z $BPCELLS_DEBUG_INSTALL ]; then exec 3>/dev/null @@ -16,7 +16,7 @@ fi # or set the CI or ENABLE_INSTALL_COUNTING environment variables ahead of installation. if [ -z "$CI" ]; then ENABLE_INSTALL_COUNTING=${ENABLE_INSTALL_COUNTING:-yes}; fi -if [ "$ENABLE_INSTALL_COUNTING" == "yes" ]; then +if [ "$ENABLE_INSTALL_COUNTING" = "yes" ]; then curl --silent "https://plausible.benparks.net/flask-plausible/bpcells-configure" > /dev/null 2> /dev/null \ || true echo "Recording install count metrics" @@ -159,7 +159,9 @@ printf "\nTesting availability of highway SIMD library...\n" HWY_OK="" # Minimum required version (may override via env var HWY_MIN_VERSION=X.Y.Z) HWY_MIN_VERSION=${HWY_MIN_VERSION:-1.0.5} -IFS=. read -r HWY_MIN_MAJOR HWY_MIN_MINOR HWY_MIN_PATCH <<< "$HWY_MIN_VERSION" +HWY_MIN_MAJOR=$(echo "$HWY_MIN_VERSION" | cut -d. -f1) +HWY_MIN_MINOR=$(echo "$HWY_MIN_VERSION" | cut -d. -f2) +HWY_MIN_PATCH=$(echo "$HWY_MIN_VERSION" | cut -d. -f3) sed \ -e "s/@HWY_MIN_MAJOR@/$HWY_MIN_MAJOR/g" \ -e "s/@HWY_MIN_MINOR@/$HWY_MIN_MINOR/g" \ @@ -188,14 +190,16 @@ else HWY_LIBS="" fi # Only attempt second compile if pkg-config succeeded - if [ -n "$HWY_LIBS" ] && $CXX tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > /dev/null 2> "$HWY_COMPILE_LOG"; then - HWY_VERSION_OUTPUT=$(tools/hwy-test) - printf "$HWY_VERSION_OUTPUT" - HWY_OK="yes" - elif grep -q "Highway too old" "$HWY_COMPILE_LOG"; then + if [ -n "$HWY_LIBS" ]; then + if $CXX tools/hwy-test.cpp -o tools/hwy-test $CXXFLAGS $LDFLAGS $HWY_CFLAGS $HWY_LIBS > /dev/null 2> "$HWY_COMPILE_LOG"; then + HWY_VERSION_OUTPUT=$(tools/hwy-test) + printf "$HWY_VERSION_OUTPUT" + HWY_OK="yes" + elif grep -q "Highway too old" "$HWY_COMPILE_LOG"; then printf "\nHighway is installed but too old: %s\n" "$(sed -n 's/.*#pragma message: //p' "$HWY_COMPILE_LOG")" - else + else printf "Highway not found or unusable\n" + fi fi fi rm -f tools/hwy-test "$HWY_COMPILE_LOG" tools/hwy-test.cpp @@ -203,7 +207,7 @@ rm -f tools/hwy-test "$HWY_COMPILE_LOG" tools/hwy-test.cpp if [ -z $HWY_OK ]; then if [ ! -f tools/highway/lib/libhwy.a ]; then printf "\nBuilding highway SIMD library from source\n" - CXX=$CXX bash src/vendor/highway/manual-build/build_highway.sh src/vendor/highway tools/highway && HWY_OK="yes"; + CXX=$CXX sh src/vendor/highway/manual-build/build_highway.sh src/vendor/highway tools/highway && HWY_OK="yes"; if [ -z $HWY_OK ]; then printf "\n\nUnable to build highway SIMD library from source\n" exit 1 @@ -224,15 +228,15 @@ fi OPTIONAL_CXXFLAGS="" -# Test for -Wno-ignored-attributes support -if $CXX -xc++ -c -Wno-ignored-attributes /dev/null -o /dev/null 2>/dev/null; then - OPTIONAL_CXXFLAGS="$OPTIONAL_CXXFLAGS -Wno-ignored-attributes" -fi +# # Test for -Wno-ignored-attributes support +# if $CXX -xc++ -c -Wno-ignored-attributes /dev/null -o /dev/null 2>/dev/null; then +# OPTIONAL_CXXFLAGS="$OPTIONAL_CXXFLAGS -Wno-ignored-attributes" +# fi -# Test for -Wno-unknown-pragmas support -if $CXX -xc++ -c -Wno-unknown-pragmas /dev/null -o /dev/null 2>/dev/null; then - OPTIONAL_CXXFLAGS="$OPTIONAL_CXXFLAGS -Wno-unknown-pragmas" -fi +# # Test for -Wno-unknown-pragmas support +# if $CXX -xc++ -c -Wno-unknown-pragmas /dev/null -o /dev/null 2>/dev/null; then +# OPTIONAL_CXXFLAGS="$OPTIONAL_CXXFLAGS -Wno-unknown-pragmas" +# fi # Make substitutions in Makevars.in sed \ @@ -246,7 +250,12 @@ sed \ -e "s|%OPTIONAL_CXXFLAGS%|${OPTIONAL_CXXFLAGS}|g" \ src/Makevars.in > src/Makevars -if [ "$ENABLE_INSTALL_COUNTING" == "yes" ]; then +# Clean up highway build directory to avoid CRAN NOTE about object files +# The highway library will be rebuilt as needed during installation +rm -rf tools/highway/ + +if [ "$ENABLE_INSTALL_COUNTING" = "yes" ]; then curl --silent https://plausible.benparks.net/flask-plausible/bpcells-configure-success > /dev/null 2> /dev/null \ || true fi + diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods.Rd index 182c0a5e..b3488f94 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods.Rd @@ -142,6 +142,8 @@ expm1_slow(x) \item{na.rm}{(Logical) Should missing values (NA) be removed?} +\item{center}{Optional center values (vector of length nrow(x) or ncol(x))} + \item{useNames}{(Logical) Whether to use row and column names in the output.} \item{probs}{(Numeric) Quantile value(s) to be computed, between 0 and 1.} @@ -149,6 +151,10 @@ expm1_slow(x) \item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} \item{drop}{(Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects).} + +\item{e1}{First element of comparison} + +\item{e2}{Second element of comparison} } \value{ \itemize{ @@ -355,6 +361,8 @@ rowQuantiles(transpose_storage_order(mat)) ## colQuantiles() example ####################################################################### colQuantiles(mat) + + ####################################################################### ## log1p() example ####################################################################### diff --git a/r/man/fragment_R_conversion.Rd b/r/man/fragment_R_conversion.Rd index 8ff87992..6533da63 100644 --- a/r/man/fragment_R_conversion.Rd +++ b/r/man/fragment_R_conversion.Rd @@ -2,7 +2,6 @@ % Please edit documentation in R/fragments.R \name{convert_to_fragments} \alias{convert_to_fragments} -\alias{as} \alias{as.data.frame} \title{Convert between BPCells fragments and R objects.} \usage{ @@ -27,6 +26,12 @@ coordinate system to a 0-based end-exclusive coordinate system. Defaults to true for GRanges and false for other formats (see this \href{https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} +\item{IterableFragments}{BPCells IterableFragments object} + +\item{data.frame}{Data frame with columns chr, start, end, and cell_id} + +\item{GRanges}{GenomicRanges object with metadata column cell_id} + \item{...}{Additional arguments passed to methods} } \value{ diff --git a/r/man/matrix_R_conversion.Rd b/r/man/matrix_R_conversion.Rd index f50dea11..31923191 100644 --- a/r/man/matrix_R_conversion.Rd +++ b/r/man/matrix_R_conversion.Rd @@ -2,7 +2,6 @@ % Please edit documentation in R/matrix.R \name{matrix_R_conversion} \alias{matrix_R_conversion} -\alias{as} \alias{as.matrix} \title{Convert between BPCells matrix and R objects.} \usage{ @@ -16,6 +15,10 @@ as(x, "IterableMatrix") \arguments{ \item{x}{Matrix object to convert} +\item{dgCMatrix}{Sparse matrix in dgCMatrix format} + +\item{IterableMatrix}{IterableMatrix object} + \item{...}{Additional arguments passed to methods} } \description{ diff --git a/r/man/read_bed.Rd b/r/man/read_bed.Rd index 3ec34b3b..ebd8a85b 100644 --- a/r/man/read_bed.Rd +++ b/r/man/read_bed.Rd @@ -66,7 +66,7 @@ read_bed(file_name) ####################################################################### ## read_encode_blacklist() example ####################################################################### -read_encode_blacklist("./reference") +read_encode_blacklist(file.path(tempdir(), "reference")) } diff --git a/r/man/read_gtf.Rd b/r/man/read_gtf.Rd index eb886d5b..7d9d9d62 100644 --- a/r/man/read_gtf.Rd +++ b/r/man/read_gtf.Rd @@ -114,7 +114,7 @@ Read transcript models from GENCODE, for use with trackplot_gene() species <- "Saccharomyces_cerevisiae" version <- "GCF_000146045.2_R64" head(read_gtf( - path = sprintf("./reference/\%s_genomic.gtf.gz", version), + path = sprintf("\%s/\%s_genomic.gtf.gz", file.path(tempdir(), "reference"), version), backup_url = sprintf( "https://ftp.ncbi.nlm.nih.gov/genomes/refseq/fungi/\%s/reference/\%s/\%s_genomic.gtf.gz", species, version, version @@ -125,7 +125,7 @@ head(read_gtf( ####################################################################### ## read_gencode_genes() example ####################################################################### -read_gencode_genes("./references", release = "42", timeout = 3000) +read_gencode_genes(file.path(tempdir(), "reference"), release = "42", timeout = 3000) ####################################################################### @@ -133,7 +133,7 @@ read_gencode_genes("./references", release = "42", timeout = 3000) ####################################################################### ## If read_gencode_genes() was already ran on the same release, ## will reuse previously downloaded annotations -read_gencode_transcripts("./references", release = "42", timeout = 3000) +read_gencode_transcripts(file.path(tempdir(), "reference"), release = "42", timeout = 3000) } diff --git a/r/man/read_ucsc_chrom_sizes.Rd b/r/man/read_ucsc_chrom_sizes.Rd index 6cb99488..5a74310a 100644 --- a/r/man/read_ucsc_chrom_sizes.Rd +++ b/r/man/read_ucsc_chrom_sizes.Rd @@ -27,5 +27,5 @@ chromosome. The underlying data is pulled from here: \url{https://hgdownload.soe.ucsc.edu/downloads.html} } \examples{ -read_ucsc_chrom_sizes("./reference") +read_ucsc_chrom_sizes(file.path(tempdir(), "reference")) } diff --git a/r/man/trackplot_coverage.Rd b/r/man/trackplot_coverage.Rd index 4d3d3f29..8b58053f 100644 --- a/r/man/trackplot_coverage.Rd +++ b/r/man/trackplot_coverage.Rd @@ -45,8 +45,6 @@ for GRanges and false for other formats (see this \href{https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} \item{return_data}{If true, return data from just before plotting rather than a plot.} - -\item{scale_bar}{Whether to include a scale bar in the top track (\code{TRUE} or \code{FALSE})} } \value{ Returns a combined plot of pseudobulk genome tracks. For compatability with diff --git a/r/man/write_insertion_bedgraph.Rd b/r/man/write_insertion_bedgraph.Rd index c8767023..e8f471b3 100644 --- a/r/man/write_insertion_bedgraph.Rd +++ b/r/man/write_insertion_bedgraph.Rd @@ -75,7 +75,7 @@ write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all.tar.gz")) list.files(bedgraph_outputs) # With tiling -chrom_sizes <- read_ucsc_chrom_sizes("./reference", genome="hg38") \%>\% +chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "reference"), genome="hg38") \%>\% dplyr::filter(chr \%in\% c("chr4", "chr11")) write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all_tiled.bedGraph"), chrom_sizes = chrom_sizes, normalization_method = "cpm", tile_width = 100) diff --git a/r/vignettes/pbmc3k.Rmd b/r/vignettes/pbmc3k.Rmd index c2b98bd2..b897e538 100644 --- a/r/vignettes/pbmc3k.Rmd +++ b/r/vignettes/pbmc3k.Rmd @@ -239,7 +239,7 @@ the name of a directory to save the files in. This also allows us to skip re-dow the same files next time. ```{r} genes <- read_gencode_transcripts( - "./references", + file.path(tempdir(), "references"), release="42", transcript_choice="MANE_Select", annotation_set = "basic", @@ -249,12 +249,12 @@ head(genes) ``` ```{r} -blacklist <- read_encode_blacklist("./references", genome="hg38") +blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") head(blacklist) ``` ```{r} -chrom_sizes <- read_ucsc_chrom_sizes("./references", genome="hg38") +chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "referencs"), genome="hg38") head(chrom_sizes) ``` @@ -778,7 +778,7 @@ coverage_plot This is much more useful with a gene annotation track added in. For this we'll get a set of canonical transcripts (one per gene) from Gencode ```{r} -transcripts <- read_gencode_transcripts("./references", release="42") +transcripts <- read_gencode_transcripts("references", release="42") head(transcripts) ``` From 33d8b8c21d499ca3c6441078143013351edc4ecf Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 21 Oct 2025 16:21:21 -0700 Subject: [PATCH 09/84] [r] add in all styling fixes for CRAN --- r/.Rbuildignore | 2 - r/NAMESPACE | 1 + r/R/fragments.R | 82 +++++++-- r/R/matrix.R | 122 ++++++++++++-- r/R/matrix_stats.R | 39 ++++- r/R/transforms.R | 15 +- r/man/IterableFragments-methods.Rd | 35 ++++ r/man/IterableFragments-misc-methods.Rd | 119 +++++++++++++ r/man/IterableMatrix-matrixgenerics.Rd | 35 ++++ r/man/IterableMatrix-methods.Rd | 162 +++++++++++++++++- r/man/IterableMatrix-misc-methods.Rd | 211 ++++++++++++++++++++++++ r/man/LinearOperator-math.Rd | 39 +++++ r/man/fragment_R_conversion.Rd | 37 ++++- r/man/matrix_R_conversion.Rd | 30 +++- r/pkgdown/_pkgdown.yml | 4 +- 15 files changed, 878 insertions(+), 55 deletions(-) create mode 100644 r/man/IterableFragments-misc-methods.Rd create mode 100644 r/man/IterableMatrix-matrixgenerics.Rd create mode 100644 r/man/IterableMatrix-misc-methods.Rd create mode 100644 r/man/LinearOperator-math.Rd diff --git a/r/.Rbuildignore b/r/.Rbuildignore index 5f4bbfbf..9644e694 100644 --- a/r/.Rbuildignore +++ b/r/.Rbuildignore @@ -7,7 +7,6 @@ ^pkgdown$ ^.*\.Rproj$ ^\.Rproj\.user$ -^LICENSE$ ^\.idea @@ -26,4 +25,3 @@ cmake-build-debug/ \.vscode/ \.snakemake/ - diff --git a/r/NAMESPACE b/r/NAMESPACE index 799ed795..53f0dc9c 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -144,6 +144,7 @@ export(write_matrix_anndata_hdf5_dense) export(write_matrix_dir) export(write_matrix_hdf5) export(write_matrix_memory) +exportMethods("dimnames<-") exportMethods(as.data.frame) exportMethods(as.matrix) exportMethods(t) diff --git a/r/R/fragments.R b/r/R/fragments.R index 9733d6a7..a79a039b 100644 --- a/r/R/fragments.R +++ b/r/R/fragments.R @@ -10,6 +10,12 @@ #' #' Methods for IterableFragments objects #' +#' @param x an IterableFragments object +#' @param ... Additional arguments (not used unless specified) +#' @param row.names Optional row names for compatibility with `as.data.frame()`. +#' Ignored by IterableFragments methods. +#' @param optional Logical flag for compatibility with `as.data.frame()`; ignored. +#' @param value Replacement value (when applicable). #' @name IterableFragments-methods #' @rdname IterableFragments-methods NULL @@ -96,6 +102,7 @@ setMethod("show", "IterableFragments", function(object) { #' #' @export setGeneric("cellNames", function(x) standardGeneric("cellNames")) +#' @describeIn IterableFragments-methods Get cell names for IterableFragments setMethod("cellNames", "IterableFragments", function(x) { if (.hasSlot(x, "fragments")) { return(cellNames(x@fragments)) @@ -119,6 +126,7 @@ setMethod("cellNames", "IterableFragments", function(x) { #' #' @export setGeneric("cellNames<-", function(x, ..., value) standardGeneric("cellNames<-")) +#' @describeIn IterableFragments-methods Set cell names for IterableFragments setMethod("cellNames<-", "IterableFragments", function(x, ..., value) { if (is.null(cellNames(x))) { stop("Assigning new cellNames is not allowed, only renaming") @@ -141,6 +149,7 @@ setMethod("cellNames<-", "IterableFragments", function(x, ..., value) { #' #' @export setGeneric("chrNames", function(x) standardGeneric("chrNames")) +#' @describeIn IterableFragments-methods Get chromosome names for IterableFragments setMethod("chrNames", "IterableFragments", function(x) { if (.hasSlot(x, "fragments")) { return(chrNames(x@fragments)) @@ -163,6 +172,7 @@ setMethod("chrNames", "IterableFragments", function(x) { #' #' @export setGeneric("chrNames<-", function(x, ..., value) standardGeneric("chrNames<-")) +#' @describeIn IterableFragments-methods Set chromosome names for IterableFragments setMethod("chrNames<-", "IterableFragments", function(x, ..., value) { if (is.null(chrNames(x))) { stop("Assigning new chrNames is not allowed, only renaming") @@ -184,7 +194,9 @@ setClass("FragmentsTsv", comment = "" ) ) +#' @describeIn IterableFragments-misc-methods Get chromosome names for FragmentsTsv setMethod("chrNames", "FragmentsTsv", function(x) NULL) +#' @describeIn IterableFragments-misc-methods Get cell names for FragmentsTsv setMethod("cellNames", "FragmentsTsv", function(x) NULL) setMethod("iterate_fragments", "FragmentsTsv", function(x) iterate_10x_fragments_cpp(normalizePath(x@path), x@comment)) @@ -306,7 +318,9 @@ setClass("UnpackedMemFragments", version = character(0) ) ) +#' @describeIn IterableFragments-misc-methods Get chromosome names for UnpackedMemFragments setMethod("chrNames", "UnpackedMemFragments", function(x) x@chr_names) +#' @describeIn IterableFragments-misc-methods Get cell names for UnpackedMemFragments setMethod("cellNames", "UnpackedMemFragments", function(x) x@cell_names) setMethod("iterate_fragments", "UnpackedMemFragments", function(x) { iterate_unpacked_fragments_cpp(x) @@ -352,7 +366,9 @@ setClass("PackedMemFragments", version = character(0) ) ) +#' @describeIn IterableFragments-misc-methods Get chromosome names for PackedMemFragments setMethod("chrNames", "PackedMemFragments", function(x) x@chr_names) +#' @describeIn IterableFragments-misc-methods Get cell names for PackedMemFragments setMethod("cellNames", "PackedMemFragments", function(x) x@cell_names) setMethod("iterate_fragments", "PackedMemFragments", function(x) { iterate_packed_fragments_cpp(x) @@ -424,7 +440,9 @@ setClass("FragmentsDir", cell_names = character(0) ) ) +#' @describeIn IterableFragments-misc-methods Get chromosome names for FragmentsDir setMethod("chrNames", "FragmentsDir", function(x) x@chr_names) +#' @describeIn IterableFragments-misc-methods Get cell names for FragmentsDir setMethod("cellNames", "FragmentsDir", function(x) x@cell_names) setMethod("iterate_fragments", "FragmentsDir", function(x) { if (x@compressed) { @@ -534,7 +552,9 @@ setClass("FragmentsHDF5", cell_names = character(0) ) ) +#' @describeIn IterableFragments-misc-methods Get chromosome names for FragmentsHDF5 setMethod("chrNames", "FragmentsHDF5", function(x) x@chr_names) +#' @describeIn IterableFragments-misc-methods Get cell names for FragmentsHDF5 setMethod("cellNames", "FragmentsHDF5", function(x) x@cell_names) setMethod("iterate_fragments", "FragmentsHDF5", function(x) { if (x@compressed) { @@ -658,27 +678,27 @@ open_fragments_hdf5 <- function(path, group = "fragments", buffer_size = 16384L) #' GRanges, BPCells assumes a 0-based, end-exclusive coordinate system. (See #' [genomic-ranges-like] reference for details) #' -#' @aliases as.data.frame +#' @details Coercions rely on base R's `as()`; for example `as(frags, "data.frame")` +#' converts BPCells fragments back to a tabular format, while `as(x, "IterableFragments")` +#' materialises supported R objects as fragment stores. Coercions to and from +#' `GRanges` require the GenomicRanges package to be installed. #' -#' @usage -#' # Convert from R to BPCells -#' convert_to_fragments(x, zero_based_coords = !is(x, "GRanges")) -#' as(x, "IterableFragments") -#' -#' # Convert from BPCells to R -#' as.data.frame(x, ...) -#' as(x, "data.frame") -#' as(x, "GRanges") +#' @aliases as.data.frame.IterableFragments #' #' @param x `r document_granges("Fragment coordinates", extras=c("cell_id" = "cell barcodes or unique identifiers as string or factor"))` #' @param IterableFragments BPCells IterableFragments object #' @param data.frame Data frame with columns chr, start, end, and cell_id #' @param GRanges GenomicRanges object with metadata column cell_id +#' @param from Object supplied to `base::coerce()` (typically generated by `as()`) +#' @param to Target class name for coercion #' @param zero_based_coords Whether to convert the ranges from a 1-based end-inclusive #' coordinate system to a 0-based end-exclusive coordinate system. Defaults to true #' for GRanges and false for other formats #' (see this [archived UCSC blogpost](https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/)) #' @param ... Additional arguments passed to methods +#' @param row.names Optional row names for compatibility with `as.data.frame()`. +#' Ignored for IterableFragments objects. +#' @param optional Logical flag for compatibility with `as.data.frame()`; ignored. #' @return **convert_to_fragments()**: IterableFragments object #' @examples #' frags_table <- tibble::tibble( @@ -722,6 +742,33 @@ open_fragments_hdf5 <- function(path, group = "fragments", buffer_size = 16384L) #' frags_granges #' #' +#' @rdname fragment_R_conversion +#' @name fragment_R_conversion_coercions +#' @aliases coerce,data.frame,IterableFragments-method +#' @aliases coerce,IterableFragments,data.frame-method +#' @aliases coerce,GRanges,IterableFragments-method +#' @aliases coerce,IterableFragments,GRanges-method +#' @usage +#' \method{as.data.frame}{IterableFragments}(x, row.names = NULL, optional = FALSE, ...) +#' \S4method{coerce}{data.frame,IterableFragments}(from, to, ...) +#' \S4method{coerce}{IterableFragments,data.frame}(from, to, ...) +#' \S4method{coerce}{IterableFragments,GRanges}(from, to, ...) +#' \S4method{coerce}{GRanges,IterableFragments}(from, to, ...) +NULL + +#' IterableFragments subclass methods +#' +#' Methods defined for classes that extend `IterableFragments`, providing access +#' to metadata or specialised behaviours for storage backends and selection +#' wrappers. +#' +#' @param x An object inheriting from `IterableFragments`. +#' @name IterableFragments-misc-methods +#' @rdname IterableFragments-misc-methods +#' @docType methods +#' @keywords internal +NULL + #' @rdname fragment_R_conversion #' @export convert_to_fragments <- function(x, zero_based_coords = !is(x, "GRanges")) { @@ -801,9 +848,11 @@ setAs("IterableFragments", "data.frame", function(from) { }) #' @exportS3Method base::as.data.frame -as.data.frame.IterableFragments <- function(x, ...) as(x, "data.frame") +as.data.frame.IterableFragments <- function(x, row.names = NULL, optional = FALSE, ...) as(x, "data.frame") #' @export +#' @describeIn IterableFragments-methods Coerce IterableFragments to a data.frame setMethod("as.data.frame", signature(x = "IterableFragments"), function(x, ...) as(x, "data.frame")) + setAs("data.frame", "IterableFragments", function(from) { convert_to_fragments(from) }) @@ -935,6 +984,7 @@ setClass("ChrSelectName", chr_names = character(0) ) ) +#' @describeIn IterableFragments-misc-methods Get chromosome names for ChrSelectName setMethod("chrNames", "ChrSelectName", function(x) x@chr_names) setMethod("iterate_fragments", "ChrSelectName", function(x) { iterate_chr_name_select_cpp(iterate_fragments(x@fragments), x@chr_names) @@ -960,6 +1010,7 @@ setClass("ChrSelectIndex", chr_index_selection = NA_integer_ ) ) +#' @describeIn IterableFragments-misc-methods Get chromosome names for ChrSelectIndex setMethod("chrNames", "ChrSelectIndex", function(x) chrNames(x@fragments)[x@chr_index_selection]) setMethod("iterate_fragments", "ChrSelectIndex", function(x) { iterate_chr_index_select_cpp(iterate_fragments(x@fragments), x@chr_index_selection - 1) @@ -1038,6 +1089,7 @@ setClass("CellSelectName", cell_names = character(0) ) ) +#' @describeIn IterableFragments-misc-methods Get cell names for CellSelectName setMethod("cellNames", "CellSelectName", function(x) x@cell_names) setMethod("iterate_fragments", "CellSelectName", function(x) { iterate_cell_name_select_cpp(iterate_fragments(x@fragments), x@cell_names) @@ -1063,6 +1115,7 @@ setClass("CellSelectIndex", cell_index_selection = NA_integer_ ) ) +#' @describeIn IterableFragments-misc-methods Get cell names for CellSelectIndex setMethod("cellNames", "CellSelectIndex", function(x) cellNames(x@fragments)[x@cell_index_selection]) setMethod("iterate_fragments", "CellSelectIndex", function(x) { iterate_cell_index_select_cpp(iterate_fragments(x@fragments), x@cell_index_selection - 1) @@ -1138,6 +1191,7 @@ setClass("CellMerge", group_names = character(0) ) ) +#' @describeIn IterableFragments-misc-methods Get cell names for CellMerge setMethod("cellNames", "CellMerge", function(x) x@group_names) setMethod("iterate_fragments", "CellMerge", function(x) { iterate_cell_merge_cpp(iterate_fragments(x@fragments), x@group_ids, x@group_names) @@ -1196,6 +1250,7 @@ setClass("ChrRename", chr_names = character(0) ) ) +#' @describeIn IterableFragments-misc-methods Get chromosome names for ChrRename setMethod("chrNames", "ChrRename", function(x) x@chr_names) setMethod("iterate_fragments", "ChrRename", function(x) { iterate_chr_rename_cpp(iterate_fragments(x@fragments), x@chr_names) @@ -1219,6 +1274,7 @@ setClass("CellRename", cell_names = character(0) ) ) +#' @describeIn IterableFragments-misc-methods Get cell names for CellRename setMethod("cellNames", "CellRename", function(x) x@cell_names) setMethod("iterate_fragments", "CellRename", function(x) { iterate_cell_rename_cpp(iterate_fragments(x@fragments), x@cell_names) @@ -1241,6 +1297,7 @@ setClass("CellPrefix", prefix = "" ) ) +#' @describeIn IterableFragments-misc-methods Get cell names for CellPrefix setMethod("cellNames", "CellPrefix", function(x) { if (is.null(cellNames(x@fragments))) return(NULL) paste0(x@prefix, cellNames(x@fragments)) @@ -1376,9 +1433,11 @@ setClass("MergeFragments", fragments_list = list() ) ) +#' @describeIn IterableFragments-misc-methods Get chromosome names for MergeFragments setMethod("chrNames", "MergeFragments", function(x) { Reduce(union, lapply(x@fragments_list, chrNames)) }) +#' @describeIn IterableFragments-misc-methods Get cell names for MergeFragments setMethod("cellNames", "MergeFragments", function(x) { do.call(c, lapply(x@fragments_list, cellNames)) }) @@ -1396,6 +1455,7 @@ setMethod("short_description", "MergeFragments", function(x) { }) # Allow merging fragments using standard concatenation method +#' @describeIn IterableFragments-methods Concatenate IterableFragments objects setMethod("c", "IterableFragments", function(x, ...) { tail <- list(...) if (length(tail) == 1 && is.null(tail[[1]])) { diff --git a/r/R/matrix.R b/r/R/matrix.R index cee98952..f7766be5 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -10,10 +10,35 @@ #' #' Generic methods and built-in functions for IterableMatrix objects #' +#' @param ... Additional arguments passed to methods +#' @param digits Number of decimal places for quantile calculations +#' @param i Row indices or selection helpers. +#' @param j Column indices or selection helpers. +#' @param drop Logical indicating whether to drop dimensions when subsetting. +#' @param value Replacement value supplied to assignment methods. #' @name IterableMatrix-methods #' @rdname IterableMatrix-methods NULL +#' IterableMatrix subclass methods +#' +#' Methods for classes that extend `IterableMatrix` but are not dispatched +#' directly on the base class. These are typically helper objects that wrap +#' another matrix or alter behaviour (e.g., concatenation, on-disk access). +#' +#' @param x An object inheriting from `IterableMatrix`. +#' @param i Row indices or selection helpers. +#' @param j Column indices or selection helpers. +#' @param drop Logical indicating whether to drop dimensions (for subsetting). +#' @param e1 Left operand for binary operations. +#' @param e2 Right operand for binary operations. +#' @param ... Additional arguments passed through the call. +#' @name IterableMatrix-misc-methods +#' @rdname IterableMatrix-misc-methods +#' @docType methods +#' @keywords internal +NULL + setClass("IterableMatrix", slots = c( dim = "numeric", @@ -74,7 +99,7 @@ setGeneric("iterate_matrix", function(x) standardGeneric("iterate_matrix")) #' @export setGeneric("matrix_type", function(x) standardGeneric("matrix_type")) -#' @describeIn IterableMatrix-methods Get the matrix storage order ("row" or "col") +#' @describeIn IterableMatrix-methods Get the matrix storage order ("row" or "col") (generic) #' @examples #' ####################################################################### #' ## storage_order() example @@ -85,6 +110,7 @@ setGeneric("matrix_type", function(x) standardGeneric("matrix_type")) #' @export setGeneric("storage_order", function(x) standardGeneric("storage_order")) +#' @describeIn IterableMatrix-methods Get the matrix storage order ("row" or "col") setMethod("storage_order", "IterableMatrix", function(x) if(x@transpose) "row" else "col") #' Return a list of input matrices to the current matrix (experimental) @@ -264,6 +290,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "matrix"), function(x, y) { res }) +#' @describeIn IterableMatrix-methods Multiply a dense matrix by an IterableMatrix setMethod("%*%", signature(x = "matrix", y = "IterableMatrix"), function(x, y) { iter <- iterate_matrix(convert_matrix_type(y, "double")) if (y@transpose) { @@ -276,6 +303,7 @@ setMethod("%*%", signature(x = "matrix", y = "IterableMatrix"), function(x, y) { res }) +#' @describeIn IterableMatrix-methods Multiply an IterableMatrix by a numeric vector setMethod("%*%", signature(x = "IterableMatrix", y = "numeric"), function(x, y) { iter <- iterate_matrix(convert_matrix_type(x, "double")) if (x@transpose) { @@ -288,6 +316,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "numeric"), function(x, y) res }) +#' @describeIn IterableMatrix-methods Multiply a numeric row vector by an IterableMatrix setMethod("%*%", signature(x = "numeric", y = "IterableMatrix"), function(x, y) { iter <- iterate_matrix(convert_matrix_type(y, "double")) if (y@transpose) { @@ -328,6 +357,18 @@ linear_operator <- function(mat) { new("LinearOperator", dim = dim(mat), xptr = iterate_matrix(convert_matrix_type(mat, "double")), transpose = mat@transpose) } +#' LinearOperator multiplication helpers +#' +#' Methods enabling `\%*%` between `LinearOperator` objects and dense matrices or numeric vectors. +#' +#' @param x Left operand. +#' @param y Right operand. +#' @name LinearOperator-math +#' @docType methods +#' @keywords internal +NULL + +#' @describeIn LinearOperator-math Multiply a LinearOperator by a dense matrix setMethod("%*%", signature(x = "LinearOperator", y = "matrix"), function(x, y) { if (x@transpose) { return(t(dense_multiply_left_preserve_loader_cpp(x@xptr, t(y)))) @@ -336,6 +377,7 @@ setMethod("%*%", signature(x = "LinearOperator", y = "matrix"), function(x, y) { } }) +#' @describeIn LinearOperator-math Multiply a dense matrix by a LinearOperator setMethod("%*%", signature(x = "matrix", y = "LinearOperator"), function(x, y) { if (y@transpose) { return(t(dense_multiply_right_preserve_loader_cpp(y@xptr, t(x)))) @@ -344,6 +386,7 @@ setMethod("%*%", signature(x = "matrix", y = "LinearOperator"), function(x, y) { } }) +#' @describeIn LinearOperator-math Multiply a LinearOperator by a numeric vector setMethod("%*%", signature(x = "LinearOperator", y = "numeric"), function(x, y) { if (x@transpose) { return(vec_multiply_left_preserve_loader_cpp(x@xptr, y)) @@ -352,6 +395,7 @@ setMethod("%*%", signature(x = "LinearOperator", y = "numeric"), function(x, y) } }) +#' @describeIn LinearOperator-math Multiply a numeric vector by a LinearOperator setMethod("%*%", signature(x = "numeric", y = "LinearOperator"), function(x, y) { if (y@transpose) { return(vec_multiply_right_preserve_loader_cpp(y@xptr, x)) @@ -373,6 +417,7 @@ setClass("MatrixMultiply", right = NULL ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for MatrixMultiply objects setMethod("matrix_type", signature(x = "MatrixMultiply"), function(x) matrix_type(x@left)) setMethod("matrix_inputs", "MatrixMultiply", function(x) list(x@left, x@right)) setMethod("matrix_inputs<-", "MatrixMultiply", function(x, ..., value) { @@ -406,6 +451,7 @@ setMethod("short_description", "MatrixMultiply", function(x) { } }) +#' @describeIn IterableMatrix-methods Multiply two IterableMatrix objects setMethod("%*%", signature(x = "IterableMatrix", y = "IterableMatrix"), function(x, y) { if (x@transpose != y@transpose) stop("Cannot multiply matrices with different internal transpose states.\nPlease use transpose_storage_order().") if (x@transpose) { @@ -425,6 +471,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "IterableMatrix"), function new("MatrixMultiply", left = x, right = y, transpose = FALSE, dim = dim, dimnames = dimnames) }) +#' @describeIn IterableMatrix-methods Multiply an IterableMatrix by a dgCMatrix setMethod("%*%", signature(x = "IterableMatrix", y = "dgCMatrix"), function(x, y) { if (x@transpose) { t(as(t(y), "IterableMatrix") %*% t(x)) @@ -433,6 +480,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "dgCMatrix"), function(x, y } }) +#' @describeIn IterableMatrix-methods Multiply a dgCMatrix by an IterableMatrix setMethod("%*%", signature(x = "dgCMatrix", y = "IterableMatrix"), function(x, y) { if (y@transpose) { t(t(y) %*% as(t(x), "IterableMatrix")) @@ -443,6 +491,7 @@ setMethod("%*%", signature(x = "dgCMatrix", y = "IterableMatrix"), function(x, y # Subsetting on MatrixMultiply +#' @describeIn IterableMatrix-misc-methods Subset MatrixMultiply results setMethod("[", "MatrixMultiply", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") # Handle transpose via recursive call @@ -478,6 +527,7 @@ setClass("MatrixMask", invert = FALSE ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for MatrixMask objects setMethod("matrix_type", signature(x = "MatrixMask"), function(x) matrix_type(x@matrix)) setMethod("matrix_inputs", "MatrixMask", function(x) list(x@matrix, x@mask)) setMethod("matrix_inputs<-", "MatrixMask", function(x, ..., value) { @@ -544,6 +594,7 @@ setClass("MatrixRankTransform", matrix = NULL ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for MatrixRankTransform objects setMethod("matrix_type", signature(x = "MatrixRankTransform"), function(x) "double") setMethod("iterate_matrix", "MatrixRankTransform", function(x) { iter_function <- get(sprintf("iterate_matrix_rank_%s_cpp", matrix_type(x@matrix))) @@ -699,7 +750,7 @@ rlang::on_load({ } }) -#' @describeIn IterableMatrix-methods Calculate rowVars (replacement for `matrixStats::rowVars()`) +#' @describeIn IterableMatrix-methods Calculate rowVars (replacement for `matrixStats::rowVars()`) (generic) #' @return * `rowVars()`: vector of row variance #' @export rowVars <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) UseMethod("rowVars") @@ -715,6 +766,7 @@ rowVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = } } #' @export +#' @describeIn IterableMatrix-methods Calculate rowVars (replacement for `matrixStats::rowVars()`) #' @method rowVars IterableMatrix rowVars.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (!is.null(rows) || !is.null(cols) || !isFALSE(na.rm) || !is.null(center) || !isTRUE(useNames)) { @@ -731,7 +783,7 @@ rlang::on_load({ #' Get the max of each row in an iterable matrix #' @param x IterableMatrix object/dgCMatrix object #' @return * `rowMaxs()`: vector of maxes for every row -#' @describeIn IterableMatrix-methods Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) +#' @describeIn IterableMatrix-methods Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) (generic) #' @examples #' ####################################################################### #' ## rowMaxs() example @@ -754,6 +806,7 @@ rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., use } } #' @export +#' @describeIn IterableMatrix-methods Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) #' @method rowMaxs IterableMatrix rowMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if(!is.null(rows) || !is.null(cols) || !isFALSE(na.rm)) { @@ -832,6 +885,7 @@ setClass("MatrixSubset", zero_dims = c(FALSE, FALSE) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for MatrixSubset objects setMethod("matrix_type", signature(x = "MatrixSubset"), function(x) matrix_type(x@matrix)) # Helper function to convert logical/character indexing into numeric indexing @@ -885,6 +939,7 @@ unsplit_selection <- function(selection) { selection$subset[selection$reorder] } +#' @describeIn IterableMatrix-methods Subset an IterableMatrix setMethod("[", "IterableMatrix", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") if (rlang::is_missing(i) && rlang::is_missing(j)) { @@ -921,6 +976,7 @@ setMethod("[", "IterableMatrix", function(x, i, j, ...) { # Simulate assigning to a subset of the matrix. # We concatenate the un-modified matrix subsets with the new values, # then reorder rows/columns appropriately +#' @describeIn IterableMatrix-methods Assign into an IterableMatrix setMethod("[<-", "IterableMatrix", function(x, i, j, ..., value) { # Do type conversions if needed if (is.matrix(value)) value <- as(value, "dgCMatrix") @@ -982,6 +1038,7 @@ setMethod("[<-", "IterableMatrix", function(x, i, j, ..., value) { return(x) }) +#' @describeIn IterableMatrix-misc-methods Subset MatrixSubset transforms setMethod("[", "MatrixSubset", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") @@ -1063,6 +1120,7 @@ setClass("RenameDims", matrix = "IterableMatrix" ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for RenameDims objects setMethod("matrix_type", "RenameDims", function(x) matrix_type(x@matrix)) setMethod("iterate_matrix", "RenameDims", function(x) { if (x@transpose) { @@ -1077,6 +1135,7 @@ setMethod("iterate_matrix", "RenameDims", function(x) { iter_function(iterate_matrix(x@matrix), row_names, col_names, is.null(rownames(x)), is.null(colnames(x))) }) +#' @describeIn IterableMatrix-misc-methods Subset RenameDims transforms setMethod("[", "RenameDims", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") @@ -1099,6 +1158,9 @@ setMethod("short_description", "RenameDims", function(x) { sprintf("Reset dimnames") ) }) +#' @export +#' @param value New dimnames (list of length 2, or NULL) +#' @describeIn IterableMatrix-methods Set dimnames of an IterableMatrix, similar to base R `dimnames<-()` setMethod("dimnames<-", signature(x = "IterableMatrix", value = "list"), function(x, value) { if (identical(dimnames(x), value)) return(x) d <- dim(x) @@ -1123,6 +1185,8 @@ setMethod("dimnames<-", signature(x = "IterableMatrix", value = "list"), functio } x }) +#' @export +#' @describeIn IterableMatrix-methods Remove dimnames of an IterableMatrix setMethod("dimnames<-", signature(x = "IterableMatrix", value = "NULL"), function(x, value) { if (identical(dimnames(x), value)) return(x) if (!is(x, "RenameDims")) { @@ -1178,6 +1242,7 @@ setClass("RowBindMatrices", threads = 0L ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for RowBindMatrices objects setMethod("matrix_type", signature(x = "RowBindMatrices"), function(x) matrix_type(x@matrix_list[[1]])) setMethod("iterate_matrix", "RowBindMatrices", function(x) { @@ -1286,6 +1351,7 @@ setClass("ColBindMatrices", threads = 0L ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for ColBindMatrices objects setMethod("matrix_type", signature(x = "ColBindMatrices"), function(x) matrix_type(x@matrix_list[[1]])) setMethod("iterate_matrix", "ColBindMatrices", function(x) { @@ -1368,6 +1434,7 @@ setMethod("cbind2", signature(x = "IterableMatrix", y = "dgCMatrix"), function(x setMethod("cbind2", signature(x = "dgCMatrix", y = "IterableMatrix"), function(x, y, ...) cbind2(as(x, "IterableMatrix"), y)) # Row bind needs specialization because there's not a default row-seek operation +#' @describeIn IterableMatrix-misc-methods Subset RowBindMatrices transforms setMethod("[", "RowBindMatrices", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") # Handle transpose via recursive call @@ -1438,6 +1505,7 @@ setMethod("[", "RowBindMatrices", function(x, i, j, ...) { return(x) }) +#' @describeIn IterableMatrix-misc-methods Subset ColBindMatrices transforms setMethod("[", "ColBindMatrices", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") # Handle transpose via recursive call @@ -1588,6 +1656,7 @@ setClass("PackedMatrixMem_uint32_t", val_idx_offsets = numeric(0) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for PackedMatrixMem_uint32_t objects setMethod("matrix_type", "PackedMatrixMem_uint32_t", function(x) "uint32_t") setMethod("iterate_matrix", "PackedMatrixMem_uint32_t", function(x) { if (x@transpose) x <- t(x) @@ -1600,6 +1669,7 @@ setClass("PackedMatrixMem_float", slots = c(val = "integer"), prototype = list(val = integer(0)) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for PackedMatrixMem_float objects setMethod("matrix_type", "PackedMatrixMem_float", function(x) "float") setMethod("iterate_matrix", "PackedMatrixMem_float", function(x) { if (x@transpose) x <- t(x) @@ -1612,6 +1682,7 @@ setClass("PackedMatrixMem_double", slots = c(val = "numeric"), prototype = list(val = numeric(0)) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for PackedMatrixMem_double objects setMethod("matrix_type", "PackedMatrixMem_double", function(x) "double") setMethod("iterate_matrix", "PackedMatrixMem_double", function(x) { if (x@transpose) x <- t(x) @@ -1643,6 +1714,7 @@ setClass("UnpackedMatrixMem_uint32_t", slots = c(val = "integer"), prototype = list(val = integer()) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for UnpackedMatrixMem_uint32_t objects setMethod("matrix_type", "UnpackedMatrixMem_uint32_t", function(x) "uint32_t") setMethod("iterate_matrix", "UnpackedMatrixMem_uint32_t", function(x) { if (x@transpose) x <- t(x) @@ -1655,6 +1727,7 @@ setClass("UnpackedMatrixMem_float", slots = c(val = "integer"), prototype = list(val = integer(0)) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for UnpackedMatrixMem_float objects setMethod("matrix_type", "UnpackedMatrixMem_float", function(x) "float") setMethod("iterate_matrix", "UnpackedMatrixMem_float", function(x) { if (x@transpose) x <- t(x) @@ -1667,6 +1740,7 @@ setClass("UnpackedMatrixMem_double", slots = c(val = "numeric"), prototype = list(val = numeric(0)) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for UnpackedMatrixMem_double objects setMethod("matrix_type", "UnpackedMatrixMem_double", function(x) "double") setMethod("iterate_matrix", "UnpackedMatrixMem_double", function(x) { if (x@transpose) x <- t(x) @@ -1810,6 +1884,7 @@ setClass("MatrixDir", type = character(0) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for MatrixDir objects setMethod("matrix_type", "MatrixDir", function(x) x@type) setMethod("matrix_inputs", "MatrixDir", function(x) list()) @@ -1928,6 +2003,7 @@ setClass("EXPERIMENTAL_MatrixDirCompressedCol", buffer_size = integer(0) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for EXPERIMENTAL_MatrixDirCompressedCol objects setMethod("matrix_type", "EXPERIMENTAL_MatrixDirCompressedCol", function(x) "uint32_t") setMethod("matrix_inputs", "EXPERIMENTAL_MatrixDirCompressedCol", function(x) list()) @@ -2031,6 +2107,7 @@ setClass("MatrixH5", type = character(0) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for MatrixH5 objects setMethod("matrix_type", "MatrixH5", function(x) x@type) setMethod("matrix_inputs", "MatrixH5", function(x) list()) @@ -2168,6 +2245,7 @@ setClass("10xMatrixH5", buffer_size = integer(0) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for 10xMatrixH5 objects setMethod("matrix_type", "10xMatrixH5", function(x) x@type) setMethod("matrix_inputs", "10xMatrixH5", function(x) list()) setMethod("iterate_matrix", "10xMatrixH5", function(x) { @@ -2367,6 +2445,7 @@ setClass("AnnDataMatrixH5", buffer_size = integer(0) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for AnnDataMatrixH5 objects setMethod("matrix_type", "AnnDataMatrixH5", function(x) x@type) setMethod("matrix_inputs", "AnnDataMatrixH5", function(x) list()) setMethod("iterate_matrix", "AnnDataMatrixH5", function(x) { @@ -2615,6 +2694,7 @@ setClass("PeakMatrix", mode = "insertions" ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for PeakMatrix objects setMethod("matrix_type", "PeakMatrix", function(x) "uint32_t") setMethod("matrix_inputs", "PeakMatrix", function(x) list()) @@ -2706,6 +2786,7 @@ setMethod("short_description", "PeakMatrix", function(x) { ) }) +#' @describeIn IterableMatrix-misc-methods Subset a PeakMatrix setMethod("[", "PeakMatrix", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") # Handle transpose via recursive call @@ -2757,6 +2838,7 @@ setClass("TileMatrix", mode = character(0) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for TileMatrix objects setMethod("matrix_type", "TileMatrix", function(x) "uint32_t") setMethod("matrix_inputs", "TileMatrix", function(x) list()) @@ -2884,6 +2966,7 @@ setMethod("short_description", "TileMatrix", function(x) { ) }) +#' @describeIn IterableMatrix-misc-methods Subset a TileMatrix setMethod("[", "TileMatrix", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") @@ -2936,6 +3019,7 @@ setClass("ConvertMatrixType", type = character(0) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for ConvertMatrixType objects setMethod("matrix_type", signature(x = "ConvertMatrixType"), function(x) x@type) setMethod("iterate_matrix", "ConvertMatrixType", function(x) { iter_function <- get(sprintf("convert_matrix_%s_%s_cpp", matrix_type(x@matrix), matrix_type(x))) @@ -2949,6 +3033,7 @@ setMethod("short_description", "ConvertMatrixType", function(x) { ) }) +#' @describeIn IterableMatrix-misc-methods Subset ConvertMatrixType transforms setMethod("[", "ConvertMatrixType", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") @@ -3005,19 +3090,18 @@ convert_matrix_type <- function(matrix, type = c("uint32_t", "double", "float")) #' dgCMatrix sparse matrices, as well as base R #' dense matrices (though this may result in high memory usage for large matrices) #' -#' @aliases as.matrix +#' @aliases as.matrix.IterableMatrix +#' @aliases as.matrix,IterableMatrix-method #' -#' @usage -#' # Convert to R from BPCells -#' as(x, "dgCMatrix") # Sparse matrix conversion -#' as.matrix(x, ...) # Dense matrix conversion -#' -#' # Convert to BPCells from R -#' as(x, "IterableMatrix") +#' @details Use base R's `as()` to convert between BPCells matrices and +#' `dgCMatrix`/`matrix` representations, while `as.matrix()` materialises +#' dense matrices directly when needed. #' @param x Matrix object to convert #' @param dgCMatrix Sparse matrix in dgCMatrix format #' @param IterableMatrix IterableMatrix object #' @param ... Additional arguments passed to methods +#' @param from Object supplied to `base::coerce()` (typically generated by `as()`) +#' @param to Target class name for coercion #' @examples #' mat <- get_demo_mat()[1:2, 1:2] #' mat @@ -3042,6 +3126,20 @@ convert_matrix_type <- function(matrix, type = c("uint32_t", "double", "float")) #' as(mat_dgc, "IterableMatrix") #' #' +#' @rdname matrix_R_conversion +#' @name matrix_R_conversion_coercions +#' @aliases coerce,dgCMatrix,IterableMatrix-method +#' @aliases coerce,IterableMatrix,dgCMatrix-method +#' @aliases coerce,matrix,IterableMatrix-method +#' @aliases coerce,IterableMatrix,matrix-method +#' @usage +#' \method{as.matrix}{IterableMatrix}(x, ...) +#' \S4method{coerce}{dgCMatrix,IterableMatrix}(from, to, ...) +#' \S4method{coerce}{IterableMatrix,dgCMatrix}(from, to, ...) +#' \S4method{coerce}{matrix,IterableMatrix}(from, to, ...) +#' \S4method{coerce}{IterableMatrix,matrix}(from, to, ...) +NULL + #' @name matrix_R_conversion NULL @@ -3054,6 +3152,7 @@ setClass("Iterable_dgCMatrix_wrapper", mat = NULL ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for Iterable_dgCMatrix_wrapper objects setMethod("matrix_type", signature(x = "Iterable_dgCMatrix_wrapper"), function(x) "double") setMethod("matrix_inputs", "Iterable_dgCMatrix_wrapper", function(x) list()) @@ -3400,4 +3499,3 @@ apply_by_col <- function(mat, fun, ...) { } apply_matrix_double_cpp(iterate_matrix(convert_matrix_type(mat, "double")), f, FALSE) } - diff --git a/r/R/matrix_stats.R b/r/R/matrix_stats.R index 98c916d7..d846ddfc 100644 --- a/r/R/matrix_stats.R +++ b/r/R/matrix_stats.R @@ -17,7 +17,7 @@ #' @param drop (Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects). #' @return - `rowQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of rows in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. -#' @describeIn IterableMatrix-methods Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) +#' @describeIn IterableMatrix-methods Calculate rowQuantiles (generic) #' @usage rowQuantiles( #' x, #' rows = NULL, @@ -60,6 +60,7 @@ rowQuantiles.default <- function(x, rows = NULL, cols = NULL, } #' @export #' @method rowQuantiles IterableMatrix +#' @describeIn IterableMatrix-methods Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -101,8 +102,7 @@ rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, #' Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. #' @return - `colQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of columns in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. -#' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) -#' @inheritParams rowQuantiles +#' @describeIn IterableMatrix-methods Calculate colQuantiles (generic) #' @usage colQuantiles( #' x, #' rows = NULL, @@ -144,6 +144,7 @@ colQuantiles.default <- function(x, rows = NULL, cols = NULL, } } #' @export +#' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) colQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -186,4 +187,34 @@ rlang::on_load({ setMethod(MatrixGenerics::colQuantiles, "IterableMatrix", colQuantiles.IterableMatrix) setMethod(MatrixGenerics::rowQuantiles, "IterableMatrix", rowQuantiles.IterableMatrix) } -}) \ No newline at end of file +}) + +#' MatrixGenerics methods for IterableMatrix +#' +#' S4 methods enabling MatrixGenerics generics (e.g., \code{rowQuantiles}, +#' \code{colQuantiles}, \code{rowVars}, \code{colVars}, \code{rowMaxs}, \code{colMaxs}) +#' to operate on \code{IterableMatrix}. These are registered at runtime only +#' when MatrixGenerics is available. +#' +#' @section Availability: +#' Methods are registered conditionally; if MatrixGenerics is not installed, +#' nothing is registered and the generics fall back as usual. +#' +#' @param x An \code{IterableMatrix}. +#' @param ... Passed to the underlying implementation. +#' +#' @name IterableMatrix-matrixgenerics +#' @docType methods +#' +#' @aliases rowQuantiles,IterableMatrix-method +#' @aliases colQuantiles,IterableMatrix-method +#' @aliases rowVars,IterableMatrix-method +#' @aliases colVars,IterableMatrix-method +#' @aliases rowMaxs,IterableMatrix-method +#' @aliases colMaxs,IterableMatrix-method +#' +#' @seealso \code{\link{rowQuantiles}}, \code{\link{colQuantiles}}, +#' \code{\link{rowVars}}, \code{\link{colVars}}, +#' \code{\link{rowMaxs}}, \code{\link{colMaxs}} +#' @keywords internal +NULL \ No newline at end of file diff --git a/r/R/transforms.R b/r/R/transforms.R index 3c3a21ba..d7275b50 100644 --- a/r/R/transforms.R +++ b/r/R/transforms.R @@ -20,9 +20,11 @@ setClass("TransformedMatrix", global_params = numeric(0) ) ) +#' @describeIn IterableMatrix-misc-methods Matrix data type for TransformedMatrix objects setMethod("matrix_type", "TransformedMatrix", function(x) "double") # Subsetting on TransformedMatrix objects +#' @describeIn IterableMatrix-misc-methods Subset TransformedMatrix results setMethod("[", "TransformedMatrix", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") # Handle transpose via recursive call @@ -368,7 +370,7 @@ binarize <- function(mat, threshold=0, strict_inequality=TRUE) { global_params=c(threshold, strict_inequality)) convert_matrix_type(res, "uint32_t") } - +#' @describeIn IterableMatrix-methods Perform matrix < numeric comparison (unsupported) setMethod("<", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { stop("matrix < numeric not supported for IterableMatrix objects") }) @@ -396,10 +398,11 @@ setMethod("<", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) setMethod(">", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { binarize(e1, threshold=e2, strict_inequality=TRUE) }) +#' @describeIn IterableMatrix-methods Perform numeric > matrix comparison (unsupported) setMethod(">", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) { stop("numeric > matrix not supported for IterableMatrix objects") }) - +#' @describeIn IterableMatrix-methods Perform matrix <= numeric comparison (unsupported) setMethod("<=", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { stop("matrix <= numeric not supported for IterableMatrix objects") }) @@ -425,6 +428,7 @@ setMethod("<=", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) setMethod(">=", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { binarize(e1, threshold=e2, strict_inequality=FALSE) }) +#' @describeIn IterableMatrix-methods Compare a numeric value to an IterableMatrix using >= (numeric left operand) setMethod(">=", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) { stop("numeric >= matrix not supported for IterableMatrix objects") }) @@ -726,6 +730,7 @@ setMethod("*", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2 e1 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e1, "double")) e1 * e2 }) +#' @describeIn IterableMatrix-methods Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) setMethod("*", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2) { e2 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e2, "double")) e2 * e1 @@ -747,6 +752,7 @@ setMethod("+", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2 e1 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e1, "double")) e1 + e2 }) +#' @describeIn IterableMatrix-methods Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) setMethod("+", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2) { if (all(e1 == 0)) return(e2) e2 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e2, "double")) @@ -783,11 +789,13 @@ setMethod("/", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2 setMethod("-", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2) { e1 + (-e2) }) +#' @describeIn IterableMatrix-methods Subtract matrix from a numeric constant/vector setMethod("-", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2) { e2 * -1 + e1 }) # Full dispatch for scaling/shifting +#' @describeIn IterableMatrix-misc-methods Scale TransformScaleShift results by numeric values setMethod("*", signature(e1 = "TransformScaleShift", e2 = "numeric"), function(e1, e2) { # Convenience renaming - x is matrix, y is vector/scalar x <- e1 @@ -859,6 +867,7 @@ setMethod("*", signature(e1 = "TransformScaleShift", e2 = "numeric"), function(e } return(x) }) +#' @describeIn IterableMatrix-misc-methods Shift TransformScaleShift results by numeric values setMethod("+", signature(e1 = "TransformScaleShift", e2 = "numeric"), function(e1, e2) { if (all(e2 == 0)) return(e1) # Convenience renaming - x is matrix, y is vector/scalar @@ -897,9 +906,11 @@ setMethod("+", signature(e1 = "TransformScaleShift", e2 = "numeric"), function(e return(x) }) # Just take advantage of commutative property to only implement half +#' @describeIn IterableMatrix-misc-methods Apply numeric scaling on the left to TransformScaleShift results setMethod("*", signature(e1 = "numeric", e2 = "TransformScaleShift"), function(e1, e2) { e2 * e1 }) +#' @describeIn IterableMatrix-misc-methods Add TransformScaleShift results to numeric values (numeric left operand) setMethod("+", signature(e1 = "numeric", e2 = "TransformScaleShift"), function(e1, e2) { e2 + e1 }) diff --git a/r/man/IterableFragments-methods.Rd b/r/man/IterableFragments-methods.Rd index 4d00e60c..a98e68de 100644 --- a/r/man/IterableFragments-methods.Rd +++ b/r/man/IterableFragments-methods.Rd @@ -4,20 +4,38 @@ \alias{IterableFragments-methods} \alias{show,IterableFragments-method} \alias{cellNames} +\alias{cellNames,IterableFragments-method} \alias{cellNames<-} +\alias{cellNames<-,IterableFragments-method} \alias{chrNames} +\alias{chrNames,IterableFragments-method} \alias{chrNames<-} +\alias{chrNames<-,IterableFragments-method} +\alias{as.data.frame,IterableFragments-method} +\alias{c,IterableFragments-method} \title{IterableFragments methods} \usage{ \S4method{show}{IterableFragments}(object) cellNames(x) +\S4method{cellNames}{IterableFragments}(x) + cellNames(x, ...) <- value +\S4method{cellNames}{IterableFragments}(x, ...) <- value + chrNames(x) +\S4method{chrNames}{IterableFragments}(x) + chrNames(x, ...) <- value + +\S4method{chrNames}{IterableFragments}(x, ...) <- value + +\S4method{as.data.frame}{IterableFragments}(x, row.names = NULL, optional = FALSE, ...) + +\S4method{c}{IterableFragments}(x, ...) } \arguments{ \item{object}{IterableFragments object} @@ -27,6 +45,11 @@ chrNames(x, ...) <- value \item{...}{Additional arguments (not used)} \item{value}{Character vector of new names} + +\item{row.names}{Optional row names for compatibility with \code{as.data.frame()}. +Ignored by IterableFragments methods.} + +\item{optional}{Logical flag for compatibility with \code{as.data.frame()}; ignored.} } \value{ \itemize{ @@ -55,12 +78,24 @@ Methods for IterableFragments objects \item \code{cellNames()}: Get cell names +\item \code{cellNames(IterableFragments)}: Get cell names for IterableFragments + \item \code{cellNames(x, ...) <- value}: Set cell names +\item \code{cellNames(IterableFragments) <- value}: Set cell names for IterableFragments + \item \code{chrNames()}: Set chromosome names +\item \code{chrNames(IterableFragments)}: Get chromosome names for IterableFragments + \item \code{chrNames(x, ...) <- value}: Set chromosome names +\item \code{chrNames(IterableFragments) <- value}: Set chromosome names for IterableFragments + +\item \code{as.data.frame(IterableFragments)}: Coerce IterableFragments to a data.frame + +\item \code{c(IterableFragments)}: Concatenate IterableFragments objects + }} \examples{ ## Prep data diff --git a/r/man/IterableFragments-misc-methods.Rd b/r/man/IterableFragments-misc-methods.Rd new file mode 100644 index 00000000..0992a531 --- /dev/null +++ b/r/man/IterableFragments-misc-methods.Rd @@ -0,0 +1,119 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fragments.R +\docType{methods} +\name{chrNames,FragmentsTsv-method} +\alias{chrNames,FragmentsTsv-method} +\alias{cellNames,FragmentsTsv-method} +\alias{chrNames,UnpackedMemFragments-method} +\alias{cellNames,UnpackedMemFragments-method} +\alias{chrNames,PackedMemFragments-method} +\alias{cellNames,PackedMemFragments-method} +\alias{chrNames,FragmentsDir-method} +\alias{cellNames,FragmentsDir-method} +\alias{chrNames,FragmentsHDF5-method} +\alias{cellNames,FragmentsHDF5-method} +\alias{IterableFragments-misc-methods} +\alias{chrNames,ChrSelectName-method} +\alias{chrNames,ChrSelectIndex-method} +\alias{cellNames,CellSelectName-method} +\alias{cellNames,CellSelectIndex-method} +\alias{cellNames,CellMerge-method} +\alias{chrNames,ChrRename-method} +\alias{cellNames,CellRename-method} +\alias{cellNames,CellPrefix-method} +\alias{chrNames,MergeFragments-method} +\alias{cellNames,MergeFragments-method} +\title{IterableFragments subclass methods} +\usage{ +\S4method{chrNames}{FragmentsTsv}(x) + +\S4method{cellNames}{FragmentsTsv}(x) + +\S4method{chrNames}{UnpackedMemFragments}(x) + +\S4method{cellNames}{UnpackedMemFragments}(x) + +\S4method{chrNames}{PackedMemFragments}(x) + +\S4method{cellNames}{PackedMemFragments}(x) + +\S4method{chrNames}{FragmentsDir}(x) + +\S4method{cellNames}{FragmentsDir}(x) + +\S4method{chrNames}{FragmentsHDF5}(x) + +\S4method{cellNames}{FragmentsHDF5}(x) + +\S4method{chrNames}{ChrSelectName}(x) + +\S4method{chrNames}{ChrSelectIndex}(x) + +\S4method{cellNames}{CellSelectName}(x) + +\S4method{cellNames}{CellSelectIndex}(x) + +\S4method{cellNames}{CellMerge}(x) + +\S4method{chrNames}{ChrRename}(x) + +\S4method{cellNames}{CellRename}(x) + +\S4method{cellNames}{CellPrefix}(x) + +\S4method{chrNames}{MergeFragments}(x) + +\S4method{cellNames}{MergeFragments}(x) +} +\arguments{ +\item{x}{An object inheriting from \code{IterableFragments}.} +} +\description{ +Methods defined for classes that extend \code{IterableFragments}, providing access +to metadata or specialised behaviours for storage backends and selection +wrappers. +} +\section{Functions}{ +\itemize{ +\item \code{chrNames(FragmentsTsv)}: Get chromosome names for FragmentsTsv + +\item \code{cellNames(FragmentsTsv)}: Get cell names for FragmentsTsv + +\item \code{chrNames(UnpackedMemFragments)}: Get chromosome names for UnpackedMemFragments + +\item \code{cellNames(UnpackedMemFragments)}: Get cell names for UnpackedMemFragments + +\item \code{chrNames(PackedMemFragments)}: Get chromosome names for PackedMemFragments + +\item \code{cellNames(PackedMemFragments)}: Get cell names for PackedMemFragments + +\item \code{chrNames(FragmentsDir)}: Get chromosome names for FragmentsDir + +\item \code{cellNames(FragmentsDir)}: Get cell names for FragmentsDir + +\item \code{chrNames(FragmentsHDF5)}: Get chromosome names for FragmentsHDF5 + +\item \code{cellNames(FragmentsHDF5)}: Get cell names for FragmentsHDF5 + +\item \code{chrNames(ChrSelectName)}: Get chromosome names for ChrSelectName + +\item \code{chrNames(ChrSelectIndex)}: Get chromosome names for ChrSelectIndex + +\item \code{cellNames(CellSelectName)}: Get cell names for CellSelectName + +\item \code{cellNames(CellSelectIndex)}: Get cell names for CellSelectIndex + +\item \code{cellNames(CellMerge)}: Get cell names for CellMerge + +\item \code{chrNames(ChrRename)}: Get chromosome names for ChrRename + +\item \code{cellNames(CellRename)}: Get cell names for CellRename + +\item \code{cellNames(CellPrefix)}: Get cell names for CellPrefix + +\item \code{chrNames(MergeFragments)}: Get chromosome names for MergeFragments + +\item \code{cellNames(MergeFragments)}: Get cell names for MergeFragments + +}} +\keyword{internal} diff --git a/r/man/IterableMatrix-matrixgenerics.Rd b/r/man/IterableMatrix-matrixgenerics.Rd new file mode 100644 index 00000000..e0fb7526 --- /dev/null +++ b/r/man/IterableMatrix-matrixgenerics.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix_stats.R +\docType{methods} +\name{IterableMatrix-matrixgenerics} +\alias{IterableMatrix-matrixgenerics} +\alias{rowQuantiles,IterableMatrix-method} +\alias{colQuantiles,IterableMatrix-method} +\alias{rowVars,IterableMatrix-method} +\alias{colVars,IterableMatrix-method} +\alias{rowMaxs,IterableMatrix-method} +\alias{colMaxs,IterableMatrix-method} +\title{MatrixGenerics methods for IterableMatrix} +\arguments{ +\item{x}{An \code{IterableMatrix}.} + +\item{...}{Passed to the underlying implementation.} +} +\description{ +S4 methods enabling MatrixGenerics generics (e.g., \code{rowQuantiles}, +\code{colQuantiles}, \code{rowVars}, \code{colVars}, \code{rowMaxs}, \code{colMaxs}) +to operate on \code{IterableMatrix}. These are registered at runtime only +when MatrixGenerics is available. +} +\section{Availability}{ + +Methods are registered conditionally; if MatrixGenerics is not installed, +nothing is registered and the generics fall back as usual. +} + +\seealso{ +\code{\link{rowQuantiles}}, \code{\link{colQuantiles}}, +\code{\link{rowVars}}, \code{\link{colVars}}, +\code{\link{rowMaxs}}, \code{\link{colMaxs}} +} +\keyword{internal} diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods.Rd index b3488f94..fee00cca 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods.Rd @@ -4,45 +4,81 @@ \alias{IterableMatrix-methods} \alias{matrix_type} \alias{storage_order} +\alias{storage_order,IterableMatrix-method} \alias{show,IterableMatrix-method} \alias{t,IterableMatrix-method} \alias{\%*\%,IterableMatrix,matrix-method} +\alias{\%*\%,matrix,IterableMatrix-method} +\alias{\%*\%,IterableMatrix,numeric-method} +\alias{\%*\%,numeric,IterableMatrix-method} +\alias{\%*\%,IterableMatrix,IterableMatrix-method} +\alias{\%*\%,IterableMatrix,dgCMatrix-method} +\alias{\%*\%,dgCMatrix,IterableMatrix-method} \alias{rowSums,IterableMatrix-method} \alias{colSums,IterableMatrix-method} \alias{rowMeans,IterableMatrix-method} \alias{colMeans,IterableMatrix-method} \alias{colVars} \alias{rowVars} +\alias{rowVars.IterableMatrix} \alias{rowMaxs} +\alias{rowMaxs.IterableMatrix} \alias{colMaxs} +\alias{[,IterableMatrix,ANY,ANY,ANY-method} +\alias{[<-,IterableMatrix,ANY,ANY,ANY-method} +\alias{dimnames<-,IterableMatrix,list-method} +\alias{dimnames<-,IterableMatrix,NULL-method} \alias{rowQuantiles} +\alias{rowQuantiles.IterableMatrix} \alias{colQuantiles} +\alias{colQuantiles.IterableMatrix} \alias{log1p,IterableMatrix-method} \alias{log1p_slow} \alias{expm1,IterableMatrix-method} \alias{expm1_slow} \alias{^,IterableMatrix,numeric-method} +\alias{<,IterableMatrix,numeric-method} \alias{<,numeric,IterableMatrix-method} \alias{>,IterableMatrix,numeric-method} +\alias{>,numeric,IterableMatrix-method} +\alias{<=,IterableMatrix,numeric-method} \alias{<=,numeric,IterableMatrix-method} \alias{>=,IterableMatrix,numeric-method} +\alias{>=,numeric,IterableMatrix-method} \alias{round,IterableMatrix-method} \alias{*,IterableMatrix,numeric-method} +\alias{*,numeric,IterableMatrix-method} \alias{+,IterableMatrix,numeric-method} +\alias{+,numeric,IterableMatrix-method} \alias{/,IterableMatrix,numeric-method} \alias{-,IterableMatrix,numeric-method} +\alias{-,numeric,IterableMatrix-method} \title{IterableMatrix methods} \usage{ matrix_type(x) storage_order(x) +\S4method{storage_order}{IterableMatrix}(x) + \S4method{show}{IterableMatrix}(object) \S4method{t}{IterableMatrix}(x) \S4method{\%*\%}{IterableMatrix,matrix}(x, y) +\S4method{\%*\%}{matrix,IterableMatrix}(x, y) + +\S4method{\%*\%}{IterableMatrix,numeric}(x, y) + +\S4method{\%*\%}{numeric,IterableMatrix}(x, y) + +\S4method{\%*\%}{IterableMatrix,IterableMatrix}(x, y) + +\S4method{\%*\%}{IterableMatrix,dgCMatrix}(x, y) + +\S4method{\%*\%}{dgCMatrix,IterableMatrix}(x, y) + \S4method{rowSums}{IterableMatrix}(x) \S4method{colSums}{IterableMatrix}(x) @@ -71,10 +107,30 @@ rowVars( useNames = TRUE ) +\method{rowVars}{IterableMatrix}( + x, + rows = NULL, + cols = NULL, + na.rm = FALSE, + center = NULL, + ..., + useNames = TRUE +) + rowMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) +\method{rowMaxs}{IterableMatrix}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) + colMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) +\S4method{[}{IterableMatrix,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{[}{IterableMatrix,ANY,ANY,ANY}(x, i, j, ...) <- value + +\S4method{dimnames}{IterableMatrix,list}(x) <- value + +\S4method{dimnames}{IterableMatrix,NULL}(x) <- value + rowQuantiles( x, rows = NULL, @@ -88,6 +144,19 @@ rowQuantiles( drop = TRUE ) +\method{rowQuantiles}{IterableMatrix}( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) + colQuantiles( x, rows = NULL, @@ -101,6 +170,19 @@ colQuantiles( drop = TRUE ) +colQuantiles.IterableMatrix( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) + \S4method{log1p}{IterableMatrix}(x) log1p_slow(x) @@ -111,23 +193,37 @@ expm1_slow(x) \S4method{^}{IterableMatrix,numeric}(e1, e2) +\S4method{<}{IterableMatrix,numeric}(e1, e2) + \S4method{<}{numeric,IterableMatrix}(e1, e2) \S4method{>}{IterableMatrix,numeric}(e1, e2) +\S4method{>}{numeric,IterableMatrix}(e1, e2) + +\S4method{<=}{IterableMatrix,numeric}(e1, e2) + \S4method{<=}{numeric,IterableMatrix}(e1, e2) \S4method{>=}{IterableMatrix,numeric}(e1, e2) +\S4method{>=}{numeric,IterableMatrix}(e1, e2) + \S4method{round}{IterableMatrix}(x, digits = 0) \S4method{*}{IterableMatrix,numeric}(e1, e2) +\S4method{*}{numeric,IterableMatrix}(e1, e2) + \S4method{+}{IterableMatrix,numeric}(e1, e2) +\S4method{+}{numeric,IterableMatrix}(e1, e2) + \S4method{/}{IterableMatrix,numeric}(e1, e2) \S4method{-}{IterableMatrix,numeric}(e1, e2) + +\S4method{-}{numeric,IterableMatrix}(e1, e2) } \arguments{ \item{x}{IterableMatrix object or a matrix-like object.} @@ -144,13 +240,23 @@ expm1_slow(x) \item{center}{Optional center values (vector of length nrow(x) or ncol(x))} +\item{...}{Additional arguments passed to methods} + \item{useNames}{(Logical) Whether to use row and column names in the output.} +\item{i}{Row indices or selection helpers.} + +\item{j}{Column indices or selection helpers.} + +\item{drop}{(Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects).} + +\item{value}{New dimnames (list of length 2, or NULL)} + \item{probs}{(Numeric) Quantile value(s) to be computed, between 0 and 1.} \item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} -\item{drop}{(Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects).} +\item{digits}{Number of decimal places for quantile calculations} \item{e1}{First element of comparison} @@ -214,7 +320,9 @@ Generic methods and built-in functions for IterableMatrix objects \itemize{ \item \code{matrix_type()}: Get the matrix data type (mat_uint32_t, mat_float, or mat_double for now) -\item \code{storage_order()}: Get the matrix storage order ("row" or "col") +\item \code{storage_order()}: Get the matrix storage order ("row" or "col") (generic) + +\item \code{storage_order(IterableMatrix)}: Get the matrix storage order ("row" or "col") \item \code{show(IterableMatrix)}: Display an IterableMatrix @@ -222,6 +330,18 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{x \%*\% y}: Multiply by a dense matrix +\item \code{x \%*\% y}: Multiply a dense matrix by an IterableMatrix + +\item \code{x \%*\% y}: Multiply an IterableMatrix by a numeric vector + +\item \code{x \%*\% y}: Multiply a numeric row vector by an IterableMatrix + +\item \code{x \%*\% y}: Multiply two IterableMatrix objects + +\item \code{x \%*\% y}: Multiply an IterableMatrix by a dgCMatrix + +\item \code{x \%*\% y}: Multiply a dgCMatrix by an IterableMatrix + \item \code{rowSums(IterableMatrix)}: Calculate rowSums \item \code{colSums(IterableMatrix)}: Calculate colSums @@ -232,15 +352,31 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{colVars()}: Calculate colVars (replacement for \code{matrixStats::colVars()}) -\item \code{rowVars()}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) +\item \code{rowVars()}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) (generic) -\item \code{rowMaxs()}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) +\item \code{rowVars(IterableMatrix)}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) + +\item \code{rowMaxs()}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) (generic) + +\item \code{rowMaxs(IterableMatrix)}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) \item \code{colMaxs()}: Calculate colMax (replacement for \code{matrixStats::colMax()}) -\item \code{rowQuantiles()}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) +\item \code{x[i}: Subset an IterableMatrix + +\item \code{`[`(x = IterableMatrix, i = ANY, j = ANY) <- value}: Assign into an IterableMatrix + +\item \code{dimnames(x = IterableMatrix) <- value}: Set dimnames of an IterableMatrix, similar to base R \verb{dimnames<-()} + +\item \code{dimnames(x = IterableMatrix) <- value}: Remove dimnames of an IterableMatrix -\item \code{colQuantiles()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) +\item \code{rowQuantiles()}: Calculate rowQuantiles (generic) + +\item \code{rowQuantiles(IterableMatrix)}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) + +\item \code{colQuantiles()}: Calculate colQuantiles (generic) + +\item \code{colQuantiles.IterableMatrix()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) \item \code{log1p(IterableMatrix)}: Calculate log(x + 1) @@ -252,24 +388,38 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{e1^e2}: Calculate x^y (elementwise; y > 0) +\item \code{e1 < e2}: Perform matrix < numeric comparison (unsupported) + \item \code{e1 < e2}: Binarize matrix according to numeric < matrix comparison \item \code{e1 > e2}: Binarize matrix according to matrix > numeric comparison +\item \code{e1 > e2}: Perform numeric > matrix comparison (unsupported) + +\item \code{e1 <= e2}: Perform matrix <= numeric comparison (unsupported) + \item \code{e1 <= e2}: Binarize matrix according to numeric <= matrix comparison \item \code{e1 >= e2}: Binarize matrix according to matrix >= numeric comparison +\item \code{e1 >= e2}: Compare a numeric value to an IterableMatrix using >= (numeric left operand) + \item \code{round(IterableMatrix)}: round to nearest integer (digits must be 0) \item \code{e1 * e2}: Multiply by a constant, or multiply rows by a vector length nrow(mat) +\item \code{e1 * e2}: Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) + \item \code{e1 + e2}: Add a constant, or row-wise addition with a vector length nrow(mat) +\item \code{e1 + e2}: Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) + \item \code{e1 / e2}: Divide by a constant, or divide rows by a vector length nrow(mat) \item \code{e1 - e2}: Subtract a constant, or row-wise subtraction with a vector length nrow(mat) +\item \code{e1 - e2}: Subtract matrix from a numeric constant/vector + }} \examples{ ## Prep data diff --git a/r/man/IterableMatrix-misc-methods.Rd b/r/man/IterableMatrix-misc-methods.Rd new file mode 100644 index 00000000..e16f1d88 --- /dev/null +++ b/r/man/IterableMatrix-misc-methods.Rd @@ -0,0 +1,211 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix.R, R/transforms.R +\docType{methods} +\name{IterableMatrix-misc-methods} +\alias{IterableMatrix-misc-methods} +\alias{matrix_type,MatrixMultiply-method} +\alias{[,MatrixMultiply,ANY,ANY,ANY-method} +\alias{matrix_type,MatrixMask-method} +\alias{matrix_type,MatrixRankTransform-method} +\alias{matrix_type,MatrixSubset-method} +\alias{[,MatrixSubset,ANY,ANY,ANY-method} +\alias{matrix_type,RenameDims-method} +\alias{[,RenameDims,ANY,ANY,ANY-method} +\alias{matrix_type,RowBindMatrices-method} +\alias{matrix_type,ColBindMatrices-method} +\alias{[,RowBindMatrices,ANY,ANY,ANY-method} +\alias{[,ColBindMatrices,ANY,ANY,ANY-method} +\alias{matrix_type,PackedMatrixMem_uint32_t-method} +\alias{matrix_type,PackedMatrixMem_float-method} +\alias{matrix_type,PackedMatrixMem_double-method} +\alias{matrix_type,UnpackedMatrixMem_uint32_t-method} +\alias{matrix_type,UnpackedMatrixMem_float-method} +\alias{matrix_type,UnpackedMatrixMem_double-method} +\alias{matrix_type,MatrixDir-method} +\alias{matrix_type,EXPERIMENTAL_MatrixDirCompressedCol-method} +\alias{matrix_type,MatrixH5-method} +\alias{matrix_type,10xMatrixH5-method} +\alias{matrix_type,AnnDataMatrixH5-method} +\alias{matrix_type,PeakMatrix-method} +\alias{[,PeakMatrix,ANY,ANY,ANY-method} +\alias{matrix_type,TileMatrix-method} +\alias{[,TileMatrix,ANY,ANY,ANY-method} +\alias{matrix_type,ConvertMatrixType-method} +\alias{[,ConvertMatrixType,ANY,ANY,ANY-method} +\alias{matrix_type,Iterable_dgCMatrix_wrapper-method} +\alias{matrix_type,TransformedMatrix-method} +\alias{[,TransformedMatrix,ANY,ANY,ANY-method} +\alias{*,TransformScaleShift,numeric-method} +\alias{+,TransformScaleShift,numeric-method} +\alias{*,numeric,TransformScaleShift-method} +\alias{+,numeric,TransformScaleShift-method} +\title{IterableMatrix subclass methods} +\usage{ +\S4method{matrix_type}{MatrixMultiply}(x) + +\S4method{[}{MatrixMultiply,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{matrix_type}{MatrixMask}(x) + +\S4method{matrix_type}{MatrixRankTransform}(x) + +\S4method{matrix_type}{MatrixSubset}(x) + +\S4method{[}{MatrixSubset,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{matrix_type}{RenameDims}(x) + +\S4method{[}{RenameDims,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{matrix_type}{RowBindMatrices}(x) + +\S4method{matrix_type}{ColBindMatrices}(x) + +\S4method{[}{RowBindMatrices,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{[}{ColBindMatrices,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{matrix_type}{PackedMatrixMem_uint32_t}(x) + +\S4method{matrix_type}{PackedMatrixMem_float}(x) + +\S4method{matrix_type}{PackedMatrixMem_double}(x) + +\S4method{matrix_type}{UnpackedMatrixMem_uint32_t}(x) + +\S4method{matrix_type}{UnpackedMatrixMem_float}(x) + +\S4method{matrix_type}{UnpackedMatrixMem_double}(x) + +\S4method{matrix_type}{MatrixDir}(x) + +\S4method{matrix_type}{EXPERIMENTAL_MatrixDirCompressedCol}(x) + +\S4method{matrix_type}{MatrixH5}(x) + +\S4method{matrix_type}{10xMatrixH5}(x) + +\S4method{matrix_type}{AnnDataMatrixH5}(x) + +\S4method{matrix_type}{PeakMatrix}(x) + +\S4method{[}{PeakMatrix,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{matrix_type}{TileMatrix}(x) + +\S4method{[}{TileMatrix,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{matrix_type}{ConvertMatrixType}(x) + +\S4method{[}{ConvertMatrixType,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{matrix_type}{Iterable_dgCMatrix_wrapper}(x) + +\S4method{matrix_type}{TransformedMatrix}(x) + +\S4method{[}{TransformedMatrix,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{*}{TransformScaleShift,numeric}(e1, e2) + +\S4method{+}{TransformScaleShift,numeric}(e1, e2) + +\S4method{*}{numeric,TransformScaleShift}(e1, e2) + +\S4method{+}{numeric,TransformScaleShift}(e1, e2) +} +\arguments{ +\item{x}{An object inheriting from \code{IterableMatrix}.} + +\item{i}{Row indices or selection helpers.} + +\item{j}{Column indices or selection helpers.} + +\item{...}{Additional arguments passed through the call.} + +\item{drop}{Logical indicating whether to drop dimensions (for subsetting).} + +\item{e1}{Left operand for binary operations.} + +\item{e2}{Right operand for binary operations.} +} +\description{ +Methods for classes that extend \code{IterableMatrix} but are not dispatched +directly on the base class. These are typically helper objects that wrap +another matrix or alter behaviour (e.g., concatenation, on-disk access). +} +\section{Functions}{ +\itemize{ +\item \code{matrix_type(MatrixMultiply)}: Matrix data type for MatrixMultiply objects + +\item \code{x[i}: Subset MatrixMultiply results + +\item \code{matrix_type(MatrixMask)}: Matrix data type for MatrixMask objects + +\item \code{matrix_type(MatrixRankTransform)}: Matrix data type for MatrixRankTransform objects + +\item \code{matrix_type(MatrixSubset)}: Matrix data type for MatrixSubset objects + +\item \code{x[i}: Subset MatrixSubset transforms + +\item \code{matrix_type(RenameDims)}: Matrix data type for RenameDims objects + +\item \code{x[i}: Subset RenameDims transforms + +\item \code{matrix_type(RowBindMatrices)}: Matrix data type for RowBindMatrices objects + +\item \code{matrix_type(ColBindMatrices)}: Matrix data type for ColBindMatrices objects + +\item \code{x[i}: Subset RowBindMatrices transforms + +\item \code{x[i}: Subset ColBindMatrices transforms + +\item \code{matrix_type(PackedMatrixMem_uint32_t)}: Matrix data type for PackedMatrixMem_uint32_t objects + +\item \code{matrix_type(PackedMatrixMem_float)}: Matrix data type for PackedMatrixMem_float objects + +\item \code{matrix_type(PackedMatrixMem_double)}: Matrix data type for PackedMatrixMem_double objects + +\item \code{matrix_type(UnpackedMatrixMem_uint32_t)}: Matrix data type for UnpackedMatrixMem_uint32_t objects + +\item \code{matrix_type(UnpackedMatrixMem_float)}: Matrix data type for UnpackedMatrixMem_float objects + +\item \code{matrix_type(UnpackedMatrixMem_double)}: Matrix data type for UnpackedMatrixMem_double objects + +\item \code{matrix_type(MatrixDir)}: Matrix data type for MatrixDir objects + +\item \code{matrix_type(EXPERIMENTAL_MatrixDirCompressedCol)}: Matrix data type for EXPERIMENTAL_MatrixDirCompressedCol objects + +\item \code{matrix_type(MatrixH5)}: Matrix data type for MatrixH5 objects + +\item \code{matrix_type(`10xMatrixH5`)}: Matrix data type for 10xMatrixH5 objects + +\item \code{matrix_type(AnnDataMatrixH5)}: Matrix data type for AnnDataMatrixH5 objects + +\item \code{matrix_type(PeakMatrix)}: Matrix data type for PeakMatrix objects + +\item \code{x[i}: Subset a PeakMatrix + +\item \code{matrix_type(TileMatrix)}: Matrix data type for TileMatrix objects + +\item \code{x[i}: Subset a TileMatrix + +\item \code{matrix_type(ConvertMatrixType)}: Matrix data type for ConvertMatrixType objects + +\item \code{x[i}: Subset ConvertMatrixType transforms + +\item \code{matrix_type(Iterable_dgCMatrix_wrapper)}: Matrix data type for Iterable_dgCMatrix_wrapper objects + +\item \code{matrix_type(TransformedMatrix)}: Matrix data type for TransformedMatrix objects + +\item \code{x[i}: Subset TransformedMatrix results + +\item \code{e1 * e2}: Scale TransformScaleShift results by numeric values + +\item \code{e1 + e2}: Shift TransformScaleShift results by numeric values + +\item \code{e1 * e2}: Apply numeric scaling on the left to TransformScaleShift results + +\item \code{e1 + e2}: Add TransformScaleShift results to numeric values (numeric left operand) + +}} +\keyword{internal} diff --git a/r/man/LinearOperator-math.Rd b/r/man/LinearOperator-math.Rd new file mode 100644 index 00000000..e8e18f28 --- /dev/null +++ b/r/man/LinearOperator-math.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix.R +\docType{methods} +\name{LinearOperator-math} +\alias{LinearOperator-math} +\alias{\%*\%,LinearOperator,matrix-method} +\alias{\%*\%,matrix,LinearOperator-method} +\alias{\%*\%,LinearOperator,numeric-method} +\alias{\%*\%,numeric,LinearOperator-method} +\title{LinearOperator multiplication helpers} +\usage{ +\S4method{\%*\%}{LinearOperator,matrix}(x, y) + +\S4method{\%*\%}{matrix,LinearOperator}(x, y) + +\S4method{\%*\%}{LinearOperator,numeric}(x, y) + +\S4method{\%*\%}{numeric,LinearOperator}(x, y) +} +\arguments{ +\item{x}{Left operand.} + +\item{y}{Right operand.} +} +\description{ +Methods enabling \verb{\\\%*\%} between \code{LinearOperator} objects and dense matrices or numeric vectors. +} +\section{Functions}{ +\itemize{ +\item \code{x \%*\% y}: Multiply a LinearOperator by a dense matrix + +\item \code{x \%*\% y}: Multiply a dense matrix by a LinearOperator + +\item \code{x \%*\% y}: Multiply a LinearOperator by a numeric vector + +\item \code{x \%*\% y}: Multiply a numeric vector by a LinearOperator + +}} +\keyword{internal} diff --git a/r/man/fragment_R_conversion.Rd b/r/man/fragment_R_conversion.Rd index 6533da63..3abed3ac 100644 --- a/r/man/fragment_R_conversion.Rd +++ b/r/man/fragment_R_conversion.Rd @@ -1,18 +1,22 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/fragments.R -\name{convert_to_fragments} +\name{fragment_R_conversion_coercions} +\alias{fragment_R_conversion_coercions} +\alias{as.data.frame.IterableFragments} +\alias{coerce,data.frame,IterableFragments-method} +\alias{coerce,IterableFragments,data.frame-method} +\alias{coerce,GRanges,IterableFragments-method} +\alias{coerce,IterableFragments,GRanges-method} \alias{convert_to_fragments} -\alias{as.data.frame} \title{Convert between BPCells fragments and R objects.} \usage{ -# Convert from R to BPCells -convert_to_fragments(x, zero_based_coords = !is(x, "GRanges")) -as(x, "IterableFragments") +\method{as.data.frame}{IterableFragments}(x, row.names = NULL, optional = FALSE, ...) +\S4method{coerce}{data.frame,IterableFragments}(from, to, ...) +\S4method{coerce}{IterableFragments,data.frame}(from, to, ...) +\S4method{coerce}{IterableFragments,GRanges}(from, to, ...) +\S4method{coerce}{GRanges,IterableFragments}(from, to, ...) -# Convert from BPCells to R -as.data.frame(x, ...) -as(x, "data.frame") -as(x, "GRanges") +convert_to_fragments(x, zero_based_coords = !is(x, "GRanges")) } \arguments{ \item{x}{Fragment coordinates given as GRanges, data.frame, or list. See \code{help("genomic-ranges-like")} for details on format and coordinate systems. Required attributes: @@ -32,7 +36,16 @@ for GRanges and false for other formats \item{GRanges}{GenomicRanges object with metadata column cell_id} +\item{from}{Object supplied to \code{base::coerce()} (typically generated by \code{as()})} + +\item{to}{Target class name for coercion} + \item{...}{Additional arguments passed to methods} + +\item{row.names}{Optional row names for compatibility with \code{as.data.frame()}. +Ignored for IterableFragments objects.} + +\item{optional}{Logical flag for compatibility with \code{as.data.frame()}; ignored.} } \value{ \strong{convert_to_fragments()}: IterableFragments object @@ -44,6 +57,12 @@ The main conversion method is R's builtin \code{as()} function, though the GRanges, BPCells assumes a 0-based, end-exclusive coordinate system. (See \link{genomic-ranges-like} reference for details) } +\details{ +Coercions rely on base R's \code{as()}; for example \code{as(frags, "data.frame")} +converts BPCells fragments back to a tabular format, while \code{as(x, "IterableFragments")} +materialises supported R objects as fragment stores. Coercions to and from +\code{GRanges} require the GenomicRanges package to be installed. +} \examples{ frags_table <- tibble::tibble( chr = paste0("chr", 1:10), diff --git a/r/man/matrix_R_conversion.Rd b/r/man/matrix_R_conversion.Rd index 31923191..4f8da8b9 100644 --- a/r/man/matrix_R_conversion.Rd +++ b/r/man/matrix_R_conversion.Rd @@ -1,16 +1,21 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/matrix.R -\name{matrix_R_conversion} +\name{matrix_R_conversion_coercions} +\alias{matrix_R_conversion_coercions} +\alias{as.matrix.IterableMatrix} +\alias{as.matrix,IterableMatrix-method} +\alias{coerce,dgCMatrix,IterableMatrix-method} +\alias{coerce,IterableMatrix,dgCMatrix-method} +\alias{coerce,matrix,IterableMatrix-method} +\alias{coerce,IterableMatrix,matrix-method} \alias{matrix_R_conversion} -\alias{as.matrix} \title{Convert between BPCells matrix and R objects.} \usage{ -# Convert to R from BPCells -as(x, "dgCMatrix") # Sparse matrix conversion -as.matrix(x, ...) # Dense matrix conversion - -# Convert to BPCells from R -as(x, "IterableMatrix") +\method{as.matrix}{IterableMatrix}(x, ...) +\S4method{coerce}{dgCMatrix,IterableMatrix}(from, to, ...) +\S4method{coerce}{IterableMatrix,dgCMatrix}(from, to, ...) +\S4method{coerce}{matrix,IterableMatrix}(from, to, ...) +\S4method{coerce}{IterableMatrix,matrix}(from, to, ...) } \arguments{ \item{x}{Matrix object to convert} @@ -20,12 +25,21 @@ as(x, "IterableMatrix") \item{IterableMatrix}{IterableMatrix object} \item{...}{Additional arguments passed to methods} + +\item{from}{Object supplied to \code{base::coerce()} (typically generated by \code{as()})} + +\item{to}{Target class name for coercion} } \description{ BPCells matrices can be interconverted with Matrix package dgCMatrix sparse matrices, as well as base R dense matrices (though this may result in high memory usage for large matrices) } +\details{ +Use base R's \code{as()} to convert between BPCells matrices and +\code{dgCMatrix}/\code{matrix} representations, while \code{as.matrix()} materialises +dense matrices directly when needed. +} \examples{ mat <- get_demo_mat()[1:2, 1:2] mat diff --git a/r/pkgdown/_pkgdown.yml b/r/pkgdown/_pkgdown.yml index a8b2f2e9..2a99ab14 100644 --- a/r/pkgdown/_pkgdown.yml +++ b/r/pkgdown/_pkgdown.yml @@ -139,8 +139,9 @@ reference: - checksum - apply_by_row - regress_out - - IterableMatrix-methods - pseudobulk_matrix + - IterableMatrix-methods + - title: "Reference Annotations" - contents: @@ -193,3 +194,4 @@ reference: - title: "Data" - contents: - get_demo_mat + From 7681e32a10b47af867d0f6dbf7e1e053252ac899 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 21 Oct 2025 16:42:08 -0700 Subject: [PATCH 10/84] [r] add some small ci cleanup, version bump --- .github/workflows/deploy-docs.yml | 3 +++ .github/workflows/deploy-full-website.yml | 3 +++ .github/workflows/r-test.yml | 3 +++ r/DESCRIPTION | 4 ++-- r/NEWS.md | 24 +++++++++++++++-------- r/configure | 16 --------------- r/src/Makevars.in | 4 ++-- 7 files changed, 29 insertions(+), 28 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index a6b7bf67..9ffb6dac 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -24,6 +24,9 @@ jobs: cache-version: 1 working-directory: 'r' needs: website + extra-repositories: | + https://bioconductor.org/packages/release/data/annotation + https://bpcells.github.io/drat - name: Install BPCells run: | Rscript -e 'install.packages("r", repos=NULL, type="source")' diff --git a/.github/workflows/deploy-full-website.yml b/.github/workflows/deploy-full-website.yml index 64b4fd37..4ad61df5 100644 --- a/.github/workflows/deploy-full-website.yml +++ b/.github/workflows/deploy-full-website.yml @@ -22,6 +22,9 @@ jobs: cache-version: 1 working-directory: 'r' needs: website + extra-repositories: | + https://bioconductor.org/packages/release/data/annotation + https://bpcells.github.io/drat - name: Install BPCells run: | Rscript -e 'install.packages("r", repos=NULL, type="source")' diff --git a/.github/workflows/r-test.yml b/.github/workflows/r-test.yml index aadedf6d..2fe2e769 100644 --- a/.github/workflows/r-test.yml +++ b/.github/workflows/r-test.yml @@ -45,6 +45,9 @@ jobs: any::testthat any::decor working-directory: 'r' + extra-repositories: | + https://bioconductor.org/packages/release/data/annotation + https://bpcells.github.io/drat # Do a normal install rather than a pkgbuild-mediated install so we can control compilation flags via Makevars file - name: Install BPCells run: Rscript -e 'install.packages("r", repos=NULL, type="source")' diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 1f738599..e2e29800 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -1,6 +1,6 @@ Package: BPCells Title: Single Cell Counts Matrices to PCA -Version: 0.3.1 +Version: 0.3.2 Authors@R: c( person(given = "Benjamin", family = "Parks", @@ -73,7 +73,7 @@ Suggests: testthat (>= 3.0.0) Additional_repositories: https://bioconductor.org/packages/release/data/annotation, - https://immanuelazn.github.io/drat + https://bpcells.github.io/drat Depends: R (>= 4.0.0) SystemRequirements: C++17 diff --git a/r/NEWS.md b/r/NEWS.md index ad688a10..a79c2ee9 100644 --- a/r/NEWS.md +++ b/r/NEWS.md @@ -1,20 +1,28 @@ -# BPCells 0.4.0 (in-progress main branch) +# BPCells 0.4.0 (in-progress main branch) +## To-dos +- Add support for sparse pseudobulking in `pseudobulk_matrix()`. Currently in progress in #268. +- Add support for duplicate rows/cols in subsetting operations. +- Add support for matrix matrix addition. +- Maybe add CCA support? +- Refactor C++ backend to take in the logic in R S4 methods. This would allow for a cleaner seperation of R and C++ code, and would allow for much quicker porting + to Python in the future. + +# BPCells 0.3.2 +The BPCells 0.3.2 release covers 3 months of changes and 4 commits from @immanuelazn. +Most notably, this release prepares (finally!) BPCells for CRAN submission. This means that users can easily install BPCells using pre-compiled binaries, rather than having to compile from source. +Full details of changes below. ## Breaking changes - Change first parameter name of `cluster_graph_leiden()`, `cluster_graph_louvain()` and `cluster_graph_seurat()` from `snn` to `mat` to more accurately reflect the input type. (pull request #292) +## Improvements +- Prepare BPCells for CRAN submission by adjusting styling and adding additional documentation for S3/S4 methods of IterableMatrix/IterableFragments. (pull request #311) + ## Features - Create a wrapper function `cluster_cells_graph()` that wraps the steps of knn object creation, graph adjacency creation, and clustering all within a single function (pull request #292) - Add `tile_width` and `normalization` arguments to `write_insertion_bedgraph()` to allow for more flexible bedgraph creation (pull request #299) - Export `write_insertion_bed()`, which originally was only a helper for peak calling (pull request #302) -## To-dos -- Add support for sparse pseudobulking in `pseudobulk_matrix()`. Currently in progress in #268. -- Add support for duplicate rows/cols in subsetting operations. -- Add support for matrix matrix addition. -- Maybe add CCA support? -- Refactor C++ backend to take in the logic in R S4 methods. This would allow for a cleaner seperation of R and C++ code, and would allow for much quicker porting - to Python in the future. # BPCells 0.3.1 (7/21/2025) diff --git a/r/configure b/r/configure index b8f6e09e..9f11d979 100755 --- a/r/configure +++ b/r/configure @@ -222,21 +222,6 @@ else printf "\nFound working highway SIMD library\n" fi -############################ -# Compiler flag compatibility check -############################ - -OPTIONAL_CXXFLAGS="" - -# # Test for -Wno-ignored-attributes support -# if $CXX -xc++ -c -Wno-ignored-attributes /dev/null -o /dev/null 2>/dev/null; then -# OPTIONAL_CXXFLAGS="$OPTIONAL_CXXFLAGS -Wno-ignored-attributes" -# fi - -# # Test for -Wno-unknown-pragmas support -# if $CXX -xc++ -c -Wno-unknown-pragmas /dev/null -o /dev/null 2>/dev/null; then -# OPTIONAL_CXXFLAGS="$OPTIONAL_CXXFLAGS -Wno-unknown-pragmas" -# fi # Make substitutions in Makevars.in sed \ @@ -247,7 +232,6 @@ sed \ -e "s|%HWY_LIBS%|${HWY_LIBS}|g" \ -e "s|%ENV_CFLAGS%|${ENV_CFLAGS}|g" \ -e "s|%ENV_LDFLAGS%|${ENV_LDFLAGS}|g" \ - -e "s|%OPTIONAL_CXXFLAGS%|${OPTIONAL_CXXFLAGS}|g" \ src/Makevars.in > src/Makevars # Clean up highway build directory to avoid CRAN NOTE about object files diff --git a/r/src/Makevars.in b/r/src/Makevars.in index 42be685f..5b919ba1 100644 --- a/r/src/Makevars.in +++ b/r/src/Makevars.in @@ -1,9 +1,9 @@ # CXX_STD = CXX17 CXX_STD = CXX17 -PKG_CXXFLAGS = %HDF5_CFLAGS% %HWY_CFLAGS% %ENV_CFLAGS% -Ivendor -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS%OPTIONAL_CXXFLAGS% # -Wall -Wextra -Wpedantic +PKG_CXXFLAGS = %HDF5_CFLAGS% %HWY_CFLAGS% %ENV_CFLAGS% -Ivendor -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS # -Wall -Wextra -Wpedantic PKG_LIBS = -lz %HDF5_LIBS% %CXX_FS_FLAG% %HWY_LIBS% %ENV_LDFLAGS% -# PKG_CXXFLAGS = -Wno-deprecated-declarations -Wno-unused-but-set-variable -fsanitize=undefined %HDF5_CFLAGS% %HWY_CFLAGS% -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS%OPTIONAL_CXXFLAGS% # -Wall -Wextra -Wpedantic +# PKG_CXXFLAGS = -Wno-deprecated-declarations -Wno-unused-but-set-variable -fsanitize=undefined %HDF5_CFLAGS% %HWY_CFLAGS% -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS # -Wall -Wextra -Wpedantic # PKG_LIBS = -fsanitize=undefined -lz %HDF5_LIBS% %CXX_FS_FLAG% %HWY_LIBS% OBJECTS=\ From 9a8dd09037dc74fb959070eb2be9ff7ea3685db1 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 21 Oct 2025 16:57:43 -0700 Subject: [PATCH 11/84] [ci] move around r dependency flags for drat --- .github/workflows/deploy-full-website.yml | 9 +++++--- .github/workflows/r-test.yml | 6 +++--- r/src/Makevars.in | 25 +++++++++++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy-full-website.yml b/.github/workflows/deploy-full-website.yml index 4ad61df5..39a52c0b 100644 --- a/.github/workflows/deploy-full-website.yml +++ b/.github/workflows/deploy-full-website.yml @@ -16,15 +16,18 @@ jobs: run: bash -c 'echo -e "MAKEFLAGS=--jobs=3\nCXXFLAGS += -O1 -UNDEBUG" > "$GITHUB_WORKSPACE/Makevars.user" && echo "R_MAKEVARS_USER=$GITHUB_WORKSPACE/Makevars.user" >> "$GITHUB_ENV"' - name: Setup R uses: r-lib/actions/setup-r@v2 + with: + Ncpus: '3' + use-public-rspm: true + extra-repositories: | + https://bioconductor.org/packages/release/data/annotation + https://bpcells.github.io/drat - name: Install R dependencies uses: r-lib/actions/setup-r-dependencies@v2 with: cache-version: 1 working-directory: 'r' needs: website - extra-repositories: | - https://bioconductor.org/packages/release/data/annotation - https://bpcells.github.io/drat - name: Install BPCells run: | Rscript -e 'install.packages("r", repos=NULL, type="source")' diff --git a/.github/workflows/r-test.yml b/.github/workflows/r-test.yml index 2fe2e769..0af5c491 100644 --- a/.github/workflows/r-test.yml +++ b/.github/workflows/r-test.yml @@ -38,6 +38,9 @@ jobs: with: Ncpus: '3' use-public-rspm: true + extra-repositories: | + https://bioconductor.org/packages/release/data/annotation + https://bpcells.github.io/drat - uses: r-lib/actions/setup-r-dependencies@v2 with: cache-version: 1 @@ -45,9 +48,6 @@ jobs: any::testthat any::decor working-directory: 'r' - extra-repositories: | - https://bioconductor.org/packages/release/data/annotation - https://bpcells.github.io/drat # Do a normal install rather than a pkgbuild-mediated install so we can control compilation flags via Makevars file - name: Install BPCells run: Rscript -e 'install.packages("r", repos=NULL, type="source")' diff --git a/r/src/Makevars.in b/r/src/Makevars.in index 5b919ba1..dc403548 100644 --- a/r/src/Makevars.in +++ b/r/src/Makevars.in @@ -90,3 +90,28 @@ vendor/md5/md5.o \ # matrixIterators/MatrixOps.o \ # matrixIterators/PackedMatrix.o \ # matrixIterators/UnpackedMatrix.o \ + +# Automatically strip debug symbols from the shared library unless opted out +ifeq ($(strip $(BP_DISABLE_STRIP)),) +STRIP ?= $(shell "${R_HOME}/bin/R" CMD config STRIP 2>/dev/null) +ifeq ($(strip $(STRIP)),) +STRIP := $(shell command -v strip 2>/dev/null) +endif +STRIPFLAGS ?= --strip-debug +ifeq ($(shell uname -s 2>/dev/null),Darwin) +STRIPFLAGS := -S +endif + +ifeq ($(strip $(STRIP)),) +strip-shlib: $(SHLIB) + @echo "Skipping shared library stripping; no strip tool detected" +else +strip-shlib: $(SHLIB) + @echo "Stripping debug symbols from $(SHLIB)" + @$(STRIP) $(STRIPFLAGS) $(SHLIB) || true +endif + +.PHONY: strip-shlib +all: strip-shlib +endif + From 1a57cad53e71f9da4ab6adc454cfe8489c557bb2 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 21 Oct 2025 16:57:56 -0700 Subject: [PATCH 12/84] [ci] move around r dependency flags for drat --- .github/workflows/deploy-docs.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 9ffb6dac..29eb5ed6 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -18,15 +18,18 @@ jobs: run: bash -c 'echo -e "MAKEFLAGS=--jobs=3\nCXXFLAGS += -O1 -UNDEBUG" > "$GITHUB_WORKSPACE/Makevars.user" && echo "R_MAKEVARS_USER=$GITHUB_WORKSPACE/Makevars.user" >> "$GITHUB_ENV"' - name: Setup R uses: r-lib/actions/setup-r@v2 + with: + Ncpus: '3' + use-public-rspm: true + extra-repositories: | + https://bioconductor.org/packages/release/data/annotation + https://bpcells.github.io/drat - name: Install R dependencies uses: r-lib/actions/setup-r-dependencies@v2 with: cache-version: 1 working-directory: 'r' needs: website - extra-repositories: | - https://bioconductor.org/packages/release/data/annotation - https://bpcells.github.io/drat - name: Install BPCells run: | Rscript -e 'install.packages("r", repos=NULL, type="source")' From 60d8f2746f1ad641585efb58281718b1315e2a61 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 21 Oct 2025 17:31:37 -0700 Subject: [PATCH 13/84] [cpp] remove linker optimizations not allowed with cran --- r/src/Makevars.in | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/r/src/Makevars.in b/r/src/Makevars.in index dc403548..32f55be2 100644 --- a/r/src/Makevars.in +++ b/r/src/Makevars.in @@ -3,6 +3,8 @@ CXX_STD = CXX17 PKG_CXXFLAGS = %HDF5_CFLAGS% %HWY_CFLAGS% %ENV_CFLAGS% -Ivendor -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS # -Wall -Wextra -Wpedantic PKG_LIBS = -lz %HDF5_LIBS% %CXX_FS_FLAG% %HWY_LIBS% %ENV_LDFLAGS% + + # PKG_CXXFLAGS = -Wno-deprecated-declarations -Wno-unused-but-set-variable -fsanitize=undefined %HDF5_CFLAGS% %HWY_CFLAGS% -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS # -Wall -Wextra -Wpedantic # PKG_LIBS = -fsanitize=undefined -lz %HDF5_LIBS% %CXX_FS_FLAG% %HWY_LIBS% @@ -91,27 +93,4 @@ vendor/md5/md5.o \ # matrixIterators/PackedMatrix.o \ # matrixIterators/UnpackedMatrix.o \ -# Automatically strip debug symbols from the shared library unless opted out -ifeq ($(strip $(BP_DISABLE_STRIP)),) -STRIP ?= $(shell "${R_HOME}/bin/R" CMD config STRIP 2>/dev/null) -ifeq ($(strip $(STRIP)),) -STRIP := $(shell command -v strip 2>/dev/null) -endif -STRIPFLAGS ?= --strip-debug -ifeq ($(shell uname -s 2>/dev/null),Darwin) -STRIPFLAGS := -S -endif - -ifeq ($(strip $(STRIP)),) -strip-shlib: $(SHLIB) - @echo "Skipping shared library stripping; no strip tool detected" -else -strip-shlib: $(SHLIB) - @echo "Stripping debug symbols from $(SHLIB)" - @$(STRIP) $(STRIPFLAGS) $(SHLIB) || true -endif - -.PHONY: strip-shlib -all: strip-shlib -endif From b6088a2e4bf0750124d8fc6f095f07189ecb8c32 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 21 Oct 2025 17:49:02 -0700 Subject: [PATCH 14/84] [ci] check removing highway compilation from rbuildignore --- r/.Rbuildignore | 1 - 1 file changed, 1 deletion(-) diff --git a/r/.Rbuildignore b/r/.Rbuildignore index 9644e694..40bda369 100644 --- a/r/.Rbuildignore +++ b/r/.Rbuildignore @@ -13,7 +13,6 @@ ^\.cache$ ^bench$ ^vignettes$ -^tools/highway/ .*\.o$ .*\.so$ From 29c078c94fdcd12861372123a6217b03c8f50a82 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 21 Oct 2025 18:12:55 -0700 Subject: [PATCH 15/84] [ci] check removing highway compilation from configure --- r/configure | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/r/configure b/r/configure index 9f11d979..d6030c9d 100755 --- a/r/configure +++ b/r/configure @@ -234,12 +234,11 @@ sed \ -e "s|%ENV_LDFLAGS%|${ENV_LDFLAGS}|g" \ src/Makevars.in > src/Makevars -# Clean up highway build directory to avoid CRAN NOTE about object files -# The highway library will be rebuilt as needed during installation -rm -rf tools/highway/ +# # Clean up highway build directory to avoid CRAN NOTE about object files +# # The highway library will be rebuilt as needed during installation +# rm -rf tools/highway/ if [ "$ENABLE_INSTALL_COUNTING" = "yes" ]; then curl --silent https://plausible.benparks.net/flask-plausible/bpcells-configure-success > /dev/null 2> /dev/null \ || true fi - From cdca012a696ab0865b10697468f4f9eca0ca6718 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 21 Oct 2025 18:32:13 -0700 Subject: [PATCH 16/84] [cpp] test highway --- .../vendor/highway/manual-build/build_highway.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/r/src/vendor/highway/manual-build/build_highway.sh b/r/src/vendor/highway/manual-build/build_highway.sh index 1291c138..99c593f9 100644 --- a/r/src/vendor/highway/manual-build/build_highway.sh +++ b/r/src/vendor/highway/manual-build/build_highway.sh @@ -1,6 +1,20 @@ #!/usr/bin/env bash -set -euo pipefail +if [ -z "${BASH_VERSION:-}" ]; then + if command -v bash >/dev/null 2>&1; then + exec bash "$0" "$@" + else + echo "Error: bash is required to run this script" >&2 + exit 1 + fi +fi + +set -eu +if command -v bash >/dev/null 2>&1 && [ -n "$BASH_VERSION" ]; then + set -o pipefail +else + (set -o pipefail >/dev/null 2>&1) && set -o pipefail || true +fi # This is a fairly direct translation of the google/highway CMakeLists.txt from version 1.0.5 # https://github.com/google/highway/blob/1.0.5/CMakeLists.txt From a229baf83d12094003df335eb9be8427f15460a7 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 11:17:49 -0700 Subject: [PATCH 17/84] [cpp] check with adding tools/highway back into .Rbuildignore --- r/.Rbuildignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r/.Rbuildignore b/r/.Rbuildignore index 40bda369..ff5b61ba 100644 --- a/r/.Rbuildignore +++ b/r/.Rbuildignore @@ -7,7 +7,7 @@ ^pkgdown$ ^.*\.Rproj$ ^\.Rproj\.user$ - +^tools/highway$ ^\.idea ^\.cache$ From faf6c657dfea25d8c013d815d10ba23c7afb64e3 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 11:51:13 -0700 Subject: [PATCH 18/84] [ci] add cran check --- .github/workflows/check-standard-test.yaml | 80 ++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 .github/workflows/check-standard-test.yaml diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml new file mode 100644 index 00000000..bc88e4e9 --- /dev/null +++ b/.github/workflows/check-standard-test.yaml @@ -0,0 +1,80 @@ +name: R-CMD-check + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + workflow_dispatch: + +jobs: + R-CMD-check: + runs-on: ${{ matrix.os }} + name: ${{ matrix.os }} + timeout-minutes: 120 + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest, macos-13] + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + ENABLE_INSTALL_COUNTING: no + _R_CHECK_BUILD_VIGNETTES_: false + + steps: + - uses: actions/checkout@v4 + - name: Install binary dependencies on ubuntu + if: matrix.os == 'ubuntu-latest' + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y libhdf5-dev + + - name: Install binary dependencies on macOS + if: matrix.os == 'macos-latest' || matrix.os == 'macos-13' + shell: bash + run: | + brew update + brew install hdf5 + + - name: Configure compilation flags + shell: bash + run: | + cat <<'MAKEVARS' > "$GITHUB_WORKSPACE/Makevars.user" + MAKEFLAGS=--jobs=3 + MAKEVARS + echo "R_MAKEVARS_USER=$GITHUB_WORKSPACE/Makevars.user" >> "$GITHUB_ENV" + + - name: Handle Windows big object files + if: matrix.os == 'windows-latest' + shell: bash + run: | + echo "CXXFLAGS += -Wa,-mbig-obj" >> "$GITHUB_WORKSPACE/Makevars.user" + + - uses: r-lib/actions/setup-r@v2 + with: + Ncpus: '3' + use-public-rspm: true + extra-repositories: | + https://bioconductor.org/packages/release/data/annotation + https://bpcells.github.io/drat + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + cache-version: 1 + extra-packages: | + any::testthat + any::decor + working-directory: 'r' + needs: check + + - name: Check package + uses: r-lib/actions/check-r-package@v2 + with: + working-directory: r + args: 'c("--no-manual", "--no-build-vignettes")' + build-args: 'c("--no-manual", "--no-build-vignettes")' + upload-snapshots: true From 10d409d61f0986a5a8a67331274f7a82ec426186 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 11:52:35 -0700 Subject: [PATCH 19/84] [ci] cleanup cran check --- .github/workflows/check-standard-test.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index bc88e4e9..d1621c94 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -1,10 +1,8 @@ name: R-CMD-check on: - push: - branches: [main, master] pull_request: - branches: [main, master] + branches: [main] workflow_dispatch: jobs: From 8b53a66ff870259ad7b221431b4b82e69defa65d Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 12:00:41 -0700 Subject: [PATCH 20/84] [ci] cleanup cran check --- .github/workflows/check-standard-test.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index d1621c94..1ff682e8 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -73,6 +73,5 @@ jobs: uses: r-lib/actions/check-r-package@v2 with: working-directory: r - args: 'c("--no-manual", "--no-build-vignettes")' - build-args: 'c("--no-manual", "--no-build-vignettes")' + build_args: c("--no-build-vignettes") upload-snapshots: true From 846ace2e9c25a6deae9962351be4712c1a7ddd52 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 12:09:23 -0700 Subject: [PATCH 21/84] [r] wrap macs example in case ci doesn't have macs --- r/R/atac_utils.R | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index cfd7a734..e6edef6e 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -690,21 +690,23 @@ write_insertion_bed <- function(fragments, path, #' shell scripts generated at `/input/.sh`. Finally, run `call_peaks_macs()` again with the same original arguments, but #' setting `step="read-outputs"`. #' @examples -#' macs_files <- file.path(tempdir(), "peaks") -#' frags <- get_demo_frags() -#' -#' head(call_peaks_macs(frags, macs_files)) -#' -#' ## Can also just run the input prep, then run macs manually -#' ## by setting step to 'prep_inputs' -#' macs_script <- call_peaks_macs(frags, macs_files, step = "prep-inputs") -#' system2("bash", macs_script[1], stdout = FALSE, stderr = FALSE) -#' -#' ## Then read the narrow peaks files -#' list.files(file.path(macs_files, "output", "all")) -#' -#' ## call_peaks_macs() can also solely perform the output reading step -#' head(call_peaks_macs(frags, macs_files, step = "read-outputs")) +#' if (macs_path_is_valid()) { +#' macs_files <- file.path(tempdir(), "peaks") +#' frags <- get_demo_frags() +#' +#' head(call_peaks_macs(frags, macs_files)) +#' +#' ## Can also just run the input prep, then run macs manually +#' ## by setting step to 'prep_inputs' +#' macs_script <- call_peaks_macs(frags, macs_files, step = "prep-inputs") +#' system2("bash", macs_script[1], stdout = FALSE, stderr = FALSE) +#' +#' ## Then read the narrow peaks files +#' list.files(file.path(macs_files, "output", "all")) +#' +#' ## call_peaks_macs() can also solely perform the output reading step +#' head(call_peaks_macs(frags, macs_files, step = "read-outputs")) +#' } #' @inheritParams call_peaks_tile #' @export call_peaks_macs <- function(fragments, path, From bc971fd759a5194aa7d3c3b85a36e6c25f06c3a0 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 12:43:55 -0700 Subject: [PATCH 22/84] [r] wrap macs examples p2 --- r/R/atac_utils.R | 28 +++++++++++++--------------- r/man/call_peaks_macs.Rd | 2 ++ r/man/macs_path_is_valid.Rd | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index e6edef6e..be77c090 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -689,24 +689,22 @@ write_insertion_bed <- function(fragments, path, #' To run MACS manually, you will first run `call_peaks_macs()` with `step="prep-inputs`. Then, manually run all of the #' shell scripts generated at `/input/.sh`. Finally, run `call_peaks_macs()` again with the same original arguments, but #' setting `step="read-outputs"`. -#' @examples -#' if (macs_path_is_valid()) { -#' macs_files <- file.path(tempdir(), "peaks") -#' frags <- get_demo_frags() +#' @examplesIf tryCatch({ macs_path_is_valid(); TRUE }, error = function(e) FALSE) +#' macs_files <- file.path(tempdir(), "peaks") +#' frags <- get_demo_frags() #' -#' head(call_peaks_macs(frags, macs_files)) +#' head(call_peaks_macs(frags, macs_files)) #' -#' ## Can also just run the input prep, then run macs manually -#' ## by setting step to 'prep_inputs' -#' macs_script <- call_peaks_macs(frags, macs_files, step = "prep-inputs") -#' system2("bash", macs_script[1], stdout = FALSE, stderr = FALSE) +#' ## Can also just run the input prep, then run macs manually +#' ## by setting step to 'prep_inputs' +#' macs_script <- call_peaks_macs(frags, macs_files, step = "prep-inputs") +#' system2("bash", macs_script[1], stdout = FALSE, stderr = FALSE) #' -#' ## Then read the narrow peaks files -#' list.files(file.path(macs_files, "output", "all")) +#' ## Then read the narrow peaks files +#' list.files(file.path(macs_files, "output", "all")) #' -#' ## call_peaks_macs() can also solely perform the output reading step -#' head(call_peaks_macs(frags, macs_files, step = "read-outputs")) -#' } +#' ## call_peaks_macs() can also solely perform the output reading step +#' head(call_peaks_macs(frags, macs_files, step = "read-outputs")) #' @inheritParams call_peaks_tile #' @export call_peaks_macs <- function(fragments, path, @@ -833,7 +831,7 @@ call_macs_peaks <- function(...) { #' Test if MACS executable is valid. #' If macs_executable is NULL, this function will try to auto-detect MACS from PATH, with preference for MACS3 over MACS2. #' If macs_executable is provided, this function will check if MACS can be called. -#' @return MACS executable path. +#' @return MACS executable path if valid, otherwise throws an error. #' @inheritParams call_peaks_macs #' @keywords internal macs_path_is_valid <- function(macs_executable) { diff --git a/r/man/call_peaks_macs.Rd b/r/man/call_peaks_macs.Rd index 5deba269..edf4e96f 100644 --- a/r/man/call_peaks_macs.Rd +++ b/r/man/call_peaks_macs.Rd @@ -89,6 +89,7 @@ shell scripts generated at \verb{/input/.sh}. Finally, run \code{ca setting \code{step="read-outputs"}. } \examples{ +\dontshow{if (tryCatch({ macs_path_is_valid(); TRUE }, error = function(e) FALSE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} macs_files <- file.path(tempdir(), "peaks") frags <- get_demo_frags() @@ -104,4 +105,5 @@ list.files(file.path(macs_files, "output", "all")) ## call_peaks_macs() can also solely perform the output reading step head(call_peaks_macs(frags, macs_files, step = "read-outputs")) +\dontshow{\}) # examplesIf} } diff --git a/r/man/macs_path_is_valid.Rd b/r/man/macs_path_is_valid.Rd index 829d8190..4aa06566 100644 --- a/r/man/macs_path_is_valid.Rd +++ b/r/man/macs_path_is_valid.Rd @@ -12,7 +12,7 @@ macs_path_is_valid(macs_executable) \item{macs_executable}{(string) Path to either MACS2/3 executable. Default (\code{NULL}) will autodetect from PATH.} } \value{ -MACS executable path. +MACS executable path if valid, otherwise throws an error. } \description{ Test if MACS executable is valid. From 4fa4517738afe1cd6ec8f7d1ce19e75d579a6baa Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 13:19:05 -0700 Subject: [PATCH 23/84] [ci] error on r cmd check only on error --- .github/workflows/check-standard-test.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index 1ff682e8..d7831579 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -74,4 +74,6 @@ jobs: with: working-directory: r build_args: c("--no-build-vignettes") - upload-snapshots: true + upload-snapshots: false + error-on: error + From cfbda00b5b0c59a19e8ac914f22dbfd7cdd94a93 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 15:22:56 -0700 Subject: [PATCH 24/84] [ci] fix ci errors --- .github/workflows/check-standard-test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index d7831579..13a13a76 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest, macos-13] + os: [ubuntu-latest, windows-latest, macos-latest] env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} @@ -75,5 +75,5 @@ jobs: working-directory: r build_args: c("--no-build-vignettes") upload-snapshots: false - error-on: error + error-on: "error" From f07c6d5a72276604fd7432cb20b67b710cd400c5 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 15:30:44 -0700 Subject: [PATCH 25/84] [ci] fix ci errors --- .github/workflows/check-standard-test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index 13a13a76..7b04bb7e 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -75,5 +75,5 @@ jobs: working-directory: r build_args: c("--no-build-vignettes") upload-snapshots: false - error-on: "error" + error-on: '"error"' From b6998eb9cd50bed31c68a833a9bf3871a499fdbe Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 15:49:09 -0700 Subject: [PATCH 26/84] [ci] try vendoring highway for cran --- .github/workflows/check-standard-test.yaml | 30 ++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index 7b04bb7e..e86db0d8 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -29,14 +29,15 @@ jobs: shell: bash run: | sudo apt-get update - sudo apt-get install -y libhdf5-dev + sudo apt-get install -y libhdf5-dev libhwy-dev + sudo apt-get isntall -y libhwy-dev || true - name: Install binary dependencies on macOS if: matrix.os == 'macos-latest' || matrix.os == 'macos-13' shell: bash run: | brew update - brew install hdf5 + brew install hdf5 pkg-config highway - name: Configure compilation flags shell: bash @@ -46,6 +47,31 @@ jobs: MAKEVARS echo "R_MAKEVARS_USER=$GITHUB_WORKSPACE/Makevars.user" >> "$GITHUB_ENV" + - name: Install Highway on Windows (MSYS2 UCRT64) + if: matrix.os == 'windows-latest' + uses: msys2/setup-msys2@v2 + with: + release: false + update: true + cache: true + install: >- + base-devel + git + mingw-w64-ucrt-x86_64-toolchain + mingw-w64-ucrt-x86_64-pkgconf + mingw-w64-ucrt-x86_64-highway + msystem: UCRT64 + path-type: minimal + + - name: Expose UCRT64 pkg-config to PATH (Windows) + if: matrix.os == 'windows-latest' + shell: bash + run: | + echo "C:/msys64/ucrt64/bin" >> $GITHUB_PATH + # Ensure pkg-config finds the .pc files for UCRT64 + echo "PKG_CONFIG_PATH=C:/msys64/ucrt64/lib/pkgconfig" >> $GITHUB_ENV + echo "PKG_CONFIG=C:/msys64/ucrt64/bin/pkg-config.exe" >> $GITHUB_ENV + - name: Handle Windows big object files if: matrix.os == 'windows-latest' shell: bash From 5eba2b8135e9c12b2044f1de06a29e568bb463a8 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 16:13:37 -0700 Subject: [PATCH 27/84] [ci] add in more comprehensive systemrequirements --- r/DESCRIPTION | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/r/DESCRIPTION b/r/DESCRIPTION index e2e29800..5dd2ea80 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -76,5 +76,9 @@ Additional_repositories: https://bpcells.github.io/drat Depends: R (>= 4.0.0) -SystemRequirements: C++17 +SystemRequirements: C++17, + HDF5 (>= 1.10) [optional; detected via pkg-config 'hdf5' or 'h5cc'; + else set HDF5_CFLAGS/HDF5_LIBS], + Highway (>= 1.0.5) [optional; detected via pkg-config 'libhwy'/'hwy'; + falls back to vendored build if not found] Config/Needs/website: pkgdown, devtools, uwot, irlba, RcppHNSW, igraph, BiocManager, bioc::BSgenome.Hsapiens.UCSC.hg38, github::GreenleafLab/motifmatchr, github::GreenleafLab/chromVARmotifs, png From 620f0755b758d6e2b0a83d291e7002ffff593377 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 22 Oct 2025 17:08:51 -0700 Subject: [PATCH 28/84] [r] update data locations for human_gene_mapping --- r/DESCRIPTION | 2 +- r/R/data.R | 2 +- r/R/genomeAnnotations.R | 2 +- r/data-raw/human_gene_mapping.R | 2 +- r/man/gene_mapping.Rd | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 5dd2ea80..4bc33cec 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -10,7 +10,7 @@ Authors@R: c( person("Immanuel", "Abdi", role = "aut"), person("Stanford University", role=c("cph", "fnd")), person("Genentech, Inc.", role=c("cph", "fnd"))) -Description: > Efficient operations for single cell ATAC-seq fragments and +Description: Efficient operations for single cell ATAC-seq fragments and RNA counts matrices. Interoperable with standard file formats, and introduces efficient bit-packed formats that allow large storage savings and increased read speeds. diff --git a/r/R/data.R b/r/R/data.R index 5f50f9fe..b0f73b4f 100644 --- a/r/R/data.R +++ b/r/R/data.R @@ -268,7 +268,7 @@ remove_demo_data <- function() { #' `data-raw/mouse_gene_mapping.R` for exactly how these mappings were made. #' @source **human_gene_mapping** #' -#' +#' #' #' @examples #' ####################################################################### diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index 8c7e464e..22446820 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -240,7 +240,7 @@ read_bed <- function(path, additional_columns = character(0), backup_url = NULL, #' @rdname read_bed #' @details **read_encode_blacklist** #' -#' Downloads the Boyle Lab blacklist, as described in +#' Downloads the Boyle Lab blacklist, as described in \doi{10.1038/s41598-019-45839-z} #' @param genome genome name #' @examples #' ####################################################################### diff --git a/r/data-raw/human_gene_mapping.R b/r/data-raw/human_gene_mapping.R index 91657800..245dfe06 100644 --- a/r/data-raw/human_gene_mapping.R +++ b/r/data-raw/human_gene_mapping.R @@ -11,7 +11,7 @@ library(magrittr) # Pull data from HGNC, and make a named vector that maps non-canonical gene names/ # symbols to their canonical names. Only unambiguous mappings will be stored hgnc <- readr::read_tsv( - "http://ftp.ebi.ac.uk/pub/databases/genenames/hgnc/tsv/non_alt_loci_set.txt", + "http://ftp.ebi.ac.uk/pub/databases/genenames/out_of_date_hgnc/tsv/non_alt_loci_set.txt", col_types=readr::cols(.default=readr::col_character()) ) diff --git a/r/man/gene_mapping.Rd b/r/man/gene_mapping.Rd index f57ac819..eda1559a 100644 --- a/r/man/gene_mapping.Rd +++ b/r/man/gene_mapping.Rd @@ -19,7 +19,7 @@ are the corresponding canonical gene symbol \source{ \strong{human_gene_mapping} -\url{http://ftp.ebi.ac.uk/pub/databases/genenames/hgnc/tsv/non_alt_loci_set.txt} +\url{http://ftp.ebi.ac.uk/pub/databases/genenames/out_of_date_hgnc/tsv/non_alt_loci_set.txt} \strong{mouse_gene_mapping} From 99d68f59091d56f1d73b730d71925317bc4d1074 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 29 Oct 2025 12:14:56 -0700 Subject: [PATCH 29/84] [r] reorganize docs for iterablematrix-methods --- r/R/matrix.R | 25 +++++- r/R/matrix_stats.R | 9 ++- r/R/transforms.R | 14 ++-- r/man/IterableMatrix-methods-misc.Rd | 111 +++++++++++++++++++++++++++ r/man/IterableMatrix-methods.Rd | 90 +--------------------- r/man/read_bed.Rd | 2 +- 6 files changed, 150 insertions(+), 101 deletions(-) create mode 100644 r/man/IterableMatrix-methods-misc.Rd diff --git a/r/R/matrix.R b/r/R/matrix.R index f7766be5..a2c2d6c9 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -20,6 +20,25 @@ #' @rdname IterableMatrix-methods NULL + +#' IterableMatrix methods miscellaneous +#' +#' Generic methods and built-in functions for IterableMatrix objects. These include +#' methods that are described in `IterableMatrix-methods` but have some sense of redundancy. +#' For instance, `%*%` is described between `IterableMatrix` and `matrix` on the left and right respectively. +#' We do not need to show the method `IterableMatrix` on the right instead. +#' +#' @param ... Additional arguments passed to methods +#' @param digits Number of decimal places for quantile calculations +#' @param i Row indices or selection helpers. +#' @param j Column indices or selection helpers. +#' @param drop Logical indicating whether to drop dimensions when subsetting. +#' @param value Replacement value supplied to assignment methods. +#' @name IterableMatrix-methods-misc +#' @rdname IterableMatrix-methods-misc +#' @keywords internal +NULL + #' IterableMatrix subclass methods #' #' Methods for classes that extend `IterableMatrix` but are not dispatched @@ -290,7 +309,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "matrix"), function(x, y) { res }) -#' @describeIn IterableMatrix-methods Multiply a dense matrix by an IterableMatrix +#' @describeIn IterableMatrix-methods-misc Multiply a dense matrix by an IterableMatrix setMethod("%*%", signature(x = "matrix", y = "IterableMatrix"), function(x, y) { iter <- iterate_matrix(convert_matrix_type(y, "double")) if (y@transpose) { @@ -316,7 +335,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "numeric"), function(x, y) res }) -#' @describeIn IterableMatrix-methods Multiply a numeric row vector by an IterableMatrix +#' @describeIn IterableMatrix-methods-misc Multiply a numeric row vector by an IterableMatrix setMethod("%*%", signature(x = "numeric", y = "IterableMatrix"), function(x, y) { iter <- iterate_matrix(convert_matrix_type(y, "double")) if (y@transpose) { @@ -480,7 +499,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "dgCMatrix"), function(x, y } }) -#' @describeIn IterableMatrix-methods Multiply a dgCMatrix by an IterableMatrix +#' @describeIn IterableMatrix-methods-misc Multiply a dgCMatrix by an IterableMatrix setMethod("%*%", signature(x = "dgCMatrix", y = "IterableMatrix"), function(x, y) { if (y@transpose) { t(t(y) %*% as(t(x), "IterableMatrix")) diff --git a/r/R/matrix_stats.R b/r/R/matrix_stats.R index d846ddfc..786254c4 100644 --- a/r/R/matrix_stats.R +++ b/r/R/matrix_stats.R @@ -17,7 +17,7 @@ #' @param drop (Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects). #' @return - `rowQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of rows in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. -#' @describeIn IterableMatrix-methods Calculate rowQuantiles (generic) +#' @describeIn IterableMatrix-methods Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) #' @usage rowQuantiles( #' x, #' rows = NULL, @@ -60,7 +60,7 @@ rowQuantiles.default <- function(x, rows = NULL, cols = NULL, } #' @export #' @method rowQuantiles IterableMatrix -#' @describeIn IterableMatrix-methods Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) +#' @describeIn IterableMatrix-methods-misc Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -102,7 +102,7 @@ rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, #' Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. #' @return - `colQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of columns in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. -#' @describeIn IterableMatrix-methods Calculate colQuantiles (generic) +#' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) #' @usage colQuantiles( #' x, #' rows = NULL, @@ -143,8 +143,9 @@ colQuantiles.default <- function(x, rows = NULL, cols = NULL, rlang::abort("Cannot run colQuantiles on a non-BPCells object unless MatrixGenerics or matrixStats is installed.") } } +#' Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. #' @export -#' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) +#' @describeIn IterableMatrix-methods-misc Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) colQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., diff --git a/r/R/transforms.R b/r/R/transforms.R index d7275b50..d829c7d7 100644 --- a/r/R/transforms.R +++ b/r/R/transforms.R @@ -370,7 +370,7 @@ binarize <- function(mat, threshold=0, strict_inequality=TRUE) { global_params=c(threshold, strict_inequality)) convert_matrix_type(res, "uint32_t") } -#' @describeIn IterableMatrix-methods Perform matrix < numeric comparison (unsupported) +#' @describeIn IterableMatrix-methods-misc Perform matrix < numeric comparison (unsupported) setMethod("<", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { stop("matrix < numeric not supported for IterableMatrix objects") }) @@ -398,11 +398,11 @@ setMethod("<", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) setMethod(">", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { binarize(e1, threshold=e2, strict_inequality=TRUE) }) -#' @describeIn IterableMatrix-methods Perform numeric > matrix comparison (unsupported) +#' @describeIn IterableMatrix-methods-misc Perform numeric > matrix comparison (unsupported) setMethod(">", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) { stop("numeric > matrix not supported for IterableMatrix objects") }) -#' @describeIn IterableMatrix-methods Perform matrix <= numeric comparison (unsupported) +#' @describeIn IterableMatrix-methods-misc Perform matrix <= numeric comparison (unsupported) setMethod("<=", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { stop("matrix <= numeric not supported for IterableMatrix objects") }) @@ -428,7 +428,7 @@ setMethod("<=", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) setMethod(">=", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { binarize(e1, threshold=e2, strict_inequality=FALSE) }) -#' @describeIn IterableMatrix-methods Compare a numeric value to an IterableMatrix using >= (numeric left operand) +#' @describeIn IterableMatrix-methods-misc Compare a numeric value to an IterableMatrix using >= (numeric left operand) setMethod(">=", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) { stop("numeric >= matrix not supported for IterableMatrix objects") }) @@ -730,7 +730,7 @@ setMethod("*", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2 e1 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e1, "double")) e1 * e2 }) -#' @describeIn IterableMatrix-methods Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) +#' @describeIn IterableMatrix-methods-misc Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) setMethod("*", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2) { e2 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e2, "double")) e2 * e1 @@ -752,7 +752,7 @@ setMethod("+", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2 e1 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e1, "double")) e1 + e2 }) -#' @describeIn IterableMatrix-methods Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) +#' @describeIn IterableMatrix-methods-misc Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) setMethod("+", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2) { if (all(e1 == 0)) return(e2) e2 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e2, "double")) @@ -789,7 +789,7 @@ setMethod("/", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2 setMethod("-", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2) { e1 + (-e2) }) -#' @describeIn IterableMatrix-methods Subtract matrix from a numeric constant/vector +#' @describeIn IterableMatrix-methods-misc Subtract matrix from a numeric constant/vector setMethod("-", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2) { e2 * -1 + e1 }) diff --git a/r/man/IterableMatrix-methods-misc.Rd b/r/man/IterableMatrix-methods-misc.Rd new file mode 100644 index 00000000..8c503f6e --- /dev/null +++ b/r/man/IterableMatrix-methods-misc.Rd @@ -0,0 +1,111 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix.R, R/matrix_stats.R, R/transforms.R +\name{IterableMatrix-methods-misc} +\alias{IterableMatrix-methods-misc} +\alias{\%*\%,matrix,IterableMatrix-method} +\alias{\%*\%,numeric,IterableMatrix-method} +\alias{\%*\%,dgCMatrix,IterableMatrix-method} +\alias{rowQuantiles.IterableMatrix} +\alias{colQuantiles.IterableMatrix} +\alias{<,IterableMatrix,numeric-method} +\alias{>,numeric,IterableMatrix-method} +\alias{<=,IterableMatrix,numeric-method} +\alias{>=,numeric,IterableMatrix-method} +\alias{*,numeric,IterableMatrix-method} +\alias{+,numeric,IterableMatrix-method} +\alias{-,numeric,IterableMatrix-method} +\title{IterableMatrix methods miscellaneous} +\usage{ +\S4method{\%*\%}{matrix,IterableMatrix}(x, y) + +\S4method{\%*\%}{numeric,IterableMatrix}(x, y) + +\S4method{\%*\%}{dgCMatrix,IterableMatrix}(x, y) + +\method{rowQuantiles}{IterableMatrix}( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) + +colQuantiles.IterableMatrix( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) + +\S4method{<}{IterableMatrix,numeric}(e1, e2) + +\S4method{>}{numeric,IterableMatrix}(e1, e2) + +\S4method{<=}{IterableMatrix,numeric}(e1, e2) + +\S4method{>=}{numeric,IterableMatrix}(e1, e2) + +\S4method{*}{numeric,IterableMatrix}(e1, e2) + +\S4method{+}{numeric,IterableMatrix}(e1, e2) + +\S4method{-}{numeric,IterableMatrix}(e1, e2) +} +\arguments{ +\item{digits}{Number of decimal places for quantile calculations} + +\item{...}{Additional arguments passed to methods} + +\item{drop}{Logical indicating whether to drop dimensions when subsetting.} + +\item{i}{Row indices or selection helpers.} + +\item{j}{Column indices or selection helpers.} + +\item{value}{Replacement value supplied to assignment methods.} +} +\description{ +Generic methods and built-in functions for IterableMatrix objects. These include +methods that are described in \code{IterableMatrix-methods} but have some sense of redundancy. +For instance, \code{\%*\%} is described between \code{IterableMatrix} and \code{matrix} on the left and right respectively. +We do not need to show the method \code{IterableMatrix} on the right instead. +} +\section{Functions}{ +\itemize{ +\item \code{x \%*\% y}: Multiply a dense matrix by an IterableMatrix + +\item \code{x \%*\% y}: Multiply a numeric row vector by an IterableMatrix + +\item \code{x \%*\% y}: Multiply a dgCMatrix by an IterableMatrix + +\item \code{rowQuantiles(IterableMatrix)}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) + +\item \code{colQuantiles.IterableMatrix()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) + +\item \code{e1 < e2}: Perform matrix < numeric comparison (unsupported) + +\item \code{e1 > e2}: Perform numeric > matrix comparison (unsupported) + +\item \code{e1 <= e2}: Perform matrix <= numeric comparison (unsupported) + +\item \code{e1 >= e2}: Compare a numeric value to an IterableMatrix using >= (numeric left operand) + +\item \code{e1 * e2}: Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) + +\item \code{e1 + e2}: Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) + +\item \code{e1 - e2}: Subtract matrix from a numeric constant/vector + +}} +\keyword{internal} diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods.Rd index fee00cca..761694c5 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods.Rd @@ -8,12 +8,9 @@ \alias{show,IterableMatrix-method} \alias{t,IterableMatrix-method} \alias{\%*\%,IterableMatrix,matrix-method} -\alias{\%*\%,matrix,IterableMatrix-method} \alias{\%*\%,IterableMatrix,numeric-method} -\alias{\%*\%,numeric,IterableMatrix-method} \alias{\%*\%,IterableMatrix,IterableMatrix-method} \alias{\%*\%,IterableMatrix,dgCMatrix-method} -\alias{\%*\%,dgCMatrix,IterableMatrix-method} \alias{rowSums,IterableMatrix-method} \alias{colSums,IterableMatrix-method} \alias{rowMeans,IterableMatrix-method} @@ -29,30 +26,21 @@ \alias{dimnames<-,IterableMatrix,list-method} \alias{dimnames<-,IterableMatrix,NULL-method} \alias{rowQuantiles} -\alias{rowQuantiles.IterableMatrix} \alias{colQuantiles} -\alias{colQuantiles.IterableMatrix} \alias{log1p,IterableMatrix-method} \alias{log1p_slow} \alias{expm1,IterableMatrix-method} \alias{expm1_slow} \alias{^,IterableMatrix,numeric-method} -\alias{<,IterableMatrix,numeric-method} \alias{<,numeric,IterableMatrix-method} \alias{>,IterableMatrix,numeric-method} -\alias{>,numeric,IterableMatrix-method} -\alias{<=,IterableMatrix,numeric-method} \alias{<=,numeric,IterableMatrix-method} \alias{>=,IterableMatrix,numeric-method} -\alias{>=,numeric,IterableMatrix-method} \alias{round,IterableMatrix-method} \alias{*,IterableMatrix,numeric-method} -\alias{*,numeric,IterableMatrix-method} \alias{+,IterableMatrix,numeric-method} -\alias{+,numeric,IterableMatrix-method} \alias{/,IterableMatrix,numeric-method} \alias{-,IterableMatrix,numeric-method} -\alias{-,numeric,IterableMatrix-method} \title{IterableMatrix methods} \usage{ matrix_type(x) @@ -67,18 +55,12 @@ storage_order(x) \S4method{\%*\%}{IterableMatrix,matrix}(x, y) -\S4method{\%*\%}{matrix,IterableMatrix}(x, y) - \S4method{\%*\%}{IterableMatrix,numeric}(x, y) -\S4method{\%*\%}{numeric,IterableMatrix}(x, y) - \S4method{\%*\%}{IterableMatrix,IterableMatrix}(x, y) \S4method{\%*\%}{IterableMatrix,dgCMatrix}(x, y) -\S4method{\%*\%}{dgCMatrix,IterableMatrix}(x, y) - \S4method{rowSums}{IterableMatrix}(x) \S4method{colSums}{IterableMatrix}(x) @@ -144,19 +126,6 @@ rowQuantiles( drop = TRUE ) -\method{rowQuantiles}{IterableMatrix}( - x, - rows = NULL, - cols = NULL, - probs = seq(from = 0, to = 1, by = 0.25), - na.rm = FALSE, - type = 7L, - digits = 7L, - ..., - useNames = TRUE, - drop = TRUE -) - colQuantiles( x, rows = NULL, @@ -170,19 +139,6 @@ colQuantiles( drop = TRUE ) -colQuantiles.IterableMatrix( - x, - rows = NULL, - cols = NULL, - probs = seq(from = 0, to = 1, by = 0.25), - na.rm = FALSE, - type = 7L, - digits = 7L, - ..., - useNames = TRUE, - drop = TRUE -) - \S4method{log1p}{IterableMatrix}(x) log1p_slow(x) @@ -193,37 +149,23 @@ expm1_slow(x) \S4method{^}{IterableMatrix,numeric}(e1, e2) -\S4method{<}{IterableMatrix,numeric}(e1, e2) - \S4method{<}{numeric,IterableMatrix}(e1, e2) \S4method{>}{IterableMatrix,numeric}(e1, e2) -\S4method{>}{numeric,IterableMatrix}(e1, e2) - -\S4method{<=}{IterableMatrix,numeric}(e1, e2) - \S4method{<=}{numeric,IterableMatrix}(e1, e2) \S4method{>=}{IterableMatrix,numeric}(e1, e2) -\S4method{>=}{numeric,IterableMatrix}(e1, e2) - \S4method{round}{IterableMatrix}(x, digits = 0) \S4method{*}{IterableMatrix,numeric}(e1, e2) -\S4method{*}{numeric,IterableMatrix}(e1, e2) - \S4method{+}{IterableMatrix,numeric}(e1, e2) -\S4method{+}{numeric,IterableMatrix}(e1, e2) - \S4method{/}{IterableMatrix,numeric}(e1, e2) \S4method{-}{IterableMatrix,numeric}(e1, e2) - -\S4method{-}{numeric,IterableMatrix}(e1, e2) } \arguments{ \item{x}{IterableMatrix object or a matrix-like object.} @@ -256,11 +198,11 @@ expm1_slow(x) \item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} -\item{digits}{Number of decimal places for quantile calculations} - \item{e1}{First element of comparison} \item{e2}{Second element of comparison} + +\item{digits}{Number of decimal places for quantile calculations} } \value{ \itemize{ @@ -330,18 +272,12 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{x \%*\% y}: Multiply by a dense matrix -\item \code{x \%*\% y}: Multiply a dense matrix by an IterableMatrix - \item \code{x \%*\% y}: Multiply an IterableMatrix by a numeric vector -\item \code{x \%*\% y}: Multiply a numeric row vector by an IterableMatrix - \item \code{x \%*\% y}: Multiply two IterableMatrix objects \item \code{x \%*\% y}: Multiply an IterableMatrix by a dgCMatrix -\item \code{x \%*\% y}: Multiply a dgCMatrix by an IterableMatrix - \item \code{rowSums(IterableMatrix)}: Calculate rowSums \item \code{colSums(IterableMatrix)}: Calculate colSums @@ -370,13 +306,9 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{dimnames(x = IterableMatrix) <- value}: Remove dimnames of an IterableMatrix -\item \code{rowQuantiles()}: Calculate rowQuantiles (generic) +\item \code{rowQuantiles()}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) -\item \code{rowQuantiles(IterableMatrix)}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) - -\item \code{colQuantiles()}: Calculate colQuantiles (generic) - -\item \code{colQuantiles.IterableMatrix()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) +\item \code{colQuantiles()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) \item \code{log1p(IterableMatrix)}: Calculate log(x + 1) @@ -388,38 +320,24 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{e1^e2}: Calculate x^y (elementwise; y > 0) -\item \code{e1 < e2}: Perform matrix < numeric comparison (unsupported) - \item \code{e1 < e2}: Binarize matrix according to numeric < matrix comparison \item \code{e1 > e2}: Binarize matrix according to matrix > numeric comparison -\item \code{e1 > e2}: Perform numeric > matrix comparison (unsupported) - -\item \code{e1 <= e2}: Perform matrix <= numeric comparison (unsupported) - \item \code{e1 <= e2}: Binarize matrix according to numeric <= matrix comparison \item \code{e1 >= e2}: Binarize matrix according to matrix >= numeric comparison -\item \code{e1 >= e2}: Compare a numeric value to an IterableMatrix using >= (numeric left operand) - \item \code{round(IterableMatrix)}: round to nearest integer (digits must be 0) \item \code{e1 * e2}: Multiply by a constant, or multiply rows by a vector length nrow(mat) -\item \code{e1 * e2}: Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) - \item \code{e1 + e2}: Add a constant, or row-wise addition with a vector length nrow(mat) -\item \code{e1 + e2}: Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) - \item \code{e1 / e2}: Divide by a constant, or divide rows by a vector length nrow(mat) \item \code{e1 - e2}: Subtract a constant, or row-wise subtraction with a vector length nrow(mat) -\item \code{e1 - e2}: Subtract matrix from a numeric constant/vector - }} \examples{ ## Prep data diff --git a/r/man/read_bed.Rd b/r/man/read_bed.Rd index ebd8a85b..906f8b20 100644 --- a/r/man/read_bed.Rd +++ b/r/man/read_bed.Rd @@ -45,7 +45,7 @@ Read a bed file from disk or a url. \strong{read_encode_blacklist} -Downloads the Boyle Lab blacklist, as described in \url{https://doi.org/10.1038/s41598-019-45839-z} +Downloads the Boyle Lab blacklist, as described in \doi{10.1038/s41598-019-45839-z} } \examples{ ## Dummy bed file creation From 58ca719d80a30aa77d6521cf095681afd0ef339c Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 29 Oct 2025 12:48:08 -0700 Subject: [PATCH 30/84] [r] remove unnecessary params in IterableMatrix-methods-misc --- r/R/matrix.R | 3 --- 1 file changed, 3 deletions(-) diff --git a/r/R/matrix.R b/r/R/matrix.R index a2c2d6c9..78617cf4 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -30,10 +30,7 @@ NULL #' #' @param ... Additional arguments passed to methods #' @param digits Number of decimal places for quantile calculations -#' @param i Row indices or selection helpers. -#' @param j Column indices or selection helpers. #' @param drop Logical indicating whether to drop dimensions when subsetting. -#' @param value Replacement value supplied to assignment methods. #' @name IterableMatrix-methods-misc #' @rdname IterableMatrix-methods-misc #' @keywords internal From 385015d07bba3fed394643fe23c301b985d219f8 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 10 Nov 2025 14:04:29 -0800 Subject: [PATCH 31/84] [r] misc documentation changes --- r/DESCRIPTION | 2 +- r/R/matrix.R | 2 ++ r/man/IterableMatrix-methods-misc.Rd | 6 ------ r/man/IterableMatrix-methods.Rd | 4 ++-- r/man/peak_matrix.Rd | 2 ++ 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 4bc33cec..c05c22ca 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -19,7 +19,7 @@ Encoding: UTF-8 LazyData: true RoxygenNote: 7.3.2 Roxygen: list(markdown = TRUE) -URL: https://bnprks.github.io/BPCells, https://github.com/bnprks/BPCells +URL: https://bnprks.github.io/BPCells/, https://github.com/bnprks/BPCells LinkingTo: Rcpp, RcppEigen diff --git a/r/R/matrix.R b/r/R/matrix.R index 78617cf4..8ac40d47 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -2737,6 +2737,7 @@ setMethod("matrix_inputs", "PeakMatrix", function(x) list()) #' spans the peak even if neither the start or end falls within the peak #' @examples #' ## Prep demo data +#' \dontrun{ #' frags <- get_demo_frags(subset = FALSE) #' chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "references"), genome="hg38") #' blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") @@ -2751,6 +2752,7 @@ setMethod("matrix_inputs", "PeakMatrix", function(x) list()) #' #' ## Get peak matrix #' peak_matrix(frags_filter_blacklist, top_peaks, mode="insertions") +#' } #' @export peak_matrix <- function(fragments, ranges, mode = c("insertions", "fragments", "overlaps"), zero_based_coords = !is(ranges, "GRanges"), explicit_peak_names = TRUE) { assert_is(fragments, "IterableFragments") diff --git a/r/man/IterableMatrix-methods-misc.Rd b/r/man/IterableMatrix-methods-misc.Rd index 8c503f6e..164cb398 100644 --- a/r/man/IterableMatrix-methods-misc.Rd +++ b/r/man/IterableMatrix-methods-misc.Rd @@ -68,12 +68,6 @@ colQuantiles.IterableMatrix( \item{...}{Additional arguments passed to methods} \item{drop}{Logical indicating whether to drop dimensions when subsetting.} - -\item{i}{Row indices or selection helpers.} - -\item{j}{Column indices or selection helpers.} - -\item{value}{Replacement value supplied to assignment methods.} } \description{ Generic methods and built-in functions for IterableMatrix objects. These include diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods.Rd index 761694c5..16f9df69 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods.Rd @@ -198,11 +198,11 @@ expm1_slow(x) \item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} +\item{digits}{Number of decimal places for quantile calculations} + \item{e1}{First element of comparison} \item{e2}{Second element of comparison} - -\item{digits}{Number of decimal places for quantile calculations} } \value{ \itemize{ diff --git a/r/man/peak_matrix.Rd b/r/man/peak_matrix.Rd index c8e98fe7..0a25030e 100644 --- a/r/man/peak_matrix.Rd +++ b/r/man/peak_matrix.Rd @@ -54,6 +54,7 @@ provide the ordering of chromosomes to expect while reading the tsv. } \examples{ ## Prep demo data +\dontrun{ frags <- get_demo_frags(subset = FALSE) chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "references"), genome="hg38") blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") @@ -69,3 +70,4 @@ top_peaks <- top_peaks[order_ranges(top_peaks, chrNames(frags)),] ## Get peak matrix peak_matrix(frags_filter_blacklist, top_peaks, mode="insertions") } +} From 3d63e8191d8e3c9953db319b2fc21253453bee60 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Thu, 20 Nov 2025 14:48:09 -0800 Subject: [PATCH 32/84] remove event.json --- event.json | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 event.json diff --git a/event.json b/event.json deleted file mode 100644 index ecde619a..00000000 --- a/event.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "inputs": { - "version": "0.3.0rc1", - "target": "testpypi" - } -} \ No newline at end of file From 4ca1b4ee1d43f0c2035a9bc24062e9ae134af97f Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Thu, 20 Nov 2025 14:49:48 -0800 Subject: [PATCH 33/84] add hexbin back into imports --- r/DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r/DESCRIPTION b/r/DESCRIPTION index c05c22ca..35f71e69 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -47,9 +47,9 @@ Imports: scattermore, ggrepel, RColorBrewer, + hexbin Suggests: IRanges, - hexbin, tidyr, GenomicRanges, GenomeInfoDb, From 44f70e595c71ddd870fe578512b7a58984334b4b Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 14:04:34 -0800 Subject: [PATCH 34/84] change windows check for cran ci --- .github/workflows/check-standard-test.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index e86db0d8..c1e6a27a 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -94,7 +94,12 @@ jobs: any::decor working-directory: 'r' needs: check - + # Do this because Windows has an error with file timestamps + - name: Touch files on Windows + if: matrix.os == 'windows-latest' + shell: bash + run: | + find r -type f -exec touch {} + - name: Check package uses: r-lib/actions/check-r-package@v2 with: From 4a1c68675a2dfab72afaa8e9349d1d86104e6505 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 14:17:03 -0800 Subject: [PATCH 35/84] update configure.win to also use sh instead of bash --- r/configure.win | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/r/configure.win b/r/configure.win index 24e56ca3..15bd8d16 100755 --- a/r/configure.win +++ b/r/configure.win @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh if [ -z $BPCELLS_DEBUG_INSTALL ]; then exec 3>/dev/null @@ -15,7 +15,7 @@ fi # or set the CI or ENABLE_INSTALL_COUNTING environment variables ahead of installation. if [ -z "$CI" ]; then ENABLE_INSTALL_COUNTING=${ENABLE_INSTALL_COUNTING:-yes}; fi -if [ "$ENABLE_INSTALL_COUNTING" == "yes" ]; then +if [ "$ENABLE_INSTALL_COUNTING" = "yes" ]; then curl --silent "https://plausible.benparks.net/flask-plausible/bpcells-configure" > /dev/null 2> /dev/null \ || true echo "Recording install count metrics" @@ -180,7 +180,7 @@ sed \ -e "s|%ENV_LDFLAGS%|${ENV_LDFLAGS}|g" \ src/Makevars.in > src/Makevars -if [ "$ENABLE_INSTALL_COUNTING" == "yes" ]; then +if [ "$ENABLE_INSTALL_COUNTING" = "yes" ]; then curl --silent https://plausible.benparks.net/flask-plausible/bpcells-configure-success > /dev/null 2> /dev/null \ || true fi From 278d25cb6a81512da79dcc93f754118f44de8ece Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 14:33:07 -0800 Subject: [PATCH 36/84] disable timestamp check for windows --- .github/workflows/check-standard-test.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index c1e6a27a..21784380 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -94,12 +94,11 @@ jobs: any::decor working-directory: 'r' needs: check - # Do this because Windows has an error with file timestamps - - name: Touch files on Windows + # Skip fragile future-timestamp check on Windows (file.mtime() can be NA) + - name: Disable future timestamp check on Windows if: matrix.os == 'windows-latest' shell: bash - run: | - find r -type f -exec touch {} + + run: echo "_R_CHECK_FUTURE_FILE_TIMESTAMPS_=FALSE" >> "$GITHUB_ENV" - name: Check package uses: r-lib/actions/check-r-package@v2 with: @@ -107,4 +106,3 @@ jobs: build_args: c("--no-build-vignettes") upload-snapshots: false error-on: '"error"' - From 1841d70067d8c4570ff7ce75cea4f2ac8c220b8a Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 14:58:03 -0800 Subject: [PATCH 37/84] check removing future file timestamps entirely in ci --- .github/workflows/check-standard-test.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index 21784380..caf296a7 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -106,3 +106,5 @@ jobs: build_args: c("--no-build-vignettes") upload-snapshots: false error-on: '"error"' + env: + _R_CHECK_FUTURE_FILE_TIMESTAMPS_: "FALSE" From b3da9a3b6774b60d340e7efaae8e3117f227ce3e Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 15:04:44 -0800 Subject: [PATCH 38/84] set the correct env variable to remove time check in ci --- .github/workflows/check-standard-test.yaml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index caf296a7..fb906568 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -94,11 +94,6 @@ jobs: any::decor working-directory: 'r' needs: check - # Skip fragile future-timestamp check on Windows (file.mtime() can be NA) - - name: Disable future timestamp check on Windows - if: matrix.os == 'windows-latest' - shell: bash - run: echo "_R_CHECK_FUTURE_FILE_TIMESTAMPS_=FALSE" >> "$GITHUB_ENV" - name: Check package uses: r-lib/actions/check-r-package@v2 with: @@ -106,5 +101,7 @@ jobs: build_args: c("--no-build-vignettes") upload-snapshots: false error-on: '"error"' + # Skip fragile future-timestamp check on Windows (file.mtime() can be NA) env: - _R_CHECK_FUTURE_FILE_TIMESTAMPS_: "FALSE" + _R_CHECK_SYSTEM_CLOCK_: 0 + From ca3f8709be8fffd23aa21bab091f9302fd0bed09 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 15:18:19 -0800 Subject: [PATCH 39/84] see if this turns off the timestamp issue in windows --- .github/workflows/check-standard-test.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index fb906568..b471aa11 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -104,4 +104,5 @@ jobs: # Skip fragile future-timestamp check on Windows (file.mtime() can be NA) env: _R_CHECK_SYSTEM_CLOCK_: 0 + _R_CHECK_FUTURE_FILE_TIMESTAMPS_: false From d4e12125dcbabbac43b22f526ff8f786b4bc1d0c Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 15:25:26 -0800 Subject: [PATCH 40/84] change trackplot rendering to use ragg::wrap --- r/NAMESPACE | 2 + r/R/plots.R | 8 +-- r/R/trackplots.R | 96 +++++++++++++++++----------- r/man/IterableMatrix-methods.Rd | 4 +- r/man/plot_dot.Rd | 7 +- r/man/ragg_wrap.Rd | 30 +++++++++ r/man/render_plot_from_storage.Rd | 20 ------ r/man/scale_next_plot_height.Rd | 19 ++++++ r/man/trackplot_combine.Rd | 6 +- r/man/trackplot_coverage.Rd | 10 ++- r/man/trackplot_gene.Rd | 5 +- r/man/trackplot_genome_annotation.Rd | 6 +- r/man/trackplot_loop.Rd | 4 +- r/man/trackplot_scalebar.Rd | 5 +- r/pkgdown/_pkgdown.yml | 4 ++ 15 files changed, 136 insertions(+), 90 deletions(-) create mode 100644 r/man/ragg_wrap.Rd delete mode 100644 r/man/render_plot_from_storage.Rd create mode 100644 r/man/scale_next_plot_height.Rd diff --git a/r/NAMESPACE b/r/NAMESPACE index 53f0dc9c..f73d54c7 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -98,6 +98,7 @@ export(plot_tss_scatter) export(prefix_cell_names) export(pseudobulk_matrix) export(qc_scATAC) +export(ragg_wrap) export(range_distance_to_nearest) export(read_bed) export(read_encode_blacklist) @@ -113,6 +114,7 @@ export(rowMeans) export(rowQuantiles) export(rowSums) export(rowVars) +export(scale_next_plot_height) export(sctransform_pearson) export(select_cells) export(select_chromosomes) diff --git a/r/R/plots.R b/r/R/plots.R index 0ff24dff..b1a5354d 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -827,11 +827,9 @@ rotate_x_labels <- function(degrees = 45) { #' cell_types <- paste("Group", rep(1:3, length.out = length(colnames(mat)))) #' #' ## Plot dot -#' plot <- plot_dot(mat, c("MS4A1", "CD3E"), cell_types) -#' -#' BPCells:::render_plot_from_storage( -#' plot, width = 4, height = 5 -#' ) +#' scale_next_plot_height(0.8) +#' plot_dot(mat, c("MS4A1", "CD3E"), cell_types) + #' @export plot_dot <- function(source, features, groups, group_order = NULL, gene_mapping = human_gene_mapping, colors = c("lightgrey", "#4682B4"), diff --git a/r/R/trackplots.R b/r/R/trackplots.R index cce7ea28..de539302 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -279,21 +279,6 @@ trackplot_normalize_ranges_with_metadata <- function(data, metadata) { return(data) } -#' Render a plot with intermediate disk storage step -#' -#' Take a plotting object and save in temp storage, so it can be outputted with exact dimensions. -#' Primarily used to allow for adjusting plot dimensions within function reference examples. -#' @param plot (ggplot) ggplot output from a plotting function -#' @param width (numeric) width of rendered plot -#' @param height (numeric) height of rendered plot -#' @keywords internal -render_plot_from_storage <- function(plot, width, height) { - assert_is(plot, "ggplot") - image_path <- tempfile(fileext = ".png") - ggplot2::ggsave(image_path, plot, width = width, height = height) - img <- png::readPNG(image_path) - grid::grid.raster(img) -} #' Combine track plots #' @@ -344,11 +329,11 @@ render_plot_from_storage <- function(plot, width, height) { #' #' ## Combine trackplots and render #' ## Also remove colors from gene track -#' plot <- trackplot_combine( +#' scale_next_plot_height(0.6) +#' trackplot_combine( #' list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) #' ) -#' BPCells:::render_plot_from_storage( -#' plot, width = 6, height = 4) +#' plot #' @export trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_width = 0.3) { for (plot in tracks) { @@ -502,12 +487,10 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ #' region <- "chr4:3034877-4034877" #' cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) #' -#' BPCells:::render_plot_from_storage( -#' trackplot_coverage( -#' frags, region, groups = cell_types, -#' cell_read_counts = read_counts -#' ), -#' width = 6, height = 3 +#' scale_next_plot_height(0.5) +#' trackplot_coverage( +#' frags, region, groups = cell_types, +#' cell_read_counts = read_counts #' ) #' @export trackplot_coverage <- function(fragments, region, groups, @@ -618,11 +601,10 @@ trackplot_coverage <- function(fragments, region, groups, #' annotation_set = "basic", features = "transcript", timeout = 3000 #' ) #' region <- "chr4:3034877-4034877" -#' -#' +#' #' ## Plot gene trackplot -#' plot <- trackplot_gene(transcripts, region) -#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1) +#' scale_next_plot_height(0.3) +#' trackplot_gene(transcripts, region) #' @export trackplot_gene <- function(transcripts, region, exon_size = 2.5, gene_size = 0.5, label_size = 11*.8/ggplot2::.pt, track_label="Genes", return_data = FALSE) { region <- normalize_ranges(region) @@ -739,10 +721,8 @@ trackplot_gene <- function(transcripts, region, exon_size = 2.5, gene_size = 0.5 #' region <- "chr4:3034877-3044877" #' #' ## Plot peaks -#' BPCells:::render_plot_from_storage( -#' trackplot_genome_annotation(peaks, region, color_by = "enrichment"), -#' width = 6, height = 1 -#' ) +#' scale_next_plot_height(0.3) +#' trackplot_genome_annotation(peaks, region, color_by = "enrichment") #' @export trackplot_genome_annotation <- function(loci, region, color_by = NULL, colors = NULL, label_by = NULL, label_size = 11*.8/ggplot2::.pt, show_strand=FALSE, annotation_size = 2.5, track_label="Peaks", return_data = FALSE) { @@ -877,8 +857,8 @@ trackplot_genome_annotation <- function(loci, region, color_by = NULL, colors = #' region <- "chr4:3034877-4034877" #' #' ## Plot loops -#' plot <- trackplot_loop(loops, region, color_by = "score") -#' BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) +#' scale_next_plot_height(0.3) +#' trackplot_loop(loops, region, color_by = "score") #' @export trackplot_loop <- function(loops, region, color_by=NULL, colors=NULL, allow_truncated=TRUE, curvature=0.75, track_label="Links", return_data = FALSE) { region <- normalize_ranges(region) @@ -978,9 +958,8 @@ trackplot_loop <- function(loops, region, color_by=NULL, colors=NULL, allow_trun #' @seealso `trackplot_combine()`, `trackplot_coverage()`, `trackplot_gene()`, `trackplot_loop()` #' @examples #' region <- "chr4:3034877-3044877" -#' BPCells:::render_plot_from_storage( -#' trackplot_scalebar(region), width = 6, height = 1 -#' ) +#' scale_next_plot_height(0.3) +#' trackplot_scalebar(region) #' @export trackplot_scalebar <- function(region, font_pt=11) { region <- normalize_ranges(region) @@ -1288,3 +1267,46 @@ trackplot_bulk <- function(fragments, region, groups, return(plot) } } + +#' Temporarily scale the height of the next plot device +#' +#' Stores a scaling factor that `ragg_wrap()` consumes once, letting you tweak +#' the rendered height of the next PNG device without modifying the plot code. +#' +#' @param scale Numeric multiplier applied to the `height` argument the next +#' time `ragg_wrap()` is called. +#' @return Returns the previous option value (as returned by `options()`). +#' @export +scale_next_plot_height <- function(scale) { + options("BPCells.scale_next_plot_height" = scale) +} + +#' Wrap `ragg::agg_png()` with optional one-shot height scaling +#' +#' Use `scale_next_plot_height()` to temporarily adjust the height of the *next* +#' call to `ragg_wrap()`. This is handy when a downstream plot (e.g., produced +#' by `trackplot_combine()`) renders too tall/short in a pipeline and you want a +#' quick scaling tweak without touching the plot code itself. The scaling factor +#' is applied once and then cleared. +#' @return A graphics device as returned by `ragg::agg_png()`. +#' @export +ragg_wrap <- function( + filename = "Rplot%03d.png", width = 480, height = 480, + units = "px", pointsize = 12, background = "white", res = 72, scaling = 1, snap_rect = TRUE, bitsize = 8, bg +) { + height_scale <- getOption("BPCells.scale_next_plot_height", default = 1) + options("BPCells.scale_next_plot_height" = NULL) + ragg::agg_png( + filename = filename, + width = width, + height = height * height_scale, + units = units, + pointsize = pointsize, + background = background, + res = res, + scaling = scaling, + snap_rect = snap_rect, + bitsize = bitsize, + bg = bg + ) +} diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods.Rd index 16f9df69..761694c5 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods.Rd @@ -198,11 +198,11 @@ expm1_slow(x) \item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} -\item{digits}{Number of decimal places for quantile calculations} - \item{e1}{First element of comparison} \item{e2}{Second element of comparison} + +\item{digits}{Number of decimal places for quantile calculations} } \value{ \itemize{ diff --git a/r/man/plot_dot.Rd b/r/man/plot_dot.Rd index 3f5fbdb5..6b9e99af 100644 --- a/r/man/plot_dot.Rd +++ b/r/man/plot_dot.Rd @@ -44,9 +44,6 @@ mat <- get_demo_mat() cell_types <- paste("Group", rep(1:3, length.out = length(colnames(mat)))) ## Plot dot -plot <- plot_dot(mat, c("MS4A1", "CD3E"), cell_types) - - BPCells:::render_plot_from_storage( - plot, width = 4, height = 5 -) +scale_next_plot_height(0.8) +plot_dot(mat, c("MS4A1", "CD3E"), cell_types) } diff --git a/r/man/ragg_wrap.Rd b/r/man/ragg_wrap.Rd new file mode 100644 index 00000000..817a1c13 --- /dev/null +++ b/r/man/ragg_wrap.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/trackplots.R +\name{ragg_wrap} +\alias{ragg_wrap} +\title{Wrap \code{ragg::agg_png()} with optional one-shot height scaling} +\usage{ +ragg_wrap( + filename = "Rplot\%03d.png", + width = 480, + height = 480, + units = "px", + pointsize = 12, + background = "white", + res = 72, + scaling = 1, + snap_rect = TRUE, + bitsize = 8, + bg +) +} +\value{ +A graphics device as returned by \code{ragg::agg_png()}. +} +\description{ +Use \code{scale_next_plot_height()} to temporarily adjust the height of the \emph{next} +call to \code{ragg_wrap()}. This is handy when a downstream plot (e.g., produced +by \code{trackplot_combine()}) renders too tall/short in a pipeline and you want a +quick scaling tweak without touching the plot code itself. The scaling factor +is applied once and then cleared. +} diff --git a/r/man/render_plot_from_storage.Rd b/r/man/render_plot_from_storage.Rd deleted file mode 100644 index bfcea1f6..00000000 --- a/r/man/render_plot_from_storage.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/trackplots.R -\name{render_plot_from_storage} -\alias{render_plot_from_storage} -\title{Render a plot with intermediate disk storage step} -\usage{ -render_plot_from_storage(plot, width, height) -} -\arguments{ -\item{plot}{(ggplot) ggplot output from a plotting function} - -\item{width}{(numeric) width of rendered plot} - -\item{height}{(numeric) height of rendered plot} -} -\description{ -Take a plotting object and save in temp storage, so it can be outputted with exact dimensions. -Primarily used to allow for adjusting plot dimensions within function reference examples. -} -\keyword{internal} diff --git a/r/man/scale_next_plot_height.Rd b/r/man/scale_next_plot_height.Rd new file mode 100644 index 00000000..91433730 --- /dev/null +++ b/r/man/scale_next_plot_height.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/trackplots.R +\name{scale_next_plot_height} +\alias{scale_next_plot_height} +\title{Temporarily scale the height of the next plot device} +\usage{ +scale_next_plot_height(scale) +} +\arguments{ +\item{scale}{Numeric multiplier applied to the \code{height} argument the next +time \code{ragg_wrap()} is called.} +} +\value{ +Returns the previous option value (as returned by \code{options()}). +} +\description{ +Stores a scaling factor that \code{ragg_wrap()} consumes once, letting you tweak +the rendered height of the next PNG device without modifying the plot code. +} diff --git a/r/man/trackplot_combine.Rd b/r/man/trackplot_combine.Rd index 71670273..a4ef0389 100644 --- a/r/man/trackplot_combine.Rd +++ b/r/man/trackplot_combine.Rd @@ -65,11 +65,11 @@ plot_coverage <- trackplot_coverage( ## Combine trackplots and render ## Also remove colors from gene track -plot <- trackplot_combine( +scale_next_plot_height(0.6) +trackplot_combine( list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) ) -BPCells:::render_plot_from_storage( - plot, width = 6, height = 4) +plot } \seealso{ \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} diff --git a/r/man/trackplot_coverage.Rd b/r/man/trackplot_coverage.Rd index 8b58053f..8db8e38a 100644 --- a/r/man/trackplot_coverage.Rd +++ b/r/man/trackplot_coverage.Rd @@ -71,12 +71,10 @@ read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags region <- "chr4:3034877-4034877" cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) -BPCells:::render_plot_from_storage( - trackplot_coverage( - frags, region, groups = cell_types, - cell_read_counts = read_counts - ), - width = 6, height = 3 +scale_next_plot_height(0.5) +trackplot_coverage( + frags, region, groups = cell_types, + cell_read_counts = read_counts ) } \seealso{ diff --git a/r/man/trackplot_gene.Rd b/r/man/trackplot_gene.Rd index 92c11d57..d287d8a9 100644 --- a/r/man/trackplot_gene.Rd +++ b/r/man/trackplot_gene.Rd @@ -53,10 +53,9 @@ transcripts <- read_gencode_transcripts( ) region <- "chr4:3034877-4034877" - ## Plot gene trackplot -plot <- trackplot_gene(transcripts, region) -BPCells:::render_plot_from_storage(plot, width = 6, height = 1) +scale_next_plot_height(0.3) +trackplot_gene(transcripts, region) } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} diff --git a/r/man/trackplot_genome_annotation.Rd b/r/man/trackplot_genome_annotation.Rd index fe616b7e..8e9f66ff 100644 --- a/r/man/trackplot_genome_annotation.Rd +++ b/r/man/trackplot_genome_annotation.Rd @@ -67,10 +67,8 @@ peaks <- tibble::tibble( region <- "chr4:3034877-3044877" ## Plot peaks -BPCells:::render_plot_from_storage( - trackplot_genome_annotation(peaks, region, color_by = "enrichment"), - width = 6, height = 1 -) +scale_next_plot_height(0.3) +trackplot_genome_annotation(peaks, region, color_by = "enrichment") } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_loop()}, \code{trackplot_scalebar()}, \code{trackplot_gene()} diff --git a/r/man/trackplot_loop.Rd b/r/man/trackplot_loop.Rd index 4cab9fbb..9f87c832 100644 --- a/r/man/trackplot_loop.Rd +++ b/r/man/trackplot_loop.Rd @@ -54,8 +54,8 @@ loops <- tibble::tibble( region <- "chr4:3034877-4034877" ## Plot loops -plot <- trackplot_loop(loops, region, color_by = "score") -BPCells:::render_plot_from_storage(plot, width = 6, height = 1.5) +scale_next_plot_height(0.3) +trackplot_loop(loops, region, color_by = "score") } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_scalebar()}, \code{trackplot_genome_annotation()} diff --git a/r/man/trackplot_scalebar.Rd b/r/man/trackplot_scalebar.Rd index f52f663e..f958f423 100644 --- a/r/man/trackplot_scalebar.Rd +++ b/r/man/trackplot_scalebar.Rd @@ -20,9 +20,8 @@ Plots a human-readable scale bar and coordinates of the region being plotted } \examples{ region <- "chr4:3034877-3044877" -BPCells:::render_plot_from_storage( - trackplot_scalebar(region), width = 6, height = 1 -) +scale_next_plot_height(0.3) +trackplot_scalebar(region) } \seealso{ \code{trackplot_combine()}, \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_loop()} diff --git a/r/pkgdown/_pkgdown.yml b/r/pkgdown/_pkgdown.yml index 2a99ab14..cac5ea8a 100644 --- a/r/pkgdown/_pkgdown.yml +++ b/r/pkgdown/_pkgdown.yml @@ -190,8 +190,12 @@ reference: - discrete_palette - collect_features - rotate_x_labels + - ragg_wrap + - scale_next_plot_height - title: "Data" - contents: - get_demo_mat +figures: + dev: BPCells::ragg_wrap From 2a2a5752b6e080659a66e5f92f38ec58a9f9883f Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 15:26:03 -0800 Subject: [PATCH 41/84] update Makevars.in --- r/src/Makevars.in | 1 - 1 file changed, 1 deletion(-) diff --git a/r/src/Makevars.in b/r/src/Makevars.in index 32f55be2..ef312ca9 100644 --- a/r/src/Makevars.in +++ b/r/src/Makevars.in @@ -1,4 +1,3 @@ -# CXX_STD = CXX17 CXX_STD = CXX17 PKG_CXXFLAGS = %HDF5_CFLAGS% %HWY_CFLAGS% %ENV_CFLAGS% -Ivendor -DRCPP_EIGEN -DEIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS # -Wall -Wextra -Wpedantic PKG_LIBS = -lz %HDF5_LIBS% %CXX_FS_FLAG% %HWY_LIBS% %ENV_LDFLAGS% From 39a730e3524a89117289d8cfded78b95d273949a Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 15:41:18 -0800 Subject: [PATCH 42/84] add env check on check-standard-test.yaml --- .github/workflows/check-standard-test.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index b471aa11..7f6eb5d0 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -21,6 +21,8 @@ jobs: R_KEEP_PKG_SOURCE: yes ENABLE_INSTALL_COUNTING: no _R_CHECK_BUILD_VIGNETTES_: false + _R_CHECK_SYSTEM_CLOCK_: 0 + _R_CHECK_FUTURE_FILE_TIMESTAMPS_: false steps: - uses: actions/checkout@v4 @@ -101,8 +103,5 @@ jobs: build_args: c("--no-build-vignettes") upload-snapshots: false error-on: '"error"' - # Skip fragile future-timestamp check on Windows (file.mtime() can be NA) - env: - _R_CHECK_SYSTEM_CLOCK_: 0 - _R_CHECK_FUTURE_FILE_TIMESTAMPS_: false + From 09ba9a767e0d19cb3ba8781974a2f0422b95871e Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 15:53:30 -0800 Subject: [PATCH 43/84] remove some importFrom calls in BPCells-package.R --- r/NAMESPACE | 2 -- r/R/BPCells-package.R | 4 ++-- r/R/data.R | 4 ++-- r/R/trackplots.R | 8 ++++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/r/NAMESPACE b/r/NAMESPACE index f73d54c7..31a69691 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -157,7 +157,6 @@ importFrom(Matrix,rowMeans) importFrom(Matrix,rowSums) importFrom(Matrix,t) importFrom(Rcpp,sourceCpp) -importFrom(ggplot2,element_text) importFrom(ggplot2,theme) importFrom(graphics,text) importFrom(magrittr,"%>%") @@ -189,7 +188,6 @@ importFrom(stats,start) importFrom(utils,download.file) importFrom(utils,head) importFrom(utils,tail) -importFrom(utils,untar) importMethodsFrom(Matrix,colMeans) importMethodsFrom(Matrix,colSums) importMethodsFrom(Matrix,rowMeans) diff --git a/r/R/BPCells-package.R b/r/R/BPCells-package.R index fa679b39..58260d48 100644 --- a/r/R/BPCells-package.R +++ b/r/R/BPCells-package.R @@ -12,9 +12,9 @@ #' @importFrom Matrix t #' @importFrom methods .hasSlot Arith as callNextMethod canCoerce cbind2 Compare is Math Math2 new rbind2 setAs setClass setGeneric setMethod show #' @importFrom stats as.formula end model.matrix p.adjust ppois qpois quantile start -#' @importFrom utils download.file head tail untar +#' @importFrom utils download.file head tail #' @importFrom graphics text -#' @importFrom ggplot2 theme element_text +#' @importFrom ggplot2 theme NULL # Suppress CMD check warnings for legitimate NSE usage diff --git a/r/R/data.R b/r/R/data.R index b0f73b4f..bd05b2af 100644 --- a/r/R/data.R +++ b/r/R/data.R @@ -188,7 +188,7 @@ get_demo_mat <- function(filter_qc = TRUE, subset = TRUE) { if (!file.exists(file.path(data_dir, paste0(mat_name, ".tar.gz")))) { prepare_demo_data(data_dir, filter_qc = filter_qc, subset = subset) } else { - untar(file.path(data_dir, paste0(mat_name, ".tar.gz")), exdir=data_dir) + untar(file.path(data_dir, paste0(mat_name, ".tar.gz")), exdir=data_dir) + importFrom(utils, untar) file.remove(file.path(data_dir, paste0(mat_name, ".tar.gz"))) } } @@ -222,7 +222,7 @@ get_demo_frags <- function(filter_qc = TRUE, subset = TRUE) { if (!file.exists(file.path(data_dir, paste0(frags_name, ".tar.gz")))) { prepare_demo_data(data_dir) } else { - untar(file.path(data_dir, paste0(frags_name, ".tar.gz")), exdir = data_dir) + untar(file.path(data_dir, paste0(frags_name, ".tar.gz")), exdir = data_dir) + importFrom(utils, untar) file.remove(file.path(data_dir, paste0(frags_name, ".tar.gz"))) } } diff --git a/r/R/trackplots.R b/r/R/trackplots.R index de539302..a3194817 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -18,10 +18,10 @@ trackplot_theme <- function(base_size=11) { ggplot2::theme( panel.grid = ggplot2::element_blank(), panel.spacing.y = ggplot2::unit(0, "pt"), - strip.text.y.left = ggplot2::element_text(angle=0, hjust=1, size=ggplot2::rel(1.2)), + strip.text.y.left = ggplot2::element_text(angle=0, hjust=1, size=ggplot2::rel(1.2)) + importFrom(ggplot2, element_text), strip.background = ggplot2::element_blank(), strip.placement = "outside", - axis.title.y.left = ggplot2::element_text(size=ggplot2::rel(1)) + axis.title.y.left = ggplot2::element_text(size=ggplot2::rel(1)) + importFrom(ggplot2, element_text) ) } @@ -441,7 +441,7 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ ) } if (!is.null(title)) { - patch <- patch + patchwork::plot_annotation(title = title, theme = ggplot2::theme(plot.title = ggplot2::element_text(hjust = 0.5))) + patch <- patch + patchwork::plot_annotation(title = title, theme = ggplot2::theme(plot.title = ggplot2::element_text(hjust = 0.5) + importFrom(ggplot2, element_text))) } return(patch) } @@ -1125,7 +1125,7 @@ draw_trackplot_grid <- function(..., labels, title = NULL, patch <- Reduce(`+`, c(labels_plots, data_plots)) + patchwork::plot_layout(ncol = 2, byrow = FALSE, widths = c(label_width, 1), heights = heights, guides = "collect") if (!is.null(title)) { - patch <- patch + patchwork::plot_annotation(title = title, theme = theme(plot.title = element_text(hjust = 0.5))) + patch <- patch + patchwork::plot_annotation(title = title, theme = theme(plot.title = element_text(hjust = 0.5) + importFrom(ggplot2, element_text))) } return(patch) } From fae9542620ab0b5bbefa208bdfc81adc845aa4c1 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 15:56:38 -0800 Subject: [PATCH 44/84] check timing change --- .github/workflows/check-standard-test.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index 7f6eb5d0..29d838bf 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -21,8 +21,6 @@ jobs: R_KEEP_PKG_SOURCE: yes ENABLE_INSTALL_COUNTING: no _R_CHECK_BUILD_VIGNETTES_: false - _R_CHECK_SYSTEM_CLOCK_: 0 - _R_CHECK_FUTURE_FILE_TIMESTAMPS_: false steps: - uses: actions/checkout@v4 @@ -96,6 +94,11 @@ jobs: any::decor working-directory: 'r' needs: check + - name: Normalize timestamps (Windows) + if: matrix.os == 'windows-latest' + shell: bash + run: | + find r -type f -exec touch -d "2020-01-01 00:00:00" {} + - name: Check package uses: r-lib/actions/check-r-package@v2 with: From 793926b12a5bf955badba21c812190a77e501a9e Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 16:07:36 -0800 Subject: [PATCH 45/84] undo importFrom changes --- r/R/BPCells-package.R | 4 ++-- r/R/data.R | 4 ++-- r/R/trackplots.R | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/r/R/BPCells-package.R b/r/R/BPCells-package.R index 58260d48..fa679b39 100644 --- a/r/R/BPCells-package.R +++ b/r/R/BPCells-package.R @@ -12,9 +12,9 @@ #' @importFrom Matrix t #' @importFrom methods .hasSlot Arith as callNextMethod canCoerce cbind2 Compare is Math Math2 new rbind2 setAs setClass setGeneric setMethod show #' @importFrom stats as.formula end model.matrix p.adjust ppois qpois quantile start -#' @importFrom utils download.file head tail +#' @importFrom utils download.file head tail untar #' @importFrom graphics text -#' @importFrom ggplot2 theme +#' @importFrom ggplot2 theme element_text NULL # Suppress CMD check warnings for legitimate NSE usage diff --git a/r/R/data.R b/r/R/data.R index bd05b2af..b0f73b4f 100644 --- a/r/R/data.R +++ b/r/R/data.R @@ -188,7 +188,7 @@ get_demo_mat <- function(filter_qc = TRUE, subset = TRUE) { if (!file.exists(file.path(data_dir, paste0(mat_name, ".tar.gz")))) { prepare_demo_data(data_dir, filter_qc = filter_qc, subset = subset) } else { - untar(file.path(data_dir, paste0(mat_name, ".tar.gz")), exdir=data_dir) + importFrom(utils, untar) + untar(file.path(data_dir, paste0(mat_name, ".tar.gz")), exdir=data_dir) file.remove(file.path(data_dir, paste0(mat_name, ".tar.gz"))) } } @@ -222,7 +222,7 @@ get_demo_frags <- function(filter_qc = TRUE, subset = TRUE) { if (!file.exists(file.path(data_dir, paste0(frags_name, ".tar.gz")))) { prepare_demo_data(data_dir) } else { - untar(file.path(data_dir, paste0(frags_name, ".tar.gz")), exdir = data_dir) + importFrom(utils, untar) + untar(file.path(data_dir, paste0(frags_name, ".tar.gz")), exdir = data_dir) file.remove(file.path(data_dir, paste0(frags_name, ".tar.gz"))) } } diff --git a/r/R/trackplots.R b/r/R/trackplots.R index a3194817..5c346726 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -18,10 +18,10 @@ trackplot_theme <- function(base_size=11) { ggplot2::theme( panel.grid = ggplot2::element_blank(), panel.spacing.y = ggplot2::unit(0, "pt"), - strip.text.y.left = ggplot2::element_text(angle=0, hjust=1, size=ggplot2::rel(1.2)) + importFrom(ggplot2, element_text), + strip.text.y.left = ggplot2::element_text(angle=0, hjust=1, size=ggplot2::rel(1.2)), strip.background = ggplot2::element_blank(), strip.placement = "outside", - axis.title.y.left = ggplot2::element_text(size=ggplot2::rel(1)) + importFrom(ggplot2, element_text) + axis.title.y.left = ggplot2::element_text(size=ggplot2::rel(1)) ) } @@ -441,7 +441,7 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ ) } if (!is.null(title)) { - patch <- patch + patchwork::plot_annotation(title = title, theme = ggplot2::theme(plot.title = ggplot2::element_text(hjust = 0.5) + importFrom(ggplot2, element_text))) + patch <- patch + patchwork::plot_annotation(title = title, theme = ggplot2::theme(plot.title = ggplot2::element_text(hjust = 0.5) } return(patch) } @@ -1125,7 +1125,7 @@ draw_trackplot_grid <- function(..., labels, title = NULL, patch <- Reduce(`+`, c(labels_plots, data_plots)) + patchwork::plot_layout(ncol = 2, byrow = FALSE, widths = c(label_width, 1), heights = heights, guides = "collect") if (!is.null(title)) { - patch <- patch + patchwork::plot_annotation(title = title, theme = theme(plot.title = element_text(hjust = 0.5) + importFrom(ggplot2, element_text))) + patch <- patch + patchwork::plot_annotation(title = title, theme = ggplot2::theme(plot.title = ggplot2::element_text(hjust = 0.5))) } return(patch) } From b81f8c92e863a69fd7c931e86c2f9e47da60b6a0 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 24 Nov 2025 16:13:31 -0800 Subject: [PATCH 46/84] test --- .github/workflows/check-standard-test.yaml | 1 + r/check-wrapper.R | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 r/check-wrapper.R diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index 29d838bf..be10cb31 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -103,6 +103,7 @@ jobs: uses: r-lib/actions/check-r-package@v2 with: working-directory: r + check-script: check-wrapper.R build_args: c("--no-build-vignettes") upload-snapshots: false error-on: '"error"' diff --git a/r/check-wrapper.R b/r/check-wrapper.R new file mode 100644 index 00000000..84ef27ea --- /dev/null +++ b/r/check-wrapper.R @@ -0,0 +1,9 @@ + +args <- commandArgs(TRUE) + +# Disable timestamp check completely +Sys.setenv("_R_CHECK_FUTURE_FILE_TIMESTAMPS_"="false") +Sys.setenv("_R_CHECK_SYSTEM_CLOCK_"="0") + +# Call R CMD check as normal +tools:::.check_packages(args) \ No newline at end of file From 89d0adeb671b3845466f1da6838ed54b605ca15b Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 25 Nov 2025 20:48:51 -0800 Subject: [PATCH 47/84] remove syntax error in trackplots.R --- r/R/trackplots.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r/R/trackplots.R b/r/R/trackplots.R index 5c346726..54dc82a9 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -441,7 +441,7 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ ) } if (!is.null(title)) { - patch <- patch + patchwork::plot_annotation(title = title, theme = ggplot2::theme(plot.title = ggplot2::element_text(hjust = 0.5) + patch <- patch + patchwork::plot_annotation(title = title, theme = ggplot2::theme(plot.title = ggplot2::element_text(hjust = 0.5))) } return(patch) } From 5e9b8e1a7135cc07c10d4ed9d6c5b481c53902cf Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 25 Nov 2025 21:13:14 -0800 Subject: [PATCH 48/84] add some code cleanup to removve some cmd check warnings --- r/DESCRIPTION | 4 ++-- r/R/data.R | 4 ++-- r/R/plots.R | 1 + r/R/trackplots.R | 18 ++++++++++++++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 35f71e69..301e3849 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -46,11 +46,11 @@ Imports: purrr, scattermore, ggrepel, - RColorBrewer, - hexbin + RColorBrewer Suggests: IRanges, tidyr, + hexbin, GenomicRanges, GenomeInfoDb, S4Vectors, diff --git a/r/R/data.R b/r/R/data.R index b0f73b4f..8cc43bde 100644 --- a/r/R/data.R +++ b/r/R/data.R @@ -188,7 +188,7 @@ get_demo_mat <- function(filter_qc = TRUE, subset = TRUE) { if (!file.exists(file.path(data_dir, paste0(mat_name, ".tar.gz")))) { prepare_demo_data(data_dir, filter_qc = filter_qc, subset = subset) } else { - untar(file.path(data_dir, paste0(mat_name, ".tar.gz")), exdir=data_dir) + utils::untar(file.path(data_dir, paste0(mat_name, ".tar.gz")), exdir=data_dir) file.remove(file.path(data_dir, paste0(mat_name, ".tar.gz"))) } } @@ -222,7 +222,7 @@ get_demo_frags <- function(filter_qc = TRUE, subset = TRUE) { if (!file.exists(file.path(data_dir, paste0(frags_name, ".tar.gz")))) { prepare_demo_data(data_dir) } else { - untar(file.path(data_dir, paste0(frags_name, ".tar.gz")), exdir = data_dir) + utils::untar(file.path(data_dir, paste0(frags_name, ".tar.gz")), exdir = data_dir) file.remove(file.path(data_dir, paste0(frags_name, ".tar.gz"))) } } diff --git a/r/R/plots.R b/r/R/plots.R index b1a5354d..753cae87 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -201,6 +201,7 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE #' plot_tss_scatter(atac_qc, min_frags = 1000, min_tss = 10) #' @export plot_tss_scatter <- function(atac_qc, min_frags = NULL, min_tss = NULL, bins = 100, apply_styling = TRUE) { + assert_has_package("hexbin") assert_is(atac_qc, "data.frame") if (!is.null(min_frags)) { assert_is_numeric(min_frags) diff --git a/r/R/trackplots.R b/r/R/trackplots.R index 54dc82a9..ed1a0a64 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -1288,6 +1288,24 @@ scale_next_plot_height <- function(scale) { #' by `trackplot_combine()`) renders too tall/short in a pipeline and you want a #' quick scaling tweak without touching the plot code itself. The scaling factor #' is applied once and then cleared. +#' @param filename The name of the file. Follows the same semantics as the file naming in `grDevices::png()`, +#' meaning that you can provide a sprintf() compliant string format to name multiple plots (such as the default value) +#' @param width,height The dimensions of the device +#' @param units The unit width and height is measured in, +#' in either pixels `('px')`, inches `('in')`, millimeters `('mm')`, or centimeter `('cm')`. +#' @param pointsize The default pointsize of the device in pt. +#' This will in general not have any effect on grid graphics (including ggplot2) as text size is always set explicitly there. +#' @param background The background color of the device +#' @param res The resolution of the device. +#' This setting will govern how device dimensions given in inches, centimeters, or millimeters will be converted to pixels. +#' Further, it will be used to scale text sizes and linewidths +#' @param scaling A scaling factor to apply to the rendered line width and text size. Useful for getting the right dimensions +#' at the resolution that you need. If e.g. you need to render a plot at 4000x3000 pixels for it to fit into a layout, +#' but you find that the result appears to small, you can increase the `scaling` argument to make everything appear bigger at the same resolution. +#' @param snap_rect Should axis-aligned rectangles drawn with only fill snap to the pixel grid. +#' This will prevent anti-aliasing artifacts when two rectangles are touching at their border. +#' @param bitsize Should the dvice record colour as 8 or 16bit +#' @param bg Same as `background` for compatibility with old graphic device APIs` #' @return A graphics device as returned by `ragg::agg_png()`. #' @export ragg_wrap <- function( From 28b5bc1f5ab41b51860d883830a7f5aec4dfa4d2 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 25 Nov 2025 21:15:18 -0800 Subject: [PATCH 49/84] add cleanup.win, misc leftovers from last commit --- r/NAMESPACE | 2 ++ r/cleanup.win | 17 +++++++++++++++++ r/man/IterableMatrix-methods.Rd | 4 ++-- r/man/ragg_wrap.Rd | 29 +++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 r/cleanup.win diff --git a/r/NAMESPACE b/r/NAMESPACE index 31a69691..f73d54c7 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -157,6 +157,7 @@ importFrom(Matrix,rowMeans) importFrom(Matrix,rowSums) importFrom(Matrix,t) importFrom(Rcpp,sourceCpp) +importFrom(ggplot2,element_text) importFrom(ggplot2,theme) importFrom(graphics,text) importFrom(magrittr,"%>%") @@ -188,6 +189,7 @@ importFrom(stats,start) importFrom(utils,download.file) importFrom(utils,head) importFrom(utils,tail) +importFrom(utils,untar) importMethodsFrom(Matrix,colMeans) importMethodsFrom(Matrix,colSums) importMethodsFrom(Matrix,rowMeans) diff --git a/r/cleanup.win b/r/cleanup.win new file mode 100644 index 00000000..44856041 --- /dev/null +++ b/r/cleanup.win @@ -0,0 +1,17 @@ +#!/bin/sh + +if [ -f src/Makevars ]; then + rm src/Makevars +fi + +if [ -f tools/h5write ]; then + rm tools/h5write +fi + +if [ -f tools/h5write.exe ]; then + rm tools/h5write.exe +fi + +if [ -d tools/highway/lib ]; then + rm -r tools/highway/lib +fi diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods.Rd index 761694c5..16f9df69 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods.Rd @@ -198,11 +198,11 @@ expm1_slow(x) \item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} +\item{digits}{Number of decimal places for quantile calculations} + \item{e1}{First element of comparison} \item{e2}{Second element of comparison} - -\item{digits}{Number of decimal places for quantile calculations} } \value{ \itemize{ diff --git a/r/man/ragg_wrap.Rd b/r/man/ragg_wrap.Rd index 817a1c13..07cbb3b1 100644 --- a/r/man/ragg_wrap.Rd +++ b/r/man/ragg_wrap.Rd @@ -18,6 +18,35 @@ ragg_wrap( bg ) } +\arguments{ +\item{filename}{The name of the file. Follows the same semantics as the file naming in \code{grDevices::png()}, +meaning that you can provide a sprintf() compliant string format to name multiple plots (such as the default value)} + +\item{width, height}{The dimensions of the device} + +\item{units}{The unit width and height is measured in, +in either pixels \code{('px')}, inches \code{('in')}, millimeters \code{('mm')}, or centimeter \code{('cm')}.} + +\item{pointsize}{The default pointsize of the device in pt. +This will in general not have any effect on grid graphics (including ggplot2) as text size is always set explicitly there.} + +\item{background}{The background color of the device} + +\item{res}{The resolution of the device. +This setting will govern how device dimensions given in inches, centimeters, or millimeters will be converted to pixels. +Further, it will be used to scale text sizes and linewidths} + +\item{scaling}{A scaling factor to apply to the rendered line width and text size. Useful for getting the right dimensions +at the resolution that you need. If e.g. you need to render a plot at 4000x3000 pixels for it to fit into a layout, +but you find that the result appears to small, you can increase the \code{scaling} argument to make everything appear bigger at the same resolution.} + +\item{snap_rect}{Should axis-aligned rectangles drawn with only fill snap to the pixel grid. +This will prevent anti-aliasing artifacts when two rectangles are touching at their border.} + +\item{bitsize}{Should the dvice record colour as 8 or 16bit} + +\item{bg}{Same as \code{background} for compatibility with old graphic device APIs`} +} \value{ A graphics device as returned by \code{ragg::agg_png()}. } From 6861ced4401e89ec139a15a3024bfc1b9c0a033b Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 26 Nov 2025 00:45:41 -0800 Subject: [PATCH 50/84] add ragg changes, clean up coesion docs --- r/DESCRIPTION | 1 + r/NAMESPACE | 1 + r/R/fragments.R | 36 +++++++++++++++++++++-------- r/R/matrix.R | 20 +++++++++++++--- r/R/trackplots.R | 1 + r/man/fragment_R_conversion.Rd | 12 ---------- r/man/fragment_r_conversion-misc.Rd | 31 +++++++++++++++++++++++++ r/man/matrix_R_conversion.Rd | 12 ---------- r/man/matrix_r_conversion-misc.Rd | 29 +++++++++++++++++++++++ 9 files changed, 106 insertions(+), 37 deletions(-) create mode 100644 r/man/fragment_r_conversion-misc.Rd create mode 100644 r/man/matrix_r_conversion-misc.Rd diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 301e3849..45cd74fb 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -43,6 +43,7 @@ Imports: ggplot2 (>= 3.4.0), scales, patchwork, + ragg, purrr, scattermore, ggrepel, diff --git a/r/NAMESPACE b/r/NAMESPACE index f73d54c7..f9933d68 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -178,6 +178,7 @@ importFrom(methods,setClass) importFrom(methods,setGeneric) importFrom(methods,setMethod) importFrom(methods,show) +importFrom(ragg,agg_png) importFrom(stats,as.formula) importFrom(stats,end) importFrom(stats,model.matrix) diff --git a/r/R/fragments.R b/r/R/fragments.R index a79a039b..19b1c747 100644 --- a/r/R/fragments.R +++ b/r/R/fragments.R @@ -689,8 +689,6 @@ open_fragments_hdf5 <- function(path, group = "fragments", buffer_size = 16384L) #' @param IterableFragments BPCells IterableFragments object #' @param data.frame Data frame with columns chr, start, end, and cell_id #' @param GRanges GenomicRanges object with metadata column cell_id -#' @param from Object supplied to `base::coerce()` (typically generated by `as()`) -#' @param to Target class name for coercion #' @param zero_based_coords Whether to convert the ranges from a 1-based end-inclusive #' coordinate system to a 0-based end-exclusive coordinate system. Defaults to true #' for GRanges and false for other formats @@ -744,16 +742,8 @@ open_fragments_hdf5 <- function(path, group = "fragments", buffer_size = 16384L) #' #' @rdname fragment_R_conversion #' @name fragment_R_conversion_coercions -#' @aliases coerce,data.frame,IterableFragments-method -#' @aliases coerce,IterableFragments,data.frame-method -#' @aliases coerce,GRanges,IterableFragments-method -#' @aliases coerce,IterableFragments,GRanges-method #' @usage #' \method{as.data.frame}{IterableFragments}(x, row.names = NULL, optional = FALSE, ...) -#' \S4method{coerce}{data.frame,IterableFragments}(from, to, ...) -#' \S4method{coerce}{IterableFragments,data.frame}(from, to, ...) -#' \S4method{coerce}{IterableFragments,GRanges}(from, to, ...) -#' \S4method{coerce}{GRanges,IterableFragments}(from, to, ...) NULL #' IterableFragments subclass methods @@ -769,6 +759,32 @@ NULL #' @keywords internal NULL +#' Convert between BPCells fraagments and R objects misc. +#' +#' See `fragment_R_conversion` for main page. +#' BPCells fragments can be interconverted with GRanges and data.frame R objects. +#' The main conversion method is R's builtin `as()` function, though the convert_to_fragments() helper is also available. +#' For all R objects except GRanges, BPCells assumes a 0-based, end-exclusive coordinate system. +#' (See `genomic-ranges-like`` reference for details) +#' +#' @param from Object supplied to `base::coerce()` (typically generated by `as()`) +#' @param to Target class name for coercion +#' @param ... Additional arguments passed to methods +#' @aliases coerce,data.frame,IterableFragments-method +#' @aliases coerce,IterableFragments,data.frame-method +#' @aliases coerce,GRanges,IterableFragments-method +#' @aliases coerce,IterableFragments,GRanges-method +#' @usage +#' \S4method{coerce}{data.frame,IterableFragments}(from, to, ...) +#' \S4method{coerce}{IterableFragments,data.frame}(from, to, ...) +#' \S4method{coerce}{IterableFragments,GRanges}(from, to, ...) +#' \S4method{coerce}{GRanges,IterableFragments}(from, to, ...) +#' @name fragment_r_conversion-misc +#' @rdname fragment_r_conversion-misc +#' @docType methods +#' @keywords internal +NULL + #' @rdname fragment_R_conversion #' @export convert_to_fragments <- function(x, zero_based_coords = !is(x, "GRanges")) { diff --git a/r/R/matrix.R b/r/R/matrix.R index 8ac40d47..1a28b039 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -3118,8 +3118,6 @@ convert_matrix_type <- function(matrix, type = c("uint32_t", "double", "float")) #' @param dgCMatrix Sparse matrix in dgCMatrix format #' @param IterableMatrix IterableMatrix object #' @param ... Additional arguments passed to methods -#' @param from Object supplied to `base::coerce()` (typically generated by `as()`) -#' @param to Target class name for coercion #' @examples #' mat <- get_demo_mat()[1:2, 1:2] #' mat @@ -3146,16 +3144,32 @@ convert_matrix_type <- function(matrix, type = c("uint32_t", "double", "float")) #' #' @rdname matrix_R_conversion #' @name matrix_R_conversion_coercions +#' @usage +#' \method{as.matrix}{IterableMatrix}(x, ...) +NULL + +#' Convert between BPCells matrices and R objects misc. +#' +#' See `matrix_R_conversion` for main page. +#' BPCells matrices can be interconverted with Matrix package `dgCMatrix` sparse matrices, +#' as well as base R dense matrices (though this may result in high memory usage for large matrices). +#' +#' @param from Object supplied to `base::coerce()` (typically generated by `as()`) +#' @param to Target class name for coercion +#' @param ... Additional arguments passed to methods #' @aliases coerce,dgCMatrix,IterableMatrix-method #' @aliases coerce,IterableMatrix,dgCMatrix-method #' @aliases coerce,matrix,IterableMatrix-method #' @aliases coerce,IterableMatrix,matrix-method #' @usage -#' \method{as.matrix}{IterableMatrix}(x, ...) #' \S4method{coerce}{dgCMatrix,IterableMatrix}(from, to, ...) #' \S4method{coerce}{IterableMatrix,dgCMatrix}(from, to, ...) #' \S4method{coerce}{matrix,IterableMatrix}(from, to, ...) #' \S4method{coerce}{IterableMatrix,matrix}(from, to, ...) +#' @name matrix_r_conversion-misc +#' @rdname matrix_r_conversion-misc +#' @docType methods +#' @keywords internal NULL #' @name matrix_R_conversion diff --git a/r/R/trackplots.R b/r/R/trackplots.R index ed1a0a64..45f3a4ec 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -1288,6 +1288,7 @@ scale_next_plot_height <- function(scale) { #' by `trackplot_combine()`) renders too tall/short in a pipeline and you want a #' quick scaling tweak without touching the plot code itself. The scaling factor #' is applied once and then cleared. +#' @importFrom ragg agg_png #' @param filename The name of the file. Follows the same semantics as the file naming in `grDevices::png()`, #' meaning that you can provide a sprintf() compliant string format to name multiple plots (such as the default value) #' @param width,height The dimensions of the device diff --git a/r/man/fragment_R_conversion.Rd b/r/man/fragment_R_conversion.Rd index 3abed3ac..4c76c46e 100644 --- a/r/man/fragment_R_conversion.Rd +++ b/r/man/fragment_R_conversion.Rd @@ -3,18 +3,10 @@ \name{fragment_R_conversion_coercions} \alias{fragment_R_conversion_coercions} \alias{as.data.frame.IterableFragments} -\alias{coerce,data.frame,IterableFragments-method} -\alias{coerce,IterableFragments,data.frame-method} -\alias{coerce,GRanges,IterableFragments-method} -\alias{coerce,IterableFragments,GRanges-method} \alias{convert_to_fragments} \title{Convert between BPCells fragments and R objects.} \usage{ \method{as.data.frame}{IterableFragments}(x, row.names = NULL, optional = FALSE, ...) -\S4method{coerce}{data.frame,IterableFragments}(from, to, ...) -\S4method{coerce}{IterableFragments,data.frame}(from, to, ...) -\S4method{coerce}{IterableFragments,GRanges}(from, to, ...) -\S4method{coerce}{GRanges,IterableFragments}(from, to, ...) convert_to_fragments(x, zero_based_coords = !is(x, "GRanges")) } @@ -36,10 +28,6 @@ for GRanges and false for other formats \item{GRanges}{GenomicRanges object with metadata column cell_id} -\item{from}{Object supplied to \code{base::coerce()} (typically generated by \code{as()})} - -\item{to}{Target class name for coercion} - \item{...}{Additional arguments passed to methods} \item{row.names}{Optional row names for compatibility with \code{as.data.frame()}. diff --git a/r/man/fragment_r_conversion-misc.Rd b/r/man/fragment_r_conversion-misc.Rd new file mode 100644 index 00000000..b86ccccc --- /dev/null +++ b/r/man/fragment_r_conversion-misc.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fragments.R +\docType{methods} +\name{fragment_r_conversion-misc} +\alias{fragment_r_conversion-misc} +\alias{coerce,data.frame,IterableFragments-method} +\alias{coerce,IterableFragments,data.frame-method} +\alias{coerce,GRanges,IterableFragments-method} +\alias{coerce,IterableFragments,GRanges-method} +\title{Convert between BPCells fraagments and R objects misc.} +\usage{ +\S4method{coerce}{data.frame,IterableFragments}(from, to, ...) +\S4method{coerce}{IterableFragments,data.frame}(from, to, ...) +\S4method{coerce}{IterableFragments,GRanges}(from, to, ...) +\S4method{coerce}{GRanges,IterableFragments}(from, to, ...) +} +\arguments{ +\item{from}{Object supplied to \code{base::coerce()} (typically generated by \code{as()})} + +\item{to}{Target class name for coercion} + +\item{...}{Additional arguments passed to methods} +} +\description{ +See \code{fragment_R_conversion} for main page. +BPCells fragments can be interconverted with GRanges and data.frame R objects. +The main conversion method is R's builtin \code{as()} function, though the convert_to_fragments() helper is also available. +For all R objects except GRanges, BPCells assumes a 0-based, end-exclusive coordinate system. +(See `genomic-ranges-like`` reference for details) +} +\keyword{internal} diff --git a/r/man/matrix_R_conversion.Rd b/r/man/matrix_R_conversion.Rd index 4f8da8b9..4feb7314 100644 --- a/r/man/matrix_R_conversion.Rd +++ b/r/man/matrix_R_conversion.Rd @@ -4,18 +4,10 @@ \alias{matrix_R_conversion_coercions} \alias{as.matrix.IterableMatrix} \alias{as.matrix,IterableMatrix-method} -\alias{coerce,dgCMatrix,IterableMatrix-method} -\alias{coerce,IterableMatrix,dgCMatrix-method} -\alias{coerce,matrix,IterableMatrix-method} -\alias{coerce,IterableMatrix,matrix-method} \alias{matrix_R_conversion} \title{Convert between BPCells matrix and R objects.} \usage{ \method{as.matrix}{IterableMatrix}(x, ...) -\S4method{coerce}{dgCMatrix,IterableMatrix}(from, to, ...) -\S4method{coerce}{IterableMatrix,dgCMatrix}(from, to, ...) -\S4method{coerce}{matrix,IterableMatrix}(from, to, ...) -\S4method{coerce}{IterableMatrix,matrix}(from, to, ...) } \arguments{ \item{x}{Matrix object to convert} @@ -25,10 +17,6 @@ \item{IterableMatrix}{IterableMatrix object} \item{...}{Additional arguments passed to methods} - -\item{from}{Object supplied to \code{base::coerce()} (typically generated by \code{as()})} - -\item{to}{Target class name for coercion} } \description{ BPCells matrices can be interconverted with Matrix package diff --git a/r/man/matrix_r_conversion-misc.Rd b/r/man/matrix_r_conversion-misc.Rd new file mode 100644 index 00000000..95065fca --- /dev/null +++ b/r/man/matrix_r_conversion-misc.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix.R +\docType{methods} +\name{matrix_r_conversion-misc} +\alias{matrix_r_conversion-misc} +\alias{coerce,dgCMatrix,IterableMatrix-method} +\alias{coerce,IterableMatrix,dgCMatrix-method} +\alias{coerce,matrix,IterableMatrix-method} +\alias{coerce,IterableMatrix,matrix-method} +\title{Convert between BPCells matrices and R objects misc.} +\usage{ +\S4method{coerce}{dgCMatrix,IterableMatrix}(from, to, ...) +\S4method{coerce}{IterableMatrix,dgCMatrix}(from, to, ...) +\S4method{coerce}{matrix,IterableMatrix}(from, to, ...) +\S4method{coerce}{IterableMatrix,matrix}(from, to, ...) +} +\arguments{ +\item{from}{Object supplied to \code{base::coerce()} (typically generated by \code{as()})} + +\item{to}{Target class name for coercion} + +\item{...}{Additional arguments passed to methods} +} +\description{ +See \code{matrix_R_conversion} for main page. +BPCells matrices can be interconverted with Matrix package \code{dgCMatrix} sparse matrices, +as well as base R dense matrices (though this may result in high memory usage for large matrices). +} +\keyword{internal} From a9857561d554beb28c04cc748ceb760d6c05311c Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 1 Dec 2025 22:00:01 -0800 Subject: [PATCH 51/84] add cleanup to iterablematrix-methods documentation --- r/R/matrix.R | 15 +++++---- r/man/IterableMatrix-methods-misc.Rd | 46 +++++++++++++++++++++++++++- r/man/IterableMatrix-methods.Rd | 38 ----------------------- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/r/R/matrix.R b/r/R/matrix.R index 1a28b039..243fcb05 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -28,8 +28,11 @@ NULL #' For instance, `%*%` is described between `IterableMatrix` and `matrix` on the left and right respectively. #' We do not need to show the method `IterableMatrix` on the right instead. #' +#' @param x IterableMatrix object or compatible operand +#' @param y IterableMatrix object or compatible operand #' @param ... Additional arguments passed to methods #' @param digits Number of decimal places for quantile calculations +#' @param value Replacement value supplied to assignment methods. #' @param drop Logical indicating whether to drop dimensions when subsetting. #' @name IterableMatrix-methods-misc #' @rdname IterableMatrix-methods-misc @@ -319,7 +322,7 @@ setMethod("%*%", signature(x = "matrix", y = "IterableMatrix"), function(x, y) { res }) -#' @describeIn IterableMatrix-methods Multiply an IterableMatrix by a numeric vector +#' @describeIn IterableMatrix-methods-misc Multiply an IterableMatrix by a numeric vector setMethod("%*%", signature(x = "IterableMatrix", y = "numeric"), function(x, y) { iter <- iterate_matrix(convert_matrix_type(x, "double")) if (x@transpose) { @@ -467,7 +470,7 @@ setMethod("short_description", "MatrixMultiply", function(x) { } }) -#' @describeIn IterableMatrix-methods Multiply two IterableMatrix objects +#' @describeIn IterableMatrix-methods-misc Multiply two IterableMatrix objects setMethod("%*%", signature(x = "IterableMatrix", y = "IterableMatrix"), function(x, y) { if (x@transpose != y@transpose) stop("Cannot multiply matrices with different internal transpose states.\nPlease use transpose_storage_order().") if (x@transpose) { @@ -487,7 +490,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "IterableMatrix"), function new("MatrixMultiply", left = x, right = y, transpose = FALSE, dim = dim, dimnames = dimnames) }) -#' @describeIn IterableMatrix-methods Multiply an IterableMatrix by a dgCMatrix +#' @describeIn IterableMatrix-methods-misc Multiply an IterableMatrix by a dgCMatrix setMethod("%*%", signature(x = "IterableMatrix", y = "dgCMatrix"), function(x, y) { if (x@transpose) { t(as(t(y), "IterableMatrix") %*% t(x)) @@ -782,7 +785,7 @@ rowVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = } } #' @export -#' @describeIn IterableMatrix-methods Calculate rowVars (replacement for `matrixStats::rowVars()`) +#' @describeIn IterableMatrix-methods-misc Calculate rowVars (replacement for `matrixStats::rowVars()`) #' @method rowVars IterableMatrix rowVars.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (!is.null(rows) || !is.null(cols) || !isFALSE(na.rm) || !is.null(center) || !isTRUE(useNames)) { @@ -822,7 +825,7 @@ rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., use } } #' @export -#' @describeIn IterableMatrix-methods Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) +#' @describeIn IterableMatrix-methods-misc Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) #' @method rowMaxs IterableMatrix rowMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if(!is.null(rows) || !is.null(cols) || !isFALSE(na.rm)) { @@ -1202,7 +1205,7 @@ setMethod("dimnames<-", signature(x = "IterableMatrix", value = "list"), functio x }) #' @export -#' @describeIn IterableMatrix-methods Remove dimnames of an IterableMatrix +#' @describeIn IterableMatrix-methods-misc Remove dimnames of an IterableMatrix setMethod("dimnames<-", signature(x = "IterableMatrix", value = "NULL"), function(x, value) { if (identical(dimnames(x), value)) return(x) if (!is(x, "RenameDims")) { diff --git a/r/man/IterableMatrix-methods-misc.Rd b/r/man/IterableMatrix-methods-misc.Rd index 164cb398..06a9cf4b 100644 --- a/r/man/IterableMatrix-methods-misc.Rd +++ b/r/man/IterableMatrix-methods-misc.Rd @@ -3,8 +3,14 @@ \name{IterableMatrix-methods-misc} \alias{IterableMatrix-methods-misc} \alias{\%*\%,matrix,IterableMatrix-method} +\alias{\%*\%,IterableMatrix,numeric-method} \alias{\%*\%,numeric,IterableMatrix-method} +\alias{\%*\%,IterableMatrix,IterableMatrix-method} +\alias{\%*\%,IterableMatrix,dgCMatrix-method} \alias{\%*\%,dgCMatrix,IterableMatrix-method} +\alias{rowVars.IterableMatrix} +\alias{rowMaxs.IterableMatrix} +\alias{dimnames<-,IterableMatrix,NULL-method} \alias{rowQuantiles.IterableMatrix} \alias{colQuantiles.IterableMatrix} \alias{<,IterableMatrix,numeric-method} @@ -18,10 +24,30 @@ \usage{ \S4method{\%*\%}{matrix,IterableMatrix}(x, y) +\S4method{\%*\%}{IterableMatrix,numeric}(x, y) + \S4method{\%*\%}{numeric,IterableMatrix}(x, y) +\S4method{\%*\%}{IterableMatrix,IterableMatrix}(x, y) + +\S4method{\%*\%}{IterableMatrix,dgCMatrix}(x, y) + \S4method{\%*\%}{dgCMatrix,IterableMatrix}(x, y) +\method{rowVars}{IterableMatrix}( + x, + rows = NULL, + cols = NULL, + na.rm = FALSE, + center = NULL, + ..., + useNames = TRUE +) + +\method{rowMaxs}{IterableMatrix}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) + +\S4method{dimnames}{IterableMatrix,NULL}(x) <- value + \method{rowQuantiles}{IterableMatrix}( x, rows = NULL, @@ -63,10 +89,16 @@ colQuantiles.IterableMatrix( \S4method{-}{numeric,IterableMatrix}(e1, e2) } \arguments{ -\item{digits}{Number of decimal places for quantile calculations} +\item{x}{IterableMatrix object or compatible operand} + +\item{y}{IterableMatrix object or compatible operand} \item{...}{Additional arguments passed to methods} +\item{value}{Replacement value supplied to assignment methods.} + +\item{digits}{Number of decimal places for quantile calculations} + \item{drop}{Logical indicating whether to drop dimensions when subsetting.} } \description{ @@ -79,10 +111,22 @@ We do not need to show the method \code{IterableMatrix} on the right instead. \itemize{ \item \code{x \%*\% y}: Multiply a dense matrix by an IterableMatrix +\item \code{x \%*\% y}: Multiply an IterableMatrix by a numeric vector + \item \code{x \%*\% y}: Multiply a numeric row vector by an IterableMatrix +\item \code{x \%*\% y}: Multiply two IterableMatrix objects + +\item \code{x \%*\% y}: Multiply an IterableMatrix by a dgCMatrix + \item \code{x \%*\% y}: Multiply a dgCMatrix by an IterableMatrix +\item \code{rowVars(IterableMatrix)}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) + +\item \code{rowMaxs(IterableMatrix)}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) + +\item \code{dimnames(x = IterableMatrix) <- value}: Remove dimnames of an IterableMatrix + \item \code{rowQuantiles(IterableMatrix)}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) \item \code{colQuantiles.IterableMatrix()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods.Rd index 16f9df69..05d997c8 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods.Rd @@ -8,23 +8,17 @@ \alias{show,IterableMatrix-method} \alias{t,IterableMatrix-method} \alias{\%*\%,IterableMatrix,matrix-method} -\alias{\%*\%,IterableMatrix,numeric-method} -\alias{\%*\%,IterableMatrix,IterableMatrix-method} -\alias{\%*\%,IterableMatrix,dgCMatrix-method} \alias{rowSums,IterableMatrix-method} \alias{colSums,IterableMatrix-method} \alias{rowMeans,IterableMatrix-method} \alias{colMeans,IterableMatrix-method} \alias{colVars} \alias{rowVars} -\alias{rowVars.IterableMatrix} \alias{rowMaxs} -\alias{rowMaxs.IterableMatrix} \alias{colMaxs} \alias{[,IterableMatrix,ANY,ANY,ANY-method} \alias{[<-,IterableMatrix,ANY,ANY,ANY-method} \alias{dimnames<-,IterableMatrix,list-method} -\alias{dimnames<-,IterableMatrix,NULL-method} \alias{rowQuantiles} \alias{colQuantiles} \alias{log1p,IterableMatrix-method} @@ -55,12 +49,6 @@ storage_order(x) \S4method{\%*\%}{IterableMatrix,matrix}(x, y) -\S4method{\%*\%}{IterableMatrix,numeric}(x, y) - -\S4method{\%*\%}{IterableMatrix,IterableMatrix}(x, y) - -\S4method{\%*\%}{IterableMatrix,dgCMatrix}(x, y) - \S4method{rowSums}{IterableMatrix}(x) \S4method{colSums}{IterableMatrix}(x) @@ -89,20 +77,8 @@ rowVars( useNames = TRUE ) -\method{rowVars}{IterableMatrix}( - x, - rows = NULL, - cols = NULL, - na.rm = FALSE, - center = NULL, - ..., - useNames = TRUE -) - rowMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) -\method{rowMaxs}{IterableMatrix}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) - colMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) \S4method{[}{IterableMatrix,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) @@ -111,8 +87,6 @@ colMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) \S4method{dimnames}{IterableMatrix,list}(x) <- value -\S4method{dimnames}{IterableMatrix,NULL}(x) <- value - rowQuantiles( x, rows = NULL, @@ -272,12 +246,6 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{x \%*\% y}: Multiply by a dense matrix -\item \code{x \%*\% y}: Multiply an IterableMatrix by a numeric vector - -\item \code{x \%*\% y}: Multiply two IterableMatrix objects - -\item \code{x \%*\% y}: Multiply an IterableMatrix by a dgCMatrix - \item \code{rowSums(IterableMatrix)}: Calculate rowSums \item \code{colSums(IterableMatrix)}: Calculate colSums @@ -290,12 +258,8 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{rowVars()}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) (generic) -\item \code{rowVars(IterableMatrix)}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) - \item \code{rowMaxs()}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) (generic) -\item \code{rowMaxs(IterableMatrix)}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) - \item \code{colMaxs()}: Calculate colMax (replacement for \code{matrixStats::colMax()}) \item \code{x[i}: Subset an IterableMatrix @@ -304,8 +268,6 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{dimnames(x = IterableMatrix) <- value}: Set dimnames of an IterableMatrix, similar to base R \verb{dimnames<-()} -\item \code{dimnames(x = IterableMatrix) <- value}: Remove dimnames of an IterableMatrix - \item \code{rowQuantiles()}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) \item \code{colQuantiles()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) From c453c40a32e3ad7acefa63c4a4f9ec9a17faa4b4 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 1 Dec 2025 22:05:25 -0800 Subject: [PATCH 52/84] remove removal of hitools/highway --- r/configure | 1 - 1 file changed, 1 deletion(-) diff --git a/r/configure b/r/configure index d6030c9d..ebbf6fc6 100755 --- a/r/configure +++ b/r/configure @@ -236,7 +236,6 @@ sed \ # # Clean up highway build directory to avoid CRAN NOTE about object files # # The highway library will be rebuilt as needed during installation -# rm -rf tools/highway/ if [ "$ENABLE_INSTALL_COUNTING" = "yes" ]; then curl --silent https://plausible.benparks.net/flask-plausible/bpcells-configure-success > /dev/null 2> /dev/null \ From f59e00313d19a65bc1684e229f3117dc884cf901 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 2 Dec 2025 00:37:10 -0800 Subject: [PATCH 53/84] clean up various R docs pages --- r/R/atac_utils.R | 19 +++++++++- r/R/fragments.R | 48 ++++++++++++------------- r/R/genomeAnnotations.R | 58 +++++++++++++++++++++++++++---- r/R/matrix.R | 56 +++++++++++++++++++++-------- r/R/plots.R | 13 ++----- r/man/call_peaks_tile.Rd | 16 +++++++++ r/man/fragment_R_conversion.Rd | 11 +++--- r/man/matrix_R_conversion.Rd | 7 ++-- r/man/open_fragments_10x.Rd | 36 +++++++++---------- r/man/peak_matrix.Rd | 47 ++++++++++++++++++------- r/man/read_bed.Rd | 2 +- r/man/read_gtf.Rd | 54 +++++++++++++++++++++++++--- r/man/read_ucsc_chrom_sizes.Rd | 2 +- r/man/write_insertion_bedgraph.Rd | 2 +- 14 files changed, 267 insertions(+), 104 deletions(-) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index 9855ce0d..708f3a10 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -380,7 +380,23 @@ merge_peaks_iterative <- function(peaks) { #' #' #' ## Call peaks +#' \dontrun{ #' call_peaks_tile(frags_filter_blacklist, chrom_sizes, effective_genome_size = 2.8e9) +#' } +#' #> # A tibble: 73,160 × 7 +#' #> chr start end group p_val q_val enrichment +#' #> +#' #> 1 chr11 65615400 65615600 all 0 0 6764. +#' #> 2 chr4 2262266 2262466 all 0 0 6422. +#' #> 3 chr11 119057200 119057400 all 0 0 6188. +#' #> 4 chr11 695133 695333 all 0 0 6180. +#' #> 5 chr11 2400400 2400600 all 0 0 6166. +#' #> 6 chr4 1346933 1347133 all 0 0 6109. +#' #> 7 chr11 3797600 3797800 all 0 0 6017. +#' #> 8 chr11 64878600 64878800 all 0 0 5948. +#' #> 9 chr11 57667733 57667933 all 0 0 5946. +#' #> 10 chr11 83156933 83157133 all 0 0 5913. +#' #> # ℹ 73,150 more rows #' @export call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int("all", length(cellNames(fragments))), effective_genome_size = NULL, @@ -508,7 +524,7 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' list.files(bedgraph_outputs) #' #' # With tiling -#' chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "reference"), genome="hg38") %>% +#' chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "references"), genome="hg38") %>% #' dplyr::filter(chr %in% c("chr4", "chr11")) #' write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all_tiled.bedGraph"), #' chrom_sizes = chrom_sizes, normalization_method = "cpm", tile_width = 100) @@ -890,3 +906,4 @@ range_overlaps <- function(a, b) { } %>% dplyr::arrange(from, to) } + \ No newline at end of file diff --git a/r/R/fragments.R b/r/R/fragments.R index 19b1c747..af933d10 100644 --- a/r/R/fragments.R +++ b/r/R/fragments.R @@ -221,15 +221,25 @@ setMethod("short_description", "FragmentsTsv", function(x) { #' 10x default, though it's not quite standard for the bed file format. #' @return 10x fragments file object #' @examples -#' ## Download example fragments from pbmc 500 dataset and save in temp directory +#' ####################################################################### +#' ## write_fragments_10x() example +#' ####################################################################### +#' ## Prep data +#' frags_table <- tibble::tribble( +#' ~chr, ~start, ~end, ~cell_id, +#' "chr1", 0, 5, "cell1", +#' "chr1", 2, 4, "cell2", +#' "chr2", 3, 6, "cell1", +#' "chr3", 7, 9, "cell2" +#' ) +#' frags_table +#' frags <- frags_table %>% convert_to_fragments() +#' #' data_dir <- file.path(tempdir(), "frags_10x") +#' frags_file <- "demo_10x_frags.tsv.gz" #' dir.create(data_dir, recursive = TRUE, showWarnings = FALSE) -#' url_base <- "https://cf.10xgenomics.com/samples/cell-atac/2.0.0/atac_pbmc_500_nextgem/" -#' frags_file <- "atac_pbmc_500_nextgem_fragments.tsv.gz" -#' atac_raw_url <- paste0(url_base, frags_file) -#' if (!file.exists(file.path(data_dir, frags_file))) { -#' download.file(atac_raw_url, file.path(data_dir, frags_file), mode="wb") -#' } +#' write_fragments_10x(frags, file.path(data_dir, frags_file)) +#' #' #' ####################################################################### #' ## open_fragments_10x() example @@ -242,7 +252,7 @@ setMethod("short_description", "FragmentsTsv", function(x) { #' frags #' #' frags %>% write_fragments_dir( -#' file.path(data_dir, "demo_frags_from_h5"), +#' file.path(data_dir, "new_demo_10x_frags"), #' overwrite = TRUE #' ) #' @@ -268,17 +278,6 @@ open_fragments_10x <- function(path, comment = "#", end_inclusive = TRUE) { #' @details **write_fragments_10x** #' #' Fragments will be written to disk immediately, then returned in a readable object. -#' @examples -#' ####################################################################### -#' ## write_fragments_10x() example -#' ####################################################################### -#' frags <- write_fragments_10x( -#' frags, -#' file.path(data_dir, paste0("new_", frags_file)) -#' ) -#' frags -#' -#' #' @export write_fragments_10x <- function(fragments, path, end_inclusive = TRUE, append_5th_column = FALSE) { assert_is_file(path, must_exist = FALSE, extension = c(".tsv", ".tsv.gz")) @@ -699,11 +698,12 @@ open_fragments_hdf5 <- function(path, group = "fragments", buffer_size = 16384L) #' @param optional Logical flag for compatibility with `as.data.frame()`; ignored. #' @return **convert_to_fragments()**: IterableFragments object #' @examples -#' frags_table <- tibble::tibble( -#' chr = paste0("chr", 1:10), -#' start = 0, -#' end = 5, -#' cell_id = "cell1" +#' frags_table <- tibble::tribble( +#' ~chr, ~start, ~end, ~cell_id, +#' "chr1", 0, 5, "cell1", +#' "chr1", 2, 4, "cell2", +#' "chr2", 3, 6, "cell1", +#' "chr3", 7, 9, "cell2" #' ) #' frags_table #' diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index 22446820..fb197bd6 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -54,15 +54,27 @@ ensure_downloaded <- function(path, backup_url, timeout) { #' ####################################################################### #' ## read_gtf() example #' ####################################################################### +#' \dontrun{ +#' #' species <- "Saccharomyces_cerevisiae" #' version <- "GCF_000146045.2_R64" #' head(read_gtf( -#' path = sprintf("%s/%s_genomic.gtf.gz", file.path(tempdir(), "reference"), version), +#' path = sprintf("%s/%s_genomic.gtf.gz", file.path(tempdir(), "references"), version), #' backup_url = sprintf( #' "https://ftp.ncbi.nlm.nih.gov/genomes/refseq/fungi/%s/reference/%s/%s_genomic.gtf.gz", #' species, version, version #' ) #' )) +#' #> # A tibble: 6 × 9 +#' #> chr source feature start end score strand frame gene_id +#' #> +#' #> 1 NC_001133.9 RefSeq gene 1806 2169 . - . YAL068C +#' #> 2 NC_001133.9 RefSeq gene 2479 2707 . + . YAL067W-A +#' #> 3 NC_001133.9 RefSeq gene 7234 9016 . - . YAL067C +#' #> 4 NC_001133.9 RefSeq gene 11564 11951 . - . YAL065C +#' #> 5 NC_001133.9 RefSeq gene 12045 12426 . + . YAL064W-B +#' #> 6 NC_001133.9 RefSeq gene 13362 13743 . - . YAL064C-A +#' } #' #' #' @seealso [read_bed()], [read_encode_blacklist()] @@ -107,7 +119,24 @@ read_gtf <- function(path, attributes = c("gene_id"), tags = character(0), featu #' ####################################################################### #' ## read_gencode_genes() example #' ####################################################################### -#' read_gencode_genes(file.path(tempdir(), "reference"), release = "42", timeout = 3000) +#' \dontrun{ +#' read_gencode_genes(file.path(tempdir(), "references"), release = "42", timeout = 3000) +#' #> # A tibble: 39,319 × 11 +#' #> chr source feature start end score strand frame gene_id gene_type +#' #> +#' #> 1 chr1 HAVANA gene 11868 14409 . + . ENSG00000290… lncRNA +#' #> 2 chr1 HAVANA gene 29553 31109 . + . ENSG00000243… lncRNA +#' #> 3 chr1 HAVANA gene 34553 36081 . - . ENSG00000237… lncRNA +#' #> 4 chr1 HAVANA gene 57597 64116 . + . ENSG00000290… lncRNA +#' #> 5 chr1 HAVANA gene 65418 71585 . + . ENSG00000186… protein_… +#' #> 6 chr1 HAVANA gene 89294 133723 . - . ENSG00000238… lncRNA +#' #> 7 chr1 HAVANA gene 89550 91105 . - . ENSG00000239… lncRNA +#' #> 8 chr1 HAVANA gene 139789 140339 . - . ENSG00000239… lncRNA +#' #> 9 chr1 HAVANA gene 141473 173862 . - . ENSG00000241… lncRNA +#' #> 10 chr1 HAVANA gene 160445 161525 . + . ENSG00000241… lncRNA +#' #> # ℹ 39,309 more rows +#' #> # ℹ 1 more variable: gene_name +#' } #' #' #' @export @@ -159,9 +188,24 @@ read_gencode_genes <- function(dir, release = "latest", #' ####################################################################### #' ## If read_gencode_genes() was already ran on the same release, #' ## will reuse previously downloaded annotations -#' read_gencode_transcripts(file.path(tempdir(), "reference"), release = "42", timeout = 3000) -#' -#' +#' \dontrun{ +#' read_gencode_transcripts(file.path(tempdir(), "references"), release = "42", timeout = 3000) +#' #> # A tibble: 220,296 × 13 +#' #> chr source feature start end score strand frame gene_id gene_type +#' #> +#' #> 1 chr1 HAVANA transcript 65418 71585 . + . ENSG00000… protein_… +#' #> 2 chr1 HAVANA exon 65418 65433 . + . ENSG00000… protein_… +#' #> 3 chr1 HAVANA exon 65519 65573 . + . ENSG00000… protein_… +#' #> 4 chr1 HAVANA exon 69036 71585 . + . ENSG00000… protein_… +#' #> 5 chr1 HAVANA transcript 450739 451678 . - . ENSG00000… protein_… +#' #> 6 chr1 HAVANA exon 450739 451678 . - . ENSG00000… protein_… +#' #> 7 chr1 HAVANA transcript 685715 686654 . - . ENSG00000… protein_… +#' #> 8 chr1 HAVANA exon 685715 686654 . - . ENSG00000… protein_… +#' #> 9 chr1 HAVANA transcript 923922 944574 . + . ENSG00000… protein_… +#' #> 10 chr1 HAVANA exon 923922 924948 . + . ENSG00000… protein_… +#' #> # ℹ 220,286 more rows +#' #> # ℹ 3 more variables: gene_name , transcript_id , MANE_Select +#' } #' @export read_gencode_transcripts <- function(dir, release = "latest", transcript_choice = c("MANE_Select", "Ensembl_Canonical", "all"), annotation_set = c("basic", "comprehensive"), @@ -246,7 +290,7 @@ read_bed <- function(path, additional_columns = character(0), backup_url = NULL, #' ####################################################################### #' ## read_encode_blacklist() example #' ####################################################################### -#' read_encode_blacklist(file.path(tempdir(), "reference")) +#' read_encode_blacklist(file.path(tempdir(), "references")) #' #' #' @export @@ -264,7 +308,7 @@ read_encode_blacklist <- function(dir, genome = c("hg38", "mm10", "hg19", "dm6", #' The underlying data is pulled from here: #' #' @examples -#' read_ucsc_chrom_sizes(file.path(tempdir(), "reference")) +#' read_ucsc_chrom_sizes(file.path(tempdir(), "references")) #' @export #' @param dir Output directory to cache the downloaded chrom sizes file diff --git a/r/R/matrix.R b/r/R/matrix.R index 243fcb05..89cf596d 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -2717,6 +2717,8 @@ setClass("PeakMatrix", setMethod("matrix_type", "PeakMatrix", function(x) "uint32_t") setMethod("matrix_inputs", "PeakMatrix", function(x) list()) + + #' Calculate ranges x cells overlap matrix #' @param fragments Input fragments object. Must have cell names and chromosome names defined #' @param ranges `r document_granges("Peaks/ranges to overlap,")` @@ -2740,22 +2742,43 @@ setMethod("matrix_inputs", "PeakMatrix", function(x) list()) #' spans the peak even if neither the start or end falls within the peak #' @examples #' ## Prep demo data -#' \dontrun{ -#' frags <- get_demo_frags(subset = FALSE) -#' chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "references"), genome="hg38") -#' blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") -#' frags_filter_blacklist <- frags %>% select_regions(blacklist, invert_selection = TRUE) -#' peaks <- call_peaks_tile( -#' frags_filter_blacklist, -#' chrom_sizes, -#' effective_genome_size = 2.8e9 +#' frags <- tibble::tribble( +#' ~chr, ~start, ~end, ~cell_id, +#' "chr1", 0, 5, "cell1", +#' "chr1", 2, 4, "cell2", +#' "chr2", 3, 6, "cell1", +#' "chr3", 7, 9, "cell2" +#' ) %>% convert_to_fragments() +#' frags +#' +#' # Note: this is how we would normally call peaks given this data +#' # We use a toy example here +#' # chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "references"), genome="hg38") +#' # blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") +#' # frags %>% select_regions(blacklist, invert_selection = TRUE) +#' # peaks <- call_peaks_tile( +#' # frags_filter_blacklist, +#' # chrom_sizes, +#' # effective_genome_size = 2.8e9 +#' # ) +#' peaks <- tibble::tribble( +#' ~chr, ~start, ~end, ~group, ~p_val, ~q_val, ~enrichment, +#' "chr1", 1, 4, "all", 0, 0, 767, +#' "chr2", 2, 8, "all", 0, 0, 766, +#' "chr3", 5, 10, "all", 0, 0, 645 #' ) -#' top_peaks <- head(peaks, 5000) -#' top_peaks <- top_peaks[order_ranges(top_peaks, chrNames(frags)),] +#' peaks +#' +#' # We would normally select the top peaks like this: +#' # peaks <- head(peaks, 5000) +#' # peaks <- peaks[order_ranges(peaks, chrNames(frags)),] #' #' ## Get peak matrix -#' peak_matrix(frags_filter_blacklist, top_peaks, mode="insertions") -#' } +#' peak_matrix(frags, peaks, mode="insertions") +#' peak_matrix +#' +#' peak_matrix %>% as("dgCMatrix") +#' #' @export peak_matrix <- function(fragments, ranges, mode = c("insertions", "fragments", "overlaps"), zero_based_coords = !is(ranges, "GRanges"), explicit_peak_names = TRUE) { assert_is(fragments, "IterableFragments") @@ -3122,10 +3145,13 @@ convert_matrix_type <- function(matrix, type = c("uint32_t", "double", "float")) #' @param IterableMatrix IterableMatrix object #' @param ... Additional arguments passed to methods #' @examples -#' mat <- get_demo_mat()[1:2, 1:2] +#' # setup data +#' mat <- matrix(1:25, nrow=5, ncol=5) +#' rownames(mat) <- paste0("gene", seq_len(5)) +#' colnames(mat) <- paste0("cell", seq_len(5)) +#' mat <- mat %>% as("IterableMatrix") #' mat #' -#' #' ####################################################################### #' ## as(bpcells_mat, "dgCMatrix") example #' ####################################################################### diff --git a/r/R/plots.R b/r/R/plots.R index 753cae87..bc113a04 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -154,16 +154,7 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE y = max(log10(data$data$reads)) ) rectangle_highlight <- tibble::tibble( - xmin = -Inf, xmax = Inf, - ymin = log10(cutoff), ymax = Inf - ) - plot <- plot + - ggplot2::geom_hline(yintercept = log10(cutoff), linetype = "dashed") + - ggplot2::geom_text(data = cell_label, ggplot2::aes(x, y, label = label), hjust = "inward", vjust = "inward") + - ggplot2::geom_rect( - ggplot2::aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, x = NULL, y = NULL), - data = rectangle_highlight, - alpha = 0.1 + xmin = -Inf, xmax = Inf,xxxxxx ) } @@ -278,7 +269,7 @@ plot_tss_scatter <- function(atac_qc, min_frags = NULL, min_tss = NULL, bins = 1 #' @inheritParams plot_embedding #' @return Numeric vector where index i contans the number of length-i fragments #' @examples -#' frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) +#' frags <- get_demo_frags() #' plot_fragment_length(frags) #' @export plot_fragment_length <- function(fragments, max_length = 500, return_data = FALSE, apply_styling = TRUE) { diff --git a/r/man/call_peaks_tile.Rd b/r/man/call_peaks_tile.Rd index 0552cd04..94dbcd5d 100644 --- a/r/man/call_peaks_tile.Rd +++ b/r/man/call_peaks_tile.Rd @@ -92,5 +92,21 @@ chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") \%>\% ## Call peaks +\dontrun{ call_peaks_tile(frags_filter_blacklist, chrom_sizes, effective_genome_size = 2.8e9) } +#> # A tibble: 73,160 × 7 +#> chr start end group p_val q_val enrichment +#> +#> 1 chr11 65615400 65615600 all 0 0 6764. +#> 2 chr4 2262266 2262466 all 0 0 6422. +#> 3 chr11 119057200 119057400 all 0 0 6188. +#> 4 chr11 695133 695333 all 0 0 6180. +#> 5 chr11 2400400 2400600 all 0 0 6166. +#> 6 chr4 1346933 1347133 all 0 0 6109. +#> 7 chr11 3797600 3797800 all 0 0 6017. +#> 8 chr11 64878600 64878800 all 0 0 5948. +#> 9 chr11 57667733 57667933 all 0 0 5946. +#> 10 chr11 83156933 83157133 all 0 0 5913. +#> # ℹ 73,150 more rows +} diff --git a/r/man/fragment_R_conversion.Rd b/r/man/fragment_R_conversion.Rd index 4c76c46e..465c4e94 100644 --- a/r/man/fragment_R_conversion.Rd +++ b/r/man/fragment_R_conversion.Rd @@ -52,11 +52,12 @@ materialises supported R objects as fragment stores. Coercions to and from \code{GRanges} require the GenomicRanges package to be installed. } \examples{ -frags_table <- tibble::tibble( - chr = paste0("chr", 1:10), - start = 0, - end = 5, - cell_id = "cell1" +frags_table <- tibble::tribble( + ~chr, ~start, ~end, ~cell_id, + "chr1", 0, 5, "cell1", + "chr1", 2, 4, "cell2", + "chr2", 3, 6, "cell1", + "chr3", 7, 9, "cell2" ) frags_table diff --git a/r/man/matrix_R_conversion.Rd b/r/man/matrix_R_conversion.Rd index 4feb7314..bd3fcc5a 100644 --- a/r/man/matrix_R_conversion.Rd +++ b/r/man/matrix_R_conversion.Rd @@ -29,10 +29,13 @@ Use base R's \code{as()} to convert between BPCells matrices and dense matrices directly when needed. } \examples{ -mat <- get_demo_mat()[1:2, 1:2] +# setup data +mat <- matrix(1:25, nrow=5, ncol=5) +rownames(mat) <- paste0("gene", seq_len(5)) +colnames(mat) <- paste0("cell", seq_len(5)) +mat <- mat \%>\% as("IterableMatrix") mat - ####################################################################### ## as(bpcells_mat, "dgCMatrix") example ####################################################################### diff --git a/r/man/open_fragments_10x.Rd b/r/man/open_fragments_10x.Rd index 6aa30050..f2df00ed 100644 --- a/r/man/open_fragments_10x.Rd +++ b/r/man/open_fragments_10x.Rd @@ -47,15 +47,25 @@ No disk operations will take place until the fragments are used in a function Fragments will be written to disk immediately, then returned in a readable object. } \examples{ -## Download example fragments from pbmc 500 dataset and save in temp directory +####################################################################### +## write_fragments_10x() example +####################################################################### +## Prep data +frags_table <- tibble::tribble( + ~chr, ~start, ~end, ~cell_id, + "chr1", 0, 5, "cell1", + "chr1", 2, 4, "cell2", + "chr2", 3, 6, "cell1", + "chr3", 7, 9, "cell2" +) +frags_table +frags <- frags_table \%>\% convert_to_fragments() + data_dir <- file.path(tempdir(), "frags_10x") +frags_file <- "demo_10x_frags.tsv.gz" dir.create(data_dir, recursive = TRUE, showWarnings = FALSE) -url_base <- "https://cf.10xgenomics.com/samples/cell-atac/2.0.0/atac_pbmc_500_nextgem/" -frags_file <- "atac_pbmc_500_nextgem_fragments.tsv.gz" -atac_raw_url <- paste0(url_base, frags_file) -if (!file.exists(file.path(data_dir, frags_file))) { - download.file(atac_raw_url, file.path(data_dir, frags_file), mode="wb") -} +write_fragments_10x(frags, file.path(data_dir, frags_file)) + ####################################################################### ## open_fragments_10x() example @@ -68,19 +78,9 @@ frags <- open_fragments_10x( frags frags \%>\% write_fragments_dir( - file.path(data_dir, "demo_frags_from_h5"), + file.path(data_dir, "new_demo_10x_frags"), overwrite = TRUE ) -####################################################################### -## write_fragments_10x() example -####################################################################### -frags <- write_fragments_10x( - frags, - file.path(data_dir, paste0("new_", frags_file)) -) -frags - - } diff --git a/r/man/peak_matrix.Rd b/r/man/peak_matrix.Rd index 0a25030e..b6c04450 100644 --- a/r/man/peak_matrix.Rd +++ b/r/man/peak_matrix.Rd @@ -54,20 +54,41 @@ provide the ordering of chromosomes to expect while reading the tsv. } \examples{ ## Prep demo data -\dontrun{ -frags <- get_demo_frags(subset = FALSE) -chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "references"), genome="hg38") -blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") -frags_filter_blacklist <- frags \%>\% select_regions(blacklist, invert_selection = TRUE) -peaks <- call_peaks_tile( - frags_filter_blacklist, - chrom_sizes, - effective_genome_size = 2.8e9 +frags <- tibble::tribble( + ~chr, ~start, ~end, ~cell_id, + "chr1", 0, 5, "cell1", + "chr1", 2, 4, "cell2", + "chr2", 3, 6, "cell1", + "chr3", 7, 9, "cell2" +) \%>\% convert_to_fragments() +frags + +# Note: this is how we would normally call peaks given this data +# We use a toy example here +# chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "references"), genome="hg38") +# blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") +# frags \%>\% select_regions(blacklist, invert_selection = TRUE) +# peaks <- call_peaks_tile( +# frags_filter_blacklist, +# chrom_sizes, +# effective_genome_size = 2.8e9 +# ) +peaks <- tibble::tribble( + ~chr, ~start, ~end, ~group, ~p_val, ~q_val, ~enrichment, + "chr1", 1, 4, "all", 0, 0, 767, + "chr2", 2, 8, "all", 0, 0, 766, + "chr3", 5, 10, "all", 0, 0, 645 ) -top_peaks <- head(peaks, 5000) -top_peaks <- top_peaks[order_ranges(top_peaks, chrNames(frags)),] +peaks + +# We would normally select the top peaks like this: +# peaks <- head(peaks, 5000) +# peaks <- peaks[order_ranges(peaks, chrNames(frags)),] ## Get peak matrix -peak_matrix(frags_filter_blacklist, top_peaks, mode="insertions") -} +peak_matrix(frags, peaks, mode="insertions") +peak_matrix + +peak_matrix \%>\% as("dgCMatrix") + } diff --git a/r/man/read_bed.Rd b/r/man/read_bed.Rd index 906f8b20..86530709 100644 --- a/r/man/read_bed.Rd +++ b/r/man/read_bed.Rd @@ -66,7 +66,7 @@ read_bed(file_name) ####################################################################### ## read_encode_blacklist() example ####################################################################### -read_encode_blacklist(file.path(tempdir(), "reference")) +read_encode_blacklist(file.path(tempdir(), "references")) } diff --git a/r/man/read_gtf.Rd b/r/man/read_gtf.Rd index 7d9d9d62..fe848d26 100644 --- a/r/man/read_gtf.Rd +++ b/r/man/read_gtf.Rd @@ -111,21 +111,50 @@ Read transcript models from GENCODE, for use with trackplot_gene() ####################################################################### ## read_gtf() example ####################################################################### +\dontrun{ + species <- "Saccharomyces_cerevisiae" version <- "GCF_000146045.2_R64" head(read_gtf( - path = sprintf("\%s/\%s_genomic.gtf.gz", file.path(tempdir(), "reference"), version), + path = sprintf("\%s/\%s_genomic.gtf.gz", file.path(tempdir(), "references"), version), backup_url = sprintf( "https://ftp.ncbi.nlm.nih.gov/genomes/refseq/fungi/\%s/reference/\%s/\%s_genomic.gtf.gz", species, version, version ) )) +#> # A tibble: 6 × 9 +#> chr source feature start end score strand frame gene_id +#> +#> 1 NC_001133.9 RefSeq gene 1806 2169 . - . YAL068C +#> 2 NC_001133.9 RefSeq gene 2479 2707 . + . YAL067W-A +#> 3 NC_001133.9 RefSeq gene 7234 9016 . - . YAL067C +#> 4 NC_001133.9 RefSeq gene 11564 11951 . - . YAL065C +#> 5 NC_001133.9 RefSeq gene 12045 12426 . + . YAL064W-B +#> 6 NC_001133.9 RefSeq gene 13362 13743 . - . YAL064C-A +} ####################################################################### ## read_gencode_genes() example ####################################################################### -read_gencode_genes(file.path(tempdir(), "reference"), release = "42", timeout = 3000) +\dontrun{ +read_gencode_genes(file.path(tempdir(), "references"), release = "42", timeout = 3000) +#> # A tibble: 39,319 × 11 +#> chr source feature start end score strand frame gene_id gene_type +#> +#> 1 chr1 HAVANA gene 11868 14409 . + . ENSG00000290… lncRNA +#> 2 chr1 HAVANA gene 29553 31109 . + . ENSG00000243… lncRNA +#> 3 chr1 HAVANA gene 34553 36081 . - . ENSG00000237… lncRNA +#> 4 chr1 HAVANA gene 57597 64116 . + . ENSG00000290… lncRNA +#> 5 chr1 HAVANA gene 65418 71585 . + . ENSG00000186… protein_… +#> 6 chr1 HAVANA gene 89294 133723 . - . ENSG00000238… lncRNA +#> 7 chr1 HAVANA gene 89550 91105 . - . ENSG00000239… lncRNA +#> 8 chr1 HAVANA gene 139789 140339 . - . ENSG00000239… lncRNA +#> 9 chr1 HAVANA gene 141473 173862 . - . ENSG00000241… lncRNA +#> 10 chr1 HAVANA gene 160445 161525 . + . ENSG00000241… lncRNA +#> # ℹ 39,309 more rows +#> # ℹ 1 more variable: gene_name +} ####################################################################### @@ -133,9 +162,24 @@ read_gencode_genes(file.path(tempdir(), "reference"), release = "42", timeout = ####################################################################### ## If read_gencode_genes() was already ran on the same release, ## will reuse previously downloaded annotations -read_gencode_transcripts(file.path(tempdir(), "reference"), release = "42", timeout = 3000) - - +\dontrun{ +read_gencode_transcripts(file.path(tempdir(), "references"), release = "42", timeout = 3000) +#> # A tibble: 220,296 × 13 +#> chr source feature start end score strand frame gene_id gene_type +#> +#> 1 chr1 HAVANA transcript 65418 71585 . + . ENSG00000… protein_… +#> 2 chr1 HAVANA exon 65418 65433 . + . ENSG00000… protein_… +#> 3 chr1 HAVANA exon 65519 65573 . + . ENSG00000… protein_… +#> 4 chr1 HAVANA exon 69036 71585 . + . ENSG00000… protein_… +#> 5 chr1 HAVANA transcript 450739 451678 . - . ENSG00000… protein_… +#> 6 chr1 HAVANA exon 450739 451678 . - . ENSG00000… protein_… +#> 7 chr1 HAVANA transcript 685715 686654 . - . ENSG00000… protein_… +#> 8 chr1 HAVANA exon 685715 686654 . - . ENSG00000… protein_… +#> 9 chr1 HAVANA transcript 923922 944574 . + . ENSG00000… protein_… +#> 10 chr1 HAVANA exon 923922 924948 . + . ENSG00000… protein_… +#> # ℹ 220,286 more rows +#> # ℹ 3 more variables: gene_name , transcript_id , MANE_Select +} } \seealso{ \code{\link[=read_bed]{read_bed()}}, \code{\link[=read_encode_blacklist]{read_encode_blacklist()}} diff --git a/r/man/read_ucsc_chrom_sizes.Rd b/r/man/read_ucsc_chrom_sizes.Rd index 5a74310a..669f7091 100644 --- a/r/man/read_ucsc_chrom_sizes.Rd +++ b/r/man/read_ucsc_chrom_sizes.Rd @@ -27,5 +27,5 @@ chromosome. The underlying data is pulled from here: \url{https://hgdownload.soe.ucsc.edu/downloads.html} } \examples{ -read_ucsc_chrom_sizes(file.path(tempdir(), "reference")) +read_ucsc_chrom_sizes(file.path(tempdir(), "references")) } diff --git a/r/man/write_insertion_bedgraph.Rd b/r/man/write_insertion_bedgraph.Rd index e8f471b3..fb46413d 100644 --- a/r/man/write_insertion_bedgraph.Rd +++ b/r/man/write_insertion_bedgraph.Rd @@ -75,7 +75,7 @@ write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all.tar.gz")) list.files(bedgraph_outputs) # With tiling -chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "reference"), genome="hg38") \%>\% +chrom_sizes <- read_ucsc_chrom_sizes(file.path(tempdir(), "references"), genome="hg38") \%>\% dplyr::filter(chr \%in\% c("chr4", "chr11")) write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all_tiled.bedGraph"), chrom_sizes = chrom_sizes, normalization_method = "cpm", tile_width = 100) From e2574be7220b0e87d9d58799193bbe742cb02f7a Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 2 Dec 2025 00:37:30 -0800 Subject: [PATCH 54/84] continue cleaning up docs --- r/man/plot_fragment_length.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r/man/plot_fragment_length.Rd b/r/man/plot_fragment_length.Rd index 0931b560..54add516 100644 --- a/r/man/plot_fragment_length.Rd +++ b/r/man/plot_fragment_length.Rd @@ -30,6 +30,6 @@ x-axis, and proportion of fragments on the y-axis. Typical plots will show width (about 150bp). } \examples{ -frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) +frags <- get_demo_frags() plot_fragment_length(frags) } From 32605ad7a3a658c62fec44b22fe86b02017aa452 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 2 Dec 2025 15:30:35 -0800 Subject: [PATCH 55/84] remove errant extra chars on plot_tss_scatter() leading to syntax error --- r/R/plots.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r/R/plots.R b/r/R/plots.R index bc113a04..1be6d484 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -154,7 +154,7 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE y = max(log10(data$data$reads)) ) rectangle_highlight <- tibble::tibble( - xmin = -Inf, xmax = Inf,xxxxxx + xmin = -Inf, xmax = Inf, ) } From 08c928d2b8157491df15517e1899b18d7a3f39be Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 2 Dec 2025 15:31:01 -0800 Subject: [PATCH 56/84] remove windows checks for timestamp in cran checks (seems broken still) --- .github/workflows/check-standard-test.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index be10cb31..790066f3 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -94,16 +94,10 @@ jobs: any::decor working-directory: 'r' needs: check - - name: Normalize timestamps (Windows) - if: matrix.os == 'windows-latest' - shell: bash - run: | - find r -type f -exec touch -d "2020-01-01 00:00:00" {} + - name: Check package uses: r-lib/actions/check-r-package@v2 with: working-directory: r - check-script: check-wrapper.R build_args: c("--no-build-vignettes") upload-snapshots: false error-on: '"error"' From 63f0d2f4160d8552463e1efd9c3d99ee79611fa6 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 2 Dec 2025 15:31:44 -0800 Subject: [PATCH 57/84] clean up r documentation, break up r iterable matrix methods into several sections --- r/NAMESPACE | 4 - r/R/matrix-svds-docs.R | 85 ------ r/R/matrix.R | 194 ++++++++---- r/R/matrix_stats.R | 10 +- r/R/transforms.R | 45 ++- r/check-wrapper.R | 9 - r/man/IterableMatrix-methods-core.Rd | 110 +++++++ r/man/IterableMatrix-methods-misc.Rd | 149 --------- r/man/IterableMatrix-methods-ops-misc.Rd | 43 +++ r/man/IterableMatrix-methods-ops.Rd | 169 +++++++++++ ...ods.Rd => IterableMatrix-methods-stats.Rd} | 284 ++++-------------- r/man/IterableMatrix-misc-methods.Rd | 30 ++ r/man/checksum.Rd | 2 +- r/man/matrix_R_conversion.Rd | 4 - r/man/peak_matrix.Rd | 6 +- r/man/svds-internal.Rd | 16 + r/man/svds.Rd | 82 ++--- r/pkgdown/_pkgdown.yml | 4 +- 18 files changed, 627 insertions(+), 619 deletions(-) delete mode 100644 r/R/matrix-svds-docs.R delete mode 100644 r/check-wrapper.R create mode 100644 r/man/IterableMatrix-methods-core.Rd delete mode 100644 r/man/IterableMatrix-methods-misc.Rd create mode 100644 r/man/IterableMatrix-methods-ops-misc.Rd create mode 100644 r/man/IterableMatrix-methods-ops.Rd rename r/man/{IterableMatrix-methods.Rd => IterableMatrix-methods-stats.Rd} (52%) create mode 100644 r/man/svds-internal.Rd diff --git a/r/NAMESPACE b/r/NAMESPACE index f9933d68..f4b9cf5d 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -151,10 +151,6 @@ exportMethods(as.data.frame) exportMethods(as.matrix) exportMethods(t) importClassesFrom(Matrix,dgCMatrix) -importFrom(Matrix,colMeans) -importFrom(Matrix,colSums) -importFrom(Matrix,rowMeans) -importFrom(Matrix,rowSums) importFrom(Matrix,t) importFrom(Rcpp,sourceCpp) importFrom(ggplot2,element_text) diff --git a/r/R/matrix-svds-docs.R b/r/R/matrix-svds-docs.R deleted file mode 100644 index 853dd7e0..00000000 --- a/r/R/matrix-svds-docs.R +++ /dev/null @@ -1,85 +0,0 @@ -# This file is distributed under the MPL-2.0 license -# It is adapted from the RSpectra package, which is distributed under the MPL-2.0 license. -# The RSpectra package is copyright Yixuan Qiu 2016 -# Original source code available here: https://github.com/yixuan/RSpectra -# Modifications are copyright 2024 BPCells contributors -# -# SPDX-License-Identifier: MPL-2.0 - -#' Calculate svds -#' -#' Use the C++ Spectra solver (same as RSpectra package), in order to -#' compute the largest k values and corresponding singular vectors. -#' Empirically, memory usage is much lower than using `irlba::irlba()`, likely -#' due to avoiding R garbage creation while solving due to the pure-C++ solver. -#' This documentation is a slightly-edited version of the `RSpectra::svds()` -#' documentation. -#' -#' @param A The matrix whose truncated SVD is to be computed. -#' @param k Number of singular values requested. -#' @param nu Number of left singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix) -#' @param nv Number of right singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix) -#' @param opts Control parameters related to computing algorithm. See *Details* below -#' @param threads Control threads to use calculating mat-vec producs (BPCells specific) -#' @return A list with the following components: -##' \item{d}{A vector of the computed singular values.} -##' \item{u}{An \code{m} by \code{nu} matrix whose columns contain -##' the left singular vectors. If \code{nu == 0}, \code{NULL} -##' will be returned.} -##' \item{v}{An \code{n} by \code{nv} matrix whose columns contain -##' the right singular vectors. If \code{nv == 0}, \code{NULL} -##' will be returned.} -##' \item{nconv}{Number of converged singular values.} -##' \item{niter}{Number of iterations used.} -##' \item{nops}{Number of matrix-vector multiplications used.} -#' @details -#' When RSpectra is installed, this function will just add a method to -#' `RSpectra::svds()` for the `IterableMatrix` class. -#' -#' The \code{opts} argument is a list that can supply any of the -#' following parameters: -#' -#' \describe{ -#' \item{\code{ncv}}{Number of Lanzcos basis vectors to use. More vectors -#' will result in faster convergence, but with greater -#' memory use. \code{ncv} must be satisfy -#' \eqn{k < ncv \le p}{k < ncv <= p} where -#' \code{p = min(m, n)}. -#' Default is \code{min(p, max(2*k+1, 20))}.} -#' \item{\code{tol}}{Precision parameter. Default is 1e-10.} -#' \item{\code{maxitr}}{Maximum number of iterations. Default is 1000.} -#' \item{\code{center}}{Either a logical value (\code{TRUE}/\code{FALSE}), or a numeric -#' vector of length \eqn{n}. If a vector \eqn{c} is supplied, then -#' SVD is computed on the matrix \eqn{A - 1c'}{A - 1 * c'}, -#' in an implicit way without actually forming this matrix. -#' \code{center = TRUE} has the same effect as -#' \code{center = colMeans(A)}. Default is \code{FALSE}. Ignored in BPCells} -#' \item{\code{scale}}{Either a logical value (\code{TRUE}/\code{FALSE}), or a numeric -#' vector of length \eqn{n}. If a vector \eqn{s} is supplied, then -#' SVD is computed on the matrix \eqn{(A - 1c')S}{(A - 1 * c')S}, -#' where \eqn{c} is the centering vector and \eqn{S = diag(1/s)}. -#' If \code{scale = TRUE}, then the vector \eqn{s} is computed as -#' the column norm of \eqn{A - 1c'}{A - 1 * c'}. -#' Default is \code{FALSE}. Ignored in BPCells} -#' } -#' @references Qiu Y, Mei J (2022). _RSpectra: Solvers for Large-Scale Eigenvalue and SVD Problems_. R package version 0.16-1, . -#' @usage svds(A, k, nu = k, nv = k, opts = list(), threads=0L, ...) -#' @examples -#' mat <- matrix(rnorm(500), nrow = 50, ncol = 10) -#' rownames(mat) <- paste0("gene", seq_len(50)) -#' colnames(mat) <- paste0("cell", seq_len(10)) -#' mat <- mat %>% as("dgCMatrix") %>% as("IterableMatrix") -#' -#' svd_res <- svds(mat, k = 5) -#' -#' names(svd_res) -#' -#' svd_res$d -#' -#' dim(svd_res$u) -#' -#' dim(svd_res$v) -#' # Can also pass in values directly into RSpectra::svds -#' svd_res <- svds(mat, k = 5, opts=c(maxitr = 500)) -#' @name svds -NULL \ No newline at end of file diff --git a/r/R/matrix.R b/r/R/matrix.R index 89cf596d..2df611cb 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -6,37 +6,61 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. -#' IterableMatrix methods +#' IterableMatrix core methods #' -#' Generic methods and built-in functions for IterableMatrix objects +#' Core operations for IterableMatrix objects: inspection, transpose, subsetting, and dimnames. #' -#' @param ... Additional arguments passed to methods -#' @param digits Number of decimal places for quantile calculations +#' @param x IterableMatrix object +#' @param object IterableMatrix object #' @param i Row indices or selection helpers. #' @param j Column indices or selection helpers. -#' @param drop Logical indicating whether to drop dimensions when subsetting. #' @param value Replacement value supplied to assignment methods. -#' @name IterableMatrix-methods -#' @rdname IterableMatrix-methods +#' @param drop Logical indicating whether to drop dimensions when subsetting. +#' @param ... Additional arguments passed to methods +#' @name IterableMatrix-methods-core +#' @rdname IterableMatrix-methods-core NULL -#' IterableMatrix methods miscellaneous -#' -#' Generic methods and built-in functions for IterableMatrix objects. These include -#' methods that are described in `IterableMatrix-methods` but have some sense of redundancy. -#' For instance, `%*%` is described between `IterableMatrix` and `matrix` on the left and right respectively. -#' We do not need to show the method `IterableMatrix` on the right instead. +#' IterableMatrix summary statistics #' +#' Summaries and reductions for IterableMatrix objects (sums, means, variances, quantiles, extrema). +#' +#' @param x IterableMatrix object or matrix-like object. +#' @param rows (Integer) Optional vector of row indices to operate over. +#' @param cols (Integer) Optional vector of column indices to operate over. +#' @param na.rm (Logical) Should missing values (NA) be removed? +#' @param center Optional center values (vector of length nrow(x) or ncol(x)) +#' @param probs (Numeric) Quantile value(s) to be computed, between 0 and 1. +#' @param type (Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in `matrixStats::rowQuantiles()` +#' @param digits Number of decimal places for quantile calculations +#' @param drop (Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects). +#' @param useNames (Logical) Whether to use row and column names in the output. +#' @param ... Additional arguments passed to methods +#' @name IterableMatrix-methods-stats +#' @rdname IterableMatrix-methods-stats +NULL + +#' IterableMatrix operations +#' +#' Matrix multiplication, arithmetic, and comparison operations for IterableMatrix objects. +#' #' @param x IterableMatrix object or compatible operand #' @param y IterableMatrix object or compatible operand -#' @param ... Additional arguments passed to methods -#' @param digits Number of decimal places for quantile calculations -#' @param value Replacement value supplied to assignment methods. -#' @param drop Logical indicating whether to drop dimensions when subsetting. -#' @name IterableMatrix-methods-misc -#' @rdname IterableMatrix-methods-misc +#' @param e1 Left operand for binary operations. +#' @param e2 Right operand for binary operations. +#' @param digits Number of decimal places for rounding +#' @name IterableMatrix-methods-ops +#' @rdname IterableMatrix-methods-ops +NULL + +#' IterableMatrix operations (additional overloads) +#' +#' Extra operator overloads documented separately to avoid duplicate entries in the main reference. +#' #' @keywords internal +#' @name IterableMatrix-methods-ops-misc +#' @rdname IterableMatrix-methods-ops-misc NULL #' IterableMatrix subclass methods @@ -100,7 +124,7 @@ denormalize_dimnames <- function(dimnames) { #' @keywords internal setGeneric("iterate_matrix", function(x) standardGeneric("iterate_matrix")) -#' @describeIn IterableMatrix-methods Get the matrix data type (mat_uint32_t, mat_float, or mat_double for now) +#' @describeIn IterableMatrix-methods-core Get the matrix data type (mat_uint32_t, mat_float, or mat_double for now) #' @examples #' ## Prep data #' mat <- matrix(1:25, nrow = 5) %>% as("dgCMatrix") @@ -118,7 +142,7 @@ setGeneric("iterate_matrix", function(x) standardGeneric("iterate_matrix")) #' @export setGeneric("matrix_type", function(x) standardGeneric("matrix_type")) -#' @describeIn IterableMatrix-methods Get the matrix storage order ("row" or "col") (generic) +#' @describeIn IterableMatrix-methods-core Get the matrix storage order ("row" or "col") (generic) #' @examples #' ####################################################################### #' ## storage_order() example @@ -129,7 +153,7 @@ setGeneric("matrix_type", function(x) standardGeneric("matrix_type")) #' @export setGeneric("storage_order", function(x) standardGeneric("storage_order")) -#' @describeIn IterableMatrix-methods Get the matrix storage order ("row" or "col") +#' @describeIn IterableMatrix-methods-core Get the matrix storage order ("row" or "col") setMethod("storage_order", "IterableMatrix", function(x) if(x@transpose) "row" else "col") #' Return a list of input matrices to the current matrix (experimental) @@ -228,7 +252,7 @@ setMethod("short_description", "IterableMatrix", function(x) { }) -#' @describeIn IterableMatrix-methods Display an IterableMatrix +#' @describeIn IterableMatrix-methods-core Display an IterableMatrix #' @param object IterableMatrix object #' @examples #' ####################################################################### @@ -263,7 +287,7 @@ setMethod("show", "IterableMatrix", function(object) { }) -#' @describeIn IterableMatrix-methods Transpose an IterableMatrix +#' @describeIn IterableMatrix-methods-core Transpose an IterableMatrix #' @param x IterableMatrix object #' @return * `t()` Transposed object #' @examples @@ -288,9 +312,15 @@ setMethod("t", signature(x = "IterableMatrix"), function(x) { #' @param x IterableMatrix object #' @param y matrix -#' @describeIn IterableMatrix-methods Multiply by a dense matrix +#' @describeIn IterableMatrix-methods-ops Multiply by a dense matrix #' @return * `x %*% y`: dense matrix result #' @examples +#' ## Prep data +#' mat <- matrix(1:25, nrow = 5) %>% as("dgCMatrix") +#' mat +#' mat <- as(mat, "IterableMatrix") +#' mat +#' #' ####################################################################### #' ## `x %*% y` example #' ####################################################################### @@ -309,7 +339,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "matrix"), function(x, y) { res }) -#' @describeIn IterableMatrix-methods-misc Multiply a dense matrix by an IterableMatrix +#' @describeIn IterableMatrix-misc-methods Multiply a dense matrix by an IterableMatrix setMethod("%*%", signature(x = "matrix", y = "IterableMatrix"), function(x, y) { iter <- iterate_matrix(convert_matrix_type(y, "double")) if (y@transpose) { @@ -322,7 +352,7 @@ setMethod("%*%", signature(x = "matrix", y = "IterableMatrix"), function(x, y) { res }) -#' @describeIn IterableMatrix-methods-misc Multiply an IterableMatrix by a numeric vector +#' @describeIn IterableMatrix-misc-methods Multiply an IterableMatrix by a numeric vector setMethod("%*%", signature(x = "IterableMatrix", y = "numeric"), function(x, y) { iter <- iterate_matrix(convert_matrix_type(x, "double")) if (x@transpose) { @@ -335,7 +365,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "numeric"), function(x, y) res }) -#' @describeIn IterableMatrix-methods-misc Multiply a numeric row vector by an IterableMatrix +#' @describeIn IterableMatrix-misc-methods Multiply a numeric row vector by an IterableMatrix setMethod("%*%", signature(x = "numeric", y = "IterableMatrix"), function(x, y) { iter <- iterate_matrix(convert_matrix_type(y, "double")) if (y@transpose) { @@ -470,7 +500,7 @@ setMethod("short_description", "MatrixMultiply", function(x) { } }) -#' @describeIn IterableMatrix-methods-misc Multiply two IterableMatrix objects +#' @describeIn IterableMatrix-misc-methods Multiply two IterableMatrix objects setMethod("%*%", signature(x = "IterableMatrix", y = "IterableMatrix"), function(x, y) { if (x@transpose != y@transpose) stop("Cannot multiply matrices with different internal transpose states.\nPlease use transpose_storage_order().") if (x@transpose) { @@ -490,7 +520,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "IterableMatrix"), function new("MatrixMultiply", left = x, right = y, transpose = FALSE, dim = dim, dimnames = dimnames) }) -#' @describeIn IterableMatrix-methods-misc Multiply an IterableMatrix by a dgCMatrix +#' @describeIn IterableMatrix-misc-methods Multiply an IterableMatrix by a dgCMatrix setMethod("%*%", signature(x = "IterableMatrix", y = "dgCMatrix"), function(x, y) { if (x@transpose) { t(as(t(y), "IterableMatrix") %*% t(x)) @@ -499,7 +529,7 @@ setMethod("%*%", signature(x = "IterableMatrix", y = "dgCMatrix"), function(x, y } }) -#' @describeIn IterableMatrix-methods-misc Multiply a dgCMatrix by an IterableMatrix +#' @describeIn IterableMatrix-misc-methods Multiply a dgCMatrix by an IterableMatrix setMethod("%*%", signature(x = "dgCMatrix", y = "IterableMatrix"), function(x, y) { if (y@transpose) { t(t(y) %*% as(t(x), "IterableMatrix")) @@ -657,9 +687,15 @@ rank_transform <- function(mat, axis) { # Row sums and row means #' @param x IterableMatrix object -#' @describeIn IterableMatrix-methods Calculate rowSums +#' @describeIn IterableMatrix-methods-stats Calculate rowSums #' @return * `rowSums()`: vector of row sums #' @examples +#' ## Prep data +#' mat <- matrix(1:25, nrow = 5) %>% as("dgCMatrix") +#' mat +#' mat <- as(mat, "IterableMatrix") +#' mat +#' #' ####################################################################### #' ## rowSums() example #' ####################################################################### @@ -678,7 +714,7 @@ setMethod("rowSums", signature(x = "IterableMatrix"), function(x) { }) #' @param x IterableMatrix object -#' @describeIn IterableMatrix-methods Calculate colSums +#' @describeIn IterableMatrix-methods-stats Calculate colSums #' @return * `colSums()`: vector of col sums #' @examples #' ####################################################################### @@ -699,7 +735,7 @@ setMethod("colSums", signature(x = "IterableMatrix"), function(x) { }) #' @param x IterableMatrix object -#' @describeIn IterableMatrix-methods Calculate rowMeans +#' @describeIn IterableMatrix-methods-stats Calculate rowMeans #' @return * `rowMeans()`: vector of row means #' @examples #' ####################################################################### @@ -711,7 +747,7 @@ setMethod("colSums", signature(x = "IterableMatrix"), function(x) { setMethod("rowMeans", signature(x = "IterableMatrix"), function(x) rowSums(x) / ncol(x)) #' @param x IterableMatrix object -#' @describeIn IterableMatrix-methods Calculate colMeans +#' @describeIn IterableMatrix-methods-stats Calculate colMeans #' @return * `colMeans()`: vector of col means #' @examples #' ####################################################################### @@ -732,7 +768,7 @@ setMethod("colMeans", signature(x = "IterableMatrix"), function(x) colSums(x) / # - In summary, BPCells::rowVars and BPCells::colVars will work on all inputs, and so will MatrixGenerics::rowVars and # MatrixGenerics::colVars. matrixStats::rowVars and matrixStats::colVars will only work on base R matrix objects. -#' @describeIn IterableMatrix-methods Calculate colVars (replacement for `matrixStats::colVars()`) +#' @describeIn IterableMatrix-methods-stats Calculate colVars (replacement for `matrixStats::colVars()`) #' @param center Optional center values (vector of length nrow(x) or ncol(x)) #' @return * `colVars()`: vector of col variance #' @examples @@ -769,8 +805,15 @@ rlang::on_load({ } }) -#' @describeIn IterableMatrix-methods Calculate rowVars (replacement for `matrixStats::rowVars()`) (generic) +#' @describeIn IterableMatrix-methods-stats Calculate rowVars (replacement for `matrixStats::rowVars()`) (generic) #' @return * `rowVars()`: vector of row variance +#' @examples +#' ####################################################################### +#' ## rowVars() example +#' ####################################################################### +#' rowVars(mat) +#' +#' #' @export rowVars <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) UseMethod("rowVars") #' @export @@ -785,7 +828,7 @@ rowVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = } } #' @export -#' @describeIn IterableMatrix-methods-misc Calculate rowVars (replacement for `matrixStats::rowVars()`) +#' @describeIn IterableMatrix-methods-stats Calculate rowVars (replacement for `matrixStats::rowVars()`) #' @method rowVars IterableMatrix rowVars.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (!is.null(rows) || !is.null(cols) || !isFALSE(na.rm) || !is.null(center) || !isTRUE(useNames)) { @@ -802,7 +845,7 @@ rlang::on_load({ #' Get the max of each row in an iterable matrix #' @param x IterableMatrix object/dgCMatrix object #' @return * `rowMaxs()`: vector of maxes for every row -#' @describeIn IterableMatrix-methods Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) (generic) +#' @describeIn IterableMatrix-methods-stats Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) (generic) #' @examples #' ####################################################################### #' ## rowMaxs() example @@ -825,7 +868,7 @@ rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., use } } #' @export -#' @describeIn IterableMatrix-methods-misc Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) +#' @describeIn IterableMatrix-methods-stats Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) #' @method rowMaxs IterableMatrix rowMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if(!is.null(rows) || !is.null(cols) || !isFALSE(na.rm)) { @@ -849,7 +892,7 @@ rlang::on_load({ #' Get the max of each col in an interable matrix #' @param x IterableMatrix/dgCMatrix object #' @return * `colMaxs()`: vector of column maxes -#' @describeIn IterableMatrix-methods Calculate colMax (replacement for `matrixStats::colMax()`) +#' @describeIn IterableMatrix-methods-stats Calculate colMax (replacement for `matrixStats::colMax()`) #' @examples #' ####################################################################### #' ## colMaxs() example @@ -958,7 +1001,7 @@ unsplit_selection <- function(selection) { selection$subset[selection$reorder] } -#' @describeIn IterableMatrix-methods Subset an IterableMatrix +#' @describeIn IterableMatrix-methods-core Subset an IterableMatrix setMethod("[", "IterableMatrix", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") if (rlang::is_missing(i) && rlang::is_missing(j)) { @@ -995,7 +1038,7 @@ setMethod("[", "IterableMatrix", function(x, i, j, ...) { # Simulate assigning to a subset of the matrix. # We concatenate the un-modified matrix subsets with the new values, # then reorder rows/columns appropriately -#' @describeIn IterableMatrix-methods Assign into an IterableMatrix +#' @describeIn IterableMatrix-methods-core Assign into an IterableMatrix setMethod("[<-", "IterableMatrix", function(x, i, j, ..., value) { # Do type conversions if needed if (is.matrix(value)) value <- as(value, "dgCMatrix") @@ -1179,7 +1222,7 @@ setMethod("short_description", "RenameDims", function(x) { }) #' @export #' @param value New dimnames (list of length 2, or NULL) -#' @describeIn IterableMatrix-methods Set dimnames of an IterableMatrix, similar to base R `dimnames<-()` +#' @describeIn IterableMatrix-methods-core Set dimnames of an IterableMatrix, similar to base R `dimnames<-()` setMethod("dimnames<-", signature(x = "IterableMatrix", value = "list"), function(x, value) { if (identical(dimnames(x), value)) return(x) d <- dim(x) @@ -1205,7 +1248,7 @@ setMethod("dimnames<-", signature(x = "IterableMatrix", value = "list"), functio x }) #' @export -#' @describeIn IterableMatrix-methods-misc Remove dimnames of an IterableMatrix +#' @describeIn IterableMatrix-methods-core Remove dimnames of an IterableMatrix setMethod("dimnames<-", signature(x = "IterableMatrix", value = "NULL"), function(x, value) { if (identical(dimnames(x), value)) return(x) if (!is(x, "RenameDims")) { @@ -2774,10 +2817,10 @@ setMethod("matrix_inputs", "PeakMatrix", function(x) list()) #' # peaks <- peaks[order_ranges(peaks, chrNames(frags)),] #' #' ## Get peak matrix -#' peak_matrix(frags, peaks, mode="insertions") -#' peak_matrix +#' peak_mat <- peak_matrix(frags, peaks, mode="insertions") +#' peak_mat #' -#' peak_matrix %>% as("dgCMatrix") +#' peak_mat %>% as("dgCMatrix") #' #' @export peak_matrix <- function(fragments, ranges, mode = c("insertions", "fragments", "overlaps"), zero_based_coords = !is(ranges, "GRanges"), explicit_peak_names = TRUE) { @@ -3141,8 +3184,6 @@ convert_matrix_type <- function(matrix, type = c("uint32_t", "double", "float")) #' `dgCMatrix`/`matrix` representations, while `as.matrix()` materialises #' dense matrices directly when needed. #' @param x Matrix object to convert -#' @param dgCMatrix Sparse matrix in dgCMatrix format -#' @param IterableMatrix IterableMatrix object #' @param ... Additional arguments passed to methods #' @examples #' # setup data @@ -3381,8 +3422,47 @@ matrix_stats <- function(matrix, } +#' Calculate svds +#' +#' Use the C++ Spectra solver (same as RSpectra package) to compute the largest +#' `k` singular values and corresponding singular vectors. Empirically, memory +#' use is much lower than `irlba::irlba()` because the solver runs entirely in C++. +#' +#' When RSpectra is installed, this adds a method to `RSpectra::svds()` for +#' `IterableMatrix` objects; otherwise it falls back to the bundled implementation. +#' +#' @param A The matrix whose truncated SVD is to be computed. +#' @param k Number of singular values requested. +#' @param nu Number of left singular vectors to compute (must equal `k` for IterableMatrix). +#' @param nv Number of right singular vectors to compute (must equal `k` for IterableMatrix). +#' @param opts Control parameters related to the computing algorithm (see Details). +#' @param threads Threads to use for matrix-vector products (BPCells specific). +#' @param ... Additional arguments passed to `RSpectra::svds()` when running on non-BPCells matrices. +#' @return A list with components `d`, `u`, `v`, `nconv`, `niter`, and `nops`. +#' @details +#' The `opts` list may include: +#' * `ncv`: Number of Lanczos basis vectors (`k < ncv <= min(m, n)`). Default `min(p, max(2*k+1, 20))`. +#' * `tol`: Precision parameter (default `1e-10`). +#' * `maxitr`: Maximum iterations (default `1000`). +#' * `center`, `scale`: Centering/scaling options (ignored for BPCells). +#' @examples +#' mat <- matrix(rnorm(500), nrow = 50, ncol = 10) +#' rownames(mat) <- paste0("gene", seq_len(50)) +#' colnames(mat) <- paste0("cell", seq_len(10)) +#' mat <- mat %>% as("dgCMatrix") %>% as("IterableMatrix") +#' +#' svd_res <- svds(mat, k = 5) +#' names(svd_res) +#' svd_res$d +#' dim(svd_res$u) +#' dim(svd_res$v) +#' +#' # Can also pass values directly into RSpectra::svds +#' svd_res <- svds(mat, k = 5, opts = c(maxitr = 500)) +#' +#' @references +#' Qiu Y, Mei J (2022). RSpectra: Solvers for Large-Scale Eigenvalue and SVD Problems. R package version 0.16-1. #' @export -#' @param ... Additional arguments passed to `Rspectra::svds()` if svd is ran on a non-BPCells matrix svds <- function (A, k, nu = k, nv = k, opts = list(), threads = 0L, ...) UseMethod("svds") # RSpectra exports svds as an S3 Generic, but is a suggested dependency @@ -3394,7 +3474,15 @@ rlang::on_load({ vctrs::s3_register("RSpectra::svds", "IterableMatrix") }) +#' Internal svds methods +#' @keywords internal +#' @name svds-internal +#' @rdname svds-internal +NULL + #' @export +#' @rdname svds-internal +#' @keywords internal svds.default <- function(A, k, nu = k, nv = k, opts = list(), ...) { if (requireNamespace("RSpectra", quietly = TRUE)) { RSpectra::svds(A=A, k=k, nu=nu, nv=nv, opts=opts, ...) @@ -3404,6 +3492,8 @@ svds.default <- function(A, k, nu = k, nv = k, opts = list(), ...) { } #' @export +#' @rdname svds-internal +#' @keywords internal svds.IterableMatrix <- function(A, k, nu = k, nv = k, opts = list(), threads=0, ...) { assert_is_wholenumber(threads) assert_is_wholenumber(k) @@ -3445,7 +3535,7 @@ svds.IterableMatrix <- function(A, k, nu = k, nv = k, opts = list(), threads=0, #' hexidecimal format. #' @details #' `checksum()` converts the non-zero elements of the sparse input matrix to double -#' precision, concatenates each element value with the element row and column index words, +#' precision, concatenates each element value with theF element row and column index words, #' and uses these 16-byte blocks along with the matrix dimensions and row and column #' names to calculate the checksum. The checksum value depends on the storage order so #' column- and row-order matrices with the same element values give different checksum diff --git a/r/R/matrix_stats.R b/r/R/matrix_stats.R index 786254c4..9b36792f 100644 --- a/r/R/matrix_stats.R +++ b/r/R/matrix_stats.R @@ -17,7 +17,7 @@ #' @param drop (Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects). #' @return - `rowQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of rows in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. -#' @describeIn IterableMatrix-methods Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) +#' @describeIn IterableMatrix-methods-stats Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) #' @usage rowQuantiles( #' x, #' rows = NULL, @@ -60,7 +60,7 @@ rowQuantiles.default <- function(x, rows = NULL, cols = NULL, } #' @export #' @method rowQuantiles IterableMatrix -#' @describeIn IterableMatrix-methods-misc Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) +#' @describeIn IterableMatrix-methods-stats Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -102,7 +102,7 @@ rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, #' Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. #' @return - `colQuantiles():` If `length(probs) == 1`, return a numeric with number of entries equal to the number of columns in the matrix. #' Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. -#' @describeIn IterableMatrix-methods Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) +#' @describeIn IterableMatrix-methods-stats Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) #' @usage colQuantiles( #' x, #' rows = NULL, @@ -145,7 +145,7 @@ colQuantiles.default <- function(x, rows = NULL, cols = NULL, } #' Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. #' @export -#' @describeIn IterableMatrix-methods-misc Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) +#' @describeIn IterableMatrix-methods-stats Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) colQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -218,4 +218,4 @@ rlang::on_load({ #' \code{\link{rowVars}}, \code{\link{colVars}}, #' \code{\link{rowMaxs}}, \code{\link{colMaxs}} #' @keywords internal -NULL \ No newline at end of file +NULL diff --git a/r/R/transforms.R b/r/R/transforms.R index d829c7d7..0755c6d2 100644 --- a/r/R/transforms.R +++ b/r/R/transforms.R @@ -65,7 +65,7 @@ setMethod("short_description", "TransformLog1p", function(x) { "Transform log1p" ) }) -#' @describeIn IterableMatrix-methods Calculate log(x + 1) +#' @describeIn IterableMatrix-methods-stats Calculate log(x + 1) #' @examples #' ####################################################################### #' ## log1p() example @@ -88,7 +88,7 @@ setMethod("short_description", "TransformLog1pSlow", function(x) { ) }) -#' @describeIn IterableMatrix-methods Calculate log(x + 1) (non-SIMD version) +#' @describeIn IterableMatrix-methods-stats Calculate log(x + 1) (non-SIMD version) #' @examples #' ####################################################################### #' ## log1p_slow() example @@ -112,7 +112,7 @@ setMethod("short_description", "TransformExpm1", function(x) { "Transform expm1" ) }) -#' @describeIn IterableMatrix-methods Calculate exp(x) - 1 +#' @describeIn IterableMatrix-methods-stats Calculate exp(x) - 1 #' @examples #' ####################################################################### #' ## expm1() example @@ -134,7 +134,7 @@ setMethod("short_description", "TransformExpm1Slow", function(x) { "Transform expm1 (non-SIMD implementation)" ) }) -#' @describeIn IterableMatrix-methods Calculate exp(x) - 1 (non-SIMD version) +#' @describeIn IterableMatrix-methods-stats Calculate exp(x) - 1 (non-SIMD version) #' @examples #' ####################################################################### #' ## expm1_slow() example @@ -174,7 +174,7 @@ setMethod("short_description", "TransformPow", function(x) { ) }) -#' @describeIn IterableMatrix-methods Calculate x^y (elementwise; y > 0) +#' @describeIn IterableMatrix-methods-ops Calculate x^y (elementwise; y > 0) setMethod("^", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2) { assert_len(e2, 1) assert_true(e2 > 0) @@ -370,24 +370,21 @@ binarize <- function(mat, threshold=0, strict_inequality=TRUE) { global_params=c(threshold, strict_inequality)) convert_matrix_type(res, "uint32_t") } -#' @describeIn IterableMatrix-methods-misc Perform matrix < numeric comparison (unsupported) +#' @describeIn IterableMatrix-methods-ops Perform matrix < numeric comparison (IterableMatrix left) setMethod("<", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { stop("matrix < numeric not supported for IterableMatrix objects") }) -#' @describeIn IterableMatrix-methods Binarize matrix according to numeric < matrix comparison +#' @describeIn IterableMatrix-methods-ops Perform numeric < matrix comparison (numeric left) #' @param e1 First element of comparison #' @param e2 Second element of comparison #' @examples -#' ####################################################################### -#' ## `e1 < e2` example -#' ####################################################################### #' 5 < mat #' #' setMethod("<", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) { binarize(e2, threshold=e1, strict_inequality=TRUE) }) -#' @describeIn IterableMatrix-methods Binarize matrix according to matrix > numeric comparison +#' @describeIn IterableMatrix-methods-ops Perform matrix > numeric comparison (IterableMatrix left) #' @examples #' ####################################################################### #' ## `e1 > e2` example @@ -398,15 +395,15 @@ setMethod("<", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) setMethod(">", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { binarize(e1, threshold=e2, strict_inequality=TRUE) }) -#' @describeIn IterableMatrix-methods-misc Perform numeric > matrix comparison (unsupported) +#' @describeIn IterableMatrix-methods-ops-misc Perform numeric > matrix comparison (numeric left) setMethod(">", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) { stop("numeric > matrix not supported for IterableMatrix objects") }) -#' @describeIn IterableMatrix-methods-misc Perform matrix <= numeric comparison (unsupported) +#' @describeIn IterableMatrix-methods-ops-misc Perform matrix <= numeric comparison (IterableMatrix left) setMethod("<=", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { stop("matrix <= numeric not supported for IterableMatrix objects") }) -#' @describeIn IterableMatrix-methods Binarize matrix according to numeric <= matrix comparison +#' @describeIn IterableMatrix-methods-ops Perform numeric <= matrix comparison (numeric left) #' @examples #' ####################################################################### #' ## `e1 <= e2` example @@ -417,7 +414,7 @@ setMethod("<=", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) setMethod("<=", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) { binarize(e2, threshold=e1, strict_inequality=FALSE) }) -#' @describeIn IterableMatrix-methods Binarize matrix according to matrix >= numeric comparison +#' @describeIn IterableMatrix-methods-ops Perform matrix >= numeric comparison (IterableMatrix left) #' @examples #' ####################################################################### #' ## `e1 >= e2` example @@ -428,7 +425,7 @@ setMethod("<=", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) setMethod(">=", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { binarize(e1, threshold=e2, strict_inequality=FALSE) }) -#' @describeIn IterableMatrix-methods-misc Compare a numeric value to an IterableMatrix using >= (numeric left operand) +#' @describeIn IterableMatrix-methods-ops-misc Compare a numeric value to an IterableMatrix using >= (numeric left operand) setMethod(">=", signature(e1= "numeric", e2= "IterableMatrix"), function(e1, e2) { stop("numeric >= matrix not supported for IterableMatrix objects") }) @@ -451,7 +448,7 @@ setMethod("short_description", "TransformRound", function(x) { }) # Initially, allow only digits=0. -#' @describeIn IterableMatrix-methods round to nearest integer (digits must be 0) +#' @describeIn IterableMatrix-methods-ops round to nearest integer (digits must be 0) #' @examples #' ####################################################################### #' ## round() example @@ -714,7 +711,7 @@ setMethod("short_description", "TransformScaleShift", function(x) { }) # Basic dispatch for scaling/shifting (Create TransformScaleShift and then apply function to it) -#' @describeIn IterableMatrix-methods Multiply by a constant, or multiply rows by a vector length nrow(mat) +#' @describeIn IterableMatrix-methods-ops Multiply by a constant, or multiply rows by a vector length nrow(mat) #' @examples #' ####################################################################### #' ## `e1 * e2` example @@ -730,12 +727,12 @@ setMethod("*", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2 e1 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e1, "double")) e1 * e2 }) -#' @describeIn IterableMatrix-methods-misc Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) +#' @describeIn IterableMatrix-methods-ops-misc Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) setMethod("*", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2) { e2 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e2, "double")) e2 * e1 }) -#' @describeIn IterableMatrix-methods Add a constant, or row-wise addition with a vector length nrow(mat) +#' @describeIn IterableMatrix-methods-ops Add a constant, or row-wise addition with a vector length nrow(mat) #' @examples #' ####################################################################### #' ## `e1 + e2` example @@ -752,14 +749,14 @@ setMethod("+", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2 e1 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e1, "double")) e1 + e2 }) -#' @describeIn IterableMatrix-methods-misc Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) +#' @describeIn IterableMatrix-methods-ops-misc Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) setMethod("+", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2) { if (all(e1 == 0)) return(e2) e2 <- wrapMatrix("TransformScaleShift", convert_matrix_type(e2, "double")) e2 + e1 }) # Note: we skip numeric / IterableMatrix as it would result in a lot of infinities for dividing by 0. -#' @describeIn IterableMatrix-methods Divide by a constant, or divide rows by a vector length nrow(mat) +#' @describeIn IterableMatrix-methods-ops Divide by a constant, or divide rows by a vector length nrow(mat) #' @examples #' ####################################################################### #' ## `e1 / e2` example @@ -774,7 +771,7 @@ setMethod("+", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2 setMethod("/", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2) { e1 * (1 / e2) }) -#' @describeIn IterableMatrix-methods Subtract a constant, or row-wise subtraction with a vector length nrow(mat) +#' @describeIn IterableMatrix-methods-ops Subtract a constant, or row-wise subtraction with a vector length nrow(mat) #' @examples #' ####################################################################### #' ## `e1 - e2` example @@ -789,7 +786,7 @@ setMethod("/", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2 setMethod("-", signature(e1 = "IterableMatrix", e2 = "numeric"), function(e1, e2) { e1 + (-e2) }) -#' @describeIn IterableMatrix-methods-misc Subtract matrix from a numeric constant/vector +#' @describeIn IterableMatrix-methods-ops-misc Subtract matrix from a numeric constant/vector setMethod("-", signature(e1 = "numeric", e2 = "IterableMatrix"), function(e1, e2) { e2 * -1 + e1 }) diff --git a/r/check-wrapper.R b/r/check-wrapper.R deleted file mode 100644 index 84ef27ea..00000000 --- a/r/check-wrapper.R +++ /dev/null @@ -1,9 +0,0 @@ - -args <- commandArgs(TRUE) - -# Disable timestamp check completely -Sys.setenv("_R_CHECK_FUTURE_FILE_TIMESTAMPS_"="false") -Sys.setenv("_R_CHECK_SYSTEM_CLOCK_"="0") - -# Call R CMD check as normal -tools:::.check_packages(args) \ No newline at end of file diff --git a/r/man/IterableMatrix-methods-core.Rd b/r/man/IterableMatrix-methods-core.Rd new file mode 100644 index 00000000..597a1798 --- /dev/null +++ b/r/man/IterableMatrix-methods-core.Rd @@ -0,0 +1,110 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix.R +\name{IterableMatrix-methods-core} +\alias{IterableMatrix-methods-core} +\alias{matrix_type} +\alias{storage_order} +\alias{storage_order,IterableMatrix-method} +\alias{show,IterableMatrix-method} +\alias{t,IterableMatrix-method} +\alias{[,IterableMatrix,ANY,ANY,ANY-method} +\alias{[<-,IterableMatrix,ANY,ANY,ANY-method} +\alias{dimnames<-,IterableMatrix,list-method} +\alias{dimnames<-,IterableMatrix,NULL-method} +\title{IterableMatrix core methods} +\usage{ +matrix_type(x) + +storage_order(x) + +\S4method{storage_order}{IterableMatrix}(x) + +\S4method{show}{IterableMatrix}(object) + +\S4method{t}{IterableMatrix}(x) + +\S4method{[}{IterableMatrix,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) + +\S4method{[}{IterableMatrix,ANY,ANY,ANY}(x, i, j, ...) <- value + +\S4method{dimnames}{IterableMatrix,list}(x) <- value + +\S4method{dimnames}{IterableMatrix,NULL}(x) <- value +} +\arguments{ +\item{x}{IterableMatrix object} + +\item{object}{IterableMatrix object} + +\item{i}{Row indices or selection helpers.} + +\item{j}{Column indices or selection helpers.} + +\item{...}{Additional arguments passed to methods} + +\item{drop}{Logical indicating whether to drop dimensions when subsetting.} + +\item{value}{New dimnames (list of length 2, or NULL)} +} +\value{ +\itemize{ +\item \code{t()} Transposed object +} +} +\description{ +Core operations for IterableMatrix objects: inspection, transpose, subsetting, and dimnames. +} +\section{Functions}{ +\itemize{ +\item \code{matrix_type()}: Get the matrix data type (mat_uint32_t, mat_float, or mat_double for now) + +\item \code{storage_order()}: Get the matrix storage order ("row" or "col") (generic) + +\item \code{storage_order(IterableMatrix)}: Get the matrix storage order ("row" or "col") + +\item \code{show(IterableMatrix)}: Display an IterableMatrix + +\item \code{t(IterableMatrix)}: Transpose an IterableMatrix + +\item \code{x[i}: Subset an IterableMatrix + +\item \code{`[`(x = IterableMatrix, i = ANY, j = ANY) <- value}: Assign into an IterableMatrix + +\item \code{dimnames(x = IterableMatrix) <- value}: Set dimnames of an IterableMatrix, similar to base R \verb{dimnames<-()} + +\item \code{dimnames(x = IterableMatrix) <- value}: Remove dimnames of an IterableMatrix + +}} +\examples{ +## Prep data +mat <- matrix(1:25, nrow = 5) \%>\% as("dgCMatrix") +mat +mat <- as(mat, "IterableMatrix") +mat + + +####################################################################### +## matrix_type() example +####################################################################### +matrix_type(mat) + + +####################################################################### +## storage_order() example +####################################################################### +storage_order(mat) + + +####################################################################### +## show() example +####################################################################### +show(mat) + + +####################################################################### +## t() example +####################################################################### +t(mat) + + +} diff --git a/r/man/IterableMatrix-methods-misc.Rd b/r/man/IterableMatrix-methods-misc.Rd deleted file mode 100644 index 06a9cf4b..00000000 --- a/r/man/IterableMatrix-methods-misc.Rd +++ /dev/null @@ -1,149 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/matrix.R, R/matrix_stats.R, R/transforms.R -\name{IterableMatrix-methods-misc} -\alias{IterableMatrix-methods-misc} -\alias{\%*\%,matrix,IterableMatrix-method} -\alias{\%*\%,IterableMatrix,numeric-method} -\alias{\%*\%,numeric,IterableMatrix-method} -\alias{\%*\%,IterableMatrix,IterableMatrix-method} -\alias{\%*\%,IterableMatrix,dgCMatrix-method} -\alias{\%*\%,dgCMatrix,IterableMatrix-method} -\alias{rowVars.IterableMatrix} -\alias{rowMaxs.IterableMatrix} -\alias{dimnames<-,IterableMatrix,NULL-method} -\alias{rowQuantiles.IterableMatrix} -\alias{colQuantiles.IterableMatrix} -\alias{<,IterableMatrix,numeric-method} -\alias{>,numeric,IterableMatrix-method} -\alias{<=,IterableMatrix,numeric-method} -\alias{>=,numeric,IterableMatrix-method} -\alias{*,numeric,IterableMatrix-method} -\alias{+,numeric,IterableMatrix-method} -\alias{-,numeric,IterableMatrix-method} -\title{IterableMatrix methods miscellaneous} -\usage{ -\S4method{\%*\%}{matrix,IterableMatrix}(x, y) - -\S4method{\%*\%}{IterableMatrix,numeric}(x, y) - -\S4method{\%*\%}{numeric,IterableMatrix}(x, y) - -\S4method{\%*\%}{IterableMatrix,IterableMatrix}(x, y) - -\S4method{\%*\%}{IterableMatrix,dgCMatrix}(x, y) - -\S4method{\%*\%}{dgCMatrix,IterableMatrix}(x, y) - -\method{rowVars}{IterableMatrix}( - x, - rows = NULL, - cols = NULL, - na.rm = FALSE, - center = NULL, - ..., - useNames = TRUE -) - -\method{rowMaxs}{IterableMatrix}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) - -\S4method{dimnames}{IterableMatrix,NULL}(x) <- value - -\method{rowQuantiles}{IterableMatrix}( - x, - rows = NULL, - cols = NULL, - probs = seq(from = 0, to = 1, by = 0.25), - na.rm = FALSE, - type = 7L, - digits = 7L, - ..., - useNames = TRUE, - drop = TRUE -) - -colQuantiles.IterableMatrix( - x, - rows = NULL, - cols = NULL, - probs = seq(from = 0, to = 1, by = 0.25), - na.rm = FALSE, - type = 7L, - digits = 7L, - ..., - useNames = TRUE, - drop = TRUE -) - -\S4method{<}{IterableMatrix,numeric}(e1, e2) - -\S4method{>}{numeric,IterableMatrix}(e1, e2) - -\S4method{<=}{IterableMatrix,numeric}(e1, e2) - -\S4method{>=}{numeric,IterableMatrix}(e1, e2) - -\S4method{*}{numeric,IterableMatrix}(e1, e2) - -\S4method{+}{numeric,IterableMatrix}(e1, e2) - -\S4method{-}{numeric,IterableMatrix}(e1, e2) -} -\arguments{ -\item{x}{IterableMatrix object or compatible operand} - -\item{y}{IterableMatrix object or compatible operand} - -\item{...}{Additional arguments passed to methods} - -\item{value}{Replacement value supplied to assignment methods.} - -\item{digits}{Number of decimal places for quantile calculations} - -\item{drop}{Logical indicating whether to drop dimensions when subsetting.} -} -\description{ -Generic methods and built-in functions for IterableMatrix objects. These include -methods that are described in \code{IterableMatrix-methods} but have some sense of redundancy. -For instance, \code{\%*\%} is described between \code{IterableMatrix} and \code{matrix} on the left and right respectively. -We do not need to show the method \code{IterableMatrix} on the right instead. -} -\section{Functions}{ -\itemize{ -\item \code{x \%*\% y}: Multiply a dense matrix by an IterableMatrix - -\item \code{x \%*\% y}: Multiply an IterableMatrix by a numeric vector - -\item \code{x \%*\% y}: Multiply a numeric row vector by an IterableMatrix - -\item \code{x \%*\% y}: Multiply two IterableMatrix objects - -\item \code{x \%*\% y}: Multiply an IterableMatrix by a dgCMatrix - -\item \code{x \%*\% y}: Multiply a dgCMatrix by an IterableMatrix - -\item \code{rowVars(IterableMatrix)}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) - -\item \code{rowMaxs(IterableMatrix)}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) - -\item \code{dimnames(x = IterableMatrix) <- value}: Remove dimnames of an IterableMatrix - -\item \code{rowQuantiles(IterableMatrix)}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) - -\item \code{colQuantiles.IterableMatrix()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) - -\item \code{e1 < e2}: Perform matrix < numeric comparison (unsupported) - -\item \code{e1 > e2}: Perform numeric > matrix comparison (unsupported) - -\item \code{e1 <= e2}: Perform matrix <= numeric comparison (unsupported) - -\item \code{e1 >= e2}: Compare a numeric value to an IterableMatrix using >= (numeric left operand) - -\item \code{e1 * e2}: Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) - -\item \code{e1 + e2}: Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) - -\item \code{e1 - e2}: Subtract matrix from a numeric constant/vector - -}} -\keyword{internal} diff --git a/r/man/IterableMatrix-methods-ops-misc.Rd b/r/man/IterableMatrix-methods-ops-misc.Rd new file mode 100644 index 00000000..09aeef4d --- /dev/null +++ b/r/man/IterableMatrix-methods-ops-misc.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix.R, R/transforms.R +\name{IterableMatrix-methods-ops-misc} +\alias{IterableMatrix-methods-ops-misc} +\alias{>,numeric,IterableMatrix-method} +\alias{<=,IterableMatrix,numeric-method} +\alias{>=,numeric,IterableMatrix-method} +\alias{*,numeric,IterableMatrix-method} +\alias{+,numeric,IterableMatrix-method} +\alias{-,numeric,IterableMatrix-method} +\title{IterableMatrix operations (additional overloads)} +\usage{ +\S4method{>}{numeric,IterableMatrix}(e1, e2) + +\S4method{<=}{IterableMatrix,numeric}(e1, e2) + +\S4method{>=}{numeric,IterableMatrix}(e1, e2) + +\S4method{*}{numeric,IterableMatrix}(e1, e2) + +\S4method{+}{numeric,IterableMatrix}(e1, e2) + +\S4method{-}{numeric,IterableMatrix}(e1, e2) +} +\description{ +Extra operator overloads documented separately to avoid duplicate entries in the main reference. +} +\section{Functions}{ +\itemize{ +\item \code{e1 > e2}: Perform numeric > matrix comparison (numeric left) + +\item \code{e1 <= e2}: Perform matrix <= numeric comparison (IterableMatrix left) + +\item \code{e1 >= e2}: Compare a numeric value to an IterableMatrix using >= (numeric left operand) + +\item \code{e1 * e2}: Multiply an IterableMatrix by a numeric value or row-wise vector (numeric left operand) + +\item \code{e1 + e2}: Add an IterableMatrix to a numeric value or row-wise vector (numeric left operand) + +\item \code{e1 - e2}: Subtract matrix from a numeric constant/vector + +}} +\keyword{internal} diff --git a/r/man/IterableMatrix-methods-ops.Rd b/r/man/IterableMatrix-methods-ops.Rd new file mode 100644 index 00000000..06f0f7e5 --- /dev/null +++ b/r/man/IterableMatrix-methods-ops.Rd @@ -0,0 +1,169 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix.R, R/transforms.R +\name{IterableMatrix-methods-ops} +\alias{IterableMatrix-methods-ops} +\alias{\%*\%,IterableMatrix,matrix-method} +\alias{^,IterableMatrix,numeric-method} +\alias{<,IterableMatrix,numeric-method} +\alias{<,numeric,IterableMatrix-method} +\alias{>,IterableMatrix,numeric-method} +\alias{<=,numeric,IterableMatrix-method} +\alias{>=,IterableMatrix,numeric-method} +\alias{round,IterableMatrix-method} +\alias{*,IterableMatrix,numeric-method} +\alias{+,IterableMatrix,numeric-method} +\alias{/,IterableMatrix,numeric-method} +\alias{-,IterableMatrix,numeric-method} +\title{IterableMatrix operations} +\usage{ +\S4method{\%*\%}{IterableMatrix,matrix}(x, y) + +\S4method{^}{IterableMatrix,numeric}(e1, e2) + +\S4method{<}{IterableMatrix,numeric}(e1, e2) + +\S4method{<}{numeric,IterableMatrix}(e1, e2) + +\S4method{>}{IterableMatrix,numeric}(e1, e2) + +\S4method{<=}{numeric,IterableMatrix}(e1, e2) + +\S4method{>=}{IterableMatrix,numeric}(e1, e2) + +\S4method{round}{IterableMatrix}(x, digits = 0) + +\S4method{*}{IterableMatrix,numeric}(e1, e2) + +\S4method{+}{IterableMatrix,numeric}(e1, e2) + +\S4method{/}{IterableMatrix,numeric}(e1, e2) + +\S4method{-}{IterableMatrix,numeric}(e1, e2) +} +\arguments{ +\item{x}{IterableMatrix object} + +\item{y}{matrix} + +\item{e1}{First element of comparison} + +\item{e2}{Second element of comparison} + +\item{digits}{Number of decimal places for rounding} +} +\value{ +\itemize{ +\item \code{x \%*\% y}: dense matrix result +} +} +\description{ +Matrix multiplication, arithmetic, and comparison operations for IterableMatrix objects. +} +\section{Functions}{ +\itemize{ +\item \code{x \%*\% y}: Multiply by a dense matrix + +\item \code{e1^e2}: Calculate x^y (elementwise; y > 0) + +\item \code{e1 < e2}: Perform matrix < numeric comparison (IterableMatrix left) + +\item \code{e1 < e2}: Perform numeric < matrix comparison (numeric left) + +\item \code{e1 > e2}: Perform matrix > numeric comparison (IterableMatrix left) + +\item \code{e1 <= e2}: Perform numeric <= matrix comparison (numeric left) + +\item \code{e1 >= e2}: Perform matrix >= numeric comparison (IterableMatrix left) + +\item \code{round(IterableMatrix)}: round to nearest integer (digits must be 0) + +\item \code{e1 * e2}: Multiply by a constant, or multiply rows by a vector length nrow(mat) + +\item \code{e1 + e2}: Add a constant, or row-wise addition with a vector length nrow(mat) + +\item \code{e1 / e2}: Divide by a constant, or divide rows by a vector length nrow(mat) + +\item \code{e1 - e2}: Subtract a constant, or row-wise subtraction with a vector length nrow(mat) + +}} +\examples{ +## Prep data +mat <- matrix(1:25, nrow = 5) \%>\% as("dgCMatrix") +mat +mat <- as(mat, "IterableMatrix") +mat + +####################################################################### +## `x \%*\% y` example +####################################################################### +mat \%*\% as(matrix(1:50, nrow = 5), "dgCMatrix") + + +5 < mat + + +####################################################################### +## `e1 > e2` example +####################################################################### +mat > 5 + + +####################################################################### +## `e1 <= e2` example +####################################################################### +5 <= mat + + +####################################################################### +## `e1 >= e2` example +####################################################################### +mat >= 5 + + +####################################################################### +## round() example +####################################################################### +round(mat) + + +####################################################################### +## `e1 * e2` example +####################################################################### +## Multiplying by a constant +mat * 5 + +## Multiplying by a vector of length `nrow(mat)` +mat * 1:nrow(mat) + + +####################################################################### +## `e1 + e2` example +####################################################################### +## Add by a constant +mat + 5 + +## Adding row-wise by a vector of length `nrow(mat)` +mat + 1:nrow(mat) + + +####################################################################### +## `e1 / e2` example +####################################################################### +## Divide by a constant +mat / 5 + +## Divide by a vector of length `nrow(mat)` +mat / 1:nrow(mat) + + +####################################################################### +## `e1 - e2` example +####################################################################### +## Subtracting by a constant +mat - 5 + +## Subtracting by a vector of length `nrow(mat)` +mat - 1:nrow(mat) + + +} diff --git a/r/man/IterableMatrix-methods.Rd b/r/man/IterableMatrix-methods-stats.Rd similarity index 52% rename from r/man/IterableMatrix-methods.Rd rename to r/man/IterableMatrix-methods-stats.Rd index 05d997c8..0c611339 100644 --- a/r/man/IterableMatrix-methods.Rd +++ b/r/man/IterableMatrix-methods-stats.Rd @@ -1,54 +1,27 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/matrix.R, R/matrix_stats.R, R/transforms.R -\name{IterableMatrix-methods} -\alias{IterableMatrix-methods} -\alias{matrix_type} -\alias{storage_order} -\alias{storage_order,IterableMatrix-method} -\alias{show,IterableMatrix-method} -\alias{t,IterableMatrix-method} -\alias{\%*\%,IterableMatrix,matrix-method} +\name{IterableMatrix-methods-stats} +\alias{IterableMatrix-methods-stats} \alias{rowSums,IterableMatrix-method} \alias{colSums,IterableMatrix-method} \alias{rowMeans,IterableMatrix-method} \alias{colMeans,IterableMatrix-method} \alias{colVars} \alias{rowVars} +\alias{rowVars.IterableMatrix} \alias{rowMaxs} +\alias{rowMaxs.IterableMatrix} \alias{colMaxs} -\alias{[,IterableMatrix,ANY,ANY,ANY-method} -\alias{[<-,IterableMatrix,ANY,ANY,ANY-method} -\alias{dimnames<-,IterableMatrix,list-method} \alias{rowQuantiles} +\alias{rowQuantiles.IterableMatrix} \alias{colQuantiles} +\alias{colQuantiles.IterableMatrix} \alias{log1p,IterableMatrix-method} \alias{log1p_slow} \alias{expm1,IterableMatrix-method} \alias{expm1_slow} -\alias{^,IterableMatrix,numeric-method} -\alias{<,numeric,IterableMatrix-method} -\alias{>,IterableMatrix,numeric-method} -\alias{<=,numeric,IterableMatrix-method} -\alias{>=,IterableMatrix,numeric-method} -\alias{round,IterableMatrix-method} -\alias{*,IterableMatrix,numeric-method} -\alias{+,IterableMatrix,numeric-method} -\alias{/,IterableMatrix,numeric-method} -\alias{-,IterableMatrix,numeric-method} -\title{IterableMatrix methods} +\title{IterableMatrix summary statistics} \usage{ -matrix_type(x) - -storage_order(x) - -\S4method{storage_order}{IterableMatrix}(x) - -\S4method{show}{IterableMatrix}(object) - -\S4method{t}{IterableMatrix}(x) - -\S4method{\%*\%}{IterableMatrix,matrix}(x, y) - \S4method{rowSums}{IterableMatrix}(x) \S4method{colSums}{IterableMatrix}(x) @@ -77,15 +50,21 @@ rowVars( useNames = TRUE ) -rowMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) - -colMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) +\method{rowVars}{IterableMatrix}( + x, + rows = NULL, + cols = NULL, + na.rm = FALSE, + center = NULL, + ..., + useNames = TRUE +) -\S4method{[}{IterableMatrix,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) +rowMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) -\S4method{[}{IterableMatrix,ANY,ANY,ANY}(x, i, j, ...) <- value +\method{rowMaxs}{IterableMatrix}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) -\S4method{dimnames}{IterableMatrix,list}(x) <- value +colMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) rowQuantiles( x, @@ -100,6 +79,19 @@ rowQuantiles( drop = TRUE ) +\method{rowQuantiles}{IterableMatrix}( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) + colQuantiles( x, rows = NULL, @@ -113,6 +105,19 @@ colQuantiles( drop = TRUE ) +colQuantiles.IterableMatrix( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) + \S4method{log1p}{IterableMatrix}(x) log1p_slow(x) @@ -120,34 +125,10 @@ log1p_slow(x) \S4method{expm1}{IterableMatrix}(x) expm1_slow(x) - -\S4method{^}{IterableMatrix,numeric}(e1, e2) - -\S4method{<}{numeric,IterableMatrix}(e1, e2) - -\S4method{>}{IterableMatrix,numeric}(e1, e2) - -\S4method{<=}{numeric,IterableMatrix}(e1, e2) - -\S4method{>=}{IterableMatrix,numeric}(e1, e2) - -\S4method{round}{IterableMatrix}(x, digits = 0) - -\S4method{*}{IterableMatrix,numeric}(e1, e2) - -\S4method{+}{IterableMatrix,numeric}(e1, e2) - -\S4method{/}{IterableMatrix,numeric}(e1, e2) - -\S4method{-}{IterableMatrix,numeric}(e1, e2) } \arguments{ \item{x}{IterableMatrix object or a matrix-like object.} -\item{object}{IterableMatrix object} - -\item{y}{matrix} - \item{rows}{(Integer) Optional vector of row indices to operate over.} \item{cols}{(Integer) Optional vector of column indices to operate over.} @@ -160,33 +141,15 @@ expm1_slow(x) \item{useNames}{(Logical) Whether to use row and column names in the output.} -\item{i}{Row indices or selection helpers.} - -\item{j}{Column indices or selection helpers.} - -\item{drop}{(Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects).} - -\item{value}{New dimnames (list of length 2, or NULL)} - \item{probs}{(Numeric) Quantile value(s) to be computed, between 0 and 1.} \item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} \item{digits}{Number of decimal places for quantile calculations} -\item{e1}{First element of comparison} - -\item{e2}{Second element of comparison} +\item{drop}{(Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects).} } \value{ -\itemize{ -\item \code{t()} Transposed object -} - -\itemize{ -\item \code{x \%*\% y}: dense matrix result -} - \itemize{ \item \code{rowSums()}: vector of row sums } @@ -230,22 +193,10 @@ Else, return a Matrix of quantile values, with cols representing each quantile, } } \description{ -Generic methods and built-in functions for IterableMatrix objects +Summaries and reductions for IterableMatrix objects (sums, means, variances, quantiles, extrema). } \section{Functions}{ \itemize{ -\item \code{matrix_type()}: Get the matrix data type (mat_uint32_t, mat_float, or mat_double for now) - -\item \code{storage_order()}: Get the matrix storage order ("row" or "col") (generic) - -\item \code{storage_order(IterableMatrix)}: Get the matrix storage order ("row" or "col") - -\item \code{show(IterableMatrix)}: Display an IterableMatrix - -\item \code{t(IterableMatrix)}: Transpose an IterableMatrix - -\item \code{x \%*\% y}: Multiply by a dense matrix - \item \code{rowSums(IterableMatrix)}: Calculate rowSums \item \code{colSums(IterableMatrix)}: Calculate colSums @@ -258,20 +209,22 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{rowVars()}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) (generic) -\item \code{rowMaxs()}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) (generic) - -\item \code{colMaxs()}: Calculate colMax (replacement for \code{matrixStats::colMax()}) +\item \code{rowVars(IterableMatrix)}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) -\item \code{x[i}: Subset an IterableMatrix +\item \code{rowMaxs()}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) (generic) -\item \code{`[`(x = IterableMatrix, i = ANY, j = ANY) <- value}: Assign into an IterableMatrix +\item \code{rowMaxs(IterableMatrix)}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) -\item \code{dimnames(x = IterableMatrix) <- value}: Set dimnames of an IterableMatrix, similar to base R \verb{dimnames<-()} +\item \code{colMaxs()}: Calculate colMax (replacement for \code{matrixStats::colMax()}) \item \code{rowQuantiles()}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) +\item \code{rowQuantiles(IterableMatrix)}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) + \item \code{colQuantiles()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) +\item \code{colQuantiles.IterableMatrix()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) + \item \code{log1p(IterableMatrix)}: Calculate log(x + 1) \item \code{log1p_slow()}: Calculate log(x + 1) (non-SIMD version) @@ -280,26 +233,6 @@ Generic methods and built-in functions for IterableMatrix objects \item \code{expm1_slow()}: Calculate exp(x) - 1 (non-SIMD version) -\item \code{e1^e2}: Calculate x^y (elementwise; y > 0) - -\item \code{e1 < e2}: Binarize matrix according to numeric < matrix comparison - -\item \code{e1 > e2}: Binarize matrix according to matrix > numeric comparison - -\item \code{e1 <= e2}: Binarize matrix according to numeric <= matrix comparison - -\item \code{e1 >= e2}: Binarize matrix according to matrix >= numeric comparison - -\item \code{round(IterableMatrix)}: round to nearest integer (digits must be 0) - -\item \code{e1 * e2}: Multiply by a constant, or multiply rows by a vector length nrow(mat) - -\item \code{e1 + e2}: Add a constant, or row-wise addition with a vector length nrow(mat) - -\item \code{e1 / e2}: Divide by a constant, or divide rows by a vector length nrow(mat) - -\item \code{e1 - e2}: Subtract a constant, or row-wise subtraction with a vector length nrow(mat) - }} \examples{ ## Prep data @@ -308,37 +241,6 @@ mat mat <- as(mat, "IterableMatrix") mat - -####################################################################### -## matrix_type() example -####################################################################### -matrix_type(mat) - - -####################################################################### -## storage_order() example -####################################################################### -storage_order(mat) - - -####################################################################### -## show() example -####################################################################### -show(mat) - - -####################################################################### -## t() example -####################################################################### -t(mat) - - -####################################################################### -## `x \%*\% y` example -####################################################################### -mat \%*\% as(matrix(1:50, nrow = 5), "dgCMatrix") - - ####################################################################### ## rowSums() example ####################################################################### @@ -369,6 +271,12 @@ colMeans(mat) colVars(mat) +####################################################################### +## rowVars() example +####################################################################### +rowVars(mat) + + ####################################################################### ## rowMaxs() example ####################################################################### @@ -417,74 +325,4 @@ expm1(mat) expm1_slow(mat) -####################################################################### -## `e1 < e2` example -####################################################################### -5 < mat - - -####################################################################### -## `e1 > e2` example -####################################################################### -mat > 5 - - -####################################################################### -## `e1 <= e2` example -####################################################################### -5 <= mat - - -####################################################################### -## `e1 >= e2` example -####################################################################### -mat >= 5 - - -####################################################################### -## round() example -####################################################################### -round(mat) - - -####################################################################### -## `e1 * e2` example -####################################################################### -## Multiplying by a constant -mat * 5 - -## Multiplying by a vector of length `nrow(mat)` -mat * 1:nrow(mat) - - -####################################################################### -## `e1 + e2` example -####################################################################### -## Add by a constant -mat + 5 - -## Adding row-wise by a vector of length `nrow(mat)` -mat + 1:nrow(mat) - - -####################################################################### -## `e1 / e2` example -####################################################################### -## Divide by a constant -mat / 5 - -## Divide by a vector of length `nrow(mat)` -mat / 1:nrow(mat) - - -####################################################################### -## `e1 - e2` example -####################################################################### -## Subtracting by a constant -mat - 5 - -## Subtracting by a vector of length `nrow(mat)` -mat - 1:nrow(mat) - - } diff --git a/r/man/IterableMatrix-misc-methods.Rd b/r/man/IterableMatrix-misc-methods.Rd index e16f1d88..446f882c 100644 --- a/r/man/IterableMatrix-misc-methods.Rd +++ b/r/man/IterableMatrix-misc-methods.Rd @@ -3,7 +3,13 @@ \docType{methods} \name{IterableMatrix-misc-methods} \alias{IterableMatrix-misc-methods} +\alias{\%*\%,matrix,IterableMatrix-method} +\alias{\%*\%,IterableMatrix,numeric-method} +\alias{\%*\%,numeric,IterableMatrix-method} \alias{matrix_type,MatrixMultiply-method} +\alias{\%*\%,IterableMatrix,IterableMatrix-method} +\alias{\%*\%,IterableMatrix,dgCMatrix-method} +\alias{\%*\%,dgCMatrix,IterableMatrix-method} \alias{[,MatrixMultiply,ANY,ANY,ANY-method} \alias{matrix_type,MatrixMask-method} \alias{matrix_type,MatrixRankTransform-method} @@ -41,8 +47,20 @@ \alias{+,numeric,TransformScaleShift-method} \title{IterableMatrix subclass methods} \usage{ +\S4method{\%*\%}{matrix,IterableMatrix}(x, y) + +\S4method{\%*\%}{IterableMatrix,numeric}(x, y) + +\S4method{\%*\%}{numeric,IterableMatrix}(x, y) + \S4method{matrix_type}{MatrixMultiply}(x) +\S4method{\%*\%}{IterableMatrix,IterableMatrix}(x, y) + +\S4method{\%*\%}{IterableMatrix,dgCMatrix}(x, y) + +\S4method{\%*\%}{dgCMatrix,IterableMatrix}(x, y) + \S4method{[}{MatrixMultiply,ANY,ANY,ANY}(x, i, j, ..., drop = TRUE) \S4method{matrix_type}{MatrixMask}(x) @@ -135,8 +153,20 @@ another matrix or alter behaviour (e.g., concatenation, on-disk access). } \section{Functions}{ \itemize{ +\item \code{x \%*\% y}: Multiply a dense matrix by an IterableMatrix + +\item \code{x \%*\% y}: Multiply an IterableMatrix by a numeric vector + +\item \code{x \%*\% y}: Multiply a numeric row vector by an IterableMatrix + \item \code{matrix_type(MatrixMultiply)}: Matrix data type for MatrixMultiply objects +\item \code{x \%*\% y}: Multiply two IterableMatrix objects + +\item \code{x \%*\% y}: Multiply an IterableMatrix by a dgCMatrix + +\item \code{x \%*\% y}: Multiply a dgCMatrix by an IterableMatrix + \item \code{x[i}: Subset MatrixMultiply results \item \code{matrix_type(MatrixMask)}: Matrix data type for MatrixMask objects diff --git a/r/man/checksum.Rd b/r/man/checksum.Rd index 2c4c3cd3..be92a00f 100644 --- a/r/man/checksum.Rd +++ b/r/man/checksum.Rd @@ -18,7 +18,7 @@ hexidecimal format. } \details{ \code{checksum()} converts the non-zero elements of the sparse input matrix to double -precision, concatenates each element value with the element row and column index words, +precision, concatenates each element value with theF element row and column index words, and uses these 16-byte blocks along with the matrix dimensions and row and column names to calculate the checksum. The checksum value depends on the storage order so column- and row-order matrices with the same element values give different checksum diff --git a/r/man/matrix_R_conversion.Rd b/r/man/matrix_R_conversion.Rd index bd3fcc5a..3dca282b 100644 --- a/r/man/matrix_R_conversion.Rd +++ b/r/man/matrix_R_conversion.Rd @@ -12,10 +12,6 @@ \arguments{ \item{x}{Matrix object to convert} -\item{dgCMatrix}{Sparse matrix in dgCMatrix format} - -\item{IterableMatrix}{IterableMatrix object} - \item{...}{Additional arguments passed to methods} } \description{ diff --git a/r/man/peak_matrix.Rd b/r/man/peak_matrix.Rd index b6c04450..db1d3cf1 100644 --- a/r/man/peak_matrix.Rd +++ b/r/man/peak_matrix.Rd @@ -86,9 +86,9 @@ peaks # peaks <- peaks[order_ranges(peaks, chrNames(frags)),] ## Get peak matrix -peak_matrix(frags, peaks, mode="insertions") -peak_matrix +peak_mat <- peak_matrix(frags, peaks, mode="insertions") +peak_mat -peak_matrix \%>\% as("dgCMatrix") +peak_mat \%>\% as("dgCMatrix") } diff --git a/r/man/svds-internal.Rd b/r/man/svds-internal.Rd new file mode 100644 index 00000000..8d060296 --- /dev/null +++ b/r/man/svds-internal.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/matrix.R +\name{svds-internal} +\alias{svds-internal} +\alias{svds.default} +\alias{svds.IterableMatrix} +\title{Internal svds methods} +\usage{ +\method{svds}{default}(A, k, nu = k, nv = k, opts = list(), ...) + +\method{svds}{IterableMatrix}(A, k, nu = k, nv = k, opts = list(), threads = 0, ...) +} +\description{ +Internal svds methods +} +\keyword{internal} diff --git a/r/man/svds.Rd b/r/man/svds.Rd index 3bd47c40..9822a7a4 100644 --- a/r/man/svds.Rd +++ b/r/man/svds.Rd @@ -1,11 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/matrix-svds-docs.R, R/matrix.R +% Please edit documentation in R/matrix.R \name{svds} \alias{svds} \title{Calculate svds} \usage{ -svds(A, k, nu = k, nv = k, opts = list(), threads=0L, ...) - svds(A, k, nu = k, nv = k, opts = list(), threads = 0L, ...) } \arguments{ @@ -13,66 +11,34 @@ svds(A, k, nu = k, nv = k, opts = list(), threads = 0L, ...) \item{k}{Number of singular values requested.} -\item{nu}{Number of left singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix)} +\item{nu}{Number of left singular vectors to compute (must equal \code{k} for IterableMatrix).} -\item{nv}{Number of right singular vectors to be computed. This must be between 0 and 'k'. (Must be equal to 'k' for BPCells IterableMatrix)} +\item{nv}{Number of right singular vectors to compute (must equal \code{k} for IterableMatrix).} -\item{opts}{Control parameters related to computing algorithm. See \emph{Details} below} +\item{opts}{Control parameters related to the computing algorithm (see Details).} -\item{threads}{Control threads to use calculating mat-vec producs (BPCells specific)} +\item{threads}{Threads to use for matrix-vector products (BPCells specific).} -\item{...}{Additional arguments passed to \code{Rspectra::svds()} if svd is ran on a non-BPCells matrix} +\item{...}{Additional arguments passed to \code{RSpectra::svds()} when running on non-BPCells matrices.} } \value{ -A list with the following components: -\item{d}{A vector of the computed singular values.} -\item{u}{An \code{m} by \code{nu} matrix whose columns contain -the left singular vectors. If \code{nu == 0}, \code{NULL} -will be returned.} -\item{v}{An \code{n} by \code{nv} matrix whose columns contain -the right singular vectors. If \code{nv == 0}, \code{NULL} -will be returned.} -\item{nconv}{Number of converged singular values.} -\item{niter}{Number of iterations used.} -\item{nops}{Number of matrix-vector multiplications used.} +A list with components \code{d}, \code{u}, \code{v}, \code{nconv}, \code{niter}, and \code{nops}. } \description{ -Use the C++ Spectra solver (same as RSpectra package), in order to -compute the largest k values and corresponding singular vectors. -Empirically, memory usage is much lower than using \code{irlba::irlba()}, likely -due to avoiding R garbage creation while solving due to the pure-C++ solver. -This documentation is a slightly-edited version of the \code{RSpectra::svds()} -documentation. +Use the C++ Spectra solver (same as RSpectra package) to compute the largest +\code{k} singular values and corresponding singular vectors. Empirically, memory +use is much lower than \code{irlba::irlba()} because the solver runs entirely in C++. } \details{ -When RSpectra is installed, this function will just add a method to -\code{RSpectra::svds()} for the \code{IterableMatrix} class. - -The \code{opts} argument is a list that can supply any of the -following parameters: +When RSpectra is installed, this adds a method to \code{RSpectra::svds()} for +\code{IterableMatrix} objects; otherwise it falls back to the bundled implementation. -\describe{ -\item{\code{ncv}}{Number of Lanzcos basis vectors to use. More vectors -will result in faster convergence, but with greater -memory use. \code{ncv} must be satisfy -\eqn{k < ncv \le p}{k < ncv <= p} where -\code{p = min(m, n)}. -Default is \code{min(p, max(2*k+1, 20))}.} -\item{\code{tol}}{Precision parameter. Default is 1e-10.} -\item{\code{maxitr}}{Maximum number of iterations. Default is 1000.} -\item{\code{center}}{Either a logical value (\code{TRUE}/\code{FALSE}), or a numeric -vector of length \eqn{n}. If a vector \eqn{c} is supplied, then -SVD is computed on the matrix \eqn{A - 1c'}{A - 1 * c'}, -in an implicit way without actually forming this matrix. -\code{center = TRUE} has the same effect as -\code{center = colMeans(A)}. Default is \code{FALSE}. Ignored in BPCells} -\item{\code{scale}}{Either a logical value (\code{TRUE}/\code{FALSE}), or a numeric -vector of length \eqn{n}. If a vector \eqn{s} is supplied, then -SVD is computed on the matrix \eqn{(A - 1c')S}{(A - 1 * c')S}, -where \eqn{c} is the centering vector and \eqn{S = diag(1/s)}. -If \code{scale = TRUE}, then the vector \eqn{s} is computed as -the column norm of \eqn{A - 1c'}{A - 1 * c'}. -Default is \code{FALSE}. Ignored in BPCells} +The \code{opts} list may include: +\itemize{ +\item \code{ncv}: Number of Lanczos basis vectors (\verb{k < ncv <= min(m, n)}). Default \code{min(p, max(2*k+1, 20))}. +\item \code{tol}: Precision parameter (default \code{1e-10}). +\item \code{maxitr}: Maximum iterations (default \code{1000}). +\item \code{center}, \code{scale}: Centering/scaling options (ignored for BPCells). } } \examples{ @@ -82,17 +48,15 @@ colnames(mat) <- paste0("cell", seq_len(10)) mat <- mat \%>\% as("dgCMatrix") \%>\% as("IterableMatrix") svd_res <- svds(mat, k = 5) - names(svd_res) - svd_res$d - dim(svd_res$u) - dim(svd_res$v) -# Can also pass in values directly into RSpectra::svds -svd_res <- svds(mat, k = 5, opts=c(maxitr = 500)) + +# Can also pass values directly into RSpectra::svds +svd_res <- svds(mat, k = 5, opts = c(maxitr = 500)) + } \references{ -Qiu Y, Mei J (2022). \emph{RSpectra: Solvers for Large-Scale Eigenvalue and SVD Problems}. R package version 0.16-1, \url{https://CRAN.R-project.org/package=RSpectra}. +Qiu Y, Mei J (2022). RSpectra: Solvers for Large-Scale Eigenvalue and SVD Problems. R package version 0.16-1. } diff --git a/r/pkgdown/_pkgdown.yml b/r/pkgdown/_pkgdown.yml index cac5ea8a..7ac4a3ea 100644 --- a/r/pkgdown/_pkgdown.yml +++ b/r/pkgdown/_pkgdown.yml @@ -140,7 +140,9 @@ reference: - apply_by_row - regress_out - pseudobulk_matrix - - IterableMatrix-methods + - IterableMatrix-methods-core + - IterableMatrix-methods-ops + - IterableMatrix-methods-stats - title: "Reference Annotations" From a84ba0f2da60c66bc840997b184848f43a87e8b3 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Thu, 4 Dec 2025 18:45:57 -0800 Subject: [PATCH 58/84] small cran fixes --- r/.Rbuildignore | 1 + r/NAMESPACE | 4 ++ r/NEWS.md | 2 + r/R/atac_utils.R | 8 ++-- r/R/genomeAnnotations.R | 82 ++++++++++++++++++++-------------------- r/cran-comments.md | 5 +++ r/man/call_peaks_tile.Rd | 6 +-- r/man/read_gtf.Rd | 82 ++++++++++++++++++++-------------------- 8 files changed, 101 insertions(+), 89 deletions(-) create mode 100644 r/cran-comments.md diff --git a/r/.Rbuildignore b/r/.Rbuildignore index ff5b61ba..eab151b9 100644 --- a/r/.Rbuildignore +++ b/r/.Rbuildignore @@ -24,3 +24,4 @@ cmake-build-debug/ \.vscode/ \.snakemake/ +^cran-comments\.md$ diff --git a/r/NAMESPACE b/r/NAMESPACE index f4b9cf5d..f9933d68 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -151,6 +151,10 @@ exportMethods(as.data.frame) exportMethods(as.matrix) exportMethods(t) importClassesFrom(Matrix,dgCMatrix) +importFrom(Matrix,colMeans) +importFrom(Matrix,colSums) +importFrom(Matrix,rowMeans) +importFrom(Matrix,rowSums) importFrom(Matrix,t) importFrom(Rcpp,sourceCpp) importFrom(ggplot2,element_text) diff --git a/r/NEWS.md b/r/NEWS.md index a79c2ee9..390fc833 100644 --- a/r/NEWS.md +++ b/r/NEWS.md @@ -8,6 +8,8 @@ to Python in the future. # BPCells 0.3.2 +* Initial CRAN submission. + The BPCells 0.3.2 release covers 3 months of changes and 4 commits from @immanuelazn. Most notably, this release prepares (finally!) BPCells for CRAN submission. This means that users can easily install BPCells using pre-compiled binaries, rather than having to compile from source. Full details of changes below. diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index 708f3a10..d4b040dd 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -380,10 +380,10 @@ merge_peaks_iterative <- function(peaks) { #' #' #' ## Call peaks -#' \dontrun{ +#' if (interactive()) { #' call_peaks_tile(frags_filter_blacklist, chrom_sizes, effective_genome_size = 2.8e9) #' } -#' #> # A tibble: 73,160 × 7 +#' #> # A tibble: 73,160 x 7 #' #> chr start end group p_val q_val enrichment #' #> #' #> 1 chr11 65615400 65615600 all 0 0 6764. @@ -396,7 +396,7 @@ merge_peaks_iterative <- function(peaks) { #' #> 8 chr11 64878600 64878800 all 0 0 5948. #' #> 9 chr11 57667733 57667933 all 0 0 5946. #' #> 10 chr11 83156933 83157133 all 0 0 5913. -#' #> # ℹ 73,150 more rows +#' #> # i 73,150 more rows #' @export call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int("all", length(cellNames(fragments))), effective_genome_size = NULL, @@ -906,4 +906,4 @@ range_overlaps <- function(a, b) { } %>% dplyr::arrange(from, to) } - \ No newline at end of file + diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index fb197bd6..dc22b5ca 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -54,7 +54,7 @@ ensure_downloaded <- function(path, backup_url, timeout) { #' ####################################################################### #' ## read_gtf() example #' ####################################################################### -#' \dontrun{ +#' if (interactive()) { #' #' species <- "Saccharomyces_cerevisiae" #' version <- "GCF_000146045.2_R64" @@ -65,14 +65,14 @@ ensure_downloaded <- function(path, backup_url, timeout) { #' species, version, version #' ) #' )) -#' #> # A tibble: 6 × 9 -#' #> chr source feature start end score strand frame gene_id -#' #> -#' #> 1 NC_001133.9 RefSeq gene 1806 2169 . - . YAL068C -#' #> 2 NC_001133.9 RefSeq gene 2479 2707 . + . YAL067W-A -#' #> 3 NC_001133.9 RefSeq gene 7234 9016 . - . YAL067C -#' #> 4 NC_001133.9 RefSeq gene 11564 11951 . - . YAL065C -#' #> 5 NC_001133.9 RefSeq gene 12045 12426 . + . YAL064W-B +#' #> # A tibble: 6 x 9 +#' #> chr source feature start end score strand frame gene_id +#' #> +#' #> 1 NC_001133.9 RefSeq gene 1806 2169 . - . YAL068C +#' #> 2 NC_001133.9 RefSeq gene 2479 2707 . + . YAL067W-A +#' #> 3 NC_001133.9 RefSeq gene 7234 9016 . - . YAL067C +#' #> 4 NC_001133.9 RefSeq gene 11564 11951 . - . YAL065C +#' #> 5 NC_001133.9 RefSeq gene 12045 12426 . + . YAL064W-B #' #> 6 NC_001133.9 RefSeq gene 13362 13743 . - . YAL064C-A #' } #' @@ -119,23 +119,23 @@ read_gtf <- function(path, attributes = c("gene_id"), tags = character(0), featu #' ####################################################################### #' ## read_gencode_genes() example #' ####################################################################### -#' \dontrun{ +#' if (interactive()) { #' read_gencode_genes(file.path(tempdir(), "references"), release = "42", timeout = 3000) -#' #> # A tibble: 39,319 × 11 -#' #> chr source feature start end score strand frame gene_id gene_type -#' #> -#' #> 1 chr1 HAVANA gene 11868 14409 . + . ENSG00000290… lncRNA -#' #> 2 chr1 HAVANA gene 29553 31109 . + . ENSG00000243… lncRNA -#' #> 3 chr1 HAVANA gene 34553 36081 . - . ENSG00000237… lncRNA -#' #> 4 chr1 HAVANA gene 57597 64116 . + . ENSG00000290… lncRNA -#' #> 5 chr1 HAVANA gene 65418 71585 . + . ENSG00000186… protein_… -#' #> 6 chr1 HAVANA gene 89294 133723 . - . ENSG00000238… lncRNA -#' #> 7 chr1 HAVANA gene 89550 91105 . - . ENSG00000239… lncRNA -#' #> 8 chr1 HAVANA gene 139789 140339 . - . ENSG00000239… lncRNA -#' #> 9 chr1 HAVANA gene 141473 173862 . - . ENSG00000241… lncRNA -#' #> 10 chr1 HAVANA gene 160445 161525 . + . ENSG00000241… lncRNA -#' #> # ℹ 39,309 more rows -#' #> # ℹ 1 more variable: gene_name +#' #> # A tibble: 39,319 x 11 +#' #> chr source feature start end score strand frame gene_id gene_type +#' #> +#' #> 1 chr1 HAVANA gene 11868 14409 . + . ENSG00000290... lncRNA +#' #> 2 chr1 HAVANA gene 29553 31109 . + . ENSG00000243... lncRNA +#' #> 3 chr1 HAVANA gene 34553 36081 . - . ENSG00000237... lncRNA +#' #> 4 chr1 HAVANA gene 57597 64116 . + . ENSG00000290... lncRNA +#' #> 5 chr1 HAVANA gene 65418 71585 . + . ENSG00000186... protein_... +#' #> 6 chr1 HAVANA gene 89294 133723 . - . ENSG00000238... lncRNA +#' #> 7 chr1 HAVANA gene 89550 91105 . - . ENSG00000239... lncRNA +#' #> 8 chr1 HAVANA gene 139789 140339 . - . ENSG00000239... lncRNA +#' #> 9 chr1 HAVANA gene 141473 173862 . - . ENSG00000241... lncRNA +#' #> 10 chr1 HAVANA gene 160445 161525 . + . ENSG00000241... lncRNA +#' #> # i 39,309 more rows +#' #> # i 1 more variable: gene_name #' } #' #' @@ -188,23 +188,23 @@ read_gencode_genes <- function(dir, release = "latest", #' ####################################################################### #' ## If read_gencode_genes() was already ran on the same release, #' ## will reuse previously downloaded annotations -#' \dontrun{ +#' if (interactive()) { #' read_gencode_transcripts(file.path(tempdir(), "references"), release = "42", timeout = 3000) -#' #> # A tibble: 220,296 × 13 -#' #> chr source feature start end score strand frame gene_id gene_type -#' #> -#' #> 1 chr1 HAVANA transcript 65418 71585 . + . ENSG00000… protein_… -#' #> 2 chr1 HAVANA exon 65418 65433 . + . ENSG00000… protein_… -#' #> 3 chr1 HAVANA exon 65519 65573 . + . ENSG00000… protein_… -#' #> 4 chr1 HAVANA exon 69036 71585 . + . ENSG00000… protein_… -#' #> 5 chr1 HAVANA transcript 450739 451678 . - . ENSG00000… protein_… -#' #> 6 chr1 HAVANA exon 450739 451678 . - . ENSG00000… protein_… -#' #> 7 chr1 HAVANA transcript 685715 686654 . - . ENSG00000… protein_… -#' #> 8 chr1 HAVANA exon 685715 686654 . - . ENSG00000… protein_… -#' #> 9 chr1 HAVANA transcript 923922 944574 . + . ENSG00000… protein_… -#' #> 10 chr1 HAVANA exon 923922 924948 . + . ENSG00000… protein_… -#' #> # ℹ 220,286 more rows -#' #> # ℹ 3 more variables: gene_name , transcript_id , MANE_Select +#' #> # A tibble: 220,296 x 13 +#' #> chr source feature start end score strand frame gene_id gene_type +#' #> +#' #> 1 chr1 HAVANA transcript 65418 71585 . + . ENSG00000... protein_... +#' #> 2 chr1 HAVANA exon 65418 65433 . + . ENSG00000... protein_... +#' #> 3 chr1 HAVANA exon 65519 65573 . + . ENSG00000... protein_... +#' #> 4 chr1 HAVANA exon 69036 71585 . + . ENSG00000... protein_... +#' #> 5 chr1 HAVANA transcript 450739 451678 . - . ENSG00000... protein_... +#' #> 6 chr1 HAVANA exon 450739 451678 . - . ENSG00000... protein_... +#' #> 7 chr1 HAVANA transcript 685715 686654 . - . ENSG00000... protein_... +#' #> 8 chr1 HAVANA exon 685715 686654 . - . ENSG00000... protein_... +#' #> 9 chr1 HAVANA transcript 923922 944574 . + . ENSG00000... protein_... +#' #> 10 chr1 HAVANA exon 923922 924948 . + . ENSG00000... protein_... +#' #> # i 220,286 more rows +#' #> # i 3 more variables: gene_name , transcript_id , MANE_Select #' } #' @export read_gencode_transcripts <- function(dir, release = "latest", transcript_choice = c("MANE_Select", "Ensembl_Canonical", "all"), diff --git a/r/cran-comments.md b/r/cran-comments.md new file mode 100644 index 00000000..858617db --- /dev/null +++ b/r/cran-comments.md @@ -0,0 +1,5 @@ +## R CMD check results + +0 errors | 0 warnings | 1 note + +* This is a new release. diff --git a/r/man/call_peaks_tile.Rd b/r/man/call_peaks_tile.Rd index 94dbcd5d..9430f963 100644 --- a/r/man/call_peaks_tile.Rd +++ b/r/man/call_peaks_tile.Rd @@ -92,10 +92,10 @@ chrom_sizes <- read_ucsc_chrom_sizes(reference_dir, genome="hg38") \%>\% ## Call peaks -\dontrun{ +if (interactive()) { call_peaks_tile(frags_filter_blacklist, chrom_sizes, effective_genome_size = 2.8e9) } -#> # A tibble: 73,160 × 7 +#> # A tibble: 73,160 x 7 #> chr start end group p_val q_val enrichment #> #> 1 chr11 65615400 65615600 all 0 0 6764. @@ -108,5 +108,5 @@ call_peaks_tile(frags_filter_blacklist, chrom_sizes, effective_genome_size = 2.8 #> 8 chr11 64878600 64878800 all 0 0 5948. #> 9 chr11 57667733 57667933 all 0 0 5946. #> 10 chr11 83156933 83157133 all 0 0 5913. -#> # ℹ 73,150 more rows +#> # i 73,150 more rows } diff --git a/r/man/read_gtf.Rd b/r/man/read_gtf.Rd index fe848d26..7597375b 100644 --- a/r/man/read_gtf.Rd +++ b/r/man/read_gtf.Rd @@ -111,7 +111,7 @@ Read transcript models from GENCODE, for use with trackplot_gene() ####################################################################### ## read_gtf() example ####################################################################### -\dontrun{ +if (interactive()) { species <- "Saccharomyces_cerevisiae" version <- "GCF_000146045.2_R64" @@ -122,14 +122,14 @@ head(read_gtf( species, version, version ) )) -#> # A tibble: 6 × 9 -#> chr source feature start end score strand frame gene_id -#> -#> 1 NC_001133.9 RefSeq gene 1806 2169 . - . YAL068C -#> 2 NC_001133.9 RefSeq gene 2479 2707 . + . YAL067W-A -#> 3 NC_001133.9 RefSeq gene 7234 9016 . - . YAL067C -#> 4 NC_001133.9 RefSeq gene 11564 11951 . - . YAL065C -#> 5 NC_001133.9 RefSeq gene 12045 12426 . + . YAL064W-B +#> # A tibble: 6 x 9 +#> chr source feature start end score strand frame gene_id +#> +#> 1 NC_001133.9 RefSeq gene 1806 2169 . - . YAL068C +#> 2 NC_001133.9 RefSeq gene 2479 2707 . + . YAL067W-A +#> 3 NC_001133.9 RefSeq gene 7234 9016 . - . YAL067C +#> 4 NC_001133.9 RefSeq gene 11564 11951 . - . YAL065C +#> 5 NC_001133.9 RefSeq gene 12045 12426 . + . YAL064W-B #> 6 NC_001133.9 RefSeq gene 13362 13743 . - . YAL064C-A } @@ -137,23 +137,23 @@ head(read_gtf( ####################################################################### ## read_gencode_genes() example ####################################################################### -\dontrun{ +if (interactive()) { read_gencode_genes(file.path(tempdir(), "references"), release = "42", timeout = 3000) -#> # A tibble: 39,319 × 11 -#> chr source feature start end score strand frame gene_id gene_type -#> -#> 1 chr1 HAVANA gene 11868 14409 . + . ENSG00000290… lncRNA -#> 2 chr1 HAVANA gene 29553 31109 . + . ENSG00000243… lncRNA -#> 3 chr1 HAVANA gene 34553 36081 . - . ENSG00000237… lncRNA -#> 4 chr1 HAVANA gene 57597 64116 . + . ENSG00000290… lncRNA -#> 5 chr1 HAVANA gene 65418 71585 . + . ENSG00000186… protein_… -#> 6 chr1 HAVANA gene 89294 133723 . - . ENSG00000238… lncRNA -#> 7 chr1 HAVANA gene 89550 91105 . - . ENSG00000239… lncRNA -#> 8 chr1 HAVANA gene 139789 140339 . - . ENSG00000239… lncRNA -#> 9 chr1 HAVANA gene 141473 173862 . - . ENSG00000241… lncRNA -#> 10 chr1 HAVANA gene 160445 161525 . + . ENSG00000241… lncRNA -#> # ℹ 39,309 more rows -#> # ℹ 1 more variable: gene_name +#> # A tibble: 39,319 x 11 +#> chr source feature start end score strand frame gene_id gene_type +#> +#> 1 chr1 HAVANA gene 11868 14409 . + . ENSG00000290... lncRNA +#> 2 chr1 HAVANA gene 29553 31109 . + . ENSG00000243... lncRNA +#> 3 chr1 HAVANA gene 34553 36081 . - . ENSG00000237... lncRNA +#> 4 chr1 HAVANA gene 57597 64116 . + . ENSG00000290... lncRNA +#> 5 chr1 HAVANA gene 65418 71585 . + . ENSG00000186... protein_... +#> 6 chr1 HAVANA gene 89294 133723 . - . ENSG00000238... lncRNA +#> 7 chr1 HAVANA gene 89550 91105 . - . ENSG00000239... lncRNA +#> 8 chr1 HAVANA gene 139789 140339 . - . ENSG00000239... lncRNA +#> 9 chr1 HAVANA gene 141473 173862 . - . ENSG00000241... lncRNA +#> 10 chr1 HAVANA gene 160445 161525 . + . ENSG00000241... lncRNA +#> # i 39,309 more rows +#> # i 1 more variable: gene_name } @@ -162,23 +162,23 @@ read_gencode_genes(file.path(tempdir(), "references"), release = "42", timeout = ####################################################################### ## If read_gencode_genes() was already ran on the same release, ## will reuse previously downloaded annotations -\dontrun{ +if (interactive()) { read_gencode_transcripts(file.path(tempdir(), "references"), release = "42", timeout = 3000) -#> # A tibble: 220,296 × 13 -#> chr source feature start end score strand frame gene_id gene_type -#> -#> 1 chr1 HAVANA transcript 65418 71585 . + . ENSG00000… protein_… -#> 2 chr1 HAVANA exon 65418 65433 . + . ENSG00000… protein_… -#> 3 chr1 HAVANA exon 65519 65573 . + . ENSG00000… protein_… -#> 4 chr1 HAVANA exon 69036 71585 . + . ENSG00000… protein_… -#> 5 chr1 HAVANA transcript 450739 451678 . - . ENSG00000… protein_… -#> 6 chr1 HAVANA exon 450739 451678 . - . ENSG00000… protein_… -#> 7 chr1 HAVANA transcript 685715 686654 . - . ENSG00000… protein_… -#> 8 chr1 HAVANA exon 685715 686654 . - . ENSG00000… protein_… -#> 9 chr1 HAVANA transcript 923922 944574 . + . ENSG00000… protein_… -#> 10 chr1 HAVANA exon 923922 924948 . + . ENSG00000… protein_… -#> # ℹ 220,286 more rows -#> # ℹ 3 more variables: gene_name , transcript_id , MANE_Select +#> # A tibble: 220,296 x 13 +#> chr source feature start end score strand frame gene_id gene_type +#> +#> 1 chr1 HAVANA transcript 65418 71585 . + . ENSG00000... protein_... +#> 2 chr1 HAVANA exon 65418 65433 . + . ENSG00000... protein_... +#> 3 chr1 HAVANA exon 65519 65573 . + . ENSG00000... protein_... +#> 4 chr1 HAVANA exon 69036 71585 . + . ENSG00000... protein_... +#> 5 chr1 HAVANA transcript 450739 451678 . - . ENSG00000... protein_... +#> 6 chr1 HAVANA exon 450739 451678 . - . ENSG00000... protein_... +#> 7 chr1 HAVANA transcript 685715 686654 . - . ENSG00000... protein_... +#> 8 chr1 HAVANA exon 685715 686654 . - . ENSG00000... protein_... +#> 9 chr1 HAVANA transcript 923922 944574 . + . ENSG00000... protein_... +#> 10 chr1 HAVANA exon 923922 924948 . + . ENSG00000... protein_... +#> # i 220,286 more rows +#> # i 3 more variables: gene_name , transcript_id , MANE_Select } } \seealso{ From 31e616a42ee7f32c7e71fe3dfa66582a1f8b7d51 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Fri, 5 Dec 2025 12:58:41 -0800 Subject: [PATCH 59/84] fix some plotting issues in docs --- r/R/plots.R | 9 +++++++++ r/R/trackplots.R | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/r/R/plots.R b/r/R/plots.R index 1be6d484..1ce32eca 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -155,6 +155,15 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE ) rectangle_highlight <- tibble::tibble( xmin = -Inf, xmax = Inf, + ymin = log10(cutoff), ymax = Inf + ) + plot <- plot + + ggplot2::geom_hline(yintercept = log10(cutoff), linetype = "dashed") + + ggplot2::geom_text(data = cell_label, ggplot2::aes(x, y, label = label), hjust = "inward", vjust = "inward") + + ggplot2::geom_rect( + ggplot2::aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, x = NULL, y = NULL), + data = rectangle_highlight, + alpha = 0.1 ) } diff --git a/r/R/trackplots.R b/r/R/trackplots.R index 45f3a4ec..c07baeea 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -333,7 +333,6 @@ trackplot_normalize_ranges_with_metadata <- function(data, metadata) { #' trackplot_combine( #' list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) #' ) -#' plot #' @export trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_width = 0.3) { for (plot in tracks) { @@ -1315,6 +1314,13 @@ ragg_wrap <- function( ) { height_scale <- getOption("BPCells.scale_next_plot_height", default = 1) options("BPCells.scale_next_plot_height" = NULL) + + # Heuristic: if dimensions are very small (<20) and units are pixels, assume inches were intended. + # This fixes issues where knitr passes inches to this custom device but defaults to px units. + if (units == "px" && width < 20 && height < 20) { + units <- "in" + } + ragg::agg_png( filename = filename, width = width, From 0a208ddb92a19c5b6ad1efa72aafb4b927c54653 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Mon, 15 Dec 2025 15:53:27 -0800 Subject: [PATCH 60/84] [r] add missing code snippets from trackplot_combine.Rd --- r/DESCRIPTION | 2 +- r/man/trackplot_combine.Rd | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 45cd74fb..3880d529 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -17,7 +17,7 @@ Description: Efficient operations for single cell ATAC-seq fragments and License: Apache License (>= 2) | MIT + file LICENSE Encoding: UTF-8 LazyData: true -RoxygenNote: 7.3.2 +RoxygenNote: 7.3.3 Roxygen: list(markdown = TRUE) URL: https://bnprks.github.io/BPCells/, https://github.com/bnprks/BPCells LinkingTo: diff --git a/r/man/trackplot_combine.Rd b/r/man/trackplot_combine.Rd index a4ef0389..716a2e9c 100644 --- a/r/man/trackplot_combine.Rd +++ b/r/man/trackplot_combine.Rd @@ -69,7 +69,6 @@ scale_next_plot_height(0.6) trackplot_combine( list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) ) -plot } \seealso{ \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} From 3415788446bca2e249dbb82ed574e60db6b2319d Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Mon, 15 Dec 2025 17:08:00 -0800 Subject: [PATCH 61/84] [r] misc docs cleanups --- r/R/plots.R | 2 +- r/R/trackplots.R | 2 +- r/R/transforms.R | 2 +- r/man/IterableMatrix-methods-ops-misc.Rd | 5 +++++ r/man/IterableMatrix-methods-ops.Rd | 5 ----- r/man/call_peaks_macs.Rd | 2 +- r/man/plot_tss_profile.Rd | 2 +- r/man/reexports.Rd | 2 +- r/man/trackplot_gene.Rd | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/r/R/plots.R b/r/R/plots.R index 1ce32eca..cc5a6c1e 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -325,7 +325,7 @@ plot_fragment_length <- function(fragments, max_length = 500, return_data = FALS #' @seealso `footprint()`, `plot_tf_footprint()` #' @examples #' ## Prep data -#' frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) +#' frags <- get_demo_frags() #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", #' annotation_set = "basic", diff --git a/r/R/trackplots.R b/r/R/trackplots.R index c07baeea..4f91b343 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -599,7 +599,7 @@ trackplot_coverage <- function(fragments, region, groups, #' file.path(tempdir(), "references"), release = "42", #' annotation_set = "basic", features = "transcript", timeout = 3000 #' ) -#' region <- "chr4:3034877-4034877" +#' region <- "chr4:3264877-3634877" #' #' ## Plot gene trackplot #' scale_next_plot_height(0.3) diff --git a/r/R/transforms.R b/r/R/transforms.R index 0755c6d2..72c3696c 100644 --- a/r/R/transforms.R +++ b/r/R/transforms.R @@ -370,7 +370,7 @@ binarize <- function(mat, threshold=0, strict_inequality=TRUE) { global_params=c(threshold, strict_inequality)) convert_matrix_type(res, "uint32_t") } -#' @describeIn IterableMatrix-methods-ops Perform matrix < numeric comparison (IterableMatrix left) +#' @describeIn IterableMatrix-methods-ops-misc Perform matrix < numeric comparison (IterableMatrix left) setMethod("<", signature(e1= "IterableMatrix", e2= "numeric"), function(e1, e2) { stop("matrix < numeric not supported for IterableMatrix objects") }) diff --git a/r/man/IterableMatrix-methods-ops-misc.Rd b/r/man/IterableMatrix-methods-ops-misc.Rd index 09aeef4d..1b9ce7a4 100644 --- a/r/man/IterableMatrix-methods-ops-misc.Rd +++ b/r/man/IterableMatrix-methods-ops-misc.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/matrix.R, R/transforms.R \name{IterableMatrix-methods-ops-misc} \alias{IterableMatrix-methods-ops-misc} +\alias{<,IterableMatrix,numeric-method} \alias{>,numeric,IterableMatrix-method} \alias{<=,IterableMatrix,numeric-method} \alias{>=,numeric,IterableMatrix-method} @@ -10,6 +11,8 @@ \alias{-,numeric,IterableMatrix-method} \title{IterableMatrix operations (additional overloads)} \usage{ +\S4method{<}{IterableMatrix,numeric}(e1, e2) + \S4method{>}{numeric,IterableMatrix}(e1, e2) \S4method{<=}{IterableMatrix,numeric}(e1, e2) @@ -27,6 +30,8 @@ Extra operator overloads documented separately to avoid duplicate entries in the } \section{Functions}{ \itemize{ +\item \code{e1 < e2}: Perform matrix < numeric comparison (IterableMatrix left) + \item \code{e1 > e2}: Perform numeric > matrix comparison (numeric left) \item \code{e1 <= e2}: Perform matrix <= numeric comparison (IterableMatrix left) diff --git a/r/man/IterableMatrix-methods-ops.Rd b/r/man/IterableMatrix-methods-ops.Rd index 06f0f7e5..16235c0f 100644 --- a/r/man/IterableMatrix-methods-ops.Rd +++ b/r/man/IterableMatrix-methods-ops.Rd @@ -4,7 +4,6 @@ \alias{IterableMatrix-methods-ops} \alias{\%*\%,IterableMatrix,matrix-method} \alias{^,IterableMatrix,numeric-method} -\alias{<,IterableMatrix,numeric-method} \alias{<,numeric,IterableMatrix-method} \alias{>,IterableMatrix,numeric-method} \alias{<=,numeric,IterableMatrix-method} @@ -20,8 +19,6 @@ \S4method{^}{IterableMatrix,numeric}(e1, e2) -\S4method{<}{IterableMatrix,numeric}(e1, e2) - \S4method{<}{numeric,IterableMatrix}(e1, e2) \S4method{>}{IterableMatrix,numeric}(e1, e2) @@ -65,8 +62,6 @@ Matrix multiplication, arithmetic, and comparison operations for IterableMatrix \item \code{e1^e2}: Calculate x^y (elementwise; y > 0) -\item \code{e1 < e2}: Perform matrix < numeric comparison (IterableMatrix left) - \item \code{e1 < e2}: Perform numeric < matrix comparison (numeric left) \item \code{e1 > e2}: Perform matrix > numeric comparison (IterableMatrix left) diff --git a/r/man/call_peaks_macs.Rd b/r/man/call_peaks_macs.Rd index edf4e96f..c75a5077 100644 --- a/r/man/call_peaks_macs.Rd +++ b/r/man/call_peaks_macs.Rd @@ -89,7 +89,7 @@ shell scripts generated at \verb{/input/.sh}. Finally, run \code{ca setting \code{step="read-outputs"}. } \examples{ -\dontshow{if (tryCatch({ macs_path_is_valid(); TRUE }, error = function(e) FALSE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{if (tryCatch({ macs_path_is_valid(); TRUE }, error = function(e) FALSE)) withAutoprint(\{ # examplesIf} macs_files <- file.path(tempdir(), "peaks") frags <- get_demo_frags() diff --git a/r/man/plot_tss_profile.Rd b/r/man/plot_tss_profile.Rd index e4733fe8..146b2b63 100644 --- a/r/man/plot_tss_profile.Rd +++ b/r/man/plot_tss_profile.Rd @@ -44,7 +44,7 @@ small bump downstream around 220bp downstream of the TSS for the +1 nucleosome. } \examples{ ## Prep data -frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) +frags <- get_demo_frags() genes <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", annotation_set = "basic", diff --git a/r/man/reexports.Rd b/r/man/reexports.Rd index 5d4c340d..e4ac817a 100644 --- a/r/man/reexports.Rd +++ b/r/man/reexports.Rd @@ -17,6 +17,6 @@ below to see their documentation. \describe{ \item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}} - \item{Matrix}{\code{\link[Matrix:colSums-methods]{colMeans}}, \code{\link[Matrix:colSums-methods]{colSums}}, \code{\link[Matrix:colSums-methods]{rowMeans}}, \code{\link[Matrix:colSums-methods]{rowSums}}} + \item{Matrix}{\code{\link[Matrix:colSums]{colMeans}}, \code{\link[Matrix]{colSums}}, \code{\link[Matrix:colSums]{rowMeans}}, \code{\link[Matrix:colSums]{rowSums}}} }} diff --git a/r/man/trackplot_gene.Rd b/r/man/trackplot_gene.Rd index d287d8a9..5f267945 100644 --- a/r/man/trackplot_gene.Rd +++ b/r/man/trackplot_gene.Rd @@ -51,7 +51,7 @@ transcripts <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", annotation_set = "basic", features = "transcript", timeout = 3000 ) -region <- "chr4:3034877-4034877" +region <- "chr4:3264877-3634877" ## Plot gene trackplot scale_next_plot_height(0.3) From 0467ce5eb21b64231f8e9366ca611d61b6faf793 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Mon, 15 Dec 2025 17:27:55 -0800 Subject: [PATCH 62/84] update NEWS.md --- r/NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r/NEWS.md b/r/NEWS.md index 2ca1dc09..556b0d12 100644 --- a/r/NEWS.md +++ b/r/NEWS.md @@ -10,7 +10,7 @@ # BPCells 0.3.2 * Initial CRAN submission. -The BPCells 0.3.2 release covers 3 months of changes and 4 commits from @immanuelazn. +The BPCells 0.3.2 release covers 6 months of changes and 8 commits from @immanuelazn. Most notably, this release prepares (finally!) BPCells for CRAN submission. This means that users can easily install BPCells using pre-compiled binaries, rather than having to compile from source. Full details of changes below. From 4dbba4be23e85fa1d0dad182aba2e898d3be5c2c Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 15 Dec 2025 23:24:00 -0800 Subject: [PATCH 63/84] [r] fix chr levels bug in `footprint()` --- r/R/atac_utils.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index d4b040dd..8b407097 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -112,6 +112,9 @@ footprint <- function(fragments, ranges, zero_based_coords = !is(ranges, "GRange assert_is_wholenumber(flank) chr <- as.integer(factor(ranges$chr, chrNames(fragments))) - 1 + # Filter to ranges that overlap the chromosomes from `fragments` + ranges <- ranges[!is.na(chr),] + chr <- chr[!is.na(chr)] cell_groups <- as.factor(cell_groups) iter <- iterate_fragments(fragments) From c9f9c6c6a52def2e9bb19fa8fe5e46248c72c67c Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 16 Dec 2025 09:52:58 -0800 Subject: [PATCH 64/84] [r] fix docs package for `trackplot_calculate_segment_height()` --- r/R/trackplots.R | 5 +++-- r/man/trackplot_calculate_segment_height.Rd | 14 +++----------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/r/R/trackplots.R b/r/R/trackplots.R index 4f91b343..d50a1148 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -150,13 +150,14 @@ get_trackplot_height <- function(plot) { } #' Calculate y positions for trackplot segments to avoid overlap +#' #' Steps: #' 1. Calculate the maximum overlap depth of transcripts #' 2. Iterate through start/end of segments in sorted order #' 3. Randomly assign each segment a y-coordinate between 1 and max overlap depth, -#' with the restriction that a segment can't have the same y-coordinate as an overlapping segment +#' with the restriction that a segment cannot have the same y-coordinate as an overlapping segment #' @param data tibble of genome ranges with start and end columns, assumed to be on same chromosome. -#' @return Vector of y coordinates, one per input row, such that no ranges at the same y coordinate overlap +#' @return Vector of y coordinates, one per input row, such that no ranges at the same y coordinate overlap. #' @keywords internal trackplot_calculate_segment_height <- function(data) { data$row_number <- seq_len(nrow(data)) diff --git a/r/man/trackplot_calculate_segment_height.Rd b/r/man/trackplot_calculate_segment_height.Rd index 7d785c2f..41e299d8 100644 --- a/r/man/trackplot_calculate_segment_height.Rd +++ b/r/man/trackplot_calculate_segment_height.Rd @@ -2,14 +2,7 @@ % Please edit documentation in R/trackplots.R \name{trackplot_calculate_segment_height} \alias{trackplot_calculate_segment_height} -\title{Calculate y positions for trackplot segments to avoid overlap -Steps: -\enumerate{ -\item Calculate the maximum overlap depth of transcripts -\item Iterate through start/end of segments in sorted order -\item Randomly assign each segment a y-coordinate between 1 and max overlap depth, -with the restriction that a segment can't have the same y-coordinate as an overlapping segment -}} +\title{Calculate y positions for trackplot segments to avoid overlap} \usage{ trackplot_calculate_segment_height(data) } @@ -17,16 +10,15 @@ trackplot_calculate_segment_height(data) \item{data}{tibble of genome ranges with start and end columns, assumed to be on same chromosome.} } \value{ -Vector of y coordinates, one per input row, such that no ranges at the same y coordinate overlap +Vector of y coordinates, one per input row, such that no ranges at the same y coordinate overlap. } \description{ -Calculate y positions for trackplot segments to avoid overlap Steps: \enumerate{ \item Calculate the maximum overlap depth of transcripts \item Iterate through start/end of segments in sorted order \item Randomly assign each segment a y-coordinate between 1 and max overlap depth, -with the restriction that a segment can't have the same y-coordinate as an overlapping segment +with the restriction that a segment cannot have the same y-coordinate as an overlapping segment } } \keyword{internal} From c88b36a1e2e943278542429eec8b632a19032a31 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 16 Dec 2025 09:53:44 -0800 Subject: [PATCH 65/84] [r] add cxx17_filesystem cleanup --- r/cleanup | 4 ++++ r/cleanup.win | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/r/cleanup b/r/cleanup index 388b1686..a3ec45c2 100755 --- a/r/cleanup +++ b/r/cleanup @@ -10,4 +10,8 @@ fi if [ -f tools/highway/lib ]; then rm -r tools/highway/lib +fi + +if [ -f tools/cxx17_filesystem ]; then + rm tools/cxx17_filesystem fi \ No newline at end of file diff --git a/r/cleanup.win b/r/cleanup.win index 44856041..0d966c71 100644 --- a/r/cleanup.win +++ b/r/cleanup.win @@ -12,6 +12,10 @@ if [ -f tools/h5write.exe ]; then rm tools/h5write.exe fi -if [ -d tools/highway/lib ]; then +if [ -f tools/highway/lib ]; then rm -r tools/highway/lib fi + +if [ -f tools/cxx17_filesystem]; then + rm tools/cxx17_filesystem +fi \ No newline at end of file From 8de3b88eb534534fa40e83e1e9efeff1b99aa806 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Tue, 16 Dec 2025 11:39:14 -0800 Subject: [PATCH 66/84] [r][cpp][python] change all http to https --- python/docs/source/notebooks/fragment_basics.md | 2 +- python/tests/test_real_data.py | 2 +- r/R/data.R | 6 +++--- r/R/fragments.R | 2 +- r/data-raw/human_gene_mapping.R | 2 +- r/data-raw/mouse_gene_mapping.R | 6 +++--- r/man/fragment_R_conversion.Rd | 2 +- r/man/gene_mapping.Rd | 6 +++--- r/man/peak_matrix.Rd | 2 +- r/man/reexports.Rd | 2 +- r/man/select_regions.Rd | 2 +- r/man/tile_matrix.Rd | 2 +- r/man/trackplot_bulk.Rd | 2 +- r/man/trackplot_coverage.Rd | 2 +- r/tests/old_compiler_envs/Dockerfile | 2 +- 15 files changed, 21 insertions(+), 21 deletions(-) diff --git a/python/docs/source/notebooks/fragment_basics.md b/python/docs/source/notebooks/fragment_basics.md index ca49ffc8..25f5fdac 100644 --- a/python/docs/source/notebooks/fragment_basics.md +++ b/python/docs/source/notebooks/fragment_basics.md @@ -108,7 +108,7 @@ cluster_order = sorted(set(clusters)) cell_groups_array = bpcells.experimental.build_cell_groups(fragments_bpcells_path, barcodes, clusters, cluster_order) # We could provide a dict or local file path, but URL is easier -chrom_sizes = "http://hgdownload.cse.ucsc.edu/goldenpath/hg38/bigZips/hg38.chrom.sizes" +chrom_sizes = "https://hgdownload.cse.ucsc.edu/goldenpath/hg38/bigZips/hg38.chrom.sizes" insertions_matrix_path = os.path.join(tmpdir.name, "bpcells_insertions_matrix") diff --git a/python/tests/test_real_data.py b/python/tests/test_real_data.py index b111f0cd..15d8c392 100644 --- a/python/tests/test_real_data.py +++ b/python/tests/test_real_data.py @@ -40,7 +40,7 @@ def test_500_pbmc_matrix(tmp_path, fetch_cached_file): peaks_path = fetch_cached_file("https://cf.10xgenomics.com/samples/cell-atac/2.0.0/atac_pbmc_500_nextgem/atac_pbmc_500_nextgem_peaks.bed") peak_matrix_path = fetch_cached_file("https://cf.10xgenomics.com/samples/cell-atac/2.0.0/atac_pbmc_500_nextgem/atac_pbmc_500_nextgem_raw_peak_bc_matrix.h5") barcode_metrics_path = fetch_cached_file("https://cf.10xgenomics.com/samples/cell-atac/2.0.0/atac_pbmc_500_nextgem/atac_pbmc_500_nextgem_singlecell.csv") - chrom_sizes_path = fetch_cached_file("http://hgdownload.cse.ucsc.edu/goldenpath/hg38/bigZips/hg38.chrom.sizes") + chrom_sizes_path = fetch_cached_file("https://hgdownload.cse.ucsc.edu/goldenpath/hg38/bigZips/hg38.chrom.sizes") # Convert BPCells fragments diff --git a/r/R/data.R b/r/R/data.R index 8cc43bde..05b5dd69 100644 --- a/r/R/data.R +++ b/r/R/data.R @@ -268,7 +268,7 @@ remove_demo_data <- function() { #' `data-raw/mouse_gene_mapping.R` for exactly how these mappings were made. #' @source **human_gene_mapping** #' -#' +#' #' #' @examples #' ####################################################################### @@ -286,8 +286,8 @@ remove_demo_data <- function() { #' #' @source **mouse_gene_mapping** #' -#' -#' +#' +#' #' @examples #' ####################################################################### #' ## mouse_gene_mapping diff --git a/r/R/fragments.R b/r/R/fragments.R index af933d10..7d63b142 100644 --- a/r/R/fragments.R +++ b/r/R/fragments.R @@ -691,7 +691,7 @@ open_fragments_hdf5 <- function(path, group = "fragments", buffer_size = 16384L) #' @param zero_based_coords Whether to convert the ranges from a 1-based end-inclusive #' coordinate system to a 0-based end-exclusive coordinate system. Defaults to true #' for GRanges and false for other formats -#' (see this [archived UCSC blogpost](https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/)) +#' (see this [archived UCSC blogpost](https://web.archive.org/web/20210920203703/https://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/)) #' @param ... Additional arguments passed to methods #' @param row.names Optional row names for compatibility with `as.data.frame()`. #' Ignored for IterableFragments objects. diff --git a/r/data-raw/human_gene_mapping.R b/r/data-raw/human_gene_mapping.R index 245dfe06..a7337b05 100644 --- a/r/data-raw/human_gene_mapping.R +++ b/r/data-raw/human_gene_mapping.R @@ -11,7 +11,7 @@ library(magrittr) # Pull data from HGNC, and make a named vector that maps non-canonical gene names/ # symbols to their canonical names. Only unambiguous mappings will be stored hgnc <- readr::read_tsv( - "http://ftp.ebi.ac.uk/pub/databases/genenames/out_of_date_hgnc/tsv/non_alt_loci_set.txt", + "https://ftp.ebi.ac.uk/pub/databases/genenames/out_of_date_hgnc/tsv/non_alt_loci_set.txt", col_types=readr::cols(.default=readr::col_character()) ) diff --git a/r/data-raw/mouse_gene_mapping.R b/r/data-raw/mouse_gene_mapping.R index fef4b6e5..2684d0d5 100644 --- a/r/data-raw/mouse_gene_mapping.R +++ b/r/data-raw/mouse_gene_mapping.R @@ -15,14 +15,14 @@ library(dplyr) # A full list of non-withdrawn gene IDs mgi_list <- readr::read_tsv( - "http://www.informatics.jax.org/downloads/reports/MRK_List2.rpt" + "https://www.informatics.jax.org/downloads/reports/MRK_List2.rpt" ) %>% select(mgi_id = "MGI Accession ID", symbol = "Marker Symbol", status = "Status", name = "Marker Name", type = "Marker Type", alias = "Marker Synonyms (pipe-separated)") # Contains some withdrawn IDs, and a superset of the current mgi_list mgi_entrez <- readr::read_tsv( - "http://www.informatics.jax.org/downloads/reports/MGI_EntrezGene.rpt", + "https://www.informatics.jax.org/downloads/reports/MGI_EntrezGene.rpt", col_names = c("mgi_id", "symbol", "status", "name", "cM_pos", "chr", "type", "secondary_ids", "entrez_id", "alias", "feature_type", "start", "end", "strand", "biotype") ) %>% select(mgi_id, symbol, status, name, secondary_ids, entrez_id, alias) %>% @@ -44,7 +44,7 @@ mgi_entrez_mapping <- select(mgi_entrez, symbol, alt = alias) %>% stopifnot(all.equal(mgi_list_mapping, mgi_entrez_mapping)) mgi_ensembl <- readr::read_tsv( - "http://www.informatics.jax.org/downloads/reports/MRK_ENSEMBL.rpt", + "https://www.informatics.jax.org/downloads/reports/MRK_ENSEMBL.rpt", col_names = c("mgi_id", "symbol", "name", "cM_pos", "chr", "ensembl_id", "ensembl_transcript", "ensembl_prot", "feature_type", "start", "end", "strand", "biotypes") ) %>% select(mgi_id, symbol, name, ensembl_id) diff --git a/r/man/fragment_R_conversion.Rd b/r/man/fragment_R_conversion.Rd index 465c4e94..39df698c 100644 --- a/r/man/fragment_R_conversion.Rd +++ b/r/man/fragment_R_conversion.Rd @@ -20,7 +20,7 @@ convert_to_fragments(x, zero_based_coords = !is(x, "GRanges")) \item{zero_based_coords}{Whether to convert the ranges from a 1-based end-inclusive coordinate system to a 0-based end-exclusive coordinate system. Defaults to true for GRanges and false for other formats -(see this \href{https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} +(see this \href{https://web.archive.org/web/20210920203703/https://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} \item{IterableFragments}{BPCells IterableFragments object} diff --git a/r/man/gene_mapping.Rd b/r/man/gene_mapping.Rd index eda1559a..5004e5a2 100644 --- a/r/man/gene_mapping.Rd +++ b/r/man/gene_mapping.Rd @@ -19,12 +19,12 @@ are the corresponding canonical gene symbol \source{ \strong{human_gene_mapping} -\url{http://ftp.ebi.ac.uk/pub/databases/genenames/out_of_date_hgnc/tsv/non_alt_loci_set.txt} +\url{https://ftp.ebi.ac.uk/pub/databases/genenames/out_of_date_hgnc/tsv/non_alt_loci_set.txt} \strong{mouse_gene_mapping} -\url{http://www.informatics.jax.org/downloads/reports/MGI_EntrezGene.rpt} -\url{http://www.informatics.jax.org/downloads/reports/MRK_ENSEMBL.rpt} +\url{https://www.informatics.jax.org/downloads/reports/MGI_EntrezGene.rpt} +\url{https://www.informatics.jax.org/downloads/reports/MRK_ENSEMBL.rpt} } \usage{ human_gene_mapping diff --git a/r/man/peak_matrix.Rd b/r/man/peak_matrix.Rd index db1d3cf1..51b0389a 100644 --- a/r/man/peak_matrix.Rd +++ b/r/man/peak_matrix.Rd @@ -25,7 +25,7 @@ peak_matrix( \item{zero_based_coords}{Whether to convert the ranges from a 1-based end-inclusive coordinate system to a 0-based end-exclusive coordinate system. Defaults to true for GRanges and false for other formats -(see this \href{https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} +(see this \href{https://web.archive.org/web/20210920203703/https://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} \item{explicit_peak_names}{Boolean for whether to add rownames to the output matrix in format e.g chr1:500-1000, where start and end coords are given in a 0-based coordinate system. diff --git a/r/man/reexports.Rd b/r/man/reexports.Rd index e4ac817a..5d4c340d 100644 --- a/r/man/reexports.Rd +++ b/r/man/reexports.Rd @@ -17,6 +17,6 @@ below to see their documentation. \describe{ \item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}} - \item{Matrix}{\code{\link[Matrix:colSums]{colMeans}}, \code{\link[Matrix]{colSums}}, \code{\link[Matrix:colSums]{rowMeans}}, \code{\link[Matrix:colSums]{rowSums}}} + \item{Matrix}{\code{\link[Matrix:colSums-methods]{colMeans}}, \code{\link[Matrix:colSums-methods]{colSums}}, \code{\link[Matrix:colSums-methods]{rowMeans}}, \code{\link[Matrix:colSums-methods]{rowSums}}} }} diff --git a/r/man/select_regions.Rd b/r/man/select_regions.Rd index 30b62c18..8d7e79b0 100644 --- a/r/man/select_regions.Rd +++ b/r/man/select_regions.Rd @@ -25,7 +25,7 @@ instead of only fragments overlapping the selected regions.} \item{zero_based_coords}{Whether to convert the ranges from a 1-based end-inclusive coordinate system to a 0-based end-exclusive coordinate system. Defaults to true for GRanges and false for other formats -(see this \href{https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} +(see this \href{https://web.archive.org/web/20210920203703/https://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} } \value{ Fragments object filtered according to the selected regions diff --git a/r/man/tile_matrix.Rd b/r/man/tile_matrix.Rd index 1e9c5f90..fdf4187b 100644 --- a/r/man/tile_matrix.Rd +++ b/r/man/tile_matrix.Rd @@ -29,7 +29,7 @@ Must be non-overlapping and sorted by \item{zero_based_coords}{Whether to convert the ranges from a 1-based end-inclusive coordinate system to a 0-based end-exclusive coordinate system. Defaults to true for GRanges and false for other formats -(see this \href{https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} +(see this \href{https://web.archive.org/web/20210920203703/https://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} \item{explicit_tile_names}{Boolean for whether to add rownames to the output matrix in format e.g chr1:500-1000, where start and end coords are given in a 0-based coordinate system. For diff --git a/r/man/trackplot_bulk.Rd b/r/man/trackplot_bulk.Rd index 095b87c3..67cd3497 100644 --- a/r/man/trackplot_bulk.Rd +++ b/r/man/trackplot_bulk.Rd @@ -44,7 +44,7 @@ just the most extreme outliers across the region. NULL to disable clipping} \item{zero_based_coords}{Whether to convert the ranges from a 1-based end-inclusive coordinate system to a 0-based end-exclusive coordinate system. Defaults to true for GRanges and false for other formats -(see this \href{https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} +(see this \href{https://web.archive.org/web/20210920203703/https://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} \item{return_data}{If true, return data from just before plotting rather than a plot.} diff --git a/r/man/trackplot_coverage.Rd b/r/man/trackplot_coverage.Rd index 8db8e38a..d8ea0a8b 100644 --- a/r/man/trackplot_coverage.Rd +++ b/r/man/trackplot_coverage.Rd @@ -42,7 +42,7 @@ just the most extreme outliers across the region. NULL to disable clipping} \item{zero_based_coords}{Whether to convert the ranges from a 1-based end-inclusive coordinate system to a 0-based end-exclusive coordinate system. Defaults to true for GRanges and false for other formats -(see this \href{https://web.archive.org/web/20210920203703/http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} +(see this \href{https://web.archive.org/web/20210920203703/https://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/}{archived UCSC blogpost})} \item{return_data}{If true, return data from just before plotting rather than a plot.} } diff --git a/r/tests/old_compiler_envs/Dockerfile b/r/tests/old_compiler_envs/Dockerfile index 1d839fba..59d64077 100644 --- a/r/tests/old_compiler_envs/Dockerfile +++ b/r/tests/old_compiler_envs/Dockerfile @@ -25,7 +25,7 @@ ENV LANG en_US.UTF-8 ## Install backported R 4.0 RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-key '95C0FAF38DB3CCAD0C080A7BDC78B2DDEABC47B7' && \ - echo "deb http://cloud.r-project.org/bin/linux/debian buster-cran40/" >> /etc/apt/sources.list + echo "deb https://cloud.r-project.org/bin/linux/debian buster-cran40/" >> /etc/apt/sources.list ENV R_BASE_VERSION=4.2.2 From 4ec69a0f90f3d845bd4ac2bd6d47c29da8ce5872 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 7 Jan 2026 16:06:33 -0800 Subject: [PATCH 67/84] [cpp] add highway changes to pass R CMD check --- r/src/vendor/highway/hwy/base.h | 16 +++++++++++++ r/src/vendor/highway/hwy/targets.cc | 7 ++++-- r/src/vendor/highway/manual-build/README.md | 23 +++++++++++++++++-- .../highway/manual-build/build_highway.sh | 3 +-- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/r/src/vendor/highway/hwy/base.h b/r/src/vendor/highway/hwy/base.h index 9d74f2b7..654140e8 100644 --- a/r/src/vendor/highway/hwy/base.h +++ b/r/src/vendor/highway/hwy/base.h @@ -214,9 +214,24 @@ namespace hwy { // 4 instances of a given literal value, useful as input to LoadDup128. #define HWY_REP4(literal) literal, literal, literal, literal +#ifndef HWY_NO_ABORT HWY_DLLEXPORT HWY_NORETURN void HWY_FORMAT(3, 4) Abort(const char* file, int line, const char* format, ...); +#endif + +#ifdef HWY_NO_ABORT +#define HWY_ABORT(format, ...) \ + do { \ + (void)(format); \ + (void)(__FILE__); \ + (void)(__LINE__); \ + } while (0) +#define HWY_ASSERT(condition) \ + do { \ + (void)(condition); \ + } while (0) +#else #define HWY_ABORT(format, ...) \ ::hwy::Abort(__FILE__, __LINE__, format, ##__VA_ARGS__) @@ -227,6 +242,7 @@ HWY_DLLEXPORT HWY_NORETURN void HWY_FORMAT(3, 4) HWY_ABORT("Assert %s", #condition); \ } \ } while (0) +#endif #if HWY_HAS_FEATURE(memory_sanitizer) || defined(MEMORY_SANITIZER) #define HWY_IS_MSAN 1 diff --git a/r/src/vendor/highway/hwy/targets.cc b/r/src/vendor/highway/hwy/targets.cc index e68f754d..a98d1192 100644 --- a/r/src/vendor/highway/hwy/targets.cc +++ b/r/src/vendor/highway/hwy/targets.cc @@ -469,12 +469,13 @@ int64_t DetectTargets() { if ((bits & HWY_ENABLED_BASELINE) != HWY_ENABLED_BASELINE) { const uint64_t bits_u = static_cast(bits); const uint64_t enabled = static_cast(HWY_ENABLED_BASELINE); - fprintf(stderr, + (void)bits_u; (void)enabled; + /*fprintf(stderr, "WARNING: CPU supports 0x%08x%08x, software requires 0x%08x%08x\n", static_cast(bits_u >> 32), static_cast(bits_u & 0xFFFFFFFF), static_cast(enabled >> 32), - static_cast(enabled & 0xFFFFFFFF)); + static_cast(enabled & 0xFFFFFFFF));*/ } return bits; @@ -482,6 +483,7 @@ int64_t DetectTargets() { } // namespace +#ifndef HWY_NO_ABORT HWY_DLLEXPORT HWY_NORETURN void HWY_FORMAT(3, 4) Abort(const char* file, int line, const char* format, ...) { char buf[800]; @@ -509,6 +511,7 @@ HWY_DLLEXPORT HWY_NORETURN void HWY_FORMAT(3, 4) abort(); // Compile error without this due to HWY_NORETURN. #endif } +#endif // HWY_NO_ABORT HWY_DLLEXPORT void DisableTargets(int64_t disabled_targets) { supported_mask_ = static_cast(~disabled_targets); diff --git a/r/src/vendor/highway/manual-build/README.md b/r/src/vendor/highway/manual-build/README.md index 9d98c694..02d4b11c 100644 --- a/r/src/vendor/highway/manual-build/README.md +++ b/r/src/vendor/highway/manual-build/README.md @@ -1,2 +1,21 @@ -This folder is not part of the original Highway distribution, and is instead provided to simplify integration -with non-cmake build systems \ No newline at end of file +# Highway Build Customization for BPCells + +This directory contains scripts and configurations for building the `highway` SIMD library, vendored within the BPCells project. + +The original `highway` library was modified to address CRAN check warnings related to `abort()` calls and `stderr` output. These modifications ensure compliance with CRAN policies, which disallow compiled code from terminating R or writing directly to standard error/output streams. + +## Modifications: + +1. **`src/vendor/highway/manual-build/build_highway.sh`**: + * The `HWY_FLAGS` were updated to include `-DHWY_NO_ABORT`. This preprocessor definition prevents the `highway` library from including `abort()` calls in its compiled output when the relevant code is conditionally compiled. + * `hwy/nanobenchmark.cc` and `hwy/print.cc` were removed from `HWY_SOURCES`. These files contained `fprintf(stderr, ...)` and `printf(...)` calls, which are not permitted by CRAN. These components are not essential for BPCells. + +2. **`src/vendor/highway/hwy/targets.cc`**: + * The `Abort` function definition was wrapped with `#ifndef HWY_NO_ABORT ... #endif`. This ensures that the `Abort` function (which calls `abort()` and `fprintf(stderr, ...)`) is not compiled into `libhwy.a` when `-DHWY_NO_ABORT` is defined. + * The `fprintf(stderr, ...)` warning message within the `DetectTargets` function was commented out to prevent `stderr` output during runtime target detection. + +3. **`src/vendor/highway/hwy/base.h`**: + * Added conditional compilation logic (`#ifndef HWY_NO_ABORT`) around the `Abort` function declaration. + * Added alternative definitions for `HWY_ABORT` and `HWY_ASSERT` macros when `HWY_NO_ABORT` is defined, making them no-ops. This allows the code to compile without linking to the `Abort` function when the flag is set. + +These changes are necessary to pass CRAN checks and should be reapplied if the vendored `highway` version is updated. \ No newline at end of file diff --git a/r/src/vendor/highway/manual-build/build_highway.sh b/r/src/vendor/highway/manual-build/build_highway.sh index 99c593f9..420cdc64 100644 --- a/r/src/vendor/highway/manual-build/build_highway.sh +++ b/r/src/vendor/highway/manual-build/build_highway.sh @@ -37,14 +37,13 @@ HWY_FLAGS=( -O2 -g -DNDEBUG + -DHWY_NO_ABORT ) # Skip the CONTRIB, since we don't need sorting or image libraries HWY_SOURCES=( hwy/aligned_allocator.cc - hwy/nanobenchmark.cc hwy/per_target.cc - hwy/print.cc hwy/targets.cc ) From 3f9bcdd501ce217bbf6ca3a53cf0bd6e0ef8672d Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 7 Jan 2026 17:14:05 -0800 Subject: [PATCH 68/84] [r] add TFMPvalue forcibly to requirements --- r/DESCRIPTION | 1 + 1 file changed, 1 insertion(+) diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 3880d529..3b26c6da 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -68,6 +68,7 @@ Suggests: irlba, BiocManager, BSgenome.Hsapiens.UCSC.hg38, + TFMPvalue (>= 1.0.0), motifmatchr, chromVARmotifs, png, From 243d8d422c503ac590a0f60784170c3413380881 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 7 Jan 2026 17:14:38 -0800 Subject: [PATCH 69/84] [r] delete artifacts --- r/cran-comments.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 r/cran-comments.md diff --git a/r/cran-comments.md b/r/cran-comments.md deleted file mode 100644 index 858617db..00000000 --- a/r/cran-comments.md +++ /dev/null @@ -1,5 +0,0 @@ -## R CMD check results - -0 errors | 0 warnings | 1 note - -* This is a new release. From fd475e64adde5c9eb42c3539dc4703897797e7b6 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Wed, 7 Jan 2026 17:38:26 -0800 Subject: [PATCH 70/84] [r] reduce TFMPvalue required version --- r/DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r/DESCRIPTION b/r/DESCRIPTION index 3b26c6da..ba5b7dc3 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -68,7 +68,7 @@ Suggests: irlba, BiocManager, BSgenome.Hsapiens.UCSC.hg38, - TFMPvalue (>= 1.0.0), + TFMPvalue (>= 0.0.5), motifmatchr, chromVARmotifs, png, From 221e3c3f61aced6c528b52c7e16c839aaa8bcf70 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Thu, 8 Jan 2026 14:25:19 -0800 Subject: [PATCH 71/84] [r] set long examples to skip cran execution --- r/R/atac_utils.R | 4 ++-- r/R/geneScores.R | 12 ++++++------ r/R/genomeAnnotations.R | 2 +- r/R/plots.R | 6 +++--- r/R/trackplots.R | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index 8b407097..1874a389 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -177,7 +177,7 @@ footprint <- function(fragments, ranges, zero_based_coords = !is(ranges, "GRange #' ArchR's `PromoterRatio` and `BlacklistRatio` are not included in the output, as they can be easily calculated #' from `ReadsInPromoter / nFrags` and `ReadsInBlacklist / nFrags`. Similarly, ArchR's `NucleosomeRatio` can be calculated #' as `(monoNucleosomal + multiNucleosomal) / subNucleosomal`. -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") #' ## Prep data #' frags <- get_demo_frags(subset = FALSE) #' reference_dir <- file.path(tempdir(), "references") @@ -514,7 +514,7 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' If `NULL`, then tile_width is required to be 1. #' If a data.frame or list, must contain columns `chr` and `end` (See `help("genomic-ranges-like")`). #' If a numeric vector, then it is assumed to be the chromosome sizes in the order of `chrNames(fragments)`. -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") #' ## Prep data #' frags <- get_demo_frags() #' bedgraph_outputs <- file.path(tempdir(), "bedgraph_outputs") diff --git a/r/R/geneScores.R b/r/R/geneScores.R index 4df90f53..16a47ea4 100644 --- a/r/R/geneScores.R +++ b/r/R/geneScores.R @@ -151,16 +151,16 @@ extend_ranges <- function(ranges, upstream = 0, downstream = 0, metadata_cols = #' start coordinate than the gene and the gene is on the + strand, distance will #' be negative. The distance of adjacent but non-overlapping regions is 1bp, counting #' up from there. -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") #' ## Prep data #' directory <- file.path(tempdir(), "references") #' genes <- read_gencode_genes( #' directory, #' release = "42", -#' annotation_set = "basic", +#' annotation_set = "basic", #' ) -#' -#' +#' +#' #' ## Get gene scores by tile #' gene_score_tiles_archr( #' genes @@ -225,7 +225,7 @@ gene_score_tiles_archr <- function(genes, chromosome_sizes = NULL, tile_width = #' @return **gene_score_weights_archr** #' #' Weight matrix of dimension genes x tiles -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") #' ## Prep data #' reference_dir <- file.path(tempdir(), "references") #' frags <- get_demo_frags() @@ -316,7 +316,7 @@ gene_score_weights_archr <- function(genes, chromosome_sizes, blacklist = NULL, #' @return **gene_score_archr** #' #' Gene score matrix of dimension genes x cells. -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") #' ####################################################################### #' ## gene_score_archr() example #' ####################################################################### diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index dc22b5ca..aa43358c 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -465,7 +465,7 @@ canonical_gene_symbol <- function(query, gene_mapping = human_gene_mapping) { #' @param extend_bp Bases to extend region upstream and downstream of gene. If length 1, extension is #' symmetric. If length 2, provide upstream extension then downstream extension as positive distances. #' @return List of chr, start, end positions for use with trackplot functions. -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") #' ## Prep data #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", diff --git a/r/R/plots.R b/r/R/plots.R index cc5a6c1e..e7953f8f 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -185,7 +185,7 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE #' @param min_tss Minimum TSS Enrichment cutoff #' @param bins Number of bins for density calculation #' @inheritParams plot_embedding -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") #' ## Prep data #' frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) #' genes <- read_gencode_transcripts( @@ -323,7 +323,7 @@ plot_fragment_length <- function(fragments, max_length = 500, return_data = FALS #' @param smooth Number of bases to smooth over (rolling average) #' @param colors Discrete color palette to use for cell groups #' @seealso `footprint()`, `plot_tf_footprint()` -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") #' ## Prep data #' frags <- get_demo_frags() #' genes <- read_gencode_transcripts( @@ -523,7 +523,7 @@ collect_features <- function(source, features = NULL, gene_mapping = human_gene_ #' @return By default, returns a ggplot2 object with all the requested features plotted #' in a grid. If `return_data` or `return_plot_list` is called, the return value will #' match that argument. -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") ## Prep data #' set.seed(123) #' mat <- get_demo_mat() diff --git a/r/R/trackplots.R b/r/R/trackplots.R index d50a1148..c7b650a2 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -297,7 +297,7 @@ trackplot_normalize_ranges_with_metadata <- function(data, metadata) { #' the text label, y-axis, and plot body. The relative height of each row is given #' by heights. A shared title and x-axis are put at the top. #' @seealso `trackplot_coverage()`, `trackplot_gene()`, `trackplot_loop()`, `trackplot_scalebar()` -#' @examples +#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") #' ## Prep data #' frags <- get_demo_frags() #' From 9045ead806df5446c02e085f82490dbf4d370cf9 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Thu, 8 Jan 2026 15:21:29 -0800 Subject: [PATCH 72/84] [ci] turn off NOT_CRAN for R CMD CHECK --- .github/workflows/check-standard-test.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index 790066f3..39db842b 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -21,6 +21,7 @@ jobs: R_KEEP_PKG_SOURCE: yes ENABLE_INSTALL_COUNTING: no _R_CHECK_BUILD_VIGNETTES_: false + NOT_CRAN: false steps: - uses: actions/checkout@v4 From f310745cd827b19a9963bf6d15872ce28fa4ec3b Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Thu, 8 Jan 2026 16:06:07 -0800 Subject: [PATCH 73/84] [r][ci] set NOT_CRAN flag to use R_RUN_LONG_EXAMPLES instead --- .github/workflows/check-standard-test.yaml | 1 - .github/workflows/deploy-docs.yml | 2 ++ .github/workflows/deploy-full-website.yml | 2 ++ r/R/atac_utils.R | 4 ++-- r/R/geneScores.R | 6 +++--- r/R/genomeAnnotations.R | 2 +- r/R/plots.R | 6 +++--- r/R/trackplots.R | 2 +- 8 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/workflows/check-standard-test.yaml b/.github/workflows/check-standard-test.yaml index 39db842b..790066f3 100644 --- a/.github/workflows/check-standard-test.yaml +++ b/.github/workflows/check-standard-test.yaml @@ -21,7 +21,6 @@ jobs: R_KEEP_PKG_SOURCE: yes ENABLE_INSTALL_COUNTING: no _R_CHECK_BUILD_VIGNETTES_: false - NOT_CRAN: false steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 29eb5ed6..3d49e9b0 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -7,6 +7,8 @@ jobs: build_docs: name: Build and Deploy Documentation runs-on: ubuntu-latest + env: + R_RUN_LONG_EXAMPLES: true steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/deploy-full-website.yml b/.github/workflows/deploy-full-website.yml index 39a52c0b..71a687f6 100644 --- a/.github/workflows/deploy-full-website.yml +++ b/.github/workflows/deploy-full-website.yml @@ -5,6 +5,8 @@ jobs: build_docs: name: Build and Deploy Documentation runs-on: ubuntu-latest + env: + R_RUN_LONG_EXAMPLES: true steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index 1874a389..4486a6bd 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -177,7 +177,7 @@ footprint <- function(fragments, ranges, zero_based_coords = !is(ranges, "GRange #' ArchR's `PromoterRatio` and `BlacklistRatio` are not included in the output, as they can be easily calculated #' from `ReadsInPromoter / nFrags` and `ReadsInBlacklist / nFrags`. Similarly, ArchR's `NucleosomeRatio` can be calculated #' as `(monoNucleosomal + multiNucleosomal) / subNucleosomal`. -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") #' ## Prep data #' frags <- get_demo_frags(subset = FALSE) #' reference_dir <- file.path(tempdir(), "references") @@ -514,7 +514,7 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' If `NULL`, then tile_width is required to be 1. #' If a data.frame or list, must contain columns `chr` and `end` (See `help("genomic-ranges-like")`). #' If a numeric vector, then it is assumed to be the chromosome sizes in the order of `chrNames(fragments)`. -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") #' ## Prep data #' frags <- get_demo_frags() #' bedgraph_outputs <- file.path(tempdir(), "bedgraph_outputs") diff --git a/r/R/geneScores.R b/r/R/geneScores.R index 16a47ea4..a20b55cc 100644 --- a/r/R/geneScores.R +++ b/r/R/geneScores.R @@ -151,7 +151,7 @@ extend_ranges <- function(ranges, upstream = 0, downstream = 0, metadata_cols = #' start coordinate than the gene and the gene is on the + strand, distance will #' be negative. The distance of adjacent but non-overlapping regions is 1bp, counting #' up from there. -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") #' ## Prep data #' directory <- file.path(tempdir(), "references") #' genes <- read_gencode_genes( @@ -225,7 +225,7 @@ gene_score_tiles_archr <- function(genes, chromosome_sizes = NULL, tile_width = #' @return **gene_score_weights_archr** #' #' Weight matrix of dimension genes x tiles -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") #' ## Prep data #' reference_dir <- file.path(tempdir(), "references") #' frags <- get_demo_frags() @@ -316,7 +316,7 @@ gene_score_weights_archr <- function(genes, chromosome_sizes, blacklist = NULL, #' @return **gene_score_archr** #' #' Gene score matrix of dimension genes x cells. -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") #' ####################################################################### #' ## gene_score_archr() example #' ####################################################################### diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index aa43358c..52e88633 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -465,7 +465,7 @@ canonical_gene_symbol <- function(query, gene_mapping = human_gene_mapping) { #' @param extend_bp Bases to extend region upstream and downstream of gene. If length 1, extension is #' symmetric. If length 2, provide upstream extension then downstream extension as positive distances. #' @return List of chr, start, end positions for use with trackplot functions. -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") #' ## Prep data #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", diff --git a/r/R/plots.R b/r/R/plots.R index e7953f8f..93e8b0dc 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -185,7 +185,7 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE #' @param min_tss Minimum TSS Enrichment cutoff #' @param bins Number of bins for density calculation #' @inheritParams plot_embedding -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") #' ## Prep data #' frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) #' genes <- read_gencode_transcripts( @@ -323,7 +323,7 @@ plot_fragment_length <- function(fragments, max_length = 500, return_data = FALS #' @param smooth Number of bases to smooth over (rolling average) #' @param colors Discrete color palette to use for cell groups #' @seealso `footprint()`, `plot_tf_footprint()` -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") #' ## Prep data #' frags <- get_demo_frags() #' genes <- read_gencode_transcripts( @@ -523,7 +523,7 @@ collect_features <- function(source, features = NULL, gene_mapping = human_gene_ #' @return By default, returns a ggplot2 object with all the requested features plotted #' in a grid. If `return_data` or `return_plot_list` is called, the return value will #' match that argument. -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") ## Prep data #' set.seed(123) #' mat <- get_demo_mat() diff --git a/r/R/trackplots.R b/r/R/trackplots.R index c7b650a2..e61a887e 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -297,7 +297,7 @@ trackplot_normalize_ranges_with_metadata <- function(data, metadata) { #' the text label, y-axis, and plot body. The relative height of each row is given #' by heights. A shared title and x-axis are put at the top. #' @seealso `trackplot_coverage()`, `trackplot_gene()`, `trackplot_loop()`, `trackplot_scalebar()` -#' @examplesIf identical(Sys.getenv("NOT_CRAN"), "true") +#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") #' ## Prep data #' frags <- get_demo_frags() #' From 459928fee1e06fd7ade92d809da99036c01e118b Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Thu, 8 Jan 2026 16:06:22 -0800 Subject: [PATCH 74/84] add email to immanuel --- r/DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r/DESCRIPTION b/r/DESCRIPTION index ba5b7dc3..5a27d22a 100644 --- a/r/DESCRIPTION +++ b/r/DESCRIPTION @@ -7,7 +7,7 @@ Authors@R: c( role = c("aut", "cre", "cph"), email = "bparks@alumni.stanford.edu", comment = c(ORCID = "0000-0002-0261-7472")), - person("Immanuel", "Abdi", role = "aut"), + person("Immanuel", "Abdi", email = "immanuelazn@berkeley.edu", role = "aut"), person("Stanford University", role=c("cph", "fnd")), person("Genentech, Inc.", role=c("cph", "fnd"))) Description: Efficient operations for single cell ATAC-seq fragments and From c8c63fcaf341812d7978f52bc6bb2a99e08f845a Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Thu, 8 Jan 2026 16:42:37 -0800 Subject: [PATCH 75/84] [r] set to plain skipping examples --- .github/workflows/deploy-docs.yml | 2 -- .github/workflows/deploy-full-website.yml | 2 -- r/R/atac_utils.R | 8 +++++--- r/R/geneScores.R | 12 +++++++++--- r/R/genomeAnnotations.R | 4 +++- r/R/plots.R | 13 +++++++++---- r/R/trackplots.R | 4 +++- 7 files changed, 29 insertions(+), 16 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 3d49e9b0..29eb5ed6 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -7,8 +7,6 @@ jobs: build_docs: name: Build and Deploy Documentation runs-on: ubuntu-latest - env: - R_RUN_LONG_EXAMPLES: true steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/deploy-full-website.yml b/.github/workflows/deploy-full-website.yml index 71a687f6..39a52c0b 100644 --- a/.github/workflows/deploy-full-website.yml +++ b/.github/workflows/deploy-full-website.yml @@ -5,8 +5,6 @@ jobs: build_docs: name: Build and Deploy Documentation runs-on: ubuntu-latest - env: - R_RUN_LONG_EXAMPLES: true steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index 4486a6bd..bf13d987 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -176,8 +176,8 @@ footprint <- function(fragments, ranges, zero_based_coords = !is(ranges, "GRange #' #' ArchR's `PromoterRatio` and `BlacklistRatio` are not included in the output, as they can be easily calculated #' from `ReadsInPromoter / nFrags` and `ReadsInBlacklist / nFrags`. Similarly, ArchR's `NucleosomeRatio` can be calculated -#' as `(monoNucleosomal + multiNucleosomal) / subNucleosomal`. -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @examples +#' \dontrun{ #' ## Prep data #' frags <- get_demo_frags(subset = FALSE) #' reference_dir <- file.path(tempdir(), "references") @@ -193,6 +193,7 @@ footprint <- function(fragments, ranges, zero_based_coords = !is(ranges, "GRange #' #' ## Run qc #' head(qc_scATAC(frags, genes, blacklist)) +#' } #' @export qc_scATAC <- function(fragments, genes, blacklist) { assert_is(fragments, "IterableFragments") @@ -514,7 +515,8 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' If `NULL`, then tile_width is required to be 1. #' If a data.frame or list, must contain columns `chr` and `end` (See `help("genomic-ranges-like")`). #' If a numeric vector, then it is assumed to be the chromosome sizes in the order of `chrNames(fragments)`. -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @examples +#' \dontrun{ #' ## Prep data #' frags <- get_demo_frags() #' bedgraph_outputs <- file.path(tempdir(), "bedgraph_outputs") diff --git a/r/R/geneScores.R b/r/R/geneScores.R index a20b55cc..bd4037fa 100644 --- a/r/R/geneScores.R +++ b/r/R/geneScores.R @@ -151,7 +151,8 @@ extend_ranges <- function(ranges, upstream = 0, downstream = 0, metadata_cols = #' start coordinate than the gene and the gene is on the + strand, distance will #' be negative. The distance of adjacent but non-overlapping regions is 1bp, counting #' up from there. -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @examples +#' \dontrun{ #' ## Prep data #' directory <- file.path(tempdir(), "references") #' genes <- read_gencode_genes( @@ -165,6 +166,7 @@ extend_ranges <- function(ranges, upstream = 0, downstream = 0, metadata_cols = #' gene_score_tiles_archr( #' genes #' ) +#' } #' @export gene_score_tiles_archr <- function(genes, chromosome_sizes = NULL, tile_width = 500, addArchRBug = FALSE) { assert_is_wholenumber(tile_width) @@ -225,7 +227,8 @@ gene_score_tiles_archr <- function(genes, chromosome_sizes = NULL, tile_width = #' @return **gene_score_weights_archr** #' #' Weight matrix of dimension genes x tiles -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @examples +#' \dontrun{ #' ## Prep data #' reference_dir <- file.path(tempdir(), "references") #' frags <- get_demo_frags() @@ -254,6 +257,7 @@ gene_score_tiles_archr <- function(genes, chromosome_sizes = NULL, tile_width = #' #' ## Get gene scores per cell #' gene_score_weights %*% tiles +#' } #' #' #' @export @@ -316,13 +320,15 @@ gene_score_weights_archr <- function(genes, chromosome_sizes, blacklist = NULL, #' @return **gene_score_archr** #' #' Gene score matrix of dimension genes x cells. -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @examples +#' \dontrun{ #' ####################################################################### #' ## gene_score_archr() example #' ####################################################################### #' ## This is a wrapper that creates both the gene score weight #' ## matrix and tile matrix together #' gene_score_archr(frags, genes, chrom_sizes, blacklist) +#' } #' #' #' @export diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index 52e88633..93a0dd22 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -465,7 +465,8 @@ canonical_gene_symbol <- function(query, gene_mapping = human_gene_mapping) { #' @param extend_bp Bases to extend region upstream and downstream of gene. If length 1, extension is #' symmetric. If length 2, provide upstream extension then downstream extension as positive distances. #' @return List of chr, start, end positions for use with trackplot functions. -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @examples +#' \dontrun{ #' ## Prep data #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", @@ -475,6 +476,7 @@ canonical_gene_symbol <- function(query, gene_mapping = human_gene_mapping) { #' #' ## Get gene region #' gene_region(genes, "CD19", extend_bp = 1e5) +#' } #' @export gene_region <- function(genes, gene_symbol, extend_bp = c(1e4, 1e4), gene_mapping = human_gene_mapping) { genes <- normalize_ranges(genes, metadata_cols = c("strand", "gene_name")) diff --git a/r/R/plots.R b/r/R/plots.R index 93e8b0dc..f957cca0 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -185,7 +185,8 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE #' @param min_tss Minimum TSS Enrichment cutoff #' @param bins Number of bins for density calculation #' @inheritParams plot_embedding -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @examples +#' \dontrun{ #' ## Prep data #' frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) #' genes <- read_gencode_transcripts( @@ -199,6 +200,7 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE #' #' ## Render tss enrichment vs fragment plot #' plot_tss_scatter(atac_qc, min_frags = 1000, min_tss = 10) +#' } #' @export plot_tss_scatter <- function(atac_qc, min_frags = NULL, min_tss = NULL, bins = 100, apply_styling = TRUE) { assert_has_package("hexbin") @@ -323,7 +325,8 @@ plot_fragment_length <- function(fragments, max_length = 500, return_data = FALS #' @param smooth Number of bases to smooth over (rolling average) #' @param colors Discrete color palette to use for cell groups #' @seealso `footprint()`, `plot_tf_footprint()` -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @example +#' \dontrun{ #' ## Prep data #' frags <- get_demo_frags() #' genes <- read_gencode_transcripts( @@ -334,6 +337,7 @@ plot_fragment_length <- function(fragments, max_length = 500, return_data = FALS #' #' ## Plot tss profile #' plot_tss_profile(frags, genes) +#' } #' @export plot_tss_profile <- function(fragments, genes, cell_groups = rlang::rep_along(cellNames(fragments), "all"), flank = 2000L, smooth = 0L, zero_based_coords = !is(genes, "GRanges"), @@ -523,7 +527,8 @@ collect_features <- function(source, features = NULL, gene_mapping = human_gene_ #' @return By default, returns a ggplot2 object with all the requested features plotted #' in a grid. If `return_data` or `return_plot_list` is called, the return value will #' match that argument. -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @examples +#' \dontrun{ ## Prep data #' set.seed(123) #' mat <- get_demo_mat() @@ -565,7 +570,7 @@ collect_features <- function(source, features = NULL, gene_mapping = human_gene_ #' # umap, #' # features = c("MS4A1", "CD3E"), #' #) -#' +#' } #' @export plot_embedding <- function(source, embedding, features = NULL, quantile_range = c(0.01, 0.99), diff --git a/r/R/trackplots.R b/r/R/trackplots.R index e61a887e..ff0defae 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -297,7 +297,8 @@ trackplot_normalize_ranges_with_metadata <- function(data, metadata) { #' the text label, y-axis, and plot body. The relative height of each row is given #' by heights. A shared title and x-axis are put at the top. #' @seealso `trackplot_coverage()`, `trackplot_gene()`, `trackplot_loop()`, `trackplot_scalebar()` -#' @examplesIf identical(Sys.getenv("R_RUN_LONG_EXAMPLES"), "true") +#' @examples +#' \dontrun{ #' ## Prep data #' frags <- get_demo_frags() #' @@ -334,6 +335,7 @@ trackplot_normalize_ranges_with_metadata <- function(data, metadata) { #' trackplot_combine( #' list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) #' ) +#' } #' @export trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_width = 0.3) { for (plot in tracks) { From d0bb2a171933d2d1f6a15b7aab3d706dd28c1868 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Thu, 8 Jan 2026 21:22:54 -0800 Subject: [PATCH 76/84] [r] add tiny internal data for examples (<100 kb) --- r/data-raw/internal_data.R | 37 ++++++++++++++++++ .../qc_results_filtered_example_chr_4.tsv.gz | Bin 0 -> 53982 bytes .../transcripts_filtered_example_chr_4.tsv.gz | Bin 0 -> 19585 bytes 3 files changed, 37 insertions(+) create mode 100644 r/data-raw/internal_data.R create mode 100644 r/inst/extdata/qc_results_filtered_example_chr_4.tsv.gz create mode 100644 r/inst/extdata/transcripts_filtered_example_chr_4.tsv.gz diff --git a/r/data-raw/internal_data.R b/r/data-raw/internal_data.R new file mode 100644 index 00000000..5abb7609 --- /dev/null +++ b/r/data-raw/internal_data.R @@ -0,0 +1,37 @@ +# Copyright 2026 BPCells contributors +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# Pulls transcripts from gencode, filters to only chr4 and saves as package data. +# Also runs qc_scATAC on the demo fragments filtered to chr4 and saves as package data. + +library(dplyr) +library(BPCells) + + +# Get transcripts +transcripts <- read_gencode_transcripts( + file.path(tempdir(), "references"), release = "42", + annotation_set = "basic", + features = "transcript" +) +transcripts_filtered_example_chr_4 <- transcripts %>% dplyr::filter(chr %in% "chr4") + + + +frags <- get_demo_frags() %>% select_chromosomes("chr4") +blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") +qc_results_filtered_example_chr_4 <- qc_scATAC(frags, transcripts_filtered_example_chr_4, blacklist) +readr::write_delim( + transcripts_filtered_example_chr_4, file.path("./inst/extdata/transcripts_filtered_example_chr_4.tsv.gz"), + delim = "\t" +) +readr::write_delim( + qc_results_filtered_example_chr_4, file.path("./inst/extdata/qc_results_filtered_example_chr_4.tsv.gz"), + delim = "\t" +) + diff --git a/r/inst/extdata/qc_results_filtered_example_chr_4.tsv.gz b/r/inst/extdata/qc_results_filtered_example_chr_4.tsv.gz new file mode 100644 index 0000000000000000000000000000000000000000..e27a819f16abfbdb0d6ab0dd816d2cc496bb0c44 GIT binary patch literal 53982 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 wUhc Date: Thu, 8 Jan 2026 21:23:14 -0800 Subject: [PATCH 77/84] [r] make examples use precomputed data --- r/R/atac_utils.R | 21 ++++++++++++++--- r/R/geneScores.R | 10 ++++++-- r/R/genomeAnnotations.R | 8 +++++++ r/R/plots.R | 29 ++++++++++++++++------- r/R/trackplots.R | 38 ++++++++++++++++++++++++++----- r/man/gene_region.Rd | 10 ++++++++ r/man/gene_score_tiles_archr.Rd | 10 +++++++- r/man/gene_scores.Rd | 4 ++++ r/man/plot_embedding.Rd | 6 +++-- r/man/plot_tss_profile.Rd | 11 +++++++++ r/man/plot_tss_scatter.Rd | 8 +++++++ r/man/qc_scATAC.Rd | 9 +++++++- r/man/trackplot_combine.Rd | 18 +++++++++++---- r/man/trackplot_coverage.Rd | 12 +++++++++- r/man/trackplot_gene.Rd | 8 +++++++ r/man/write_insertion_bedgraph.Rd | 14 ++++++++++-- 16 files changed, 186 insertions(+), 30 deletions(-) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index bf13d987..d3f35ef9 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -194,6 +194,12 @@ footprint <- function(fragments, ranges, zero_based_coords = !is(ranges, "GRange #' ## Run qc #' head(qc_scATAC(frags, genes, blacklist)) #' } +#' +#' ## Read precomputed +#' head(readr::read_delim( +#' file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), +#' delim = "\t", show_col_types = FALSE +#' )) #' @export qc_scATAC <- function(fragments, genes, blacklist) { assert_is(fragments, "IterableFragments") @@ -516,7 +522,7 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' If a data.frame or list, must contain columns `chr` and `end` (See `help("genomic-ranges-like")`). #' If a numeric vector, then it is assumed to be the chromosome sizes in the order of `chrNames(fragments)`. #' @examples -#' \dontrun{ +#' #' ## Prep data #' frags <- get_demo_frags() #' bedgraph_outputs <- file.path(tempdir(), "bedgraph_outputs") @@ -525,6 +531,7 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' ## `write_insertion_bedgraph()` examples #' ###################################################### #' ## Write insertions +#' \dontrun{ #' write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all.tar.gz")) #' list.files(bedgraph_outputs) #' @@ -537,8 +544,16 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' col_names = c("chr", "start", "end", "score"), #' show_col_types = FALSE) #' head(reads) -#' -#' +#' #> A tibble: 6 × 4 +#' #> chr start end score +#' #> +#' #> 1 chr4 10000 10100 1.45 +#' #> 2 chr4 10100 10200 0.869 +#' #> 3 chr4 10300 10400 0.290 +#' #> 4 chr4 10400 10500 0.145 +#' #> 5 chr4 10600 10700 0.434 +#' #> 6 chr4 11100 11200 0.145 +#' } #' @return `NULL` #' @inheritParams footprint #' @rdname write_insertion_bedgraph diff --git a/r/R/geneScores.R b/r/R/geneScores.R index bd4037fa..027a60a6 100644 --- a/r/R/geneScores.R +++ b/r/R/geneScores.R @@ -160,13 +160,19 @@ extend_ranges <- function(ranges, upstream = 0, downstream = 0, metadata_cols = #' release = "42", #' annotation_set = "basic", #' ) -#' +#' } +#' +#' ## Use pre-generated data for this example +#' ## Use pre-computed transcripts for chr4 +#' genes <- readr::read_delim( +#' file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), +#' delim = "\t", show_col_types = FALSE +#' ) #' #' ## Get gene scores by tile #' gene_score_tiles_archr( #' genes #' ) -#' } #' @export gene_score_tiles_archr <- function(genes, chromosome_sizes = NULL, tile_width = 500, addArchRBug = FALSE) { assert_is_wholenumber(tile_width) diff --git a/r/R/genomeAnnotations.R b/r/R/genomeAnnotations.R index 93a0dd22..97c1dc24 100644 --- a/r/R/genomeAnnotations.R +++ b/r/R/genomeAnnotations.R @@ -476,6 +476,14 @@ canonical_gene_symbol <- function(query, gene_mapping = human_gene_mapping) { #' #' ## Get gene region #' gene_region(genes, "CD19", extend_bp = 1e5) +#' #> $chr +#' #> [1] "chr16" +#' #> +#' #> $start +#' #> [1] 28831970 +#' #> +#' #> $end +#' #> [1] 29039342 #' } #' @export gene_region <- function(genes, gene_symbol, extend_bp = c(1e4, 1e4), gene_mapping = human_gene_mapping) { diff --git a/r/R/plots.R b/r/R/plots.R index f957cca0..24878e21 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -196,11 +196,17 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE #' ) #' blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") #' atac_qc <- qc_scATAC(frags, genes, blacklist) +#' } #' #' +#' ## Use pre-computed QC metrics for chr4 +#' atac_qc <- readr::read_delim( +#' file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), +#' delim = "\t", show_col_types = FALSE +#' ) #' ## Render tss enrichment vs fragment plot #' plot_tss_scatter(atac_qc, min_frags = 1000, min_tss = 10) -#' } +#' #' @export plot_tss_scatter <- function(atac_qc, min_frags = NULL, min_tss = NULL, bins = 100, apply_styling = TRUE) { assert_has_package("hexbin") @@ -325,19 +331,28 @@ plot_fragment_length <- function(fragments, max_length = 500, return_data = FALS #' @param smooth Number of bases to smooth over (rolling average) #' @param colors Discrete color palette to use for cell groups #' @seealso `footprint()`, `plot_tf_footprint()` -#' @example -#' \dontrun{ +#' @examples +#' #' ## Prep data #' frags <- get_demo_frags() +#' \dontrun{ #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", #' annotation_set = "basic", #' features = "transcript", timeout = 3000 #' ) +#' } +#' +#' ## Use pre-computed transcripts for chr4 +#' genes <- readr::read_delim( +#' file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), +#' delim = "\t", show_col_types = FALSE +#' ) +#' #' #' ## Plot tss profile #' plot_tss_profile(frags, genes) -#' } +#' #' @export plot_tss_profile <- function(fragments, genes, cell_groups = rlang::rep_along(cellNames(fragments), "all"), flank = 2000L, smooth = 0L, zero_based_coords = !is(genes, "GRanges"), @@ -528,10 +543,9 @@ collect_features <- function(source, features = NULL, gene_mapping = human_gene_ #' in a grid. If `return_data` or `return_plot_list` is called, the return value will #' match that argument. #' @examples -#' \dontrun{ -## Prep data +#' ## Prep data #' set.seed(123) -#' mat <- get_demo_mat() +#' mat <- get_demo_mat()[,sample(1:ncol(get_demo_mat()), 200)] #' ## Normalize matrix #' mat_norm <- log1p(multiply_cols(mat, 1/colSums(mat)) * 10000) %>% #' write_matrix_memory(compress = FALSE) @@ -570,7 +584,6 @@ collect_features <- function(source, features = NULL, gene_mapping = human_gene_ #' # umap, #' # features = c("MS4A1", "CD3E"), #' #) -#' } #' @export plot_embedding <- function(source, embedding, features = NULL, quantile_range = c(0.01, 0.99), diff --git a/r/R/trackplots.R b/r/R/trackplots.R index ff0defae..4b13e8d9 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -310,18 +310,26 @@ trackplot_normalize_ranges_with_metadata <- function(data, metadata) { #' ) #' blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") #' read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags +#' } +#' +#' ## We use pre-generated data for this example +#' frags <- get_demo_frags() #' region <- "chr4:3034877-4034877" #' cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) -#' transcripts <- read_gencode_transcripts( -#' file.path(tempdir(), "references"), release = "42", -#' annotation_set = "basic", timeout = 3000 +#' genes <- readr::read_delim( +#' file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), +#' delim = "\t", show_col_types = FALSE #' ) +#' read_counts <- readr::read_delim( +#' file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), +#' delim = "\t", show_col_types = FALSE +#' )$nFrags #' region <- "chr4:3034877-4034877" #' #' #' ## Get all trackplots and scalebars to combine #' plot_scalebar <- trackplot_scalebar(region) -#' plot_gene <- trackplot_gene(transcripts, region) +#' plot_gene <- trackplot_gene(genes, region) #' plot_coverage <- trackplot_coverage( #' frags, #' region, @@ -335,7 +343,7 @@ trackplot_normalize_ranges_with_metadata <- function(data, metadata) { #' trackplot_combine( #' list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) #' ) -#' } +#' #' @export trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_width = 0.3) { for (plot in tracks) { @@ -477,7 +485,9 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ #' @examples #' ## Prep data #' frags <- get_demo_frags() +#' cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) #' +#' \dontrun{ #' ## Use genes and blacklist to determine proper number of reads per cell #' genes <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", @@ -485,9 +495,17 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ #' features = "transcript", timeout = 3000 #' ) #' blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") +#' #' read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags +#' } #' region <- "chr4:3034877-4034877" -#' cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) +#' +#' ## We use pre-generated data for this example +#' read_counts <- readr::read_delim( +#' file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), +#' delim = "\t", show_col_types = FALSE +#' )$nFrags +#' #' #' scale_next_plot_height(0.5) #' trackplot_coverage( @@ -597,11 +615,19 @@ trackplot_coverage <- function(fragments, region, groups, #' @return Plot of gene locations #' @seealso `trackplot_combine()`, `trackplot_coverage()`, `trackplot_loop()`, `trackplot_scalebar()` #' @examples +#' \dontrun{ #' ## Prep data #' transcripts <- read_gencode_transcripts( #' file.path(tempdir(), "references"), release = "42", #' annotation_set = "basic", features = "transcript", timeout = 3000 #' ) +#' } +#' +#' ## We use pre-generated data for this example +#' transcripts <- readr::read_delim( +#' file.path(system.file("extdata", package = "BPCells"), +#' "transcripts_filtered_example_chr_4.tsv.gz")) +#' #' region <- "chr4:3264877-3634877" #' #' ## Plot gene trackplot diff --git a/r/man/gene_region.Rd b/r/man/gene_region.Rd index b60b5dd9..6577167f 100644 --- a/r/man/gene_region.Rd +++ b/r/man/gene_region.Rd @@ -36,6 +36,7 @@ can be used as the \code{region} argument for trackplot functions such as \code{trackplot_coverage()} or \code{trackplot_gene()} } \examples{ +\dontrun{ ## Prep data genes <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", @@ -45,4 +46,13 @@ genes <- read_gencode_transcripts( ## Get gene region gene_region(genes, "CD19", extend_bp = 1e5) +#> $chr +#> [1] "chr16" +#> +#> $start +#> [1] 28831970 +#> +#> $end +#> [1] 29039342 +} } diff --git a/r/man/gene_score_tiles_archr.Rd b/r/man/gene_score_tiles_archr.Rd index a9b91914..d0a31eb2 100644 --- a/r/man/gene_score_tiles_archr.Rd +++ b/r/man/gene_score_tiles_archr.Rd @@ -48,14 +48,22 @@ beyond a neighboring gene are not considered } } \examples{ +\dontrun{ ## Prep data directory <- file.path(tempdir(), "references") genes <- read_gencode_genes( directory, release = "42", - annotation_set = "basic", + annotation_set = "basic", ) +} +## Use pre-generated data for this example +## Use pre-computed transcripts for chr4 +genes <- readr::read_delim( + file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), + delim = "\t", show_col_types = FALSE +) ## Get gene scores by tile gene_score_tiles_archr( diff --git a/r/man/gene_scores.Rd b/r/man/gene_scores.Rd index 6f786b7e..be34d52d 100644 --- a/r/man/gene_scores.Rd +++ b/r/man/gene_scores.Rd @@ -86,6 +86,7 @@ calculate a weight matrix of dimensions genes x tiles. This matrix can be multiplied with a tile matrix to obtain ArchR-compatible gene activity scores. } \examples{ +\dontrun{ ## Prep data reference_dir <- file.path(tempdir(), "references") frags <- get_demo_frags() @@ -114,14 +115,17 @@ tiles <- tile_matrix(frags, chrom_sizes, mode = "fragments") ## Get gene scores per cell gene_score_weights \%*\% tiles +} +\dontrun{ ####################################################################### ## gene_score_archr() example ####################################################################### ## This is a wrapper that creates both the gene score weight ## matrix and tile matrix together gene_score_archr(frags, genes, chrom_sizes, blacklist) +} } diff --git a/r/man/plot_embedding.Rd b/r/man/plot_embedding.Rd index aef919f2..02bfba60 100644 --- a/r/man/plot_embedding.Rd +++ b/r/man/plot_embedding.Rd @@ -97,8 +97,10 @@ value stays the same. } } \examples{ +\dontrun{ +## Prep data set.seed(123) -mat <- get_demo_mat() +mat <- get_demo_mat()[,sample(1:ncol(get_demo_mat()), 200)] ## Normalize matrix mat_norm <- log1p(multiply_cols(mat, 1/colSums(mat)) * 10000) \%>\% write_matrix_memory(compress = FALSE) @@ -137,5 +139,5 @@ plot_embedding(clusts, umap) # umap, # features = c("MS4A1", "CD3E"), #) - +} } diff --git a/r/man/plot_tss_profile.Rd b/r/man/plot_tss_profile.Rd index 146b2b63..9181c3ab 100644 --- a/r/man/plot_tss_profile.Rd +++ b/r/man/plot_tss_profile.Rd @@ -43,16 +43,27 @@ Typically, this plot shows strong enrichment of insertions near a TSS, and a small bump downstream around 220bp downstream of the TSS for the +1 nucleosome. } \examples{ + ## Prep data frags <- get_demo_frags() +\dontrun{ genes <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", annotation_set = "basic", features = "transcript", timeout = 3000 ) +} + +## Use pre-computed transcripts for chr4 +genes <- readr::read_delim( + file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), + delim = "\t", show_col_types = FALSE +) + ## Plot tss profile plot_tss_profile(frags, genes) + } \seealso{ \code{footprint()}, \code{plot_tf_footprint()} diff --git a/r/man/plot_tss_scatter.Rd b/r/man/plot_tss_scatter.Rd index 444a1014..3476eeab 100644 --- a/r/man/plot_tss_scatter.Rd +++ b/r/man/plot_tss_scatter.Rd @@ -29,6 +29,7 @@ enrichment on the y-axis. This plot is most useful to select which cell barcodes in an experiment correspond to high-quality cells } \examples{ +\dontrun{ ## Prep data frags <- get_demo_frags(filter_qc = FALSE, subset = FALSE) genes <- read_gencode_transcripts( @@ -38,8 +39,15 @@ genes <- read_gencode_transcripts( ) blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") atac_qc <- qc_scATAC(frags, genes, blacklist) +} +## Use pre-computed QC metrics for chr4 +atac_qc <- readr::read_delim( + file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), + delim = "\t", show_col_types = FALSE +) ## Render tss enrichment vs fragment plot plot_tss_scatter(atac_qc, min_frags = 1000, min_tss = 10) + } diff --git a/r/man/qc_scATAC.Rd b/r/man/qc_scATAC.Rd index 476b9a7b..d7908843 100644 --- a/r/man/qc_scATAC.Rd +++ b/r/man/qc_scATAC.Rd @@ -50,9 +50,9 @@ re-calculate the ArchR QC stats. ArchR's \code{PromoterRatio} and \code{BlacklistRatio} are not included in the output, as they can be easily calculated from \code{ReadsInPromoter / nFrags} and \code{ReadsInBlacklist / nFrags}. Similarly, ArchR's \code{NucleosomeRatio} can be calculated -as \code{(monoNucleosomal + multiNucleosomal) / subNucleosomal}. } \examples{ +\dontrun{ ## Prep data frags <- get_demo_frags(subset = FALSE) reference_dir <- file.path(tempdir(), "references") @@ -69,3 +69,10 @@ blacklist <- read_encode_blacklist(reference_dir, genome = "hg38") ## Run qc head(qc_scATAC(frags, genes, blacklist)) } + +## Read precomputed +head(readr::read_delim( + file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), + delim = "\t", show_col_types = FALSE +)) +} diff --git a/r/man/trackplot_combine.Rd b/r/man/trackplot_combine.Rd index 716a2e9c..d9cc6bb3 100644 --- a/r/man/trackplot_combine.Rd +++ b/r/man/trackplot_combine.Rd @@ -33,6 +33,7 @@ Combines multiple track plots of the same region into a single grid. Uses the \code{patchwork} package to perform the alignment. } \examples{ +\dontrun{ ## Prep data frags <- get_demo_frags() @@ -44,18 +45,26 @@ genes <- read_gencode_transcripts( ) blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags +} + +## We use pre-generated data for this example +frags <- get_demo_frags() region <- "chr4:3034877-4034877" cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) -transcripts <- read_gencode_transcripts( - file.path(tempdir(), "references"), release = "42", - annotation_set = "basic", timeout = 3000 +genes <- readr::read_delim( + file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), + delim = "\t", show_col_types = FALSE ) +read_counts <- readr::read_delim( + file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), + delim = "\t", show_col_types = FALSE +)$nFrags region <- "chr4:3034877-4034877" ## Get all trackplots and scalebars to combine plot_scalebar <- trackplot_scalebar(region) -plot_gene <- trackplot_gene(transcripts, region) +plot_gene <- trackplot_gene(genes, region) plot_coverage <- trackplot_coverage( frags, region, @@ -69,6 +78,7 @@ scale_next_plot_height(0.6) trackplot_combine( list(plot_scalebar, plot_coverage, plot_gene + ggplot2::guides(color = "none")) ) + } \seealso{ \code{trackplot_coverage()}, \code{trackplot_gene()}, \code{trackplot_loop()}, \code{trackplot_scalebar()} diff --git a/r/man/trackplot_coverage.Rd b/r/man/trackplot_coverage.Rd index d8ea0a8b..7205df15 100644 --- a/r/man/trackplot_coverage.Rd +++ b/r/man/trackplot_coverage.Rd @@ -59,7 +59,9 @@ across a region for each cell type or group. \examples{ ## Prep data frags <- get_demo_frags() +cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) +\dontrun{ ## Use genes and blacklist to determine proper number of reads per cell genes <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", @@ -67,9 +69,17 @@ genes <- read_gencode_transcripts( features = "transcript", timeout = 3000 ) blacklist <- read_encode_blacklist(file.path(tempdir(), "references"), genome="hg38") + read_counts <- qc_scATAC(frags, genes, blacklist)$nFrags +} region <- "chr4:3034877-4034877" -cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) + +## We use pre-generated data for this example +read_counts <- readr::read_delim( + file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), + delim = "\t", show_col_types = FALSE +)$nFrags + scale_next_plot_height(0.5) trackplot_coverage( diff --git a/r/man/trackplot_gene.Rd b/r/man/trackplot_gene.Rd index 5f267945..fa51a562 100644 --- a/r/man/trackplot_gene.Rd +++ b/r/man/trackplot_gene.Rd @@ -46,11 +46,19 @@ Plot of gene locations Plot transcript models } \examples{ +\dontrun{ ## Prep data transcripts <- read_gencode_transcripts( file.path(tempdir(), "references"), release = "42", annotation_set = "basic", features = "transcript", timeout = 3000 ) +} + +## We use pre-generated data for this example +transcripts <- readr::read_delim( + file.path(system.file("extdata", package = "BPCells"), + "transcripts_filtered_example_chr_4.tsv.gz")) + region <- "chr4:3264877-3634877" ## Plot gene trackplot diff --git a/r/man/write_insertion_bedgraph.Rd b/r/man/write_insertion_bedgraph.Rd index fb46413d..ee821c39 100644 --- a/r/man/write_insertion_bedgraph.Rd +++ b/r/man/write_insertion_bedgraph.Rd @@ -63,6 +63,7 @@ Beds only hold chrom, start, and end data, while bedGraphs also provide a score This reports the total number of insertions at each basepair for each group listed in \code{cell_groups}. } \examples{ + ## Prep data frags <- get_demo_frags() bedgraph_outputs <- file.path(tempdir(), "bedgraph_outputs") @@ -71,6 +72,7 @@ bedgraph_outputs <- file.path(tempdir(), "bedgraph_outputs") ## `write_insertion_bedgraph()` examples ###################################################### ## Write insertions +\dontrun{ write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all.tar.gz")) list.files(bedgraph_outputs) @@ -83,8 +85,16 @@ reads <- readr::read_tsv(file.path(bedgraph_outputs, "all_tiled.bedGraph"), col_names = c("chr", "start", "end", "score"), show_col_types = FALSE) head(reads) - - +#> A tibble: 6 × 4 +#> chr start end score +#> +#> 1 chr4 10000 10100 1.45 +#> 2 chr4 10100 10200 0.869 +#> 3 chr4 10300 10400 0.290 +#> 4 chr4 10400 10500 0.145 +#> 5 chr4 10600 10700 0.434 +#> 6 chr4 11100 11200 0.145 +} ###################################################### ## `write_insertion_bed()` examples ###################################################### From 72a8b1b93f48c8777c0cccc69951e3f55f99fbd2 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Sat, 10 Jan 2026 15:29:44 -0800 Subject: [PATCH 78/84] [r] cleanup examples --- r/NAMESPACE | 2 +- r/R/atac_utils.R | 5 ++- r/R/matrix.R | 17 +++++++-- r/R/matrix_stats.R | 4 +-- r/R/plots.R | 8 +++-- r/R/trackplots.R | 11 ++++-- r/man/IterableMatrix-methods-core.Rd | 13 +++++++ r/man/IterableMatrix-methods-stats.Rd | 50 --------------------------- r/man/plot_embedding.Rd | 2 -- r/man/plot_tss_profile.Rd | 4 ++- r/man/plot_tss_scatter.Rd | 4 ++- r/man/qc_scATAC.Rd | 5 ++- r/man/reexports.Rd | 2 +- r/man/trackplot_combine.Rd | 8 +++-- r/man/trackplot_coverage.Rd | 3 +- 15 files changed, 67 insertions(+), 71 deletions(-) diff --git a/r/NAMESPACE b/r/NAMESPACE index f9933d68..d46327bf 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -4,6 +4,7 @@ S3method(base::as.data.frame,IterableFragments) S3method(base::as.matrix,IterableMatrix) S3method(colMaxs,IterableMatrix) S3method(colMaxs,default) +S3method(colQuantiles,IterableMatrix) S3method(colQuantiles,default) S3method(colVars,IterableMatrix) S3method(colVars,default) @@ -39,7 +40,6 @@ export(cluster_graph_seurat) export(colMaxs) export(colMeans) export(colQuantiles) -export(colQuantiles.IterableMatrix) export(colSums) export(colVars) export(collect_features) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index d3f35ef9..e6c073af 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -197,7 +197,10 @@ footprint <- function(fragments, ranges, zero_based_coords = !is(ranges, "GRange #' #' ## Read precomputed #' head(readr::read_delim( -#' file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), +#' file.path( +#' system.file("extdata", package = "BPCells"), +#' "qc_results_filtered_example_chr_4.tsv.gz" +#' ), #' delim = "\t", show_col_types = FALSE #' )) #' @export diff --git a/r/R/matrix.R b/r/R/matrix.R index e28c6e27..a8cfaa01 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -828,7 +828,6 @@ rowVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = } } #' @export -#' @describeIn IterableMatrix-methods-stats Calculate rowVars (replacement for `matrixStats::rowVars()`) #' @method rowVars IterableMatrix rowVars.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (!is.null(rows) || !is.null(cols) || !isFALSE(na.rm) || !is.null(center) || !isTRUE(useNames)) { @@ -868,7 +867,6 @@ rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., use } } #' @export -#' @describeIn IterableMatrix-methods-stats Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) #' @method rowMaxs IterableMatrix rowMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if(!is.null(rows) || !is.null(cols) || !isFALSE(na.rm)) { @@ -1002,6 +1000,11 @@ unsplit_selection <- function(selection) { } #' @describeIn IterableMatrix-methods-core Subset an IterableMatrix +#' @examples +#' #' #################################################################### +#' ## x[i, j, ..., drop = TRUE] example +#' ####################################################################### +#' mat[1:2, 1:2] setMethod("[", "IterableMatrix", function(x, i, j, ...) { if (missing(x)) stop("x is missing in matrix selection") if (rlang::is_missing(i) && rlang::is_missing(j)) { @@ -1038,6 +1041,16 @@ setMethod("[", "IterableMatrix", function(x, i, j, ...) { # Simulate assigning to a subset of the matrix. # We concatenate the un-modified matrix subsets with the new values, # then reorder rows/columns appropriately +#' @examples +#' ####################################################################### +#' ## x[i, j, ...] <- value example +#' ####################################################################### +#' mat_changed <- mat +#' new_mat <- matrix(rep(2,4), nrow = 2) %>% as("IterableMatrix") +#' mat_changed[1:2, 1:2] <- new_mat +#' mat_changed %>% as("dgCMatrix") +#' +#' #' @describeIn IterableMatrix-methods-core Assign into an IterableMatrix setMethod("[<-", "IterableMatrix", function(x, i, j, ..., value) { # Do type conversions if needed diff --git a/r/R/matrix_stats.R b/r/R/matrix_stats.R index 9b36792f..ed31bb0c 100644 --- a/r/R/matrix_stats.R +++ b/r/R/matrix_stats.R @@ -60,7 +60,6 @@ rowQuantiles.default <- function(x, rows = NULL, cols = NULL, } #' @export #' @method rowQuantiles IterableMatrix -#' @describeIn IterableMatrix-methods-stats Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -143,9 +142,8 @@ colQuantiles.default <- function(x, rows = NULL, cols = NULL, rlang::abort("Cannot run colQuantiles on a non-BPCells object unless MatrixGenerics or matrixStats is installed.") } } -#' Find the nth quantile value(s) of each column in a matrix. Only supports non-transposed matrices. +#' @method colQuantiles IterableMatrix #' @export -#' @describeIn IterableMatrix-methods-stats Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) colQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., diff --git a/r/R/plots.R b/r/R/plots.R index 24878e21..58645225 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -201,7 +201,9 @@ plot_read_count_knee <- function(read_counts, cutoff = NULL, return_data = FALSE #' #' ## Use pre-computed QC metrics for chr4 #' atac_qc <- readr::read_delim( -#' file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), +#' file.path( +#' system.file("extdata", package = "BPCells"), +#' "qc_results_filtered_example_chr_4.tsv.gz"), #' delim = "\t", show_col_types = FALSE #' ) #' ## Render tss enrichment vs fragment plot @@ -345,7 +347,9 @@ plot_fragment_length <- function(fragments, max_length = 500, return_data = FALS #' #' ## Use pre-computed transcripts for chr4 #' genes <- readr::read_delim( -#' file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), +#' file.path( +#' system.file("extdata", package = "BPCells"), +#' "transcripts_filtered_example_chr_4.tsv.gz"), #' delim = "\t", show_col_types = FALSE #' ) #' diff --git a/r/R/trackplots.R b/r/R/trackplots.R index 4b13e8d9..3dca0a18 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -317,11 +317,15 @@ trackplot_normalize_ranges_with_metadata <- function(data, metadata) { #' region <- "chr4:3034877-4034877" #' cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) #' genes <- readr::read_delim( -#' file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), +#' file.path( +#' system.file("extdata", package = "BPCells"), +#' "transcripts_filtered_example_chr_4.tsv.gz"), #' delim = "\t", show_col_types = FALSE #' ) #' read_counts <- readr::read_delim( -#' file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), +#' file.path( +#' system.file("extdata", package = "BPCells"), +#' "qc_results_filtered_example_chr_4.tsv.gz"), #' delim = "\t", show_col_types = FALSE #' )$nFrags #' region <- "chr4:3034877-4034877" @@ -502,7 +506,8 @@ trackplot_combine <- function(tracks, side_plot = NULL, title = NULL, side_plot_ #' #' ## We use pre-generated data for this example #' read_counts <- readr::read_delim( -#' file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), +#' file.path(system.file("extdata", package = "BPCells"), +#' "qc_results_filtered_example_chr_4.tsv.gz"), #' delim = "\t", show_col_types = FALSE #' )$nFrags #' diff --git a/r/man/IterableMatrix-methods-core.Rd b/r/man/IterableMatrix-methods-core.Rd index 597a1798..3958b051 100644 --- a/r/man/IterableMatrix-methods-core.Rd +++ b/r/man/IterableMatrix-methods-core.Rd @@ -107,4 +107,17 @@ show(mat) t(mat) +#' #################################################################### +## x[i, j, ..., drop = TRUE] example +####################################################################### +mat[1:2, 1:2] +####################################################################### +## x[i, j, ...] <- value example +####################################################################### +mat_changed <- mat +new_mat <- matrix(rep(2,4), nrow = 2) \%>\% as("IterableMatrix") +mat_changed[1:2, 1:2] <- new_mat +mat_changed \%>\% as("dgCMatrix") + + } diff --git a/r/man/IterableMatrix-methods-stats.Rd b/r/man/IterableMatrix-methods-stats.Rd index 0c611339..192ae66a 100644 --- a/r/man/IterableMatrix-methods-stats.Rd +++ b/r/man/IterableMatrix-methods-stats.Rd @@ -8,14 +8,10 @@ \alias{colMeans,IterableMatrix-method} \alias{colVars} \alias{rowVars} -\alias{rowVars.IterableMatrix} \alias{rowMaxs} -\alias{rowMaxs.IterableMatrix} \alias{colMaxs} \alias{rowQuantiles} -\alias{rowQuantiles.IterableMatrix} \alias{colQuantiles} -\alias{colQuantiles.IterableMatrix} \alias{log1p,IterableMatrix-method} \alias{log1p_slow} \alias{expm1,IterableMatrix-method} @@ -50,20 +46,8 @@ rowVars( useNames = TRUE ) -\method{rowVars}{IterableMatrix}( - x, - rows = NULL, - cols = NULL, - na.rm = FALSE, - center = NULL, - ..., - useNames = TRUE -) - rowMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) -\method{rowMaxs}{IterableMatrix}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) - colMaxs(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) rowQuantiles( @@ -79,19 +63,6 @@ rowQuantiles( drop = TRUE ) -\method{rowQuantiles}{IterableMatrix}( - x, - rows = NULL, - cols = NULL, - probs = seq(from = 0, to = 1, by = 0.25), - na.rm = FALSE, - type = 7L, - digits = 7L, - ..., - useNames = TRUE, - drop = TRUE -) - colQuantiles( x, rows = NULL, @@ -105,19 +76,6 @@ colQuantiles( drop = TRUE ) -colQuantiles.IterableMatrix( - x, - rows = NULL, - cols = NULL, - probs = seq(from = 0, to = 1, by = 0.25), - na.rm = FALSE, - type = 7L, - digits = 7L, - ..., - useNames = TRUE, - drop = TRUE -) - \S4method{log1p}{IterableMatrix}(x) log1p_slow(x) @@ -209,22 +167,14 @@ Summaries and reductions for IterableMatrix objects (sums, means, variances, qua \item \code{rowVars()}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) (generic) -\item \code{rowVars(IterableMatrix)}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) - \item \code{rowMaxs()}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) (generic) -\item \code{rowMaxs(IterableMatrix)}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) - \item \code{colMaxs()}: Calculate colMax (replacement for \code{matrixStats::colMax()}) \item \code{rowQuantiles()}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) -\item \code{rowQuantiles(IterableMatrix)}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) - \item \code{colQuantiles()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) -\item \code{colQuantiles.IterableMatrix()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) - \item \code{log1p(IterableMatrix)}: Calculate log(x + 1) \item \code{log1p_slow()}: Calculate log(x + 1) (non-SIMD version) diff --git a/r/man/plot_embedding.Rd b/r/man/plot_embedding.Rd index 02bfba60..a400b41a 100644 --- a/r/man/plot_embedding.Rd +++ b/r/man/plot_embedding.Rd @@ -97,7 +97,6 @@ value stays the same. } } \examples{ -\dontrun{ ## Prep data set.seed(123) mat <- get_demo_mat()[,sample(1:ncol(get_demo_mat()), 200)] @@ -140,4 +139,3 @@ plot_embedding(clusts, umap) # features = c("MS4A1", "CD3E"), #) } -} diff --git a/r/man/plot_tss_profile.Rd b/r/man/plot_tss_profile.Rd index 9181c3ab..d4d7471a 100644 --- a/r/man/plot_tss_profile.Rd +++ b/r/man/plot_tss_profile.Rd @@ -56,7 +56,9 @@ genes <- read_gencode_transcripts( ## Use pre-computed transcripts for chr4 genes <- readr::read_delim( - file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), + file.path( + system.file("extdata", package = "BPCells"), + "transcripts_filtered_example_chr_4.tsv.gz"), delim = "\t", show_col_types = FALSE ) diff --git a/r/man/plot_tss_scatter.Rd b/r/man/plot_tss_scatter.Rd index 3476eeab..5cc96671 100644 --- a/r/man/plot_tss_scatter.Rd +++ b/r/man/plot_tss_scatter.Rd @@ -44,7 +44,9 @@ atac_qc <- qc_scATAC(frags, genes, blacklist) ## Use pre-computed QC metrics for chr4 atac_qc <- readr::read_delim( - file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), + file.path( + system.file("extdata", package = "BPCells"), + "qc_results_filtered_example_chr_4.tsv.gz"), delim = "\t", show_col_types = FALSE ) ## Render tss enrichment vs fragment plot diff --git a/r/man/qc_scATAC.Rd b/r/man/qc_scATAC.Rd index d7908843..6eb8370c 100644 --- a/r/man/qc_scATAC.Rd +++ b/r/man/qc_scATAC.Rd @@ -72,7 +72,10 @@ head(qc_scATAC(frags, genes, blacklist)) ## Read precomputed head(readr::read_delim( - file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), + file.path( + system.file("extdata", package = "BPCells"), + "qc_results_filtered_example_chr_4.tsv.gz" + ), delim = "\t", show_col_types = FALSE )) } diff --git a/r/man/reexports.Rd b/r/man/reexports.Rd index 5d4c340d..e4ac817a 100644 --- a/r/man/reexports.Rd +++ b/r/man/reexports.Rd @@ -17,6 +17,6 @@ below to see their documentation. \describe{ \item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}} - \item{Matrix}{\code{\link[Matrix:colSums-methods]{colMeans}}, \code{\link[Matrix:colSums-methods]{colSums}}, \code{\link[Matrix:colSums-methods]{rowMeans}}, \code{\link[Matrix:colSums-methods]{rowSums}}} + \item{Matrix}{\code{\link[Matrix:colSums]{colMeans}}, \code{\link[Matrix]{colSums}}, \code{\link[Matrix:colSums]{rowMeans}}, \code{\link[Matrix:colSums]{rowSums}}} }} diff --git a/r/man/trackplot_combine.Rd b/r/man/trackplot_combine.Rd index d9cc6bb3..f6774fc4 100644 --- a/r/man/trackplot_combine.Rd +++ b/r/man/trackplot_combine.Rd @@ -52,11 +52,15 @@ frags <- get_demo_frags() region <- "chr4:3034877-4034877" cell_types <- paste("Group", rep(1:3, length.out = length(cellNames(frags)))) genes <- readr::read_delim( - file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), + file.path( + system.file("extdata", package = "BPCells"), + "transcripts_filtered_example_chr_4.tsv.gz"), delim = "\t", show_col_types = FALSE ) read_counts <- readr::read_delim( - file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), + file.path( + system.file("extdata", package = "BPCells"), + "qc_results_filtered_example_chr_4.tsv.gz"), delim = "\t", show_col_types = FALSE )$nFrags region <- "chr4:3034877-4034877" diff --git a/r/man/trackplot_coverage.Rd b/r/man/trackplot_coverage.Rd index 7205df15..6516453b 100644 --- a/r/man/trackplot_coverage.Rd +++ b/r/man/trackplot_coverage.Rd @@ -76,7 +76,8 @@ region <- "chr4:3034877-4034877" ## We use pre-generated data for this example read_counts <- readr::read_delim( - file.path(system.file("extdata", package = "BPCells"), "qc_results_filtered_example_chr_4.tsv.gz"), + file.path(system.file("extdata", package = "BPCells"), + "qc_results_filtered_example_chr_4.tsv.gz"), delim = "\t", show_col_types = FALSE )$nFrags From 31dac0d561de92a81c2e0df6bafdcc276373e1c1 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Sat, 10 Jan 2026 17:45:02 -0800 Subject: [PATCH 79/84] [r] add more examples --- r/R/plots.R | 40 ++++++++++++++++++++++++++++++++- r/R/trackplots.R | 37 ++++++++++++++++++++++++++++++ r/man/collect_features.Rd | 16 +++++++++++++ r/man/palettes.Rd | 14 ++++++++++++ r/man/ragg_wrap.Rd | 18 +++++++++++++++ r/man/rotate_x_labels.Rd | 11 +++++++++ r/man/scale_next_plot_height.Rd | 21 +++++++++++++++++ 7 files changed, 156 insertions(+), 1 deletion(-) diff --git a/r/R/plots.R b/r/R/plots.R index 58645225..6cb0b35a 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -20,6 +20,13 @@ #' @param n Minimum number of colors needed #' @return Character vector of hex color codes #' @rdname palettes +#' @examples +#' ####################################################################### +#' ## discrete_palette() example +#' ####################################################################### +#' discrete_palette("stallion") +#' +#' #' @export discrete_palette <- function(name, n = 1) { palettes <- list( @@ -85,6 +92,13 @@ discrete_palette <- function(name, n = 1) { } #' @rdname palettes +#' @examples +#' ####################################################################### +#' ## continuous_palette() example +#' ####################################################################### +#' continuous_palette("bluePurpleDark") +#' +#' #' @export continuous_palette <- function(name) { palettes <- list( @@ -458,6 +472,21 @@ plot_tf_footprint <- function(fragments, motif_positions, cell_groups = rlang::r #' @param n Internal-use parameter marking the number of nested calls. This is used for #' finding the name of the "source" input variable from the caller's perspective #' @return Data frame with one column for each feature requested +#' @examples +#' # Collect features from a matrix +#' mat <- get_demo_mat() +#' # By ID +#' features_id <- collect_features(mat, "ENSG00000272602", gene_mapping = NULL) +#' head(features_id) +#' +#' # By Gene Symbol (using default human_gene_mapping) +#' features_symbol <- collect_features(mat, "MS4A1") +#' head(features_symbol) +#' +#' # Collect features from a data frame +#' df <- data.frame(a = 1:5, b = 6:10) +#' features_df <- collect_features(df, c("a", "b")) +#' head(features_df) #' @export collect_features <- function(source, features = NULL, gene_mapping = human_gene_mapping, n = 1) { if (!is.null(features)) { @@ -826,6 +855,16 @@ plot_embedding <- function(source, embedding, features = NULL, #' Rotate ggplot x axis labels #' @param degrees Number of degrees to rotate by +#' @examples +#' mat <- get_demo_mat() +#' cell_types <- paste("Group", rep(1:3, length.out = length(colnames(mat)))) +#' +#' ## Plot dot +#' scale_next_plot_height(0.8) +#' plot_dot(mat, c("MS4A1", "CD3E"), cell_types) +#' +#' scale_next_plot_height(0.8) +#' plot_dot(mat, c("MS4A1", "CD3E"), cell_types) + rotate_x_labels(90) #' @export rotate_x_labels <- function(degrees = 45) { ggplot2::theme(axis.text.x = ggplot2::element_text(angle = degrees, hjust = 1, vjust = 1)) @@ -852,7 +891,6 @@ rotate_x_labels <- function(degrees = 45) { #' ## Plot dot #' scale_next_plot_height(0.8) #' plot_dot(mat, c("MS4A1", "CD3E"), cell_types) - #' @export plot_dot <- function(source, features, groups, group_order = NULL, gene_mapping = human_gene_mapping, colors = c("lightgrey", "#4682B4"), diff --git a/r/R/trackplots.R b/r/R/trackplots.R index 3dca0a18..387ed95d 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -1309,6 +1309,26 @@ trackplot_bulk <- function(fragments, region, groups, #' @param scale Numeric multiplier applied to the `height` argument the next #' time `ragg_wrap()` is called. #' @return Returns the previous option value (as returned by `options()`). +#' @examples +#' ## Prep data +#' ## Peaks generated from demo frags, as input into `call_peaks_tile()` +#' peaks <- tibble::tibble( +#' chr = factor(rep("chr4", 16)), +#' start = c(3041400, 3041733, 3037400, 3041933, 3040466, 3041200, +#' 3038200, 3038000, 3040266, 3037733, 3040800, 3042133, +#' 3038466, 3037200, 3043333, 3040066), +#' end = c(3041600, 3041933, 3037600, 3042133, 3040666, 3041400, +#' 3038400, 3038200, 3040466, 3037933, 3041000, 3042333, +#' 3038666, 3037400, 3043533, 3040266), +#' enrichment = c(46.4, 43.5, 28.4, 27.3, 17.3, 11.7, +#' 10.5, 7.95, 7.22, 6.86, 6.32, 6.14, +#' 5.96, 5.06, 4.51, 3.43) +#' ) +#' region <- "chr4:3034877-3044877" +#' +#' ## Plot peaks +#' scale_next_plot_height(0.3) +#' trackplot_genome_annotation(peaks, region, color_by = "enrichment") #' @export scale_next_plot_height <- function(scale) { options("BPCells.scale_next_plot_height" = scale) @@ -1341,6 +1361,23 @@ scale_next_plot_height <- function(scale) { #' @param bitsize Should the dvice record colour as 8 or 16bit #' @param bg Same as `background` for compatibility with old graphic device APIs` #' @return A graphics device as returned by `ragg::agg_png()`. +#' @examples +#' # Create a simple plot using ragg_wrap +#' tmp_file <- tempfile(fileext = ".png") +#' ragg_wrap(tmp_file, width = 400, height = 300) +#' plot(1:10, 1:10) +#' dev.off() +#' +#' # Use scale_next_plot_height to adjust height +#' scale_next_plot_height(2) +#' tmp_file_scaled <- tempfile(fileext = ".png") +#' # Height will be effectively 600 +#' ragg_wrap(tmp_file_scaled, width = 400, height = 300) +#' plot(1:10, 1:10) +#' dev.off() +#' +#' # Clean up +#' unlink(c(tmp_file, tmp_file_scaled)) #' @export ragg_wrap <- function( filename = "Rplot%03d.png", width = 480, height = 480, diff --git a/r/man/collect_features.Rd b/r/man/collect_features.Rd index 7cbc8836..3ebdf89c 100644 --- a/r/man/collect_features.Rd +++ b/r/man/collect_features.Rd @@ -35,3 +35,19 @@ If \code{source} is a data.frame, features will be drawn from the columns. If \code{source} is a matrix object (\code{IterableMatrix}, \code{dgCMatrix}, or \code{matrix}), features will be drawn from rows. } +\examples{ +# Collect features from a matrix +mat <- get_demo_mat() +# By ID +features_id <- collect_features(mat, "ENSG00000272602", gene_mapping = NULL) +head(features_id) + +# By Gene Symbol (using default human_gene_mapping) +features_symbol <- collect_features(mat, "MS4A1") +head(features_symbol) + +# Collect features from a data frame +df <- data.frame(a = 1:5, b = 6:10) +features_df <- collect_features(df, c("a", "b")) +head(features_df) +} diff --git a/r/man/palettes.Rd b/r/man/palettes.Rd index 00a01a90..7859e40b 100644 --- a/r/man/palettes.Rd +++ b/r/man/palettes.Rd @@ -27,3 +27,17 @@ large sets of distinguishable colors If the requested number of colors is too large, a new palette will be constructed via interpolation from the requested palette } +\examples{ +####################################################################### +## discrete_palette() example +####################################################################### +discrete_palette("stallion") + + +####################################################################### +## continuous_palette() example +####################################################################### +continuous_palette("bluePurpleDark") + + +} diff --git a/r/man/ragg_wrap.Rd b/r/man/ragg_wrap.Rd index 07cbb3b1..9d84a85b 100644 --- a/r/man/ragg_wrap.Rd +++ b/r/man/ragg_wrap.Rd @@ -57,3 +57,21 @@ by \code{trackplot_combine()}) renders too tall/short in a pipeline and you want quick scaling tweak without touching the plot code itself. The scaling factor is applied once and then cleared. } +\examples{ +# Create a simple plot using ragg_wrap +tmp_file <- tempfile(fileext = ".png") +ragg_wrap(tmp_file, width = 400, height = 300) +plot(1:10, 1:10) +dev.off() + +# Use scale_next_plot_height to adjust height +scale_next_plot_height(2) +tmp_file_scaled <- tempfile(fileext = ".png") +# Height will be effectively 600 +ragg_wrap(tmp_file_scaled, width = 400, height = 300) +plot(1:10, 1:10) +dev.off() + +# Clean up +unlink(c(tmp_file, tmp_file_scaled)) +} diff --git a/r/man/rotate_x_labels.Rd b/r/man/rotate_x_labels.Rd index 64dfc634..b508760c 100644 --- a/r/man/rotate_x_labels.Rd +++ b/r/man/rotate_x_labels.Rd @@ -12,3 +12,14 @@ rotate_x_labels(degrees = 45) \description{ Rotate ggplot x axis labels } +\examples{ +mat <- get_demo_mat() +cell_types <- paste("Group", rep(1:3, length.out = length(colnames(mat)))) + +## Plot dot +scale_next_plot_height(0.8) +plot_dot(mat, c("MS4A1", "CD3E"), cell_types) + +scale_next_plot_height(0.8) +plot_dot(mat, c("MS4A1", "CD3E"), cell_types) + rotate_x_labels(90) +} diff --git a/r/man/scale_next_plot_height.Rd b/r/man/scale_next_plot_height.Rd index 91433730..f20b1f10 100644 --- a/r/man/scale_next_plot_height.Rd +++ b/r/man/scale_next_plot_height.Rd @@ -17,3 +17,24 @@ Returns the previous option value (as returned by \code{options()}). Stores a scaling factor that \code{ragg_wrap()} consumes once, letting you tweak the rendered height of the next PNG device without modifying the plot code. } +\examples{ +## Prep data +## Peaks generated from demo frags, as input into `call_peaks_tile()` +peaks <- tibble::tibble( + chr = factor(rep("chr4", 16)), + start = c(3041400, 3041733, 3037400, 3041933, 3040466, 3041200, + 3038200, 3038000, 3040266, 3037733, 3040800, 3042133, + 3038466, 3037200, 3043333, 3040066), + end = c(3041600, 3041933, 3037600, 3042133, 3040666, 3041400, + 3038400, 3038200, 3040466, 3037933, 3041000, 3042333, + 3038666, 3037400, 3043533, 3040266), + enrichment = c(46.4, 43.5, 28.4, 27.3, 17.3, 11.7, + 10.5, 7.95, 7.22, 6.86, 6.32, 6.14, + 5.96, 5.06, 4.51, 3.43) +) +region <- "chr4:3034877-3044877" + +## Plot peaks +scale_next_plot_height(0.3) +trackplot_genome_annotation(peaks, region, color_by = "enrichment") +} From d8563cfe7065c80edbe3d1ff92f6bc93211e4150 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Sat, 10 Jan 2026 21:07:23 -0800 Subject: [PATCH 80/84] [r] add in colVars() specialization examples --- r/NAMESPACE | 3 +- r/R/matrix.R | 33 ++++++++++-- r/man/IterableMatrix-matrixgenerics.Rd | 69 +++++++++++++++++++++++++- r/man/IterableMatrix-methods-stats.Rd | 2 +- 4 files changed, 99 insertions(+), 8 deletions(-) diff --git a/r/NAMESPACE b/r/NAMESPACE index d46327bf..1533f448 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -6,8 +6,6 @@ S3method(colMaxs,IterableMatrix) S3method(colMaxs,default) S3method(colQuantiles,IterableMatrix) S3method(colQuantiles,default) -S3method(colVars,IterableMatrix) -S3method(colVars,default) S3method(rowMaxs,IterableMatrix) S3method(rowMaxs,default) S3method(rowQuantiles,IterableMatrix) @@ -42,6 +40,7 @@ export(colMeans) export(colQuantiles) export(colSums) export(colVars) +export(colVars.IterableMatrix) export(collect_features) export(continuous_palette) export(convert_matrix_type) diff --git a/r/R/matrix.R b/r/R/matrix.R index a8cfaa01..579bb472 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -751,7 +751,7 @@ setMethod("rowMeans", signature(x = "IterableMatrix"), function(x) rowSums(x) / #' @return * `colMeans()`: vector of col means #' @examples #' ####################################################################### -#' ## colMeans() example +#' # colMeans() example #' ####################################################################### #' colMeans(mat) #' @@ -780,7 +780,18 @@ setMethod("colMeans", signature(x = "IterableMatrix"), function(x) colSums(x) / #' #' @export colVars <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) UseMethod("colVars") -#' @export +#' @describeIn IterableMatrix-matrixgenerics Calculate colVars (replacement for `matrixStats::colVars()`) +#' @param center Optional center values (vector of length nrow(x) or ncol(x)) +#' @return * `colVars()`: vector of col variance +#' @examples +#' mat <- matrix(1:25, nrow = 5) %>% as("dgCMatrix") +#' mat +#' mat <- as(mat, "IterableMatrix") +#' ####################################################################### +#' ## colVars() example +#' ####################################################################### +#' colVars(mat) +#' #' @method colVars default colVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { @@ -792,7 +803,15 @@ colVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = } } #' @export -#' @method colVars IterableMatrix +#' @param center Optional center values (vector of length nrow(x) or ncol(x)) +#' @return * `colVars()`: vector of col variance +#' @examples +#' ####################################################################### +#' ## colVars() example +#' ####################################################################### +#' colVars(mat) +#' +#' @describeIn IterableMatrix-matrixgenerics Calculate colVars (replacement for `matrixStats::colVars()`) colVars.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (!is.null(rows) || !is.null(cols) || !isFALSE(na.rm) || !is.null(center) || !isTRUE(useNames)) { stop("colVars(IterableMatrix) doesn't support extra arguments rows, cols, na.rm, center, or useNames") @@ -912,6 +931,14 @@ colMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., use stop("Can't run colMaxs on a non-BPCells object unless MatrixGenerics or matrixStats are installed.") } } +#' @rdname IterableMatrix-matrixgenerics +#' @examples +#' ####################################################################### +#' ## colMaxs() example +#' ####################################################################### +#' colMaxs(mat) +#' +#' #' @export #' @method colMaxs IterableMatrix colMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { diff --git a/r/man/IterableMatrix-matrixgenerics.Rd b/r/man/IterableMatrix-matrixgenerics.Rd index e0fb7526..b214dc1b 100644 --- a/r/man/IterableMatrix-matrixgenerics.Rd +++ b/r/man/IterableMatrix-matrixgenerics.Rd @@ -1,7 +1,10 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/matrix_stats.R +% Please edit documentation in R/matrix.R, R/matrix_stats.R \docType{methods} -\name{IterableMatrix-matrixgenerics} +\name{colVars.default} +\alias{colVars.default} +\alias{colVars.IterableMatrix} +\alias{colMaxs.IterableMatrix} \alias{IterableMatrix-matrixgenerics} \alias{rowQuantiles,IterableMatrix-method} \alias{colQuantiles,IterableMatrix-method} @@ -10,23 +13,85 @@ \alias{rowMaxs,IterableMatrix-method} \alias{colMaxs,IterableMatrix-method} \title{MatrixGenerics methods for IterableMatrix} +\usage{ +\method{colVars}{default}( + x, + rows = NULL, + cols = NULL, + na.rm = FALSE, + center = NULL, + ..., + useNames = TRUE +) + +colVars.IterableMatrix( + x, + rows = NULL, + cols = NULL, + na.rm = FALSE, + center = NULL, + ..., + useNames = TRUE +) + +\method{colMaxs}{IterableMatrix}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) +} \arguments{ \item{x}{An \code{IterableMatrix}.} +\item{center}{Optional center values (vector of length nrow(x) or ncol(x))} + \item{...}{Passed to the underlying implementation.} } +\value{ +\itemize{ +\item \verb{colVars()}: vector of col variance +} + +\itemize{ +\item \verb{colVars()}: vector of col variance +} +} \description{ S4 methods enabling MatrixGenerics generics (e.g., \code{rowQuantiles}, \code{colQuantiles}, \code{rowVars}, \code{colVars}, \code{rowMaxs}, \code{colMaxs}) to operate on \code{IterableMatrix}. These are registered at runtime only when MatrixGenerics is available. } +\section{Functions}{ +\itemize{ +\item \code{colVars(default)}: Calculate colVars (replacement for \code{matrixStats::colVars()}) + +\item \code{colVars.IterableMatrix()}: Calculate colVars (replacement for \code{matrixStats::colVars()}) + +}} \section{Availability}{ Methods are registered conditionally; if MatrixGenerics is not installed, nothing is registered and the generics fall back as usual. } +\examples{ +mat <- matrix(1:25, nrow = 5) \%>\% as("dgCMatrix") +mat +mat <- as(mat, "IterableMatrix") +####################################################################### +## colVars() example +####################################################################### +colVars(mat) + +####################################################################### +## colVars() example +####################################################################### +colVars(mat) + +####################################################################### +## colMaxs() example +####################################################################### +colMaxs(mat) + + +} \seealso{ \code{\link{rowQuantiles}}, \code{\link{colQuantiles}}, \code{\link{rowVars}}, \code{\link{colVars}}, diff --git a/r/man/IterableMatrix-methods-stats.Rd b/r/man/IterableMatrix-methods-stats.Rd index 192ae66a..66c622f3 100644 --- a/r/man/IterableMatrix-methods-stats.Rd +++ b/r/man/IterableMatrix-methods-stats.Rd @@ -210,7 +210,7 @@ rowMeans(mat) ####################################################################### -## colMeans() example +# colMeans() example ####################################################################### colMeans(mat) From c8bdbbd1bbda8d98fc2e6a4adae0a06f68886c73 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Sat, 10 Jan 2026 23:44:59 -0800 Subject: [PATCH 81/84] [r] expand examples to all exported functions --- r/NAMESPACE | 15 +- r/R/atac_utils.R | 2 + r/R/clustering.R | 60 +++++++ r/R/geneScores.R | 4 +- r/R/matrix.R | 102 +++++++++-- r/R/matrix_stats.R | 51 +++++- r/R/plots.R | 15 +- r/R/trackplots.R | 11 ++ r/R/transforms.R | 40 +++++ r/man/IterableMatrix-matrixgenerics.Rd | 240 ++++++++++++++++++++++++- r/man/all_matrix_inputs.Rd | 10 ++ r/man/binarize.Rd | 12 ++ r/man/call_macs_peaks.Rd | 3 + r/man/cluster_cells_graph.Rd | 7 + r/man/cluster_graph.Rd | 22 +++ r/man/draw_trackplot_grid.Rd | 3 + r/man/import_matrix_market.Rd | 28 +++ r/man/knn.Rd | 19 ++ r/man/knn_graph.Rd | 12 ++ r/man/plot_tf_footprint.Rd | 16 +- r/man/regress_out.Rd | 16 ++ r/man/sctransform_pearson.Rd | 15 ++ r/man/trackplot_bulk.Rd | 3 + r/man/trackplot_utils.Rd | 8 + 24 files changed, 685 insertions(+), 29 deletions(-) diff --git a/r/NAMESPACE b/r/NAMESPACE index 1533f448..94c115eb 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -2,16 +2,6 @@ S3method(base::as.data.frame,IterableFragments) S3method(base::as.matrix,IterableMatrix) -S3method(colMaxs,IterableMatrix) -S3method(colMaxs,default) -S3method(colQuantiles,IterableMatrix) -S3method(colQuantiles,default) -S3method(rowMaxs,IterableMatrix) -S3method(rowMaxs,default) -S3method(rowQuantiles,IterableMatrix) -S3method(rowQuantiles,default) -S3method(rowVars,IterableMatrix) -S3method(rowVars,default) S3method(svds,IterableMatrix) S3method(svds,default) export("%>%") @@ -36,8 +26,10 @@ export(cluster_graph_leiden) export(cluster_graph_louvain) export(cluster_graph_seurat) export(colMaxs) +export(colMaxs.IterableMatrix) export(colMeans) export(colQuantiles) +export(colQuantiles.IterableMatrix) export(colSums) export(colVars) export(colVars.IterableMatrix) @@ -109,10 +101,13 @@ export(regress_out) export(remove_demo_data) export(rotate_x_labels) export(rowMaxs) +export(rowMaxs.IterableMatrix) export(rowMeans) export(rowQuantiles) +export(rowQuantiles.IterableMatrix) export(rowSums) export(rowVars) +export(rowVars.IterableMatrix) export(scale_next_plot_height) export(sctransform_pearson) export(select_cells) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index e6c073af..741bf24a 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -871,6 +871,8 @@ call_peaks_macs <- function(fragments, path, #' `r lifecycle::badge("deprecated")` #' #' This function has been renamed to `call_peaks_macs()` +#' @examples +#' # See ?call_peaks_macs for examples #' @export #' @keywords internal call_macs_peaks <- function(...) { diff --git a/r/R/clustering.R b/r/R/clustering.R index 9b1dd58d..db290575 100644 --- a/r/R/clustering.R +++ b/r/R/clustering.R @@ -80,6 +80,12 @@ is_adjacency_matrix <- function(mat) { #' Returns a factor vector of length `cells` with a cluster assignment for each cell. #' #' @seealso `knn_hnsw()` `knn_annoy()` `knn_to_graph()` `knn_to_snn_graph()` `knn_to_geodesic_graph()` `cluster_graph_leiden()` `cluster_graph_louvain()` `cluster_graph_seurat()` +#' @examples +#' set.seed(123) +#' mat <- matrix(rnorm(1000 * 10), nrow = 1000) +#' clusters <- cluster_cells_graph(mat, threads = 1) +#' table(clusters) +#' #' @export cluster_cells_graph <- function( mat, knn_method = knn_hnsw, @@ -161,6 +167,12 @@ knn_to_graph <- function(knn, use_weights = FALSE, self_loops = TRUE) { #' List of 3 equal-length vectors `i`, `j`, and `weight`, along with an integer `dim`. #' These correspond to the rows, cols, and values of non-zero entries in the lower triangle #' adjacency matrix. `dim` is the total number of vertices (cells) in the graph +#' @examples +#' set.seed(123) +#' mat <- matrix(rnorm(1000 * 10), nrow = 1000) +#' knn <- knn_hnsw(mat, k = 10) +#' graph <- knn_to_snn_graph(knn) +#' #' @export knn_to_snn_graph <- function(knn, min_val = 1 / 15, self_loops = FALSE, return_type=c("matrix", "list")) { return_type <- match.arg(return_type) @@ -215,6 +227,12 @@ knn_to_snn_graph <- function(knn, min_val = 1 / 15, self_loops = FALSE, return_t #' List of 3 equal-length vectors `i`, `j`, and `weight`, along with an integer `dim`. #' These correspond to the rows, cols, and values of non-zero entries in the lower triangle #' adjacency matrix. `dim` is the total number of vertices (cells) in the graph +#' @examples +#' set.seed(123) +#' mat <- matrix(rnorm(1000 * 10), nrow = 1000) +#' knn <- knn_hnsw(mat, k = 10) +#' graph <- knn_to_geodesic_graph(knn) +#' #' @export knn_to_geodesic_graph <- function(knn, return_type = c("matrix", "list"), threads = 0L) { return_type <- match.arg(return_type) @@ -247,6 +265,13 @@ knn_to_geodesic_graph <- function(knn, return_type = c("matrix", "list"), thread #' @param seed Random seed for clustering initialization #' @param ... Additional arguments to underlying clustering function #' @return Factor vector containing the cluster assignment for each cell. +#' @examples +#' set.seed(123) +#' mat <- matrix(rnorm(1000 * 10), nrow = 1000) +#' knn <- knn_hnsw(mat, k = 10) +#' graph <- knn_to_snn_graph(knn) +#' clusters <- cluster_graph_leiden(graph, resolution = 0.5) +#' #' @export cluster_graph_leiden <- function( mat, resolution = 1, objective_function = c("modularity", "CPM"), @@ -270,6 +295,13 @@ cluster_graph_leiden <- function( #' @rdname cluster_graph #' @details **cluster_graph_louvain**: Louvain graph clustering algorithm `igraph::cluster_louvain()` +#' @examples +#' set.seed(123) +#' mat <- matrix(rnorm(1000 * 10), nrow = 1000) +#' knn <- knn_hnsw(mat, k = 10) +#' graph <- knn_to_snn_graph(knn) +#' clusters <- cluster_graph_louvain(graph, resolution = 0.5) +#' #' @export cluster_graph_louvain <- function( mat, resolution = 1, seed = 12531 @@ -290,6 +322,15 @@ cluster_graph_louvain <- function( #' @rdname cluster_graph #' @details **cluster_graph_seurat**: Seurat's clustering algorithm `Seurat::FindClusters()` +#' @examples +#' \dontrun{ +#' set.seed(123) +#' mat <- matrix(rnorm(1000 * 10), nrow = 1000) +#' knn <- knn_hnsw(mat, k = 10) +#' graph <- knn_to_snn_graph(knn) +#' clusters <- cluster_graph_seurat(graph, resolution = 0.5) +#' } +#' #' @export cluster_graph_seurat <- function( mat, resolution = 0.8, ... @@ -357,6 +398,16 @@ cluster_membership_matrix <- function(groups, group_order = NULL) { #' #' If no query is given, nearest neighbors are found by mapping the data matrix to itself, #' likely including self-neighbors (i.e. `idx[c,1] == c` for most cells). +#' @examples +#' ############################################ +#' ## knn_annoy() example +#' ############################################ +#' set.seed(123) +#' mat <- matrix(rnorm(100 * 10), nrow = 10) +#' rownames(mat) <- paste0("cell", 1:10) +#' knn <- knn_hnsw(mat, k = 10) +#' knn +#' #' @export knn_hnsw <- function(data, query = NULL, k = 10, metric = c("euclidean", "cosine"), verbose = TRUE, threads = 1, ef = 100) { metric <- match.arg(metric) @@ -396,6 +447,15 @@ knn_hnsw <- function(data, query = NULL, k = 10, metric = c("euclidean", "cosine #' @details **knn_annoy**: Use RcppAnnoy as knn engine #' @param n_trees Number of trees during index build time. More trees gives higher accuracy #' @param search_k Number of nodes to inspect during the query, or -1 for default value. Higher number gives higher accuracy +#' @examples +#' ############################################ +#' ## knn_annoy() example +#' ############################################ +#' set.seed(123) +#' mat <- matrix(rnorm(100 * 10), nrow = 10) +#' rownames(mat) <- paste0("cell", 1:10) +#' knn <- knn_annoy(mat, k = 10) +#' knn #' @export knn_annoy <- function(data, query = NULL, k = 10, metric = c("euclidean", "cosine", "manhattan", "hamming"), n_trees = 50, search_k = -1) { metric <- match.arg(metric) diff --git a/r/R/geneScores.R b/r/R/geneScores.R index 027a60a6..b59a394e 100644 --- a/r/R/geneScores.R +++ b/r/R/geneScores.R @@ -165,7 +165,9 @@ extend_ranges <- function(ranges, upstream = 0, downstream = 0, metadata_cols = #' ## Use pre-generated data for this example #' ## Use pre-computed transcripts for chr4 #' genes <- readr::read_delim( -#' file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), +#' file.path( +#' system.file("extdata", package = "BPCells"), +#' "transcripts_filtered_example_chr_4.tsv.gz"), #' delim = "\t", show_col_types = FALSE #' ) #' diff --git a/r/R/matrix.R b/r/R/matrix.R index 579bb472..810d542c 100644 --- a/r/R/matrix.R +++ b/r/R/matrix.R @@ -200,6 +200,15 @@ setMethod("matrix_inputs<-", "IterableMatrix", function(x, ..., value) { #' @param value List of IterableMatrix objects #' @return List of IterableMatrix objects. If a matrix `m` is itself an input object, then #' `all_matrix_inputs(m)` will return `list(m)`. +#' @examples +#' mat <- matrix(1:9, nrow=3) %>% as("IterableMatrix") +#' +#' # Just returns the matrix itself +#' all_matrix_inputs(mat) +#' +#' # Returns the matrix twice, as they are the inputs to the cbind +#' all_matrix_inputs(cbind(mat, mat)) +#' #' @export all_matrix_inputs <- function(x) { assert_is(x, "IterableMatrix") @@ -835,7 +844,18 @@ rlang::on_load({ #' #' @export rowVars <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) UseMethod("rowVars") -#' @export +#' @describeIn IterableMatrix-matrixgenerics Calculate rowVars (replacement for `matrixStats::rowVars()`) +#' @param center Optional center values (vector of length nrow(x) or ncol(x)) +#' @return * `rowVars()`: vector of row variance +#' @examples +#' mat <- matrix(1:25, nrow = 5) %>% as("dgCMatrix") +#' mat +#' mat <- as(mat, "IterableMatrix") +#' ####################################################################### +#' ## rowVars() example +#' ####################################################################### +#' rowVars(mat) +#' #' @method rowVars default rowVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { @@ -847,7 +867,15 @@ rowVars.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = } } #' @export -#' @method rowVars IterableMatrix +#' @param center Optional center values (vector of length nrow(x) or ncol(x)) +#' @return * `rowVars()`: vector of row variance +#' @examples +#' ####################################################################### +#' ## rowVars() example +#' ####################################################################### +#' rowVars(mat) +#' +#' @describeIn IterableMatrix-matrixgenerics Calculate rowVars (replacement for `matrixStats::rowVars()`) rowVars.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, center = NULL, ..., useNames = TRUE) { if (!is.null(rows) || !is.null(cols) || !isFALSE(na.rm) || !is.null(center) || !isTRUE(useNames)) { stop("rowVars(IterableMatrix) doesn't support extra arguments rows, cols, na.rm, center, or useNames") @@ -873,7 +901,17 @@ rlang::on_load({ #' #' @export rowMaxs <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) UseMethod("rowMaxs") -#' @export +#' @describeIn IterableMatrix-matrixgenerics Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) +#' @return * `rowMaxs()`: vector of row maxs +#' @examples +#' mat <- matrix(1:25, nrow = 5) %>% as("dgCMatrix") +#' mat +#' mat <- as(mat, "IterableMatrix") +#' ####################################################################### +#' ## rowMaxs() example +#' ####################################################################### +#' rowMaxs(mat) +#' #' @method rowMaxs default rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { @@ -886,7 +924,14 @@ rowMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., use } } #' @export -#' @method rowMaxs IterableMatrix +#' @return * `rowMaxs()`: vector of row maxs +#' @examples +#' ####################################################################### +#' ## rowMaxs() example +#' ####################################################################### +#' rowMaxs(mat) +#' +#' @describeIn IterableMatrix-matrixgenerics Calculate rowMaxs (replacement for `matrixStats::rowMaxs()`) rowMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if(!is.null(rows) || !is.null(cols) || !isFALSE(na.rm)) { stop("rowMaxs(IterableMatrix) doesn't support extra arguments rows, cols, or na.rm") @@ -919,7 +964,17 @@ rlang::on_load({ #' #' @export colMaxs <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) UseMethod("colMaxs") -#' @export +#' @describeIn IterableMatrix-matrixgenerics Calculate colMaxs (replacement for `matrixStats::colMaxs()`) +#' @return * `colMaxs()`: vector of col maxs +#' @examples +#' mat <- matrix(1:25, nrow = 5) %>% as("dgCMatrix") +#' mat +#' mat <- as(mat, "IterableMatrix") +#' ####################################################################### +#' ## colMaxs() example +#' ####################################################################### +#' colMaxs(mat) +#' #' @method colMaxs default colMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { if (requireNamespace("MatrixGenerics", quietly = TRUE)) { @@ -931,16 +986,15 @@ colMaxs.default <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., use stop("Can't run colMaxs on a non-BPCells object unless MatrixGenerics or matrixStats are installed.") } } -#' @rdname IterableMatrix-matrixgenerics +#' @export +#' @return * `colMaxs()`: vector of col maxs #' @examples #' ####################################################################### -#' ## colMaxs() example +#' ## colMaxs() example #' ####################################################################### #' colMaxs(mat) #' -#' -#' @export -#' @method colMaxs IterableMatrix +#' @describeIn IterableMatrix-matrixgenerics Calculate colMaxs (replacement for `matrixStats::colMaxs()`) colMaxs.IterableMatrix <- function(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) { iter <- iterate_matrix(convert_matrix_type(x, "double")) if(x@transpose == TRUE) { @@ -2714,6 +2768,26 @@ write_matrix_anndata_hdf5_dense <- function(mat, path, dataset = "X", buffer_siz #' #' When importing from 10x mtx files, the row and column names can be read automatically #' using the `import_matrix_market_10x()` convenience function. +#' @examples +#' # Create a dummy matrix market file +#' matrix_market_path <- file.path(tempdir(), "matrix.mtx") +#' lines <- c( +#' "%%MatrixMarket matrix coordinate integer general", +#' "% This is a comment", +#' "5 10 3", +#' "1 1 1", +#' "2 2 2", +#' "5 10 3" +#' ) +#' writeLines(lines, matrix_market_path) +#' +#' # Import the matrix market file +#' mat <- import_matrix_market(matrix_market_path) +#' mat +#' +#' # Clean up +#' unlink(matrix_market_path) +#' #' @export import_matrix_market <- function( mtx_path, outdir = tempfile("matrix_market"), row_names = NULL, col_names = NULL, row_major = FALSE, @@ -2746,6 +2820,14 @@ import_matrix_market <- function( #' @rdname import_matrix_market #' @param mtx_dir Directory holding matrix.mtx.gz, barcodes.tsv.gz, and features.tsv.gz #' @param feature_type String or vector of feature types to include. (cellranger 3.0 and newer) +#' @examples +#' \dontrun{ +#' # Import 10x matrix market directory +#' mat <- import_matrix_market_10x( +#' "path/to/10x/matrix_market_dir" +#' ) +#' } +#' #' @export import_matrix_market_10x <- function( mtx_dir, outdir = tempfile("matrix_market"), feature_type=NULL, row_major = FALSE, diff --git a/r/R/matrix_stats.R b/r/R/matrix_stats.R index ed31bb0c..cadf6e11 100644 --- a/r/R/matrix_stats.R +++ b/r/R/matrix_stats.R @@ -44,7 +44,17 @@ rowQuantiles <- function(x, rows = NULL, cols = NULL, useNames = TRUE, drop = TRUE) { UseMethod("rowQuantiles") } -#' @export +#' @describeIn IterableMatrix-matrixgenerics Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) +#' @return * `rowQuantiles()`: If `length(probs) == 1`, return a numeric with number of entries equal to the number of rows in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. +#' @examples +#' mat <- matrix(1:25, nrow = 5) %>% as("dgCMatrix") +#' mat +#' mat <- as(mat, "IterableMatrix") +#' ####################################################################### +#' ## rowQuantiles() example +#' ####################################################################### +#' rowQuantiles(transpose_storage_order(mat)) +#' #' @method rowQuantiles default rowQuantiles.default <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), @@ -59,7 +69,14 @@ rowQuantiles.default <- function(x, rows = NULL, cols = NULL, } } #' @export -#' @method rowQuantiles IterableMatrix +#' @return * `rowQuantiles()`: If `length(probs) == 1`, return a numeric with number of entries equal to the number of rows in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. +#' @examples +#' ####################################################################### +#' ## rowQuantiles() example +#' ####################################################################### +#' rowQuantiles(transpose_storage_order(mat)) +#' +#' @describeIn IterableMatrix-matrixgenerics Calculate rowQuantiles (replacement for `matrixStats::rowQuantiles`) rowQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -128,7 +145,17 @@ colQuantiles <- function(x, rows = NULL, cols = NULL, useNames = TRUE, drop = TRUE) { UseMethod("colQuantiles") } -#' @export +#' @describeIn IterableMatrix-matrixgenerics Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) +#' @return * `colQuantiles()`: If `length(probs) == 1`, return a numeric with number of entries equal to the number of columns in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. +#' @examples +#' mat <- matrix(1:25, nrow = 5) %>% as("dgCMatrix") +#' mat +#' mat <- as(mat, "IterableMatrix") +#' ####################################################################### +#' ## colQuantiles() example +#' ####################################################################### +#' colQuantiles(mat) +#' #' @method colQuantiles default colQuantiles.default <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), @@ -142,8 +169,15 @@ colQuantiles.default <- function(x, rows = NULL, cols = NULL, rlang::abort("Cannot run colQuantiles on a non-BPCells object unless MatrixGenerics or matrixStats is installed.") } } -#' @method colQuantiles IterableMatrix #' @export +#' @return * `colQuantiles()`: If `length(probs) == 1`, return a numeric with number of entries equal to the number of columns in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. +#' @examples +#' ####################################################################### +#' ## colQuantiles() example +#' ####################################################################### +#' colQuantiles(mat) +#' +#' @describeIn IterableMatrix-matrixgenerics Calculate colQuantiles (replacement for `matrixStats::colQuantiles`) colQuantiles.IterableMatrix <- function(x, rows = NULL, cols = NULL, probs = seq(from = 0, to = 1, by = 0.25), na.rm = FALSE, type = 7L, digits = 7L, ..., @@ -200,6 +234,15 @@ rlang::on_load({ #' nothing is registered and the generics fall back as usual. #' #' @param x An \code{IterableMatrix}. +#' @param rows (Integer) Optional vector of row indices to operate over. +#' @param cols (Integer) Optional vector of column indices to operate over. +#' @param na.rm (Logical) Should missing values (NA) be removed? +#' @param center Optional center values (vector of length nrow(x) or ncol(x)) +#' @param probs (Numeric) Quantile value(s) to be computed, between 0 and 1. +#' @param type (Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in `matrixStats::rowQuantiles()` +#' @param digits Number of decimal places for quantile calculations +#' @param drop (Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects). +#' @param useNames (Logical) Whether to use row and column names in the output. #' @param ... Passed to the underlying implementation. #' #' @name IterableMatrix-matrixgenerics diff --git a/r/R/plots.R b/r/R/plots.R index 6cb0b35a..46f222eb 100644 --- a/r/R/plots.R +++ b/r/R/plots.R @@ -431,9 +431,22 @@ plot_tss_profile <- function(fragments, genes, cell_groups = rlang::rep_along(ce #' have constant width #' @param colors Discrete color palette to use for cell groups #' @seealso `footprint()`, `plot_tss_profile()` +#' @examples +#' \dontrun{ +#' +#' plot_tf_footprint( +#' frags, +#' motif_positions$CEBPA, +#' cell_groups = cell_types, +#' flank = 250, +#' smooth = 2 +#' ) + +#' ggplot2::labs(title="CEBPA") +#' } +#' # See example in vignette Getting Started #' @export plot_tf_footprint <- function(fragments, motif_positions, cell_groups = rlang::rep_along(cellNames(fragments), "all"), - flank = 250L, smooth = 0L, zero_based_coords = !is(genes, "GRanges"), + flank = 250L, smooth = 0L, zero_based_coords = !is(motif_positions, "GRanges"), colors = discrete_palette("stallion"), return_data = FALSE, apply_styling = TRUE) { assert_is(fragments, "IterableFragments") diff --git a/r/R/trackplots.R b/r/R/trackplots.R index 387ed95d..3ddaa6bb 100644 --- a/r/R/trackplots.R +++ b/r/R/trackplots.R @@ -100,6 +100,13 @@ get_patchwork_plots <- function(patchwork) { #' @param labels character vector of labels -- must match existing number of facets in plot #' @return **set_trackplot_label**: ggplot object with adjusted facet labels #' @rdname trackplot_utils +#' @examples +#' region <- "chr4:3034877-3044877" +#' plot <- trackplot_scalebar(region) +#' plot_labeled <- set_trackplot_label(plot, "Scalebar") +#' +#' plot_height_set <- set_trackplot_height(plot, 2) +#' get_trackplot_height(plot_height_set) #' @export set_trackplot_label <- function(plot, labels) { stopifnot(is(plot, "ggplot")) @@ -1083,6 +1090,8 @@ trackplot_helper <- function(gene, clusters, fragments, cell_read_counts, transc #' @return A plot object with aligned genome plots. Each aligned row has #' the text label, y-axis, and plot body. The relative height of each row is given #' by heights. A shared title and x-axis are put at the top. +#' @examples +#' # See ?trackplot_combine for examples #' @export #' @keywords internal draw_trackplot_grid <- function(..., labels, title = NULL, @@ -1190,6 +1199,8 @@ draw_trackplot_grid <- function(..., labels, title = NULL, #' `draw_trackplot_grid()`, the extra attribute `$patches$labels` will be added to #' specify the labels for each track. If `return_data` or `return_plot_list` is #' `TRUE`, the return value will be modified accordingly. +#' @examples +#' # See ?trackplot_coverage for examples #' @export #' @keywords internal trackplot_bulk <- function(fragments, region, groups, diff --git a/r/R/transforms.R b/r/R/transforms.R index 72c3696c..348c4d0d 100644 --- a/r/R/transforms.R +++ b/r/R/transforms.R @@ -354,6 +354,17 @@ setMethod("short_description", "TransformBinarize", function(x) { #' comparison to the threshold is >= (strict_inequality=FALSE) #' or > (strict_inequality=TRUE). #' @return binarized IterableMatrix object +#' @examples +#' set.seed(12345) +#' mat <- matrix(rpois(40, lambda = 5), nrow = 4) +#' rownames(mat) <- paste0("gene", 1:4) +#' mat <- as(mat, "dgCMatrix") %>% as("IterableMatrix") +#' +#' ####################################################################### +#' ## binarize() example +#' ####################################################################### +#' binarize(mat, threshold = 4) %>% as("dgCMatrix") +#' #' @export binarize <- function(mat, threshold=0, strict_inequality=TRUE) { assert_is(mat, "IterableMatrix") @@ -534,6 +545,20 @@ setMethod("short_description", "SCTransformPearsonTransposeSlow", function(x) { #' @param columns_are_cells Whether the columns of the matrix correspond to cells (default) or genes #' @param slow If TRUE, use a 10x slower but more precise implementation (default FALSE) #' @return IterableMatrix +#' @examples +#' set.seed(12345) +#' mat <- matrix(rpois(1000 * 100, lambda = 0.5), nrow = 1000, ncol = 100) +#' rownames(mat) <- paste0("gene", 1:1000) +#' colnames(mat) <- paste0("cell", 1:100) +#' mat <- as(mat, "dgCMatrix") %>% as("IterableMatrix") +#' +#' # Calculate dummy parameters +#' gene_theta <- runif(1000, 0.1, 10) +#' gene_beta <- runif(1000, 0.1, 10) +#' cell_read_counts <- runif(100, 1000, 10000) +#' +#' res <- sctransform_pearson(mat, gene_theta, gene_beta, cell_read_counts) +#' #' @export sctransform_pearson <- function(mat, gene_theta, gene_beta, cell_read_counts, min_var = -Inf, clip_range = c(-10, 10), columns_are_cells=TRUE, slow=FALSE) { assert_is(mat, "IterableMatrix") @@ -1062,6 +1087,21 @@ setMethod("short_description", "TransformLinearResidual", function(x) { #' (e.g. the gene axis in typical single cell analysis). Options include "row" (default) and "col". #' #' @return IterableMatrix +#' @examples +#' set.seed(12345) +#' mat <- matrix(rnorm(1000 * 100), nrow = 1000, ncol = 100) +#' rownames(mat) <- paste0("gene", 1:1000) +#' colnames(mat) <- paste0("cell", 1:100) +#' mat <- as(mat, "dgCMatrix") %>% as("IterableMatrix") +#' +#' latent_data <- data.frame( +#' batch = sample(c("A", "B"), 100, replace = TRUE), +#' age = rnorm(100, mean = 30, sd = 10) +#' ) +#' +#' # Regress out batch and age +#' res <- regress_out(mat, latent_data, prediction_axis = "row") +#' #' @export regress_out <- function(mat, latent_data, prediction_axis = c("row", "col")) { prediction_axis <- match.arg(prediction_axis) diff --git a/r/man/IterableMatrix-matrixgenerics.Rd b/r/man/IterableMatrix-matrixgenerics.Rd index b214dc1b..ccb3bf94 100644 --- a/r/man/IterableMatrix-matrixgenerics.Rd +++ b/r/man/IterableMatrix-matrixgenerics.Rd @@ -4,7 +4,16 @@ \name{colVars.default} \alias{colVars.default} \alias{colVars.IterableMatrix} +\alias{rowVars.default} +\alias{rowVars.IterableMatrix} +\alias{rowMaxs.default} +\alias{rowMaxs.IterableMatrix} +\alias{colMaxs.default} \alias{colMaxs.IterableMatrix} +\alias{rowQuantiles.default} +\alias{rowQuantiles.IterableMatrix} +\alias{colQuantiles.default} +\alias{colQuantiles.IterableMatrix} \alias{IterableMatrix-matrixgenerics} \alias{rowQuantiles,IterableMatrix-method} \alias{colQuantiles,IterableMatrix-method} @@ -34,14 +43,122 @@ colVars.IterableMatrix( useNames = TRUE ) -\method{colMaxs}{IterableMatrix}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) +\method{rowVars}{default}( + x, + rows = NULL, + cols = NULL, + na.rm = FALSE, + center = NULL, + ..., + useNames = TRUE +) + +rowVars.IterableMatrix( + x, + rows = NULL, + cols = NULL, + na.rm = FALSE, + center = NULL, + ..., + useNames = TRUE +) + +\method{rowMaxs}{default}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) + +rowMaxs.IterableMatrix( + x, + rows = NULL, + cols = NULL, + na.rm = FALSE, + ..., + useNames = TRUE +) + +\method{colMaxs}{default}(x, rows = NULL, cols = NULL, na.rm = FALSE, ..., useNames = TRUE) + +colMaxs.IterableMatrix( + x, + rows = NULL, + cols = NULL, + na.rm = FALSE, + ..., + useNames = TRUE +) + +\method{rowQuantiles}{default}( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) + +rowQuantiles.IterableMatrix( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) + +\method{colQuantiles}{default}( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) + +colQuantiles.IterableMatrix( + x, + rows = NULL, + cols = NULL, + probs = seq(from = 0, to = 1, by = 0.25), + na.rm = FALSE, + type = 7L, + digits = 7L, + ..., + useNames = TRUE, + drop = TRUE +) } \arguments{ \item{x}{An \code{IterableMatrix}.} +\item{rows}{(Integer) Optional vector of row indices to operate over.} + +\item{cols}{(Integer) Optional vector of column indices to operate over.} + +\item{na.rm}{(Logical) Should missing values (NA) be removed?} + \item{center}{Optional center values (vector of length nrow(x) or ncol(x))} \item{...}{Passed to the underlying implementation.} + +\item{useNames}{(Logical) Whether to use row and column names in the output.} + +\item{probs}{(Numeric) Quantile value(s) to be computed, between 0 and 1.} + +\item{type}{(Integer) between 4 and 9 selecting which quantile algorithm to use, detailed in \code{matrixStats::rowQuantiles()}} + +\item{digits}{Number of decimal places for quantile calculations} + +\item{drop}{(Logical) If TRUE and only one quantile is requested, the result is coerced to a vector (For non-BPCells objects).} } \value{ \itemize{ @@ -51,6 +168,46 @@ colVars.IterableMatrix( \itemize{ \item \verb{colVars()}: vector of col variance } + +\itemize{ +\item \verb{rowVars()}: vector of row variance +} + +\itemize{ +\item \verb{rowVars()}: vector of row variance +} + +\itemize{ +\item \verb{rowMaxs()}: vector of row maxs +} + +\itemize{ +\item \verb{rowMaxs()}: vector of row maxs +} + +\itemize{ +\item \verb{colMaxs()}: vector of col maxs +} + +\itemize{ +\item \verb{colMaxs()}: vector of col maxs +} + +\itemize{ +\item \verb{rowQuantiles()}: If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of rows in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. +} + +\itemize{ +\item \verb{rowQuantiles()}: If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of rows in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a row in the input matrix. +} + +\itemize{ +\item \verb{colQuantiles()}: If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of columns in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. +} + +\itemize{ +\item \verb{colQuantiles()}: If \code{length(probs) == 1}, return a numeric with number of entries equal to the number of columns in the matrix. Else, return a Matrix of quantile values, with cols representing each quantile, and each row representing a col in the input matrix. +} } \description{ S4 methods enabling MatrixGenerics generics (e.g., \code{rowQuantiles}, @@ -64,6 +221,26 @@ when MatrixGenerics is available. \item \code{colVars.IterableMatrix()}: Calculate colVars (replacement for \code{matrixStats::colVars()}) +\item \code{rowVars(default)}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) + +\item \code{rowVars.IterableMatrix()}: Calculate rowVars (replacement for \code{matrixStats::rowVars()}) + +\item \code{rowMaxs(default)}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) + +\item \code{rowMaxs.IterableMatrix()}: Calculate rowMaxs (replacement for \code{matrixStats::rowMaxs()}) + +\item \code{colMaxs(default)}: Calculate colMaxs (replacement for \code{matrixStats::colMaxs()}) + +\item \code{colMaxs.IterableMatrix()}: Calculate colMaxs (replacement for \code{matrixStats::colMaxs()}) + +\item \code{rowQuantiles(default)}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) + +\item \code{rowQuantiles.IterableMatrix()}: Calculate rowQuantiles (replacement for \code{matrixStats::rowQuantiles}) + +\item \code{colQuantiles(default)}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) + +\item \code{colQuantiles.IterableMatrix()}: Calculate colQuantiles (replacement for \code{matrixStats::colQuantiles}) + }} \section{Availability}{ @@ -85,11 +262,70 @@ colVars(mat) ####################################################################### colVars(mat) +mat <- matrix(1:25, nrow = 5) \%>\% as("dgCMatrix") +mat +mat <- as(mat, "IterableMatrix") +####################################################################### +## rowVars() example +####################################################################### +rowVars(mat) + +####################################################################### +## rowVars() example +####################################################################### +rowVars(mat) + +mat <- matrix(1:25, nrow = 5) \%>\% as("dgCMatrix") +mat +mat <- as(mat, "IterableMatrix") +####################################################################### +## rowMaxs() example +####################################################################### +rowMaxs(mat) + +####################################################################### +## rowMaxs() example +####################################################################### +rowMaxs(mat) + +mat <- matrix(1:25, nrow = 5) \%>\% as("dgCMatrix") +mat +mat <- as(mat, "IterableMatrix") +####################################################################### +## colMaxs() example +####################################################################### +colMaxs(mat) + ####################################################################### -## colMaxs() example +## colMaxs() example ####################################################################### colMaxs(mat) +mat <- matrix(1:25, nrow = 5) \%>\% as("dgCMatrix") +mat +mat <- as(mat, "IterableMatrix") +####################################################################### +## rowQuantiles() example +####################################################################### +rowQuantiles(transpose_storage_order(mat)) + +####################################################################### +## rowQuantiles() example +####################################################################### +rowQuantiles(transpose_storage_order(mat)) + +mat <- matrix(1:25, nrow = 5) \%>\% as("dgCMatrix") +mat +mat <- as(mat, "IterableMatrix") +####################################################################### +## colQuantiles() example +####################################################################### +colQuantiles(mat) + +####################################################################### +## colQuantiles() example +####################################################################### +colQuantiles(mat) } \seealso{ diff --git a/r/man/all_matrix_inputs.Rd b/r/man/all_matrix_inputs.Rd index 235f0cb1..a5110fc8 100644 --- a/r/man/all_matrix_inputs.Rd +++ b/r/man/all_matrix_inputs.Rd @@ -25,3 +25,13 @@ getter and setter functions allow accessing the base-level input matrices as a l changing them. This is useful if you want to re-locate data on disk without losing your transformed BPCells matrix. (Note: experimental API; potentially subject to revisions). } +\examples{ +mat <- matrix(1:9, nrow=3) \%>\% as("IterableMatrix") + +# Just returns the matrix itself +all_matrix_inputs(mat) + +# Returns the matrix twice, as they are the inputs to the cbind +all_matrix_inputs(cbind(mat, mat)) + +} diff --git a/r/man/binarize.Rd b/r/man/binarize.Rd index c162a8c8..26a3ee17 100644 --- a/r/man/binarize.Rd +++ b/r/man/binarize.Rd @@ -28,3 +28,15 @@ is set to FALSE, element values greater than or equal to the threshold are set to one. As an alternative, the \code{<}, \code{<=}, \code{>}, and \code{>=} operators are also supported. } +\examples{ +set.seed(12345) +mat <- matrix(rpois(40, lambda = 5), nrow = 4) +rownames(mat) <- paste0("gene", 1:4) +mat <- as(mat, "dgCMatrix") \%>\% as("IterableMatrix") + +####################################################################### +## binarize() example +####################################################################### +binarize(mat, threshold = 4) \%>\% as("dgCMatrix") + +} diff --git a/r/man/call_macs_peaks.Rd b/r/man/call_macs_peaks.Rd index 5ad425c5..4cc3dace 100644 --- a/r/man/call_macs_peaks.Rd +++ b/r/man/call_macs_peaks.Rd @@ -11,4 +11,7 @@ call_macs_peaks(...) This function has been renamed to \code{call_peaks_macs()} } +\examples{ +# See ?call_peaks_macs for examples +} \keyword{internal} diff --git a/r/man/cluster_cells_graph.Rd b/r/man/cluster_cells_graph.Rd index 0aaaa807..3c203467 100644 --- a/r/man/cluster_cells_graph.Rd +++ b/r/man/cluster_cells_graph.Rd @@ -72,6 +72,13 @@ For cells \code{i} and \code{j}, their similarity score is in \code{adjacency_ma \strong{cluster_graph_method}: First argument is a weighted similarity graph as returned by \code{knn_to_graph_method}. Returns a factor vector of length \code{cells} with a cluster assignment for each cell. +} +\examples{ +set.seed(123) +mat <- matrix(rnorm(1000 * 10), nrow = 1000) +clusters <- cluster_cells_graph(mat, threads = 1) +table(clusters) + } \seealso{ \code{knn_hnsw()} \code{knn_annoy()} \code{knn_to_graph()} \code{knn_to_snn_graph()} \code{knn_to_geodesic_graph()} \code{cluster_graph_leiden()} \code{cluster_graph_louvain()} \code{cluster_graph_seurat()} diff --git a/r/man/cluster_graph.Rd b/r/man/cluster_graph.Rd index 0794ca6c..989b8bd7 100644 --- a/r/man/cluster_graph.Rd +++ b/r/man/cluster_graph.Rd @@ -46,3 +46,25 @@ good default when \code{objective_function = "modularity"} per the default. \strong{cluster_graph_seurat}: Seurat's clustering algorithm \code{Seurat::FindClusters()} } +\examples{ +set.seed(123) +mat <- matrix(rnorm(1000 * 10), nrow = 1000) +knn <- knn_hnsw(mat, k = 10) +graph <- knn_to_snn_graph(knn) +clusters <- cluster_graph_leiden(graph, resolution = 0.5) + +set.seed(123) +mat <- matrix(rnorm(1000 * 10), nrow = 1000) +knn <- knn_hnsw(mat, k = 10) +graph <- knn_to_snn_graph(knn) +clusters <- cluster_graph_louvain(graph, resolution = 0.5) + +\dontrun{ +set.seed(123) +mat <- matrix(rnorm(1000 * 10), nrow = 1000) +knn <- knn_hnsw(mat, k = 10) +graph <- knn_to_snn_graph(knn) +clusters <- cluster_graph_seurat(graph, resolution = 0.5) +} + +} diff --git a/r/man/draw_trackplot_grid.Rd b/r/man/draw_trackplot_grid.Rd index 216649a6..4e9fc7d0 100644 --- a/r/man/draw_trackplot_grid.Rd +++ b/r/man/draw_trackplot_grid.Rd @@ -40,4 +40,7 @@ by heights. A shared title and x-axis are put at the top. This function has been renamed to \code{trackplot_combine()}. } +\examples{ +# See ?trackplot_combine for examples +} \keyword{internal} diff --git a/r/man/import_matrix_market.Rd b/r/man/import_matrix_market.Rd index 5b181651..c69536a6 100644 --- a/r/man/import_matrix_market.Rd +++ b/r/man/import_matrix_market.Rd @@ -68,3 +68,31 @@ files will be slower to import due to gzip decompression. When importing from 10x mtx files, the row and column names can be read automatically using the \code{import_matrix_market_10x()} convenience function. } +\examples{ +# Create a dummy matrix market file +matrix_market_path <- file.path(tempdir(), "matrix.mtx") +lines <- c( + "\%\%MatrixMarket matrix coordinate integer general", + "\% This is a comment", + "5 10 3", + "1 1 1", + "2 2 2", + "5 10 3" +) +writeLines(lines, matrix_market_path) + +# Import the matrix market file +mat <- import_matrix_market(matrix_market_path) +mat + +# Clean up +unlink(matrix_market_path) + +\dontrun{ +# Import 10x matrix market directory +mat <- import_matrix_market_10x( + "path/to/10x/matrix_market_dir" +) +} + +} diff --git a/r/man/knn.Rd b/r/man/knn.Rd index 07d97a07..4f655fba 100644 --- a/r/man/knn.Rd +++ b/r/man/knn.Rd @@ -68,3 +68,22 @@ utilizing both data and query. \strong{knn_annoy}: Use RcppAnnoy as knn engine } +\examples{ +############################################ +## knn_annoy() example +############################################ +set.seed(123) +mat <- matrix(rnorm(100 * 10), nrow = 10) +rownames(mat) <- paste0("cell", 1:10) +knn <- knn_hnsw(mat, k = 10) +knn + +############################################ +## knn_annoy() example +############################################ +set.seed(123) +mat <- matrix(rnorm(100 * 10), nrow = 10) +rownames(mat) <- paste0("cell", 1:10) +knn <- knn_annoy(mat, k = 10) +knn +} diff --git a/r/man/knn_graph.Rd b/r/man/knn_graph.Rd index 5d365c41..b7a3f0e6 100644 --- a/r/man/knn_graph.Rd +++ b/r/man/knn_graph.Rd @@ -84,3 +84,15 @@ less memory and return a sparser graph than \code{knn_to_snn_graph} which comput neighbor, results may differ slightly from \code{umap._umap.fuzzy_simplicial_set}, which assumes self is always successfully found in the approximate nearest neighbor search. } +\examples{ +set.seed(123) +mat <- matrix(rnorm(1000 * 10), nrow = 1000) +knn <- knn_hnsw(mat, k = 10) +graph <- knn_to_snn_graph(knn) + +set.seed(123) +mat <- matrix(rnorm(1000 * 10), nrow = 1000) +knn <- knn_hnsw(mat, k = 10) +graph <- knn_to_geodesic_graph(knn) + +} diff --git a/r/man/plot_tf_footprint.Rd b/r/man/plot_tf_footprint.Rd index d8b1b463..01d51fc8 100644 --- a/r/man/plot_tf_footprint.Rd +++ b/r/man/plot_tf_footprint.Rd @@ -10,7 +10,7 @@ plot_tf_footprint( cell_groups = rlang::rep_along(cellNames(fragments), "all"), flank = 250L, smooth = 0L, - zero_based_coords = !is(genes, "GRanges"), + zero_based_coords = !is(motif_positions, "GRanges"), colors = discrete_palette("stallion"), return_data = FALSE, apply_styling = TRUE @@ -42,6 +42,20 @@ If false, coordinates start at 1 and the end coordinate is included in the range \description{ Plot the footprinting around TF motif sites } +\examples{ +\dontrun{ + +plot_tf_footprint( + frags, + motif_positions$CEBPA, + cell_groups = cell_types, + flank = 250, + smooth = 2 +) + + ggplot2::labs(title="CEBPA") +} +# See example in vignette Getting Started +} \seealso{ \code{footprint()}, \code{plot_tss_profile()} } diff --git a/r/man/regress_out.Rd b/r/man/regress_out.Rd index 8d8e7148..b2a8422c 100644 --- a/r/man/regress_out.Rd +++ b/r/man/regress_out.Rd @@ -40,3 +40,19 @@ Generally, \code{n_features == ncol(latent_data)}, but for categorical variables category will be expanded into its own indicator variable. Memory usage will therefore be higher when using categorical input variables with many (i.e. >100) distinct values. } +\examples{ +set.seed(12345) +mat <- matrix(rnorm(1000 * 100), nrow = 1000, ncol = 100) +rownames(mat) <- paste0("gene", 1:1000) +colnames(mat) <- paste0("cell", 1:100) +mat <- as(mat, "dgCMatrix") \%>\% as("IterableMatrix") + +latent_data <- data.frame( + batch = sample(c("A", "B"), 100, replace = TRUE), + age = rnorm(100, mean = 30, sd = 10) +) + +# Regress out batch and age +res <- regress_out(mat, latent_data, prediction_axis = "row") + +} diff --git a/r/man/sctransform_pearson.Rd b/r/man/sctransform_pearson.Rd index 093bcd78..c300aab6 100644 --- a/r/man/sctransform_pearson.Rd +++ b/r/man/sctransform_pearson.Rd @@ -47,3 +47,18 @@ log-scale to represent the cell_read_counts and gene_beta variables. It also does not support the addition of arbitrary cell metadata (e.g. batch) to add to the negative binomial regression. } +\examples{ +set.seed(12345) +mat <- matrix(rpois(1000 * 100, lambda = 0.5), nrow = 1000, ncol = 100) +rownames(mat) <- paste0("gene", 1:1000) +colnames(mat) <- paste0("cell", 1:100) +mat <- as(mat, "dgCMatrix") \%>\% as("IterableMatrix") + +# Calculate dummy parameters +gene_theta <- runif(1000, 0.1, 10) +gene_beta <- runif(1000, 0.1, 10) +cell_read_counts <- runif(100, 1000, 10000) + +res <- sctransform_pearson(mat, gene_theta, gene_beta, cell_read_counts) + +} diff --git a/r/man/trackplot_bulk.Rd b/r/man/trackplot_bulk.Rd index 67cd3497..e69ef606 100644 --- a/r/man/trackplot_bulk.Rd +++ b/r/man/trackplot_bulk.Rd @@ -67,4 +67,7 @@ This function has been renamed to \code{trackplot_coverage()} Plot a pseudobulk genome track, showing the number of fragment insertions across a region. } +\examples{ +# See ?trackplot_coverage for examples +} \keyword{internal} diff --git a/r/man/trackplot_utils.Rd b/r/man/trackplot_utils.Rd index 5a4cb1c7..66bf4351 100644 --- a/r/man/trackplot_utils.Rd +++ b/r/man/trackplot_utils.Rd @@ -31,3 +31,11 @@ get_trackplot_height(plot) Adjust labels and heights on trackplots. Labels are set as facet labels in ggplot2, and heights are additional properties read by \code{trackplot_combine()} to determine relative height of input plots. } +\examples{ +region <- "chr4:3034877-3044877" +plot <- trackplot_scalebar(region) +plot_labeled <- set_trackplot_label(plot, "Scalebar") + +plot_height_set <- set_trackplot_height(plot, 2) +get_trackplot_height(plot_height_set) +} From 1397c1549df3d739ce51a97275db13a977256b06 Mon Sep 17 00:00:00 2001 From: Immanuel Abdi Date: Sun, 11 Jan 2026 11:48:00 -0800 Subject: [PATCH 82/84] [r] update old gene scores example --- r/man/gene_score_tiles_archr.Rd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/r/man/gene_score_tiles_archr.Rd b/r/man/gene_score_tiles_archr.Rd index d0a31eb2..2f36e14f 100644 --- a/r/man/gene_score_tiles_archr.Rd +++ b/r/man/gene_score_tiles_archr.Rd @@ -61,7 +61,9 @@ genes <- read_gencode_genes( ## Use pre-generated data for this example ## Use pre-computed transcripts for chr4 genes <- readr::read_delim( - file.path(system.file("extdata", package = "BPCells"), "transcripts_filtered_example_chr_4.tsv.gz"), + file.path( + system.file("extdata", package = "BPCells"), + "transcripts_filtered_example_chr_4.tsv.gz"), delim = "\t", show_col_types = FALSE ) From f991ef9ae374356346b2059dd5b270a38a57e93b Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 12 Jan 2026 20:10:01 -0800 Subject: [PATCH 83/84] [r] shorten write_insertion_bed() example runtime --- r/R/atac_utils.R | 20 +++++++++++++++++++- r/man/reexports.Rd | 2 +- r/man/write_insertion_bedgraph.Rd | 20 +++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index 741bf24a..11a9b34c 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -626,7 +626,7 @@ write_insertion_bedgraph <- function( #' ###################################################### #' ## `write_insertion_bed()` examples #' ###################################################### -#' +#' \dontrun{ #' # We utilize two groups this time #' bed_outputs <- file.path(tempdir(), "bed_outputs") #' cell_groups <- rep(c("A", "B"), length.out = length(cellNames(frags))) @@ -636,11 +636,29 @@ write_insertion_bedgraph <- function( #' frags, path = bed_paths, cell_groups = cell_groups, #' verbose = TRUE #' ) +#' #> 2026-01-08 21:19:41 Writing bed file for cluster: A +#' #> 2026-01-08 21:19:41 Bed file for cluster: A written to: +#' #> /tmp/RtmpgF9rbP/bed_outputs/A.bed +#' #> 2026-01-08 21:19:41 Writing bed file for cluster: B +#' #> 2026-01-08 21:19:42 Bed file for cluster: B written to: +#' #> /tmp/RtmpgF9rbP/bed_outputs/B.bed +#' #> 2026-01-08 21:19:42 Finished writing bed files #' list.files(bed_outputs) +#' #> [1] "A.bed" "B.bed" #' head(readr::read_tsv( #' file.path(bed_outputs, "A.bed"), #' col_names = c("chr", "start", "end"), show_col_types = FALSE) #' ) +#' #> # A tibble: 6 × 3 +#' #> chr start end +#' #> +#' #> 1 chr4 10035 10036 +#' #> 2 chr4 10045 10046 +#' #> 3 chr4 10045 10046 +#' #> 4 chr4 10046 10047 +#' #> 5 chr4 10046 10047 +#' #> 6 chr4 10066 10067 +#' } #' @export write_insertion_bed <- function(fragments, path, cell_groups = rlang::rep_along(cellNames(fragments), "all"), diff --git a/r/man/reexports.Rd b/r/man/reexports.Rd index e4ac817a..5d4c340d 100644 --- a/r/man/reexports.Rd +++ b/r/man/reexports.Rd @@ -17,6 +17,6 @@ below to see their documentation. \describe{ \item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}} - \item{Matrix}{\code{\link[Matrix:colSums]{colMeans}}, \code{\link[Matrix]{colSums}}, \code{\link[Matrix:colSums]{rowMeans}}, \code{\link[Matrix:colSums]{rowSums}}} + \item{Matrix}{\code{\link[Matrix:colSums-methods]{colMeans}}, \code{\link[Matrix:colSums-methods]{colSums}}, \code{\link[Matrix:colSums-methods]{rowMeans}}, \code{\link[Matrix:colSums-methods]{rowSums}}} }} diff --git a/r/man/write_insertion_bedgraph.Rd b/r/man/write_insertion_bedgraph.Rd index ee821c39..6c2b2379 100644 --- a/r/man/write_insertion_bedgraph.Rd +++ b/r/man/write_insertion_bedgraph.Rd @@ -98,7 +98,7 @@ head(reads) ###################################################### ## `write_insertion_bed()` examples ###################################################### - +\dontrun{ # We utilize two groups this time bed_outputs <- file.path(tempdir(), "bed_outputs") cell_groups <- rep(c("A", "B"), length.out = length(cellNames(frags))) @@ -108,9 +108,27 @@ write_insertion_bed( frags, path = bed_paths, cell_groups = cell_groups, verbose = TRUE ) +#> 2026-01-08 21:19:41 Writing bed file for cluster: A +#> 2026-01-08 21:19:41 Bed file for cluster: A written to: +#> /tmp/RtmpgF9rbP/bed_outputs/A.bed +#> 2026-01-08 21:19:41 Writing bed file for cluster: B +#> 2026-01-08 21:19:42 Bed file for cluster: B written to: +#> /tmp/RtmpgF9rbP/bed_outputs/B.bed +#> 2026-01-08 21:19:42 Finished writing bed files list.files(bed_outputs) +#> [1] "A.bed" "B.bed" head(readr::read_tsv( file.path(bed_outputs, "A.bed"), col_names = c("chr", "start", "end"), show_col_types = FALSE) ) +#> # A tibble: 6 × 3 +#> chr start end +#> +#> 1 chr4 10035 10036 +#> 2 chr4 10045 10046 +#> 3 chr4 10045 10046 +#> 4 chr4 10046 10047 +#> 5 chr4 10046 10047 +#> 6 chr4 10066 10067 +} } From daccc81d867ddf4bbda5b99a29f1bea6cfb4d983 Mon Sep 17 00:00:00 2001 From: immanuelazn Date: Mon, 12 Jan 2026 23:57:26 -0800 Subject: [PATCH 84/84] [r] remove demo frag retrieval in write_insertion_bedgraph() example --- r/R/atac_utils.R | 3 +-- r/man/write_insertion_bedgraph.Rd | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/r/R/atac_utils.R b/r/R/atac_utils.R index 11a9b34c..fc2d0bb7 100644 --- a/r/R/atac_utils.R +++ b/r/R/atac_utils.R @@ -525,7 +525,7 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' If a data.frame or list, must contain columns `chr` and `end` (See `help("genomic-ranges-like")`). #' If a numeric vector, then it is assumed to be the chromosome sizes in the order of `chrNames(fragments)`. #' @examples -#' +#' \dontrun{ #' ## Prep data #' frags <- get_demo_frags() #' bedgraph_outputs <- file.path(tempdir(), "bedgraph_outputs") @@ -534,7 +534,6 @@ call_peaks_tile <- function(fragments, chromosome_sizes, cell_groups = rep.int(" #' ## `write_insertion_bedgraph()` examples #' ###################################################### #' ## Write insertions -#' \dontrun{ #' write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all.tar.gz")) #' list.files(bedgraph_outputs) #' diff --git a/r/man/write_insertion_bedgraph.Rd b/r/man/write_insertion_bedgraph.Rd index 6c2b2379..38b5e96a 100644 --- a/r/man/write_insertion_bedgraph.Rd +++ b/r/man/write_insertion_bedgraph.Rd @@ -63,7 +63,7 @@ Beds only hold chrom, start, and end data, while bedGraphs also provide a score This reports the total number of insertions at each basepair for each group listed in \code{cell_groups}. } \examples{ - +\dontrun{ ## Prep data frags <- get_demo_frags() bedgraph_outputs <- file.path(tempdir(), "bedgraph_outputs") @@ -72,7 +72,6 @@ bedgraph_outputs <- file.path(tempdir(), "bedgraph_outputs") ## `write_insertion_bedgraph()` examples ###################################################### ## Write insertions -\dontrun{ write_insertion_bedgraph(frags, file.path(bedgraph_outputs, "all.tar.gz")) list.files(bedgraph_outputs)