diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..1803601 Binary files /dev/null and b/.DS_Store differ diff --git a/.Rbuildignore b/.Rbuildignore index 2a2cb83..299d7be 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,2 +1,5 @@ ^LICENSE\.md$ ^README\.Rmd$ +^.*\.Rproj$ +^\.Rproj\.user$ +^\.github$ diff --git a/.github/.gitignore b/.github/.gitignore new file mode 100644 index 0000000..2d19fc7 --- /dev/null +++ b/.github/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml new file mode 100644 index 0000000..05d4791 --- /dev/null +++ b/.github/workflows/R-CMD-check.yaml @@ -0,0 +1,53 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: R-CMD-check.yaml + +permissions: read-all + +jobs: + R-CMD-check: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + + strategy: + fail-fast: false + matrix: + config: + - {os: macos-latest, r: 'release'} + - {os: windows-latest, r: 'release'} + - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-latest, r: 'release'} + - {os: ubuntu-latest, r: 'oldrel-1'} + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::rcmdcheck + needs: check + + - uses: r-lib/actions/check-r-package@v2 + with: + upload-snapshots: true + build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' + diff --git a/DESCRIPTION b/DESCRIPTION index 1d485fe..48a6b33 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -11,7 +11,10 @@ Description: Implementation of univariate total variation denoising (aka License: MIT + file LICENSE Imports: Rcpp (>= 1.0.10) +Suggests: + testthat (>= 3.0.0) LinkingTo: Rcpp +Config/testthat/edition: 3 Encoding: UTF-8 RoxygenNote: 7.3.2 diff --git a/README.Rmd b/README.Rmd index f492d4e..0706b09 100644 --- a/README.Rmd +++ b/README.Rmd @@ -16,6 +16,7 @@ knitr::opts_chunk$set( # tvdenoising +[![R-CMD-check](https://github.com/glmgen/tvdenoising/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/glmgen/tvdenoising/actions/workflows/R-CMD-check.yaml) This package provides an `R` frontend to a `C` implementation of linear-time diff --git a/README.md b/README.md index f8f451e..cb7813b 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,11 @@ # tvdenoising +[![R-CMD-check](https://github.com/glmgen/tvdenoising/actions/workflows/R-CMD-check.yaml/badge.svg?branch=xli-branch)](https://github.com/glmgen/tvdenoising/actions/workflows/R-CMD-check.yaml?branch=xli-branch) + + This package provides an `R` frontend to a `C` implementation of linear-time univariate total variation denoising via dynamic programming (Johnson 2013). diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 6ed3581..622f106 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -1,6 +1,7 @@ // Generated by using Rcpp::compileAttributes() -> do not edit by hand // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 +#include "../inst/include/tvdenoising.h" #include #include #include diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 0000000..5d437f8 --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,15 @@ +# tests/testthat.R +# This file is part of the standard setup for testthat. +# It is recommended that you do not modify it. +# +# Where should you do additional test configuration? +# Learn more about the roles of various files in: +# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview +# * https://testthat.r-lib.org/articles/special-files.html + +library(testthat) +library(tvdenoising) + +test_check("tvdenoising") + + diff --git a/tests/testthat/_snaps/tvdenoising.md b/tests/testthat/_snaps/tvdenoising.md new file mode 100644 index 0000000..931eefc --- /dev/null +++ b/tests/testthat/_snaps/tvdenoising.md @@ -0,0 +1,16 @@ +# tvdenoising handles incorrect input properly + + Code + tvdenoising(y, lambda) + Condition + Error in `tvdenoising()`: + ! is.numeric(lambda) & (length(lambda) == 1) is not TRUE + +--- + + Code + tvdenoising(y, 1, weights) + Condition + Error in `tvdenoising()`: + ! length(weights) == length(y) is not TRUE + diff --git a/tests/testthat/test-tvdenoising.R b/tests/testthat/test-tvdenoising.R new file mode 100644 index 0000000..e7a9ba1 --- /dev/null +++ b/tests/testthat/test-tvdenoising.R @@ -0,0 +1,59 @@ +# tests/testthat/test-tvdenoising.R + +test_that("tvdenoising works correctly with no weights", { + y <- c(1, 2, 3, 5, 8, 13, 21) + lambda <- 1 + result <- tvdenoising(y, lambda) + expected_result <- c(2, 2, 3, 5, 8, 13, 20) + expect_type(result, "double") + expect_length(result, length(y)) + expect_equal(result, expected_result, tolerance = 1e-6) +}) + + +test_that("tvdenoising works correctly with weights", { + y <- c(1, 2, 3, 5, 8, 13, 21) + lambda <- 1 + + weights <- c(1, 3, 3, 2, 5, 6, 2) + result <- tvdenoising(y, lambda, weights) + expect_type(result, "double") + expect_length(result, length(y)) + expected_result <- c(2,2,3,5,8,13,20.5) + expect_equal(result, expected_result, tolerance = 1e-6) +}) + + +test_that("tvdenoising with uniform weights 1 matches unweighted version", { + y <- c(1, 2, 3, 5, 8, 13, 21) + lambda <- 1 + uniform_weights1 <- rep(1, length(y)) + result_no_weights <- tvdenoising(y, lambda) + result_with_weights1 <- tvdenoising(y, lambda, uniform_weights1) + expect_equal(result_no_weights, result_with_weights1, tolerance = 1e-6) +}) + +test_that("tvdenoising with uniform weights 2", { + y <- c(1, 2, 3, 5, 8, 13, 21) + lambda <- 1 + uniform_weights2 <- rep(2, length(y)) + expected_result <- c(1.5, 2, 3, 5, 8, 13, 20.5) + result_with_weights2 <- tvdenoising(y, lambda, uniform_weights2) + expect_equal(expected_result, result_with_weights2, tolerance = 1e-6) +}) + + + +test_that("tvdenoising handles incorrect input properly", { + y <- c(1, 2, 3, 5, 8, 13, 21) + lambda <- "not a number" + + # when lambda is not numeric + expect_snapshot(error = TRUE, tvdenoising(y, lambda)) + + # when weights length does not match y + weights <- c(1, 2) + expect_snapshot(error = TRUE, tvdenoising(y, 1, weights)) +}) + + diff --git a/tvdenoising.Rproj b/tvdenoising.Rproj new file mode 100644 index 0000000..21a4da0 --- /dev/null +++ b/tvdenoising.Rproj @@ -0,0 +1,17 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source