Skip to content

Commit

Permalink
Checks, fixes, tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jayhesselberth committed Dec 22, 2024
1 parent 6865ced commit 1928ba1
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 37 deletions.
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
^_pkgdown\.yml$
^docs$
^pkgdown$
^LICENSE\.md$
^README\.Rmd$
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Type: Package
Package: cpp11bigwig
Title: Read bigWig Files.
Title: Read-only access to bigWig Files
Version: 0.1.0
Authors@R:
person("Jay", "Hesselberth", , "jay.hesselberth@gmail.com", role = c("aut", "cre"))
Description: cpp11bigwig wraps libBigWig by @dpryan79.
License: MIT
License: MIT + file LICENSE
URL: https://rnabioco.github.io/cpp11bigwig/,
https://github.com/rnabioco/cpp11bigwig
Suggests:
Expand Down
2 changes: 2 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
YEAR: 2024
COPYRIGHT HOLDER: cpp11bigwig authors
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# MIT License

Copyright (c) 2024 cpp11bigwig authors

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.
4 changes: 2 additions & 2 deletions R/cpp11.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Generated by cpp11: do not edit by hand

read_bigwig_impl <- function(bwfname, chrom, start, end) {
.Call(`_cpp11bigwig_read_bigwig_impl`, bwfname, chrom, start, end)
read_bigwig_cpp <- function(bwfname, chrom, start, end, raw) {
.Call(`_cpp11bigwig_read_bigwig_cpp`, bwfname, chrom, start, end, raw)
}
11 changes: 6 additions & 5 deletions R/read_bigwig.r
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#' @param chrom read data for specific chromosome
#' @param start start position for data
#' @param end end position for data
#' @param raw return raw data, single-base intervals
#'
#' @return \code{data.frame}
#'
Expand All @@ -15,15 +16,15 @@
#' read_bigwig(bw)
#'
#' @export
read_bigwig <- function(bwfile, chrom = "", start = -1, end = -1) {
read_bigwig <- function(bwfile, chrom = NULL, start = NULL, end = NULL, raw = FALSE) {

if (!file.exists(bwfile)) {
stop("File does not exist: ", bwfile)
}

# if ((!is.null(start) && start < 0) || (!is.null(end) && end < 0)) {
# stop("`start` and `end` must both be >= 0")
# }
if ((!is.null(start) && start < 0) || (!is.null(end) && end < 0)) {
stop("`start` and `end` must both be >= 0")
}

read_bigwig_impl(bwfile, chrom, start, end)
read_bigwig_cpp(bwfile, chrom, start, end, raw)
}
4 changes: 3 additions & 1 deletion man/read_bigwig.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions src/cpp11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
#include <R_ext/Visibility.h>

// cpp11bigwig.cpp
writable::data_frame read_bigwig_impl(std::string bwfname, std::string chrom, int start, int end);
extern "C" SEXP _cpp11bigwig_read_bigwig_impl(SEXP bwfname, SEXP chrom, SEXP start, SEXP end) {
writable::data_frame read_bigwig_cpp(std::string bwfname, sexp chrom, sexp start, sexp end, sexp raw);
extern "C" SEXP _cpp11bigwig_read_bigwig_cpp(SEXP bwfname, SEXP chrom, SEXP start, SEXP end, SEXP raw) {
BEGIN_CPP11
return cpp11::as_sexp(read_bigwig_impl(cpp11::as_cpp<cpp11::decay_t<std::string>>(bwfname), cpp11::as_cpp<cpp11::decay_t<std::string>>(chrom), cpp11::as_cpp<cpp11::decay_t<int>>(start), cpp11::as_cpp<cpp11::decay_t<int>>(end)));
return cpp11::as_sexp(read_bigwig_cpp(cpp11::as_cpp<cpp11::decay_t<std::string>>(bwfname), cpp11::as_cpp<cpp11::decay_t<sexp>>(chrom), cpp11::as_cpp<cpp11::decay_t<sexp>>(start), cpp11::as_cpp<cpp11::decay_t<sexp>>(end), cpp11::as_cpp<cpp11::decay_t<sexp>>(raw)));
END_CPP11
}

extern "C" {
static const R_CallMethodDef CallEntries[] = {
{"_cpp11bigwig_read_bigwig_impl", (DL_FUNC) &_cpp11bigwig_read_bigwig_impl, 4},
{"_cpp11bigwig_read_bigwig_cpp", (DL_FUNC) &_cpp11bigwig_read_bigwig_cpp, 5},
{NULL, NULL, 0}
};
}
Expand Down
40 changes: 24 additions & 16 deletions src/cpp11bigwig.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#include <cpp11.hpp>
#include <cpp11/data_frame.hpp>

using namespace cpp11;

#include "bigWig.h"

[[cpp11::register]]
writable::data_frame read_bigwig_impl(std::string bwfname, std::string chrom, int start, int end) {
writable::data_frame read_bigwig_cpp(std::string bwfname, sexp chrom, sexp start, sexp end, sexp raw) {

//http://stackoverflow.com/questions/347949/how-to-convert-a-stdstring-to-const-char-or-char
std::vector<char> bwfile(bwfname.begin(), bwfname.end()) ;
Expand All @@ -14,11 +15,12 @@ writable::data_frame read_bigwig_impl(std::string bwfname, std::string chrom, in
const char mode = 'r' ;

bigWigFile_t *bwf = NULL;
// XXX change NULL to a CURL callback. see libBigWig demos

// NULL can be a CURL callback. see libBigWig demos
bwf = bwOpen(&bwfile[0], NULL, &mode) ;

if (!bwf)
stop("Failed to open file: %s\n", bwfname.c_str()) ;
stop("Failed to open file: '%s'\n", bwfname.c_str()) ;

std::vector<std::string> chroms ;
std::vector<int> starts ;
Expand All @@ -30,19 +32,22 @@ writable::data_frame read_bigwig_impl(std::string bwfname, std::string chrom, in
int nchrom = bwf->cl->nKeys ;
for (int nc = 0; nc<nchrom; ++nc) {

char* cur_chrom = bwf->cl->chrom[nc] ;
std::string cur_chrom_c = cur_chrom ;
char* bw_chrom = bwf->cl->chrom[nc] ;
std::string bw_chrom_c(bw_chrom) ;

if (!chrom.empty() && chrom != cur_chrom_c) continue ;
if (!Rf_isNull(chrom)) {
std::string r_chrom = as_cpp<std::string>(chrom) ;
if (r_chrom != bw_chrom_c) continue ;
}

// set maximum boundaries if start / end are not specified
if (start == -1) start = 0 ;
if (end == -1) end = bwf->cl->len[nc];
int bw_start = Rf_isNull(start) ? 0 : as_cpp<int>(start) ;
int bw_end = Rf_isNull(end) ? bwf->cl->len[nc] : as_cpp<int>(end) ;

intervals = bwGetValues(bwf, cur_chrom, start, end, 0) ;
intervals = bwGetValues(bwf, bw_chrom, bw_start, bw_end, 0) ;

if (!intervals)
stop("Failed to retreived intervals for %s\n", chrom.c_str()) ;
stop("Failed to retreived intervals for %s\n", bw_chrom) ;

int nint = intervals->l ;
for(int i=0; i<nint; ++i) {
Expand All @@ -56,17 +61,20 @@ writable::data_frame read_bigwig_impl(std::string bwfname, std::string chrom, in
ends.push_back(end) ;
vals.push_back(val) ;

chroms.push_back(cur_chrom_c) ;
chroms.push_back(bw_chrom_c) ;
}

bwDestroyOverlappingIntervals(intervals) ;
}

bwClose(bwf) ;
bwCleanup() ;

return writable::data_frame({
"chrom"_nm = chroms,
"start"_nm = starts,
"end"_nm = ends,
"value"_nm = vals
}) ;
"chrom"_nm = chroms,
"start"_nm = starts,
"end"_nm = ends,
"value"_nm = vals
}) ;

}
16 changes: 16 additions & 0 deletions tests/testthat/_snaps/read.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# results have expected shape

Expected string vector of length 1

# missing file causes error

File does not exist: missing.bw

# negative coords causes error

`start` and `end` must both be >= 0

---

`start` and `end` must both be >= 0

40 changes: 33 additions & 7 deletions tests/testthat/test-read.R
Original file line number Diff line number Diff line change
@@ -1,15 +1,41 @@

test_that("output have expected shape", {
out <- read_bigwig(test_path("data/test.bw"))
expect_equal(ncol(out), 4)
expect_equal(nrow(out), 154)
test_that("results have expected shape", {
# -- raw output -------
bw <- test_path("data/test.bw")

res <- read_bigwig(bw)
expect_equal(ncol(res), 4)
expect_equal(nrow(res), 154)

# chrom
expect_equal(nrow(read_bigwig(bw, chrom = "1")), 54)
expect_equal(nrow(read_bigwig(bw, chrom = "10")), 100)

# `chrom` must be a string
expect_snapshot_error(read_bigwig(bw, chrom = 10))

# 0 rows, chrom doesn't exist
expect_equal(nrow(read_bigwig(bw, chrom = "100")), 0)

# start/end
expect_equal(nrow(read_bigwig(bw, chrom = "1", start = 1, end = 100)), 2)
expect_equal(nrow(read_bigwig(bw, chrom = "1", start = 100, end = 100)), 0)
expect_equal(nrow(read_bigwig(bw, chrom = "10", start = 100, end = 1000)), 100)
expect_equal(nrow(read_bigwig(bw, chrom = "10", start = 200, end = 250)), 50)

# values
res <- read_bigwig(bw, chrom = "10", start = 100, end = 1000)
expect_equal(length(unique(res$value)), 1)
expect_equal(unique(res$value), 2)

# -- bedgraph output -----
})

test_that("missing file causes error", {
expect_error(read_bigwig("missing.bw"))
expect_snapshot_error(read_bigwig("missing.bw"))
})

test_that("negative coords causes error", {
expect_error(read_bigwig(test_path("data/test.bw"), start = -1))
expect_error(read_bigwig(test_path("data/test.bw"), end = -1))
expect_snapshot_error(read_bigwig(test_path("data/test.bw"), start = -1))
expect_snapshot_error(read_bigwig(test_path("data/test.bw"), end = -1))
})

0 comments on commit 1928ba1

Please sign in to comment.