Herper 1.0.2
The Herper package is a simple toolset to install and manage Conda packages and environments from within the R console.
Unfortunately many tools for data analysis are not available in R, but are present in public repositories like conda. With Herper users can install, manage, record and run conda tools from the comfort of their R session.
Furthermore, many R packages require the use of these external dependencies. Again these dependencies can be installed and managed with the Conda package repository. For example 169 Bioconductor packages have external dependencies listed in their System Requirements field (often with these packages having several requirements) [03 September, 2020].
Herper provides an ad-hoc approach to handling external system requirements for R packages. For people developing packages with python conda dependencies we recommend using basilisk to internally support these system requirements pre-hoc.
The Herper package was developed by Matt Paul, Doug Barrows and Thomas Carroll at the Rockefeller University Bioinformatics Resources Center with contributions from Kathryn Rozen-Gagnon.
Use the BiocManager
package to download and install the package from our Github repository:
if (!requireNamespace("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
BiocManager::install("Herper")
Once installed, load it into your R session:
library(Herper)
The install_CondaTools() function allows the user to specify required Conda software and the desired environment to install into.
Miniconda is installed as part of the process (by default into the r-reticulate’s default Conda location - /home/biocbuild/.local/share/r-miniconda) and the user’s requested conda environment built within the same directory (by default /home/biocbuild/.local/share/r-miniconda/envs/USERS_ENVIRONMENT_HERE).
If you already have Miniconda installed or you would like to install to a custom location, you can specify the path with the pathToMiniConda parameter. In this example we are installing in a temporary directory, but most likely you will want to install/use a stable version of Miniconda.
myMiniconda <- file.path(tempdir2(), "Test")
myMiniconda
## [1] "/tmp/RtmpEmOx06/rr/Test"
install_CondaTools("samtools", "herper", pathToMiniConda = myMiniconda)
## $pathToConda
## [1] "/tmp/RtmpEmOx06/rr/Test/bin/conda"
##
## $environment
## [1] "herper"
##
## $pathToEnvBin
## [1] "/tmp/RtmpEmOx06/rr/Test/envs/herper/bin"
We can add additional tools to our Conda environment by specifying updateEnv = TRUE. A vector of tools can be used to install several at once.
pathToConda <- install_CondaTools(c("salmon", "kallisto"), "herper", updateEnv = TRUE, pathToMiniConda = myMiniconda)
pathToConda
## $pathToConda
## [1] "/tmp/RtmpEmOx06/rr/Test/bin/conda"
##
## $environment
## [1] "herper"
##
## $pathToEnvBin
## [1] "/tmp/RtmpEmOx06/rr/Test/envs/herper/bin"
Specific package versions can be installed using conda formatted inputs into the tools argument i.e. “salmon==1.3”, “salmon>=1.3” or “salmon<=1.3”. This can also be used to specifically upgrade or downgrade existing tools in the chosen environment.
pathToConda <- install_CondaTools("salmon<=1.3", "herper", updateEnv = TRUE, pathToMiniConda = myMiniconda)
The install_CondaSysReqs checks the System Requirements for the specified R package, and uses Conda to install this software. Here we will use a test package contained within Herper. This test package has two System Requirements:
testPkg <- system.file("extdata/HerperTestPkg", package = "Herper")
install.packages(testPkg, type = "source", repos = NULL)
utils::packageDescription("HerperTestPkg", fields = "SystemRequirements")
## [1] "samtools==1.10, rmats>=v4.1.0"
The user can simply supply the name of an installed R package, and install_CondaSysReqs will install the System Requirements through conda.
install_CondaSysReqs("HerperTestPkg", pathToMiniConda = myMiniconda)
## $pathToConda
## [1] "/tmp/RtmpEmOx06/rr/Test/bin/conda"
##
## $environment
## [1] "HerperTestPkg_0.1.0"
##
## $pathToEnvBin
## [1] "/tmp/RtmpEmOx06/rr/Test/envs/HerperTestPkg_0.1.0/bin"
By default these packages are installed in a new environment, which has the name name of the R package and its version number. Users can control the environment name using the env parameter. As with install_CondaTools(), user can control which version of Miniconda with the parameter pathToMiniConda, and whether they want to amend an existing environment with the parameter updateEnv.
Note: install_CondaSysReqs can handle standard System Requirement formats, but will not work if the package has free form text. In this case just use install_CondaTools
Once installed within a conda environment, many external software can be executed directly from the conda environment’s bin directory without having to perform any additional actions.
pathToSamtools <- file.path(pathToConda$pathToEnvBin,"samtools")
Res <- system2(command=pathToSamtools, args = "help",stdout = TRUE)
Res
##
## Program: samtools (Tools for alignments in the SAM format)
## Version: 1.11 (using htslib 1.11)
##
## Usage: samtools <command> [options]
##
## Commands:
## -- Indexing
## dict create a sequence dictionary file
## faidx index/extract FASTA
## fqidx index/extract FASTQ
## index index alignment
##
## -- Editing
## calmd recalculate MD/NM tags and '=' bases
## fixmate fix mate information
## reheader replace BAM header
## targetcut cut fosmid regions (for fosmid pool only)
## addreplacerg adds or replaces RG tags
## markdup mark duplicates
## ampliconclip clip oligos from the end of reads
##
## -- File operations
## collate shuffle and group alignments by name
## cat concatenate BAMs
## merge merge sorted alignments
## mpileup multi-way pileup
## sort sort alignment file
## split splits a file by read group
## quickcheck quickly check if SAM/BAM/CRAM file appears intact
## fastq converts a BAM to a FASTQ
## fasta converts a BAM to a FASTA
##
## -- Statistics
## bedcov read depth per BED region
## coverage alignment depth and percent coverage
## depth compute the depth
## flagstat simple stats
## idxstats BAM index stats
## phase phase heterozygotes
## stats generate stats (former bamcheck)
## ampliconstats generate amplicon specific stats
##
## -- Viewing
## flags explain BAM flags
## tview text alignment viewer
## view SAM<->BAM<->CRAM conversion
## depad convert padded BAM to unpadded BAM
Some external software however require additional environmental variable to be set in order to execute correctly. An example of this would be Cytoscape which requires the java home directory and java library paths to be set prior to its execution.
The Herper package uses the withr family of functions (with_CondaEnv() and local_CondaEnv()) to provide methods to temporarily alter the system PATH and to add or update any required environmental variables. This is done without formally activating your environment or initializing your conda.
The with_CondaEnv allows users to run R code with the required PATH and environmental variables automatically set. The with_CondaEnv function simply requires the name of conda environment and the code to be executed within this environment. Additionally we can also the pathToMiniconda argument to specify any custom miniconda install location.
The with_CondaEnv function will update the PATH we can now run the above samtools command without specifying the full directory path to samtools.
res <- with_CondaEnv("herper",
system2(command="samtools",args = "help",stdout = TRUE),
pathToMiniConda=myMiniconda)
res
##
## Program: samtools (Tools for alignments in the SAM format)
## Version: 1.11 (using htslib 1.11)
##
## Usage: samtools <command> [options]
##
## Commands:
## -- Indexing
## dict create a sequence dictionary file
## faidx index/extract FASTA
## fqidx index/extract FASTQ
## index index alignment
##
## -- Editing
## calmd recalculate MD/NM tags and '=' bases
## fixmate fix mate information
## reheader replace BAM header
## targetcut cut fosmid regions (for fosmid pool only)
## addreplacerg adds or replaces RG tags
## markdup mark duplicates
## ampliconclip clip oligos from the end of reads
##
## -- File operations
## collate shuffle and group alignments by name
## cat concatenate BAMs
## merge merge sorted alignments
## mpileup multi-way pileup
## sort sort alignment file
## split splits a file by read group
## quickcheck quickly check if SAM/BAM/CRAM file appears intact
## fastq converts a BAM to a FASTQ
## fasta converts a BAM to a FASTA
##
## -- Statistics
## bedcov read depth per BED region
## coverage alignment depth and percent coverage
## depth compute the depth
## flagstat simple stats
## idxstats BAM index stats
## phase phase heterozygotes
## stats generate stats (former bamcheck)
## ampliconstats generate amplicon specific stats
##
## -- Viewing
## flags explain BAM flags
## tview text alignment viewer
## view SAM<->BAM<->CRAM conversion
## depad convert padded BAM to unpadded BAM
The local_CondaEnv function acts in a similar fashion to the with_CondaEnv function and allows the user to temporarily update the required PATH and environmental variable from within a function. The PATH and environmental variables will be modified only until the current function ends.
local_CondaEnv is best used within a user-created function, allowing access to the Conda environment’s PATH and variables from within the the function itself but resetting all environmental variables once complete.
samtoolsHelp <- function(){
local_CondaEnv("herper", pathToMiniConda=myMiniconda)
helpMessage <- system2(command="samtools",args = "help",stdout = TRUE)
helpMessage
}
samtoolsHelp()
##
## Program: samtools (Tools for alignments in the SAM format)
## Version: 1.11 (using htslib 1.11)
##
## Usage: samtools <command> [options]
##
## Commands:
## -- Indexing
## dict create a sequence dictionary file
## faidx index/extract FASTA
## fqidx index/extract FASTQ
## index index alignment
##
## -- Editing
## calmd recalculate MD/NM tags and '=' bases
## fixmate fix mate information
## reheader replace BAM header
## targetcut cut fosmid regions (for fosmid pool only)
## addreplacerg adds or replaces RG tags
## markdup mark duplicates
## ampliconclip clip oligos from the end of reads
##
## -- File operations
## collate shuffle and group alignments by name
## cat concatenate BAMs
## merge merge sorted alignments
## mpileup multi-way pileup
## sort sort alignment file
## split splits a file by read group
## quickcheck quickly check if SAM/BAM/CRAM file appears intact
## fastq converts a BAM to a FASTQ
## fasta converts a BAM to a FASTA
##
## -- Statistics
## bedcov read depth per BED region
## coverage alignment depth and percent coverage
## depth compute the depth
## flagstat simple stats
## idxstats BAM index stats
## phase phase heterozygotes
## stats generate stats (former bamcheck)
## ampliconstats generate amplicon specific stats
##
## -- Viewing
## flags explain BAM flags
## tview text alignment viewer
## view SAM<->BAM<->CRAM conversion
## depad convert padded BAM to unpadded BAM
To further demonstrate this we will use the first command from the seqCNA vignette. This step requires samtools. If this is not installed and available there is an error.
library(seqCNA)
data(seqsumm_HCC1143)
try(rco <- readSeqsumm(tumour.data = seqsumm_HCC1143), silent = FALSE)
Samtools is listed as a System Requirement for seqCNA, so we can first use install_CondaSysReqs() to install samtools. In this case we are installing samtools in the environment: seqCNA_env. We can then run the seqCNA command using with_CondaEnv specifying that we want to use our environment containing samtools. seqCNA can then find samtools and execute successfully.
install_CondaSysReqs(pkg="seqCNA",env="seqCNA_env",pathToMiniConda=myMiniconda)
rco <- with_CondaEnv(new="seqCNA_env",readSeqsumm(tumour.data=seqsumm_HCC1143)
,pathToMiniConda = myMiniconda)
summary(rco)
## Basic information:
## SeqCNAInfo object with 5314 200Kbp-long windows.
## PEM information is not available.
## Paired normal is not available.
## Genome and build unknown (chromosomes chr1 to chr5).
## The profile is not yet normalized and not yet segmented.
If the user is unsure of the exact name, or version of a tool available on conda, they can use the conda_search function.
conda_search("salmon", pathToMiniConda = myMiniconda)
## name version channel
## 1 salmon 0.5.1 https://conda.anaconda.org/bioconda/linux-64
## 5 salmon 0.6.0 https://conda.anaconda.org/bioconda/linux-64
## 8 salmon 0.7.2 https://conda.anaconda.org/bioconda/linux-64
## 10 salmon 0.8.0 https://conda.anaconda.org/bioconda/linux-64
## 11 salmon 0.8.1 https://conda.anaconda.org/bioconda/linux-64
## 13 salmon 0.8.2 https://conda.anaconda.org/bioconda/linux-64
## 14 salmon 0.9.0 https://conda.anaconda.org/bioconda/linux-64
## 16 salmon 0.9.1 https://conda.anaconda.org/bioconda/linux-64
## 17 salmon 0.10.0 https://conda.anaconda.org/bioconda/linux-64
## 18 salmon 0.10.1 https://conda.anaconda.org/bioconda/linux-64
## 19 salmon 0.10.2 https://conda.anaconda.org/bioconda/linux-64
## 20 salmon 0.11.0 https://conda.anaconda.org/bioconda/linux-64
## 21 salmon 0.11.1 https://conda.anaconda.org/bioconda/linux-64
## 22 salmon 0.11.2 https://conda.anaconda.org/bioconda/linux-64
## 24 salmon 0.11.3 https://conda.anaconda.org/bioconda/linux-64
## 25 salmon 0.12.0 https://conda.anaconda.org/bioconda/linux-64
## 27 salmon 0.13.0 https://conda.anaconda.org/bioconda/linux-64
## 28 salmon 0.13.1 https://conda.anaconda.org/bioconda/linux-64
## 30 salmon 0.14.0 https://conda.anaconda.org/bioconda/linux-64
## 33 salmon 0.14.1 https://conda.anaconda.org/bioconda/linux-64
## 35 salmon 0.14.2 https://conda.anaconda.org/bioconda/linux-64
## 36 salmon 0.15.0 https://conda.anaconda.org/bioconda/linux-64
## 37 salmon 1.0.0 https://conda.anaconda.org/bioconda/linux-64
## 38 salmon 1.1.0 https://conda.anaconda.org/bioconda/linux-64
## 39 salmon 1.2.0 https://conda.anaconda.org/bioconda/linux-64
## 40 salmon 1.2.1 https://conda.anaconda.org/bioconda/linux-64
## 41 salmon 1.3.0 https://conda.anaconda.org/bioconda/linux-64
## 42 salmon 1.4.0 https://conda.anaconda.org/bioconda/linux-64
## [1] TRUE
Specific package versions can be searched for using the conda format i.e. “salmon==1.3”, “salmon>=1.3” or “salmon<=1.3”. Searches will also find close matches for incorrect queries. Channels to search in can be controlled with channels parameter.
conda_search("salmon<=1.0", pathToMiniConda = myMiniconda)
## name version channel
## 1 salmon 0.5.1 https://conda.anaconda.org/bioconda/linux-64
## 5 salmon 0.6.0 https://conda.anaconda.org/bioconda/linux-64
## 8 salmon 0.7.2 https://conda.anaconda.org/bioconda/linux-64
## 10 salmon 0.8.0 https://conda.anaconda.org/bioconda/linux-64
## 11 salmon 0.8.1 https://conda.anaconda.org/bioconda/linux-64
## 13 salmon 0.8.2 https://conda.anaconda.org/bioconda/linux-64
## 14 salmon 0.9.0 https://conda.anaconda.org/bioconda/linux-64
## 16 salmon 0.9.1 https://conda.anaconda.org/bioconda/linux-64
## 17 salmon 0.10.0 https://conda.anaconda.org/bioconda/linux-64
## 18 salmon 0.10.1 https://conda.anaconda.org/bioconda/linux-64
## 19 salmon 0.10.2 https://conda.anaconda.org/bioconda/linux-64
## 20 salmon 0.11.0 https://conda.anaconda.org/bioconda/linux-64
## 21 salmon 0.11.1 https://conda.anaconda.org/bioconda/linux-64
## 22 salmon 0.11.2 https://conda.anaconda.org/bioconda/linux-64
## 24 salmon 0.11.3 https://conda.anaconda.org/bioconda/linux-64
## 25 salmon 0.12.0 https://conda.anaconda.org/bioconda/linux-64
## 27 salmon 0.13.0 https://conda.anaconda.org/bioconda/linux-64
## 28 salmon 0.13.1 https://conda.anaconda.org/bioconda/linux-64
## 30 salmon 0.14.0 https://conda.anaconda.org/bioconda/linux-64
## 33 salmon 0.14.1 https://conda.anaconda.org/bioconda/linux-64
## 35 salmon 0.14.2 https://conda.anaconda.org/bioconda/linux-64
## 36 salmon 0.15.0 https://conda.anaconda.org/bioconda/linux-64
## [1] TRUE
conda_search("salmo", pathToMiniConda = myMiniconda)
## [1] FALSE
The export_CondaEnv function allows the user to export the environment information to a .yml file. These environment YAML files contain all essential information about the package, allowing for reproducibility and easy distribution of Conda system configuration for collaboration.
yml_name <- paste0("herper_", format(Sys.Date(), "%Y%m%d"), ".yml")
export_CondaEnv("herper", yml_name, pathToMiniConda = myMiniconda)
## [1] "herper_20210226.yml"
The YAML export will contain all packages in the environment by default. If the user wants to only export the packages that were specifically installed and not their dependencies they can use the depends paramter.
yml_name <- paste0("herper_nodeps_", format(Sys.Date(), "%Y%m%d"), ".yml")
export_CondaEnv("herper", yml_name, depends = FALSE, pathToMiniConda = myMiniconda)
## [1] "herper_nodeps_20210226.yml"
The import_CondaEnv function allows the user to create a new conda environment from a .yml file. These can be previously exported from export_CondaEnv, conda, renv or manually created.
Users can simply provide a path to the YAML file for import. They can also specify the environment name, but by default the name will be taken from the YAML.
testYML <- system.file("extdata/test.yml",package="Herper")
import_CondaEnv(yml_import=testYML, pathToMiniConda = myMiniconda)
The list_CondaEnv function allows users to check what environments already exist within the given conda build.
If the User is using multiple builds of conda and wants to check environments across all them, they can include the parameter allCondas = TRUE.
list_CondaEnv(pathToMiniConda = myMiniconda)
## conda path env
## 1 /tmp/RtmpEmOx06/rr/Test HerperTestPkg_0.1.0
## 2 /tmp/RtmpEmOx06/rr/Test herper
## 3 /tmp/RtmpEmOx06/rr/Test my_test
## 4 /tmp/RtmpEmOx06/rr/Test r-reticulate
## 5 /tmp/RtmpEmOx06/rr/Test seqCNA_env
The list_CondaPkgs function allows users to check what packages are installed in a given environment.
list_CondaPkgs("my_test", pathToMiniConda = myMiniconda)
## name version channel platform
## 1 _libgcc_mutex 0.1 conda-forge linux-64
## 2 _openmp_mutex 4.5 conda-forge linux-64
## 3 brotlipy 0.7.0 conda-forge linux-64
## 4 ca-certificates 2020.12.5 conda-forge linux-64
## 5 certifi 2020.12.5 conda-forge linux-64
## 6 cffi 1.14.5 conda-forge linux-64
## 7 chardet 4.0.0 conda-forge linux-64
## 8 click 7.1.2 conda-forge noarch
## 9 coloredlogs 15.0 conda-forge linux-64
## 10 colormath 3.0.0 conda-forge noarch
## 11 cryptography 3.4.4 conda-forge linux-64
## 12 cycler 0.10.0 conda-forge noarch
## 13 decorator 4.4.2 conda-forge noarch
## 14 freetype 2.10.4 conda-forge linux-64
## 15 future 0.18.2 conda-forge linux-64
## 16 humanfriendly 9.1 conda-forge linux-64
## 17 idna 2.10 conda-forge noarch
## 18 importlib-metadata 3.7.0 conda-forge linux-64
## 19 jinja2 2.11.3 conda-forge noarch
## 20 jpeg 9d conda-forge linux-64
## 21 kiwisolver 1.3.1 conda-forge linux-64
## 22 lcms2 2.12 conda-forge linux-64
## 23 ld_impl_linux-64 2.35.1 conda-forge linux-64
## 24 libblas 3.9.0 conda-forge linux-64
## 25 libcblas 3.9.0 conda-forge linux-64
## 26 libffi 3.3 conda-forge linux-64
## 27 libgcc-ng 9.3.0 conda-forge linux-64
## 28 libgfortran-ng 9.3.0 conda-forge linux-64
## 29 libgfortran5 9.3.0 conda-forge linux-64
## 30 libgomp 9.3.0 conda-forge linux-64
## 31 liblapack 3.9.0 conda-forge linux-64
## 32 libopenblas 0.3.12 conda-forge linux-64
## 33 libpng 1.6.37 conda-forge linux-64
## 34 libstdcxx-ng 9.3.0 conda-forge linux-64
## 35 libtiff 4.2.0 conda-forge linux-64
## 36 libwebp-base 1.2.0 conda-forge linux-64
## 37 lz4-c 1.9.3 conda-forge linux-64
## 38 lzstring 1.0.4 conda-forge noarch
## 39 markdown 3.3.3 conda-forge noarch
## 40 markupsafe 1.1.1 conda-forge linux-64
## 41 matplotlib-base 3.3.4 conda-forge linux-64
## 42 multiqc 1.9 bioconda noarch
## 43 ncurses 6.2 conda-forge linux-64
## 44 networkx 2.5 conda-forge noarch
## 45 numpy 1.19.5 conda-forge linux-64
## 46 olefile 0.46 conda-forge noarch
## 47 openssl 1.1.1j conda-forge linux-64
## 48 pillow 8.1.0 conda-forge linux-64
## 49 pip 21.0.1 conda-forge noarch
## 50 pycparser 2.20 conda-forge noarch
## 51 pyopenssl 20.0.1 conda-forge noarch
## 52 pyparsing 2.4.7 conda-forge noarch
## 53 pysocks 1.7.1 conda-forge linux-64
## 54 python 3.6.13 conda-forge linux-64
## 55 python-dateutil 2.8.1 conda-forge noarch
## 56 python_abi 3.6 conda-forge linux-64
## 57 pyyaml 5.4.1 conda-forge linux-64
## 58 readline 8.0 conda-forge linux-64
## 59 requests 2.25.1 conda-forge noarch
## 60 setuptools 49.6.0 conda-forge linux-64
## 61 simplejson 3.8.1 bioconda linux-64
## 62 six 1.15.0 conda-forge noarch
## 63 spectra 0.0.11 conda-forge noarch
## 64 sqlite 3.34.0 conda-forge linux-64
## 65 tk 8.6.10 conda-forge linux-64
## 66 tornado 6.1 conda-forge linux-64
## 67 typing_extensions 3.7.4.3 conda-forge noarch
## 68 urllib3 1.26.3 conda-forge noarch
## 69 wheel 0.36.2 conda-forge noarch
## 70 xz 5.2.5 conda-forge linux-64
## 71 yaml 0.2.5 conda-forge linux-64
## 72 zipp 3.4.0 conda-forge noarch
## 73 zlib 1.2.11 conda-forge linux-64
## 74 zstd 1.4.8 conda-forge linux-64
Thank you to Ji-Dung Luo and Wei Wang for testing/vignette review/critical feedback and Ziwei Liang for their support.
sessionInfo()
## R version 4.0.4 (2021-02-15)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
##
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.12-bioc/R/lib/libRblas.so
## LAPACK: /home/biocbuild/bbs-3.12-bioc/R/lib/libRlapack.so
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8
## [4] LC_COLLATE=C LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C
## [10] LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] seqCNA_1.36.0 seqCNA.annot_1.26.0 adehabitatLT_0.3.25 CircStats_0.2-6
## [5] boot_1.3-27 MASS_7.3-53.1 adehabitatMA_0.3.14 ade4_1.7-16
## [9] sp_1.4-5 doSNOW_1.0.19 snow_0.4-3 iterators_1.0.13
## [13] foreach_1.5.1 GLAD_2.54.0 Herper_1.0.2 reticulate_1.18
## [17] BiocStyle_2.18.1
##
## loaded via a namespace (and not attached):
## [1] Rcpp_1.0.6 bslib_0.2.4 compiler_4.0.4 BiocManager_1.30.10
## [5] jquerylib_0.1.3 highr_0.8 prettyunits_1.1.1 progress_1.2.2
## [9] tools_4.0.4 digest_0.6.27 lifecycle_1.0.0 jsonlite_1.7.2
## [13] evaluate_0.14 lattice_0.20-41 pkgconfig_2.0.3 rlang_0.4.10
## [17] Matrix_1.3-2 yaml_2.2.1 parallel_4.0.4 xfun_0.21
## [21] withr_2.4.1 stringr_1.4.0 knitr_1.31 vctrs_0.3.6
## [25] hms_1.0.0 sass_0.3.1 rappdirs_0.3.3 grid_4.0.4
## [29] R6_2.5.0 rmarkdown_2.7 bookdown_0.21 magrittr_2.0.1
## [33] ellipsis_0.3.1 codetools_0.2-18 htmltools_0.5.1.1 stringi_1.5.3
## [37] crayon_1.4.1 rjson_0.2.20