diff --git a/.Rbuildignore b/.Rbuildignore index d4fa14e..70b6e9d 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -10,7 +10,7 @@ inst/doc/(.+?).md inst/doc/(.+?).Rmd man/roxygen LICENSE\.md$ -README\.md$ +README\.(.?)$ CRAN\.md$ TODO\.md$ ^\.gitignore$ diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml deleted file mode 100644 index b91663a..0000000 --- a/.github/workflows/create-release.yml +++ /dev/null @@ -1,115 +0,0 @@ -# Workflow derived from https://github.com/r-lib/actions/tree/master/examples -# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help -on: - workflow_dispatch: - -name: create release - -env: - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - release_name: ${{ vars.repo_name }}_${{ github.ref_name }} - -jobs: - make_release: - runs-on: ubuntu-latest - outputs: - upload_url: ${{ steps.create_release.outputs.upload_url }} - steps: - - name: create release - id: create_release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: actions/create-release@v1 - with: - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} - draft: true - prerelease: false - - source_build: - needs: make_release - runs-on: ubuntu-latest - name: Build source tarball - strategy: - fail-fast: false - - steps: - - uses: actions/checkout@v3.1.0 - - - uses: r-lib/actions/setup-r@v2.3.1 - 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.3.1 - with: - extra-packages: | - any::pkgbuild - - - name: Build source tarball - run: | - R CMD build --force --no-manual --resave-data --compact-vignettes=both --md5 . - - - name: Look around - run: ls ${{ github.workspace }} - - - name: Upload Release Asset - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.make_release.outputs.upload_url }} - asset_path: ${{ github.workspace }}/${{ env.release_name }}.tar.gz - asset_name: ${{ env.release_name }}.tar.gz - asset_content_type: application/gzip - - binary_build: - needs: make_release - runs-on: ${{ matrix.config.os }} - - name: ${{ matrix.config.os }} (${{ matrix.config.r }}) - - strategy: - fail-fast: false - matrix: - config: - - {os: macOS-latest, r: 'release', ext: 'tgz', content_type: "gzip"} - - {os: windows-latest, r: 'release', ext: 'zip', content_type: "zip"} - - steps: - - uses: actions/checkout@v3.1.0 - - - uses: r-lib/actions/setup-r@v2.3.1 - 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.3.1 - with: - extra-packages: | - any::pkgbuild - - - name: Build binary - run: pkgbuild::build(binary=TRUE,manual=TRUE) - shell: Rscript {0} - - - name: Copying tarball - run: | - mkdir -p ${{ github.workspace }}/artifacts - cp ../${{ vars.repo_name }}_* ${{ github.workspace }}/artifacts - ls ${{ github.workspace }} - ls ${{ github.workspace }}/artifacts - - - name: Upload Release Asset - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.make_release.outputs.upload_url }} - asset_path: ${{ github.workspace }}/artifacts/${{ env.release_name }}.${{ matrix.config.ext }} - asset_name: ${{ env.release_name }}.${{ matrix.config.ext }} - asset_content_type: application/${{ matrix.config.content_type }} diff --git a/.github/workflows/r-cmd-check.yml b/.github/workflows/r-cmd-check.yml index fe31978..c4e0698 100644 --- a/.github/workflows/r-cmd-check.yml +++ b/.github/workflows/r-cmd-check.yml @@ -55,4 +55,4 @@ jobs: - uses: actions/upload-artifact@v3.1.1 with: name: ${{ matrix.config.os }}-${{ matrix.config.r }}-results - path: check/circumstance.Rcheck + path: check/${{ vars.repo_name }}.Rcheck diff --git a/DESCRIPTION b/DESCRIPTION index b162a91..a7750ea 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,15 +1,16 @@ Package: circumstance Type: Package Title: pomp parallelized -Version: 0.0.3.0 -Date: 2023-01-11 +Version: 0.0.4.0 +Date: 2023-01-24 Maintainer: Aaron A. King Description: Helper functions for parallelizing pomp computations. Authors@R: c(person(given=c("Aaron","A."),family="King", role=c("aut","cre"),email="kingaa@umich.edu")) URL: https://kingaa.github.io/circumstance/ -Depends: R(>= 4.1.0), methods, foreach, pomp(>= 4.5) -Suggests: doParallel, doRNG, tidyr, ggplot2 +Depends: R(>= 4.1.0), pomp(>= 4.6) +Imports: methods, foreach +Suggests: doFuture, doRNG, dplyr, tidyr, ggplot2 Remotes: kingaa/pomp License: GPL-3 LazyData: true @@ -19,5 +20,5 @@ Encoding: UTF-8 Roxygen: list(roclets = c("collate", "namespace", "rd")) RoxygenNote: 7.2.3 Collate: - 'circumstance-package.R' + 'package.R' 'pfilter.R' diff --git a/R/circumstance-package.R b/R/package.R similarity index 86% rename from R/circumstance-package.R rename to R/package.R index 61d7bac..e3152d9 100644 --- a/R/circumstance-package.R +++ b/R/package.R @@ -4,6 +4,8 @@ ##' \pkg{circumstance} provides tools for parallelizing certain \pkg{pomp} calculations. ##' ##' @name circumstance-package +##' @aliases circumstance,package +##' @docType package ##' @import methods ##' @importFrom utils globalVariables ##' diff --git a/R/pfilter.R b/R/pfilter.R index 2136e78..4182731 100644 --- a/R/pfilter.R +++ b/R/pfilter.R @@ -6,14 +6,14 @@ ##' @rdname pfilter ##' @importFrom pomp pfilter ##' @importFrom foreach foreach %dopar% -##' @include circumstance-package.R +##' @include package.R ##' -##' @param data passed to \code{pomp::\link[pomp]{pfilter}} +##' @param data passed to \code{\link[pomp:pfilter]{pomp::pfilter}} ##' @param Nrep number of replicate particle filter computations to run. ##' By default, \code{Nrep = 1}. -##' @param ... all additional arguments are passed to \code{pomp::\link[pomp]{pfilter}} +##' @param ... all additional arguments are passed to \code{\link[pomp:pfilter]{pomp::pfilter}} ##' -##' @seealso \code{pomp::\link[pomp]{pfilter}}. +##' @seealso \code{\link[pomp:pfilter]{pomp::pfilter}}. ##' ##' @example examples/pfilter.R ##' @@ -25,8 +25,6 @@ setGeneric( standardGeneric("pfilter") ) -##' @aliases pfilter -##' @aliases pfilter-ANY,numeric ##' @rdname pfilter ##' @export setMethod( @@ -41,7 +39,6 @@ setMethod( } ) -##' @aliases pfilter-ANY,missing ##' @rdname pfilter ##' @export setMethod( @@ -50,7 +47,6 @@ setMethod( definition = pomp::pfilter ) -##' @aliases pfilter-pompList,numeric ##' @rdname pfilter ##' @export setMethod( @@ -64,31 +60,19 @@ setMethod( rep <- (iter_i-1)%/%npo+1 pomp::pfilter(data[[ipo]],...) } -> res - if (is.null(names(data))) { - names(res) <- sprintf("%d_%d",seq_len(npo),rep(seq_len(Nrep),each=npo)) - } else { - names(res) <- sprintf("%s_%d",names(data),rep(seq_len(Nrep),each=npo)) - } + nm <- names(data) + if (is.null(nm)) nm <- seq_len(npo) + names(res) <- sprintf("%s_%d",nm,rep(seq_len(Nrep),each=npo)) res } ) -##' @aliases pfilter-pompList,missing ##' @rdname pfilter ##' @export setMethod( "pfilter", signature=signature(data = "pompList", Nrep = "missing"), definition = function (data, ...) { - jobs <- seq_len(length(data)) - foreach (iter_i=jobs,.combine=c) %dopar% { - pomp::pfilter(data[[iter_i]],...) - } -> res - if (is.null(names(data))) { - names(res) <- jobs - } else { - names(res) <- names(data) - } - res + circumstance::pfilter(data,Nrep=1L,...) } ) diff --git a/examples/pfilter.R b/examples/pfilter.R index d74ba99..c7271bb 100644 --- a/examples/pfilter.R +++ b/examples/pfilter.R @@ -1,4 +1,13 @@ library(circumstance) +library(doFuture) +library(doRNG) +registerDoFuture() +registerDoRNG() ou2() -> ou2 -ou2 |> pfilter(Np=1000,Nrep=6) -> pfs + +plan(sequential) +system.time(ou2 |> pfilter(Np=10000,Nrep=6) -> pfs) + +plan(multicore) +system.time(ou2 |> pfilter(Np=10000,Nrep=6) -> pfs) diff --git a/inst/NEWS b/inst/NEWS index 1f1a170..552def0 100644 --- a/inst/NEWS +++ b/inst/NEWS @@ -1,5 +1,17 @@ _N_e_w_s _f_o_r _p_a_c_k_a_g_e '_c_i_r_c_u_m_s_t_a_n_c_e' +_C_h_a_n_g_e_s _i_n '_c_i_r_c_u_m_s_t_a_n_c_e' _v_e_r_s_i_o_n _0._0._4: + + • Use with ‘doFuture’ is intended. + + • Streamline some of the definitions. + + • Improve coverage. + +_C_h_a_n_g_e_s _i_n '_c_i_r_c_u_m_s_t_a_n_c_e' _v_e_r_s_i_o_n _0._0._3: + + • Updates for new version of ‘pomp’. + _C_h_a_n_g_e_s _i_n '_c_i_r_c_u_m_s_t_a_n_c_e' _v_e_r_s_i_o_n _0._0._1: • Improved the parallel ‘pfilter’ facility. diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index 4e1aeae..2dd828e 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -1,5 +1,17 @@ \name{NEWS} \title{News for package `circumstance'} +\section{Changes in \pkg{circumstance} version 0.0.4}{ + \itemize{ + \item Use with \pkg{doFuture} is intended. + \item Streamline some of the definitions. + \item Improve coverage. + } +} +\section{Changes in \pkg{circumstance} version 0.0.3}{ + \itemize{ + \item Updates for new version of \pkg{pomp}. + } +} \section{Changes in \pkg{circumstance} version 0.0.1}{ \itemize{ \item Improved the parallel \code{pfilter} facility. diff --git a/man/circumstance-package.Rd b/man/circumstance-package.Rd index 6fa2a6d..d5088d5 100644 --- a/man/circumstance-package.Rd +++ b/man/circumstance-package.Rd @@ -1,7 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/circumstance-package.R +% Please edit documentation in R/package.R +\docType{package} \name{circumstance-package} \alias{circumstance-package} +\alias{circumstance,package} \title{circumstance package} \description{ \pkg{circumstance} provides tools for parallelizing certain \pkg{pomp} calculations. diff --git a/man/pfilter.Rd b/man/pfilter.Rd index 55ce48d..7613fca 100644 --- a/man/pfilter.Rd +++ b/man/pfilter.Rd @@ -3,13 +3,9 @@ \name{pfilter} \alias{pfilter} \alias{pfilter,ANY,numeric-method} -\alias{pfilter-ANY,numeric} \alias{pfilter,ANY,missing-method} -\alias{pfilter-ANY,missing} \alias{pfilter,pompList,numeric-method} -\alias{pfilter-pompList,numeric} \alias{pfilter,pompList,missing-method} -\alias{pfilter-pompList,missing} \title{Parallel particle filter computations} \usage{ \S4method{pfilter}{ANY,numeric}(data, Nrep, ...) @@ -21,22 +17,31 @@ \S4method{pfilter}{pompList,missing}(data, Nrep, ...) } \arguments{ -\item{data}{passed to \code{pomp::\link[pomp]{pfilter}}} +\item{data}{passed to \code{\link[pomp:pfilter]{pomp::pfilter}}} \item{Nrep}{number of replicate particle filter computations to run. By default, \code{Nrep = 1}.} -\item{...}{all additional arguments are passed to \code{pomp::\link[pomp]{pfilter}}} +\item{...}{all additional arguments are passed to \code{\link[pomp:pfilter]{pomp::pfilter}}} } \description{ Runs multiple instances of \code{pfilter} using \code{foreach}. } \examples{ library(circumstance) +library(doFuture) +library(doRNG) +registerDoFuture() +registerDoRNG() ou2() -> ou2 -ou2 |> pfilter(Np=1000,Nrep=6) -> pfs + +plan(sequential) +system.time(ou2 |> pfilter(Np=10000,Nrep=6) -> pfs) + +plan(multicore) +system.time(ou2 |> pfilter(Np=10000,Nrep=6) -> pfs) } \seealso{ -\code{pomp::\link[pomp]{pfilter}}. +\code{\link[pomp:pfilter]{pomp::pfilter}}. } diff --git a/rules.mk b/rules.mk index e980584..bc48a67 100644 --- a/rules.mk +++ b/rules.mk @@ -19,7 +19,7 @@ SOURCE = $(sort $(wildcard R/*R src/*.c src/*.h data/* examples/*)) CSOURCE = $(sort $(wildcard src/*.c)) TESTS = $(sort $(wildcard tests/*R)) INSTDOCS = $(sort $(wildcard inst/doc/*)) -SESSION_PKGS = datasets,utils,grDevices,graphics,stats,methods,tidyverse,$(PKG) +SESSION_PKGS = datasets,utils,grDevices,graphics,stats,methods,tidyverse,doFuture,doRNG,$(PKG) .PHONY: .check check clean covr debug default fresh \ htmlhelp manual publish qcheck qqcheck \ @@ -38,7 +38,7 @@ session: RSESSION = emacs -f R debug: RSESSION = R -d gdb rsession: RSESSION = R -default: +default: .roxy .NEWS .instdocs .source .includes .headers @echo $(PKGVERS) roxy: .roxy diff --git a/tests/pfilter-01.png b/tests/pfilter-01.png index 070b4ca..f61ebc5 100644 Binary files a/tests/pfilter-01.png and b/tests/pfilter-01.png differ diff --git a/tests/pfilter.R b/tests/pfilter.R index 0f8ae5e..adb93d5 100644 --- a/tests/pfilter.R +++ b/tests/pfilter.R @@ -5,23 +5,16 @@ set.seed(789744859) library(circumstance) library(tidyr) +library(dplyr) library(ggplot2) -library(doParallel) +library(doFuture) library(doRNG) -chk <- Sys.getenv("_R_CHECK_LIMIT_CORES_", "") - -if (nzchar(chk) && chk == "TRUE") { - ## use 2 cores in CRAN/Travis/AppVeyor - ncores <- 2L -} else { - ## use all cores in devtools::test() - ncores <- parallel::detectCores() -} - -registerDoParallel(ncores) +registerDoFuture() registerDoRNG(789744859) +plan(sequential) + ou2() -> ou2 ou2 |> pfilter(Np=1000,Nrep=6) -> pfs @@ -44,15 +37,25 @@ pfs |> { \(x) do.call(c,x) }() |> - pfilter(Nrep=2,Np=200) -> pfs2 + pfilter(Np=200) -> pfs2 -pfs2 |> - data.frame() |> - separate(.id,c("po","rep")) |> +pfs |> + lapply(simulate) |> + unname() |> + { + \(x) do.call(c,x) + }() |> + pfilter(Nrep=2,Np=200) -> pfs3 + +bind_rows( + a=as.data.frame(pfs2), + b=as.data.frame(pfs3), + .id="list" +) |> + separate(.L1,c("po","rep")) |> ggplot(aes(x=time,y=ess,group=rep,color=rep))+ - geom_line()+ - facet_wrap(~po) - -registerDoSEQ() + geom_line(alpha=0.5)+ + facet_wrap(~po)+ + theme_bw() dev.off() diff --git a/tests/pfilter.Rout.save b/tests/pfilter.Rout.save index 4c79ead..3b23b5a 100644 --- a/tests/pfilter.Rout.save +++ b/tests/pfilter.Rout.save @@ -7,8 +7,6 @@ R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. - Natural language support but running in an English locale - R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. @@ -23,7 +21,6 @@ Type 'q()' to quit R. > set.seed(789744859) > > library(circumstance) -Loading required package: foreach Loading required package: pomp Welcome to pomp! @@ -41,26 +38,30 @@ The following object is masked from ‘package:pomp’: pfilter > library(tidyr) +> library(dplyr) + +Attaching package: ‘dplyr’ + +The following objects are masked from ‘package:stats’: + + filter, lag + +The following objects are masked from ‘package:base’: + + intersect, setdiff, setequal, union + > library(ggplot2) -> library(doParallel) -Loading required package: iterators -Loading required package: parallel +> library(doFuture) +Loading required package: foreach +Loading required package: future > library(doRNG) Loading required package: rngtools > -> chk <- Sys.getenv("_R_CHECK_LIMIT_CORES_", "") -> -> if (nzchar(chk) && chk == "TRUE") { -+ ## use 2 cores in CRAN/Travis/AppVeyor -+ ncores <- 2L -+ } else { -+ ## use all cores in devtools::test() -+ ncores <- parallel::detectCores() -+ } -> -> registerDoParallel(ncores) +> registerDoFuture() > registerDoRNG(789744859) > +> plan(sequential) +> > ou2() -> ou2 > ou2 |> + pfilter(Np=1000,Nrep=6) -> pfs @@ -74,7 +75,7 @@ Loading required package: rngtools > pfs |> + as.data.frame() |> + head() - .id time y1 y2 x1 x2 ess cond.logLik + .L1 time y1 y2 x1 x2 ess cond.logLik 1 1 1 -4.05 4.781 -3.718 4.25 160.6 -4.31 2 1 2 1.83 6.273 0.940 6.84 148.1 -4.42 3 1 3 -1.32 7.556 -0.373 7.59 71.4 -5.20 @@ -93,16 +94,26 @@ Loading required package: rngtools + { + \(x) do.call(c,x) + }() |> -+ pfilter(Nrep=2,Np=200) -> pfs2 ++ pfilter(Np=200) -> pfs2 > -> pfs2 |> -+ data.frame() |> -+ separate(.id,c("po","rep")) |> -+ ggplot(aes(x=time,y=ess,group=rep,color=rep))+ -+ geom_line()+ -+ facet_wrap(~po) +> pfs |> ++ lapply(simulate) |> ++ unname() |> ++ { ++ \(x) do.call(c,x) ++ }() |> ++ pfilter(Nrep=2,Np=200) -> pfs3 > -> registerDoSEQ() +> bind_rows( ++ a=as.data.frame(pfs2), ++ b=as.data.frame(pfs3), ++ .id="list" ++ ) |> ++ separate(.L1,c("po","rep")) |> ++ ggplot(aes(x=time,y=ess,group=rep,color=rep))+ ++ geom_line(alpha=0.5)+ ++ facet_wrap(~po)+ ++ theme_bw() > > dev.off() null device